summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore11
-rwxr-xr-xBUILD/compile-pentium-maintainer13
-rwxr-xr-xBUILD/compile-pentium-max5
-rw-r--r--BitKeeper/etc/logging_ok15
-rwxr-xr-xBuild-tools/Do-compile50
-rwxr-xr-xBuild-tools/Do-rpm67
-rwxr-xr-xBuild-tools/my_md5sum124
-rwxr-xr-xBuild-tools/mysql-copyright104
-rwxr-xr-xBuild-tools/mysql-copyright-21
-rw-r--r--Docs/manual_toc.html9
-rw-r--r--Makefile.am7
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/4.0.XX-classic.ipr51
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Component Definitions/Default.cdf192
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Component Definitions/Default.fgl42
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/File Groups/Clients and Tools.fgl32
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/File Groups/Default.fdf82
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/File Groups/Development.fgl240
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/File Groups/Documentation.fgl99
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/File Groups/Grant Tables.fgl36
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/File Groups/Servers.fgl227
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Registry Entries/Default.rge4
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.dbgbin28458 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.inobin58611 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.insbin57122 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.obsbin65611 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.rul.old640
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Script Files/setup.rul641
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt25
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmpbin15694 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Shell Objects/Default.shl12
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl23
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/String Tables/Default.shl74
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Text Substitutions/Build.tsb56
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/Text Substitutions/Setup.tsb76
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/4.0.XX-gpl.ipr51
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Component Definitions/Default.cdf192
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Component Definitions/Default.fgl42
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/File Groups/Clients and Tools.fgl32
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/File Groups/Default.fdf82
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/File Groups/Development.fgl242
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/File Groups/Documentation.fgl101
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/File Groups/Grant Tables.fgl36
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/File Groups/Servers.fgl229
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Registry Entries/Default.rge4
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.dbgbin28458 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.inobin58611 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.insbin57122 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.obsbin65611 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.rul.old640
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Script Files/setup.rul641
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt25
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmpbin15694 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Shell Objects/Default.shl12
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl23
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/String Tables/Default.shl74
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Text Substitutions/Build.tsb56
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/Text Substitutions/Setup.tsb76
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/4.0.XX-pro.ipr52
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Component Definitions/Default.cdf192
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Component Definitions/Default.fgl42
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/File Groups/Clients and Tools.fgl32
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/File Groups/Default.fdf82
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/File Groups/Development.fgl240
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/File Groups/Documentation.fgl99
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/File Groups/Grant Tables.fgl36
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/File Groups/Servers.fgl227
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Registry Entries/Default.rge4
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.dbgbin28458 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.inobin58611 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.insbin57122 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.obsbin65611 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.rul.old640
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Script Files/setup.rul641
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt25
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmpbin15694 -> 0 bytes
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Shell Objects/Default.shl12
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl23
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/String Tables/Default.shl74
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Text Substitutions/Build.tsb56
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/Text Substitutions/Setup.tsb76
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.dbgbin28458 -> 0 bytes
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.inobin58611 -> 0 bytes
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.insbin57122 -> 0 bytes
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.obsbin65611 -> 0 bytes
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.rul640
-rw-r--r--VC++Files/client/mysqlclient.dsp37
-rw-r--r--VC++Files/examples/udf_example/udf_example.def18
-rw-r--r--VC++Files/examples/udf_example/udf_example.dsp111
-rw-r--r--VC++Files/examples/udf_example/udf_example.dsw29
-rw-r--r--VC++Files/libmysql/libmysql.dsp4
-rw-r--r--VC++Files/libmysqld/libmysqld.dsp8
-rw-r--r--VC++Files/sql/mysqld.dsp10
-rw-r--r--VC++Files/winmysqladmin/main.cpp2
-rw-r--r--VC++Files/winmysqladmin/mysql.h4
-rw-r--r--VC++Files/winmysqladmin/mysql_com.h26
-rw-r--r--VC++Files/zlib/zlib.dsp27
-rw-r--r--acconfig.h25
-rw-r--r--acinclude.m4115
-rw-r--r--client/mysql.cc24
-rw-r--r--client/mysqladmin.c10
-rw-r--r--client/mysqlbinlog.cc1
-rw-r--r--client/mysqldump.c141
-rw-r--r--client/mysqltest.c101
-rw-r--r--configure.in236
-rw-r--r--dbug/dbug.c4
-rw-r--r--extra/Makefile.am3
-rw-r--r--extra/perror.c4
-rw-r--r--heap/hp_hash.c3
-rw-r--r--include/Makefile.am6
-rw-r--r--include/config-netware.h4
-rw-r--r--include/errmsg.h8
-rw-r--r--include/m_ctype.h17
-rw-r--r--include/m_string.h16
-rw-r--r--include/my_base.h3
-rw-r--r--include/my_dbug.h1
-rw-r--r--include/my_global.h90
-rw-r--r--include/my_time.h46
-rw-r--r--include/myisam.h2
-rw-r--r--include/myisampack.h7
-rw-r--r--include/mysql.h42
-rw-r--r--include/mysql_com.h35
-rw-r--r--include/mysql_time.h37
-rw-r--r--include/mysqld_error.h90
-rw-r--r--include/sql_state.h6
-rw-r--r--include/violite.h8
-rw-r--r--innobase/btr/btr0btr.c2
-rw-r--r--innobase/btr/btr0cur.c4
-rw-r--r--innobase/buf/buf0buf.c16
-rw-r--r--innobase/buf/buf0flu.c10
-rw-r--r--innobase/buf/buf0lru.c4
-rw-r--r--innobase/buf/buf0rea.c10
-rw-r--r--innobase/data/data0type.c2
-rw-r--r--innobase/dict/dict0boot.c105
-rw-r--r--innobase/dict/dict0crea.c22
-rw-r--r--innobase/dict/dict0dict.c63
-rw-r--r--innobase/dict/dict0load.c55
-rw-r--r--innobase/dict/dict0mem.c6
-rw-r--r--innobase/fil/fil0fil.c453
-rw-r--r--innobase/fsp/fsp0fsp.c6
-rw-r--r--innobase/fut/fut0lst.c2
-rw-r--r--innobase/ha/ha0ha.c2
-rw-r--r--innobase/ha/hash0hash.c38
-rw-r--r--innobase/ibuf/ibuf0ibuf.c19
-rw-r--r--innobase/include/Makefile.am2
-rw-r--r--innobase/include/btr0btr.h2
-rw-r--r--innobase/include/buf0buf.h10
-rw-r--r--innobase/include/buf0buf.ic6
-rw-r--r--innobase/include/buf0flu.h2
-rw-r--r--innobase/include/buf0lru.h2
-rw-r--r--innobase/include/data0data.h6
-rw-r--r--innobase/include/data0type.h3
-rw-r--r--innobase/include/dict0dict.h14
-rw-r--r--innobase/include/dict0mem.h17
-rw-r--r--innobase/include/fil0fil.h8
-rw-r--r--innobase/include/fsp0fsp.h2
-rw-r--r--innobase/include/fut0lst.h3
-rw-r--r--innobase/include/hash0hash.h20
-rw-r--r--innobase/include/hash0hash.ic8
-rw-r--r--innobase/include/lock0lock.h6
-rw-r--r--innobase/include/log0log.h39
-rw-r--r--innobase/include/log0log.ic38
-rw-r--r--innobase/include/log0recv.h19
-rw-r--r--innobase/include/mach0data.h6
-rw-r--r--innobase/include/mach0data.ic4
-rw-r--r--innobase/include/mem0dbg.h17
-rw-r--r--innobase/include/mem0dbg.ic7
-rw-r--r--innobase/include/mem0mem.h12
-rw-r--r--innobase/include/mem0mem.ic18
-rw-r--r--innobase/include/mem0pool.h3
-rw-r--r--innobase/include/mtr0log.h4
-rw-r--r--innobase/include/mtr0log.ic4
-rw-r--r--innobase/include/mtr0mtr.h28
-rw-r--r--innobase/include/os0file.h7
-rw-r--r--innobase/include/os0thread.h4
-rw-r--r--innobase/include/pars0opt.h2
-rw-r--r--innobase/include/que0que.h38
-rw-r--r--innobase/include/que0que.ic18
-rw-r--r--innobase/include/row0ins.h5
-rw-r--r--innobase/include/row0mysql.h3
-rw-r--r--innobase/include/row0upd.h5
-rw-r--r--innobase/include/srv0que.h53
-rw-r--r--innobase/include/srv0srv.h11
-rw-r--r--innobase/include/sync0rw.h2
-rw-r--r--innobase/include/sync0rw.ic2
-rw-r--r--innobase/include/sync0sync.h2
-rw-r--r--innobase/include/sync0sync.ic2
-rw-r--r--innobase/include/trx0roll.h21
-rw-r--r--innobase/include/trx0sys.h8
-rw-r--r--innobase/include/trx0trx.h31
-rw-r--r--innobase/include/usr0sess.h6
-rw-r--r--innobase/include/ut0mem.h31
-rw-r--r--innobase/lock/lock0lock.c16
-rw-r--r--innobase/log/log0log.c227
-rw-r--r--innobase/log/log0recv.c103
-rw-r--r--innobase/mem/mem0dbg.c134
-rw-r--r--innobase/mem/mem0pool.c2
-rw-r--r--innobase/mtr/mtr0mtr.c201
-rw-r--r--innobase/os/os0file.c131
-rw-r--r--innobase/os/os0thread.c9
-rw-r--r--innobase/page/page0page.c4
-rw-r--r--innobase/pars/lexyy.c262
-rw-r--r--innobase/pars/pars0lex.l45
-rw-r--r--innobase/pars/pars0opt.c2
-rw-r--r--innobase/pars/pars0pars.c4
-rw-r--r--innobase/que/que0que.c117
-rw-r--r--innobase/rem/rem0cmp.c8
-rw-r--r--innobase/row/row0ins.c33
-rw-r--r--innobase/row/row0mysql.c284
-rw-r--r--innobase/row/row0sel.c18
-rw-r--r--innobase/row/row0upd.c6
-rw-r--r--innobase/srv/Makefile.am2
-rw-r--r--innobase/srv/srv0que.c113
-rw-r--r--innobase/srv/srv0srv.c87
-rw-r--r--innobase/srv/srv0start.c76
-rw-r--r--innobase/sync/sync0rw.c8
-rw-r--r--innobase/sync/sync0sync.c14
-rw-r--r--innobase/thr/thr0loc.c10
-rw-r--r--innobase/trx/trx0purge.c3
-rw-r--r--innobase/trx/trx0roll.c95
-rw-r--r--innobase/trx/trx0sys.c44
-rw-r--r--innobase/trx/trx0trx.c177
-rw-r--r--innobase/usr/usr0sess.c2
-rw-r--r--innobase/ut/ut0mem.c75
-rw-r--r--isam/_dynrec.c6
-rw-r--r--isam/isamchk.c8
-rw-r--r--isam/isamlog.c2
-rw-r--r--isam/pack_isam.c2
-rw-r--r--isam/test1.c2
-rw-r--r--libmysql/Makefile.shared2
-rw-r--r--libmysql/errmsg.c110
-rw-r--r--libmysql/libmysql.c992
-rw-r--r--libmysql/libmysql.def11
-rw-r--r--libmysql_r/Makefile.am2
-rw-r--r--libmysqld/Makefile.am6
-rw-r--r--libmysqld/lib_sql.cc18
-rw-r--r--libmysqld/libmysqld.c7
-rw-r--r--libmysqld/libmysqld.def6
-rw-r--r--man/mysqlaccess.1.in3
-rw-r--r--man/mysqldump.1.in2
-rw-r--r--merge/mrg_open.c2
-rw-r--r--myisam/ft_boolean_search.c45
-rw-r--r--myisam/ftdefs.h1
-rw-r--r--myisam/mi_check.c12
-rw-r--r--myisam/mi_create.c7
-rw-r--r--myisam/mi_delete.c4
-rw-r--r--myisam/mi_dynrec.c1
-rw-r--r--myisam/mi_key.c7
-rw-r--r--myisam/mi_open.c9
-rw-r--r--myisam/mi_range.c2
-rw-r--r--myisam/mi_rkey.c2
-rw-r--r--myisam/mi_rnext.c5
-rw-r--r--myisam/mi_rnext_same.c2
-rw-r--r--myisam/mi_search.c5
-rw-r--r--myisam/mi_static.c2
-rw-r--r--myisam/mi_unique.c10
-rw-r--r--myisam/mi_write.c1
-rw-r--r--myisam/myisamchk.c24
-rw-r--r--myisam/myisamlog.c2
-rw-r--r--myisam/rt_index.c89
-rw-r--r--myisam/rt_index.h5
-rw-r--r--myisam/rt_key.c47
-rw-r--r--myisam/rt_key.h6
-rw-r--r--myisam/rt_mbr.c496
-rw-r--r--myisam/rt_mbr.h5
-rw-r--r--myisam/rt_split.c14
-rw-r--r--myisam/rt_test.c72
-rw-r--r--myisam/sort.c6
-rw-r--r--myisam/sp_defs.h3
-rw-r--r--myisam/sp_key.c5
-rw-r--r--myisam/sp_test.c10
-rw-r--r--myisammrg/myrg_write.c4
-rw-r--r--mysql-test/Makefile.am13
-rw-r--r--mysql-test/README2
-rw-r--r--mysql-test/include/have_archive.inc4
-rw-r--r--mysql-test/include/have_debug.inc4
-rw-r--r--mysql-test/include/have_geometry.inc4
-rw-r--r--mysql-test/include/ps_create.inc29
-rw-r--r--mysql-test/include/ps_modify.inc207
-rw-r--r--mysql-test/include/ps_modify1.inc60
-rw-r--r--mysql-test/include/ps_query.inc587
-rw-r--r--mysql-test/include/ps_renew.inc34
-rw-r--r--mysql-test/misc/kill_master.sh4
-rw-r--r--mysql-test/mysql-test-run.sh40
-rw-r--r--mysql-test/ndb/Makefile.am23
-rwxr-xr-xmysql-test/ndb/install_ndbcluster148
-rw-r--r--mysql-test/ndb/ndb_config_2_node.ini72
-rw-r--r--mysql-test/ndb/ndbcluster.sh244
-rwxr-xr-xmysql-test/ndb/stop_ndbcluster52
-rw-r--r--mysql-test/r/alter_table.result10
-rw-r--r--mysql-test/r/archive.result1396
-rw-r--r--mysql-test/r/auto_increment.result7
-rw-r--r--mysql-test/r/bdb-deadlock.result2
-rw-r--r--mysql-test/r/bdb.result70
-rw-r--r--mysql-test/r/connect.result15
-rw-r--r--mysql-test/r/create.result12
-rw-r--r--mysql-test/r/ctype_uca.result1657
-rw-r--r--mysql-test/r/ctype_ucs.result9
-rw-r--r--mysql-test/r/ctype_ujis.result15
-rw-r--r--mysql-test/r/ctype_utf8.result22
-rw-r--r--mysql-test/r/date_formats.result16
-rw-r--r--mysql-test/r/delete.result10
-rw-r--r--mysql-test/r/derived.result10
-rw-r--r--mysql-test/r/flush_table.result66
-rw-r--r--mysql-test/r/fulltext.result21
-rw-r--r--mysql-test/r/func_compress.result2
-rw-r--r--mysql-test/r/func_gconcat.result21
-rw-r--r--mysql-test/r/func_group.result28
-rw-r--r--mysql-test/r/func_if.result6
-rw-r--r--mysql-test/r/func_like.result6
-rw-r--r--mysql-test/r/func_regexp.result17
-rw-r--r--mysql-test/r/func_sapdb.result6
-rw-r--r--mysql-test/r/func_str.result9
-rw-r--r--mysql-test/r/func_time.result10
-rw-r--r--mysql-test/r/gis-rtree.result10
-rw-r--r--mysql-test/r/grant.result2
-rw-r--r--mysql-test/r/grant2.result2
-rw-r--r--mysql-test/r/grant_cache.result12
-rw-r--r--mysql-test/r/handler.result8
-rw-r--r--mysql-test/r/have_archive.require2
-rw-r--r--mysql-test/r/have_debug.require2
-rw-r--r--mysql-test/r/have_geometry.require2
-rw-r--r--mysql-test/r/innodb_cache.result21
-rw-r--r--mysql-test/r/innodb_handler.result4
-rw-r--r--mysql-test/r/insert.result88
-rw-r--r--mysql-test/r/insert_select.result4
-rw-r--r--mysql-test/r/isam.result2
-rw-r--r--mysql-test/r/join.result2
-rw-r--r--mysql-test/r/join_outer.result8
-rw-r--r--mysql-test/r/key.result4
-rw-r--r--mysql-test/r/key_cache.result4
-rw-r--r--mysql-test/r/loaddata.result4
-rw-r--r--mysql-test/r/lowercase_table2.result14
-rw-r--r--mysql-test/r/lowercase_table3.result4
-rw-r--r--mysql-test/r/merge.result18
-rw-r--r--mysql-test/r/multi_update.result3
-rw-r--r--mysql-test/r/mysqlbinlog.result9
-rw-r--r--mysql-test/r/mysqldump.result38
-rw-r--r--mysql-test/r/ndb_alter_table.result29
-rw-r--r--mysql-test/r/ndb_autodiscover.result183
-rw-r--r--mysql-test/r/ndb_autodiscover2.result10
-rw-r--r--mysql-test/r/ndb_basic.result266
-rw-r--r--mysql-test/r/ndb_index.result154
-rw-r--r--mysql-test/r/ndb_index_ordered.result190
-rw-r--r--mysql-test/r/ndb_index_unique.result413
-rw-r--r--mysql-test/r/ndb_insert.result419
-rw-r--r--mysql-test/r/ndb_minmax.result120
-rw-r--r--mysql-test/r/ndb_replace.result21
-rw-r--r--mysql-test/r/null.result18
-rw-r--r--mysql-test/r/null_key.result2
-rw-r--r--mysql-test/r/openssl_1.result8
-rw-r--r--mysql-test/r/packet.result2
-rw-r--r--mysql-test/r/ps.result221
-rw-r--r--mysql-test/r/ps_1general.result745
-rw-r--r--mysql-test/r/ps_2myisam.result1269
-rw-r--r--mysql-test/r/ps_3innodb.result1269
-rw-r--r--mysql-test/r/ps_4heap.result1270
-rw-r--r--mysql-test/r/ps_5merge.result2410
-rw-r--r--mysql-test/r/ps_6bdb.result1269
-rw-r--r--mysql-test/r/query_cache.result8
-rw-r--r--mysql-test/r/range.result23
-rw-r--r--mysql-test/r/rpl_charset.result201
-rw-r--r--mysql-test/r/rpl_delete_all.result31
-rw-r--r--mysql-test/r/rpl_free_items.result10
-rw-r--r--mysql-test/r/rpl_get_lock.result6
-rw-r--r--mysql-test/r/rpl_ps.result28
-rw-r--r--mysql-test/r/rpl_rotate_logs.result6
-rw-r--r--mysql-test/r/rpl_server_id1.result5
-rw-r--r--mysql-test/r/rpl_temporary.result4
-rw-r--r--mysql-test/r/rpl_timezone.result77
-rw-r--r--mysql-test/r/rpl_until.result10
-rw-r--r--mysql-test/r/select.result9
-rw-r--r--mysql-test/r/select_found.result17
-rw-r--r--mysql-test/r/select_safe.result6
-rw-r--r--mysql-test/r/show_check.result74
-rw-r--r--mysql-test/r/subselect.result118
-rw-r--r--mysql-test/r/subselect_innodb.result10
-rw-r--r--mysql-test/r/system_mysql_db.result5
-rw-r--r--mysql-test/r/timezone.result11
-rw-r--r--mysql-test/r/timezone2.result246
-rw-r--r--mysql-test/r/type_blob.result2
-rw-r--r--mysql-test/r/type_date.result6
-rw-r--r--mysql-test/r/type_datetime.result70
-rw-r--r--mysql-test/r/type_decimal.result107
-rw-r--r--mysql-test/r/type_float.result4
-rw-r--r--mysql-test/r/type_ranges.result38
-rw-r--r--mysql-test/r/type_time.result10
-rw-r--r--mysql-test/r/type_timestamp.result80
-rw-r--r--mysql-test/r/type_uint.result2
-rw-r--r--mysql-test/r/union.result57
-rw-r--r--mysql-test/r/user_var.result33
-rw-r--r--mysql-test/r/varbinary.result2
-rw-r--r--mysql-test/r/variables.result14
-rw-r--r--mysql-test/r/warnings.result24
-rw-r--r--mysql-test/t/alter_table.test8
-rw-r--r--mysql-test/t/archive.test1300
-rw-r--r--mysql-test/t/auto_increment.test1
-rw-r--r--mysql-test/t/bdb.test75
-rw-r--r--mysql-test/t/ctype_uca.test181
-rw-r--r--mysql-test/t/ctype_ucs.test10
-rw-r--r--mysql-test/t/ctype_ujis.test10
-rw-r--r--mysql-test/t/ctype_utf8.test16
-rw-r--r--mysql-test/t/delete.test11
-rw-r--r--mysql-test/t/flush_table.test59
-rw-r--r--mysql-test/t/fulltext.test13
-rw-r--r--mysql-test/t/func_gconcat.test20
-rw-r--r--mysql-test/t/func_group.test22
-rw-r--r--mysql-test/t/func_if.test9
-rw-r--r--mysql-test/t/func_like.test13
-rw-r--r--mysql-test/t/func_regexp.test13
-rw-r--r--mysql-test/t/func_str.test4
-rw-r--r--mysql-test/t/func_time.test2
-rw-r--r--mysql-test/t/gis-rtree.test2
-rw-r--r--mysql-test/t/gis.test2
-rw-r--r--mysql-test/t/innodb_cache.test23
-rw-r--r--mysql-test/t/lowercase_table2.test11
-rw-r--r--mysql-test/t/lowercase_table3.test4
-rw-r--r--mysql-test/t/merge.test8
-rw-r--r--mysql-test/t/multi_update.test1
-rw-r--r--mysql-test/t/mysqlbinlog.test7
-rw-r--r--mysql-test/t/mysqldump.test5
-rw-r--r--mysql-test/t/ndb_alter_table.test41
-rw-r--r--mysql-test/t/ndb_autodiscover.test267
-rw-r--r--mysql-test/t/ndb_autodiscover2-master.opt1
-rw-r--r--mysql-test/t/ndb_autodiscover2.test13
-rw-r--r--mysql-test/t/ndb_basic.test231
-rw-r--r--mysql-test/t/ndb_index.test129
-rw-r--r--mysql-test/t/ndb_index_ordered.test112
-rw-r--r--mysql-test/t/ndb_index_unique.test175
-rw-r--r--mysql-test/t/ndb_insert.test433
-rw-r--r--mysql-test/t/ndb_minmax.test66
-rw-r--r--mysql-test/t/ndb_replace.test27
-rw-r--r--mysql-test/t/ps.test208
-rw-r--r--mysql-test/t/ps_1general.test739
-rw-r--r--mysql-test/t/ps_2myisam.test17
-rw-r--r--mysql-test/t/ps_3innodb.test17
-rw-r--r--mysql-test/t/ps_4heap.test43
-rw-r--r--mysql-test/t/ps_5merge.test78
-rw-r--r--mysql-test/t/ps_6bdb.test18
-rw-r--r--mysql-test/t/range.test27
-rw-r--r--mysql-test/t/rpl000015.test2
-rw-r--r--mysql-test/t/rpl_charset.test153
-rw-r--r--mysql-test/t/rpl_delete_all.test41
-rw-r--r--mysql-test/t/rpl_free_items-slave.opt1
-rw-r--r--mysql-test/t/rpl_free_items.test20
-rw-r--r--mysql-test/t/rpl_get_lock.test2
-rw-r--r--mysql-test/t/rpl_ps.test43
-rw-r--r--mysql-test/t/rpl_relayspace-slave.opt2
-rw-r--r--mysql-test/t/rpl_server_id1.test8
-rw-r--r--mysql-test/t/rpl_timezone-master.opt1
-rw-r--r--mysql-test/t/rpl_timezone-slave.opt1
-rw-r--r--mysql-test/t/rpl_timezone.test84
-rw-r--r--mysql-test/t/select.test4
-rw-r--r--mysql-test/t/select_found.test19
-rw-r--r--mysql-test/t/show_check.test14
-rw-r--r--mysql-test/t/subselect.test56
-rw-r--r--mysql-test/t/subselect_innodb.test10
-rw-r--r--mysql-test/t/system_mysql_db_fix.test5
-rw-r--r--mysql-test/t/system_mysql_db_refs.test1
-rw-r--r--mysql-test/t/timezone.test15
-rw-r--r--mysql-test/t/timezone2.test189
-rw-r--r--mysql-test/t/type_date.test9
-rw-r--r--mysql-test/t/type_datetime.test19
-rw-r--r--mysql-test/t/type_decimal.test3
-rw-r--r--mysql-test/t/type_timestamp.test19
-rw-r--r--mysql-test/t/union.test40
-rw-r--r--mysql-test/t/user_var.test21
-rw-r--r--mysql-test/t/variables.test1
-rw-r--r--mysys/ChangeLog4
-rw-r--r--mysys/charset-def.c65
-rw-r--r--mysys/charset.c196
-rw-r--r--mysys/default.c2
-rw-r--r--mysys/hash.c3
-rw-r--r--mysys/mf_iocache.c5
-rw-r--r--mysys/mf_iocache2.c3
-rw-r--r--mysys/mf_keycache.c1
-rw-r--r--mysys/mf_pack.c12
-rw-r--r--mysys/mf_soundex.c4
-rw-r--r--mysys/mf_tempfile.c4
-rw-r--r--mysys/mf_wfile.c2
-rw-r--r--mysys/my_bitmap.c1
-rw-r--r--mysys/my_error.c74
-rw-r--r--mysys/my_gethostbyname.c1
-rw-r--r--mysys/my_getopt.c1
-rw-r--r--mysys/my_getwd.c2
-rw-r--r--mysys/my_handler.c4
-rw-r--r--mysys/my_pthread.c35
-rw-r--r--mysys/my_seek.c1
-rw-r--r--mysys/my_static.h2
-rw-r--r--mysys/my_tempnam.c2
-rw-r--r--mysys/rijndael.c1
-rw-r--r--mysys/thr_alarm.c1
-rw-r--r--ndb/BinDist.sh121
-rw-r--r--ndb/Defs.mk64
-rw-r--r--ndb/Epilogue.mk876
-rw-r--r--ndb/Makefile69
-rw-r--r--ndb/Makefile.am19
-rw-r--r--ndb/README7
-rw-r--r--ndb/SrcDist.sh87
-rwxr-xr-xndb/bin/mysqlcluster11
-rwxr-xr-xndb/bin/mysqlcluster_install_db119
-rwxr-xr-xndb/bin/mysqlclusterd34
-rw-r--r--ndb/bin/regression.sh644
-rw-r--r--ndb/config/Defs.DEBUG.mk4
-rw-r--r--ndb/config/Defs.HPUX.HPPA.GCC.mk50
-rw-r--r--ndb/config/Defs.IBMAIX.POWERPC.GCC.mk49
-rw-r--r--ndb/config/Defs.LINUX.x86.GCC.mk60
-rw-r--r--ndb/config/Defs.LINUX.x86.ICC.mk54
-rw-r--r--ndb/config/Defs.LINUX.x86_64.GCC.mk54
-rw-r--r--ndb/config/Defs.MACOSX.POWERPC.GCC.mk58
-rw-r--r--ndb/config/Defs.OSE.PPC750.DIAB.mk47
-rw-r--r--ndb/config/Defs.RELEASE.mk3
-rw-r--r--ndb/config/Defs.RELEASE_TRACE.mk3
-rw-r--r--ndb/config/Defs.SIMCELLO.SOFTOSE.GCC.mk53
-rw-r--r--ndb/config/Defs.SOFTOSE.SPARC.GCC.mk57
-rw-r--r--ndb/config/Defs.SOLARIS.SPARC.FORTE6.mk54
-rw-r--r--ndb/config/Defs.SOLARIS.SPARC.GCC.mk54
-rw-r--r--ndb/config/Defs.SOLARIS.SPARC_64.GCC.mk53
-rw-r--r--ndb/config/Defs.SOLARIS6.SPARC.GCC.mk53
-rw-r--r--ndb/config/Defs.TRU64X.ALPHA.GCC.mk49
-rw-r--r--ndb/config/Defs.WIN32.x86.VC7.mk61
-rwxr-xr-xndb/config/GuessConfig.sh115
-rw-r--r--ndb/config/Makefile.am31
-rw-r--r--ndb/config/acinclude.m41513
-rw-r--r--ndb/config/common.mk.am12
-rw-r--r--ndb/config/config.h.in993
-rw-r--r--ndb/config/configure.in2085
-rw-r--r--ndb/config/type_kernel.mk.am18
-rw-r--r--ndb/config/type_mgmapiclient.mk.am2
-rw-r--r--ndb/config/type_ndbapi.mk.am12
-rw-r--r--ndb/config/type_ndbapiclient.mk.am2
-rw-r--r--ndb/config/type_ndbapitest.mk.am11
-rw-r--r--ndb/config/type_ndbapitools.mk.am10
-rw-r--r--ndb/config/type_util.mk.am6
-rwxr-xr-xndb/configure33
-rw-r--r--ndb/docs/Makefile97
-rw-r--r--ndb/docs/Makefile.am102
-rwxr-xr-xndb/docs/doxygen/postdoxy.pl1
-rwxr-xr-xndb/docs/doxygen/predoxy.pl1
-rw-r--r--ndb/env.sh8
-rw-r--r--ndb/include/Makefile.am42
-rw-r--r--ndb/include/kernel/BlockNumbers.h1
-rw-r--r--ndb/include/kernel/GlobalSignalNumbers.h84
-rw-r--r--ndb/include/kernel/LogLevel.hpp28
-rw-r--r--ndb/include/kernel/kernel_config_parameters.h56
-rw-r--r--ndb/include/kernel/ndb_limits.h5
-rw-r--r--ndb/include/kernel/signaldata/CheckNodeGroups.hpp12
-rw-r--r--ndb/include/kernel/signaldata/CntrStart.hpp69
-rw-r--r--ndb/include/kernel/signaldata/CreateEvnt.hpp2
-rw-r--r--ndb/include/kernel/signaldata/DictTabInfo.hpp11
-rw-r--r--ndb/include/kernel/signaldata/EventSubscribeReq.hpp6
-rw-r--r--ndb/include/kernel/signaldata/FsOpenReq.hpp1
-rw-r--r--ndb/include/kernel/signaldata/ReadConfig.hpp24
-rw-r--r--ndb/include/kernel/signaldata/ReadNodesConf.hpp48
-rw-r--r--ndb/include/kernel/signaldata/SetLogLevelOrd.hpp1
-rw-r--r--ndb/include/kernel/signaldata/TcKeyConf.hpp2
-rw-r--r--ndb/include/kernel/signaldata/TupAccess.hpp2
-rw-r--r--ndb/include/kernel/signaldata/TupFrag.hpp5
-rw-r--r--ndb/include/kernel/signaldata/TuxMaint.hpp9
-rw-r--r--ndb/include/kernel/signaldata/UpgradeStartup.hpp36
-rw-r--r--ndb/include/kernel/trigger_definitions.h1
-rw-r--r--ndb/include/mgmapi/mgmapi.h35
-rw-r--r--ndb/include/mgmapi/mgmapi_config_parameters.h144
-rw-r--r--ndb/include/mgmapi/mgmapi_config_parameters_debug.h8
-rw-r--r--ndb/include/mgmcommon/ConfigRetriever.hpp32
-rw-r--r--ndb/include/mgmcommon/IPCConfig.hpp4
-rw-r--r--ndb/include/ndb_global.h10
-rw-r--r--ndb/include/ndb_types.h2
-rw-r--r--ndb/include/ndb_version.h10
-rw-r--r--ndb/include/ndbapi/AttrType.hpp329
-rw-r--r--ndb/include/ndbapi/Ndb.hpp72
-rw-r--r--ndb/include/ndbapi/NdbApi.hpp5
-rw-r--r--ndb/include/ndbapi/NdbBlob.hpp293
-rw-r--r--ndb/include/ndbapi/NdbConnection.hpp101
-rw-r--r--ndb/include/ndbapi/NdbDictionary.hpp36
-rw-r--r--ndb/include/ndbapi/NdbIndexOperation.hpp2
-rw-r--r--ndb/include/ndbapi/NdbOperation.hpp110
-rw-r--r--ndb/include/ndbapi/NdbRecAttr.hpp43
-rw-r--r--ndb/include/ndbapi/NdbReceiver.hpp4
-rw-r--r--ndb/include/ndbapi/NdbScanOperation.hpp6
-rw-r--r--ndb/include/ndbapi/NdbSchemaCon.hpp132
-rw-r--r--ndb/include/ndbapi/NdbSchemaOp.hpp456
-rw-r--r--ndb/include/ndbapi/ndbapi_limits.h20
-rw-r--r--ndb/include/portlib/PortDefs.h2
-rw-r--r--ndb/include/util/Base64.hpp5
-rw-r--r--ndb/include/util/BaseString.hpp4
-rw-r--r--ndb/include/util/Bitmask.hpp42
-rw-r--r--ndb/include/util/ConfigValues.hpp252
-rw-r--r--ndb/include/util/NdbSqlUtil.hpp36
-rw-r--r--ndb/include/util/Parser.hpp1
-rw-r--r--ndb/include/util/Properties.hpp17
-rw-r--r--ndb/include/util/UtilBuffer.hpp9
-rw-r--r--ndb/mysqlclusterenv.sh51
-rw-r--r--ndb/src/Makefile33
-rw-r--r--ndb/src/Makefile.am18
-rw-r--r--ndb/src/client/odbc/codegen/SimpleGram.ypp1629
-rw-r--r--ndb/src/client/odbc/codegen/SimpleParser.cpp95
-rw-r--r--ndb/src/client/odbc/codegen/SimpleScan.lpp241
-rw-r--r--ndb/src/client/odbc/common/Ctx.cpp356
-rw-r--r--ndb/src/client/odbc/common/DataField.cpp3024
-rw-r--r--ndb/src/client/odbc/common/DataType.cpp545
-rw-r--r--ndb/src/client/odbc/common/DataType.hpp292
-rw-r--r--ndb/src/client/odbc/common/OdbcData.cpp561
-rw-r--r--ndb/src/client/odbc/common/common.hpp120
-rw-r--r--ndb/src/client/odbc/driver/driver.cpp150
-rw-r--r--ndb/src/client/odbc/handles/HandleRoot.cpp270
-rw-r--r--ndb/src/client/odbc/handles/PoolNdb.cpp80
-rw-r--r--ndb/src/client/odbc/handles/PoolNdb.hpp44
-rw-r--r--ndb/src/common/Makefile.am13
-rw-r--r--ndb/src/common/Makefile_old (renamed from ndb/src/common/Makefile)0
-rw-r--r--ndb/src/common/debugger/LogLevel.cpp19
-rw-r--r--ndb/src/common/debugger/Makefile.am11
-rw-r--r--ndb/src/common/debugger/Makefile_old (renamed from ndb/src/common/debugger/Makefile)0
-rw-r--r--ndb/src/common/debugger/signaldata/BackupImpl.cpp2
-rw-r--r--ndb/src/common/debugger/signaldata/CntrStart.cpp37
-rw-r--r--ndb/src/common/debugger/signaldata/CreateTrig.cpp2
-rw-r--r--ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp6
-rw-r--r--ndb/src/common/debugger/signaldata/Makefile32
-rw-r--r--ndb/src/common/debugger/signaldata/Makefile.am32
-rw-r--r--ndb/src/common/debugger/signaldata/Makefile_old33
-rw-r--r--ndb/src/common/debugger/signaldata/ReadNodesConf.cpp24
-rw-r--r--ndb/src/common/debugger/signaldata/SignalDataPrint.cpp8
-rw-r--r--ndb/src/common/debugger/signaldata/SignalNames.cpp36
-rw-r--r--ndb/src/common/debugger/signaldata/TuxMaint.cpp8
-rw-r--r--ndb/src/common/editline/Makefile.am10
-rw-r--r--ndb/src/common/editline/Makefile_old (renamed from ndb/src/common/editline/Makefile)0
-rw-r--r--ndb/src/common/logger/Makefile.am11
-rw-r--r--ndb/src/common/logger/Makefile_old (renamed from ndb/src/common/logger/Makefile)0
-rw-r--r--ndb/src/common/mgmcommon/Config.cpp59
-rw-r--r--ndb/src/common/mgmcommon/Config.hpp22
-rw-r--r--ndb/src/common/mgmcommon/ConfigInfo.cpp3988
-rw-r--r--ndb/src/common/mgmcommon/ConfigInfo.hpp49
-rw-r--r--ndb/src/common/mgmcommon/ConfigRetriever.cpp386
-rw-r--r--ndb/src/common/mgmcommon/IPCConfig.cpp159
-rw-r--r--ndb/src/common/mgmcommon/InitConfigFileParser.cpp191
-rw-r--r--ndb/src/common/mgmcommon/InitConfigFileParser.hpp77
-rw-r--r--ndb/src/common/mgmcommon/Makefile26
-rw-r--r--ndb/src/common/mgmcommon/Makefile.am18
-rw-r--r--ndb/src/common/mgmcommon/Makefile_old29
-rw-r--r--ndb/src/common/mgmcommon/printConfig/Makefile6
-rw-r--r--ndb/src/common/mgmcommon/printConfig/printConfig.cpp11
-rw-r--r--ndb/src/common/portlib/Makefile.am18
-rw-r--r--ndb/src/common/portlib/Makefile_old (renamed from ndb/src/common/portlib/Makefile)0
-rw-r--r--ndb/src/common/portlib/NdbCondition.c (renamed from ndb/src/common/portlib/unix/NdbCondition.c)0
-rw-r--r--ndb/src/common/portlib/NdbDaemon.c157
-rw-r--r--ndb/src/common/portlib/NdbEnv.c (renamed from ndb/src/common/portlib/unix/NdbEnv.c)0
-rw-r--r--ndb/src/common/portlib/NdbHost.c (renamed from ndb/src/common/portlib/unix/NdbHost.c)0
-rw-r--r--ndb/src/common/portlib/NdbMem.c (renamed from ndb/src/common/portlib/unix/NdbMem.c)0
-rw-r--r--ndb/src/common/portlib/NdbMutex.c (renamed from ndb/src/common/portlib/unix/NdbMutex.c)0
-rw-r--r--ndb/src/common/portlib/NdbPortLibTest.cpp (renamed from ndb/src/common/portlib/test/NdbPortLibTest.cpp)0
-rw-r--r--ndb/src/common/portlib/NdbSleep.c (renamed from ndb/src/common/portlib/unix/NdbSleep.c)0
-rw-r--r--ndb/src/common/portlib/NdbTCP.c (renamed from ndb/src/common/portlib/unix/NdbTCP.c)0
-rw-r--r--ndb/src/common/portlib/NdbThread.c113
-rw-r--r--ndb/src/common/portlib/NdbTick.c (renamed from ndb/src/common/portlib/unix/NdbTick.c)0
-rw-r--r--ndb/src/common/portlib/gcc.cpp2
-rw-r--r--ndb/src/common/portlib/memtest.c (renamed from ndb/src/common/portlib/memtest/memtest.c)0
-rw-r--r--ndb/src/common/portlib/mmslist.cpp (renamed from ndb/src/common/portlib/mmstest/mmslist.cpp)0
-rw-r--r--ndb/src/common/portlib/mmstest.cpp (renamed from ndb/src/common/portlib/mmstest/mmstest.cpp)0
-rw-r--r--ndb/src/common/portlib/munmaptest.cpp (renamed from ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp)0
-rw-r--r--ndb/src/common/portlib/old_dirs/memtest/Makefile (renamed from ndb/src/common/portlib/memtest/Makefile)0
-rw-r--r--ndb/src/common/portlib/old_dirs/memtest/munmaptest/Makefile (renamed from ndb/src/common/portlib/memtest/munmaptest/Makefile)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/Makefile (renamed from ndb/src/common/portlib/ose/Makefile)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbCondition.c (renamed from ndb/src/common/portlib/ose/NdbCondition.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbConditionOSE.h (renamed from ndb/src/common/portlib/ose/NdbConditionOSE.h)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbEnv.c (renamed from ndb/src/common/portlib/ose/NdbEnv.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbHost.c (renamed from ndb/src/common/portlib/ose/NdbHost.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbMem.c (renamed from ndb/src/common/portlib/ose/NdbMem.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbMem_SoftOse.cpp (renamed from ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbMutex.c (renamed from ndb/src/common/portlib/ose/NdbMutex.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbOut.cpp (renamed from ndb/src/common/portlib/ose/NdbOut.cpp)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbSleep.c (renamed from ndb/src/common/portlib/ose/NdbSleep.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbTCP.c (renamed from ndb/src/common/portlib/ose/NdbTCP.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbThread.c (renamed from ndb/src/common/portlib/ose/NdbThread.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/ose/NdbTick.c (renamed from ndb/src/common/portlib/ose/NdbTick.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/test/Makefile (renamed from ndb/src/common/portlib/test/Makefile)0
-rw-r--r--ndb/src/common/portlib/old_dirs/unix/Makefile_old (renamed from ndb/src/common/portlib/unix/Makefile)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/Makefile (renamed from ndb/src/common/portlib/win32/Makefile)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbCondition.c (renamed from ndb/src/common/portlib/win32/NdbCondition.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbDaemon.c (renamed from ndb/src/common/portlib/win32/NdbDaemon.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbEnv.c (renamed from ndb/src/common/portlib/win32/NdbEnv.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbHost.c (renamed from ndb/src/common/portlib/win32/NdbHost.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbMem.c (renamed from ndb/src/common/portlib/win32/NdbMem.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbMutex.c (renamed from ndb/src/common/portlib/win32/NdbMutex.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbSleep.c (renamed from ndb/src/common/portlib/win32/NdbSleep.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbTCP.c (renamed from ndb/src/common/portlib/win32/NdbTCP.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbThread.c (renamed from ndb/src/common/portlib/win32/NdbThread.c)0
-rw-r--r--ndb/src/common/portlib/old_dirs/win32/NdbTick.c (renamed from ndb/src/common/portlib/win32/NdbTick.c)0
-rw-r--r--ndb/src/common/portlib/unix/NdbDaemon.c157
-rw-r--r--ndb/src/common/portlib/unix/NdbThread.c112
-rw-r--r--ndb/src/common/transporter/Makefile.am22
-rw-r--r--ndb/src/common/transporter/Makefile_old (renamed from ndb/src/common/transporter/Makefile)0
-rw-r--r--ndb/src/common/transporter/Transporter.hpp2
-rw-r--r--ndb/src/common/util/Base64.cpp161
-rw-r--r--ndb/src/common/util/ConfigValues.cpp743
-rw-r--r--ndb/src/common/util/Makefile28
-rw-r--r--ndb/src/common/util/Makefile.am17
-rw-r--r--ndb/src/common/util/Makefile_old28
-rw-r--r--ndb/src/common/util/NdbSqlUtil.cpp20
-rw-r--r--ndb/src/common/util/Properties.cpp122
-rw-r--r--ndb/src/common/util/md5_hash.cpp2
-rw-r--r--ndb/src/common/util/new.cpp4
-rw-r--r--ndb/src/common/util/socket_io.cpp6
-rw-r--r--ndb/src/common/util/testConfigValues/Makefile12
-rw-r--r--ndb/src/common/util/testConfigValues/testConfigValues.cpp122
-rw-r--r--ndb/src/common/util/testProperties/Makefile5
-rw-r--r--ndb/src/common/util/testProperties/testProperties.cpp11
-rw-r--r--ndb/src/cw/Makefile.am1
-rw-r--r--ndb/src/cw/Makefile_old (renamed from ndb/src/cw/Makefile)0
-rw-r--r--ndb/src/cw/cpcd/Makefile.am14
-rw-r--r--ndb/src/cw/cpcd/Makefile_old (renamed from ndb/src/cw/cpcd/Makefile)0
-rw-r--r--ndb/src/kernel/Main.cpp305
-rw-r--r--ndb/src/kernel/Makefile5
-rw-r--r--ndb/src/kernel/Makefile.am58
-rw-r--r--ndb/src/kernel/Makefile_old5
-rw-r--r--ndb/src/kernel/SimBlockList.cpp126
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt9
-rw-r--r--ndb/src/kernel/blocks/Makefile.am17
-rw-r--r--ndb/src/kernel/blocks/Makefile_old (renamed from ndb/src/kernel/blocks/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/Start.txt32
-rw-r--r--ndb/src/kernel/blocks/backup/BackupInit.cpp18
-rw-r--r--ndb/src/kernel/blocks/backup/Makefile.am12
-rw-r--r--ndb/src/kernel/blocks/backup/Makefile_old (renamed from ndb/src/kernel/blocks/backup/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/backup/restore/Makefile20
-rw-r--r--ndb/src/kernel/blocks/backup/restore/Makefile.am12
-rw-r--r--ndb/src/kernel/blocks/backup/restore/Restore.cpp818
-rw-r--r--ndb/src/kernel/blocks/backup/restore/Restore.hpp175
-rw-r--r--ndb/src/kernel/blocks/backup/restore/consumer.cpp107
-rw-r--r--ndb/src/kernel/blocks/backup/restore/consumer.hpp34
-rw-r--r--ndb/src/kernel/blocks/backup/restore/consumer_printer.cpp55
-rw-r--r--ndb/src/kernel/blocks/backup/restore/consumer_printer.hpp50
-rw-r--r--ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp516
-rw-r--r--ndb/src/kernel/blocks/backup/restore/consumer_restore.hpp75
-rw-r--r--ndb/src/kernel/blocks/backup/restore/consumer_restorem.cpp652
-rw-r--r--ndb/src/kernel/blocks/backup/restore/main.cpp1461
-rw-r--r--ndb/src/kernel/blocks/backup/restore/myVector.hpp128
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp390
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp13
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Makefile.am10
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Makefile_old (renamed from ndb/src/kernel/blocks/cmvmi/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/dbacc/Dbacc.hpp5
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccInit.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccMain.cpp114
-rw-r--r--ndb/src/kernel/blocks/dbacc/Makefile.am10
-rw-r--r--ndb/src/kernel/blocks/dbacc/Makefile_old (renamed from ndb/src/kernel/blocks/dbacc/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp72
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.hpp34
-rw-r--r--ndb/src/kernel/blocks/dbdict/Makefile.am11
-rw-r--r--ndb/src/kernel/blocks/dbdict/Makefile_old (renamed from ndb/src/kernel/blocks/dbdict/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/dbdih/Dbdih.hpp8
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihInit.cpp3
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp199
-rw-r--r--ndb/src/kernel/blocks/dbdih/Makefile.am9
-rw-r--r--ndb/src/kernel/blocks/dbdih/Makefile_old (renamed from ndb/src/kernel/blocks/dbdih/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/dblqh/Dblqh.hpp7
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhInit.cpp2
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp180
-rw-r--r--ndb/src/kernel/blocks/dblqh/Makefile.am11
-rw-r--r--ndb/src/kernel/blocks/dblqh/Makefile_old (renamed from ndb/src/kernel/blocks/dblqh/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/dbtc/Dbtc.hpp7
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcInit.cpp21
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp221
-rw-r--r--ndb/src/kernel/blocks/dbtc/Makefile.am9
-rw-r--r--ndb/src/kernel/blocks/dbtc/Makefile_old (renamed from ndb/src/kernel/blocks/dbtc/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/dbtup/Dbtup.hpp29
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupGen.cpp98
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp175
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp13
-rw-r--r--ndb/src/kernel/blocks/dbtup/Makefile.am27
-rw-r--r--ndb/src/kernel/blocks/dbtup/Makefile_old (renamed from ndb/src/kernel/blocks/dbtup/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/dbtux/Dbtux.hpp676
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp97
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp80
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp132
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp159
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp19
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp491
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp135
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp480
-rw-r--r--ndb/src/kernel/blocks/dbtux/Makefile.am19
-rw-r--r--ndb/src/kernel/blocks/dbtux/Makefile_old (renamed from ndb/src/kernel/blocks/dbtux/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/dbtux/Times.txt52
-rw-r--r--ndb/src/kernel/blocks/dbutil/Makefile.am9
-rw-r--r--ndb/src/kernel/blocks/dbutil/Makefile_old (renamed from ndb/src/kernel/blocks/dbutil/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/grep/Makefile.am9
-rw-r--r--ndb/src/kernel/blocks/grep/Makefile_old (renamed from ndb/src/kernel/blocks/grep/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/Makefile.am12
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/Makefile_old (renamed from ndb/src/kernel/blocks/ndbcntr/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp251
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp25
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp2344
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp10
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Makefile.am13
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Makefile_old (renamed from ndb/src/kernel/blocks/ndbfs/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp5
-rw-r--r--ndb/src/kernel/blocks/qmgr/Makefile.am11
-rw-r--r--ndb/src/kernel/blocks/qmgr/Makefile_old (renamed from ndb/src/kernel/blocks/qmgr/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/qmgr/Qmgr.hpp176
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrInit.cpp22
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrMain.cpp1815
-rw-r--r--ndb/src/kernel/blocks/suma/Makefile.am9
-rw-r--r--ndb/src/kernel/blocks/suma/Makefile_old (renamed from ndb/src/kernel/blocks/suma/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/trix/Makefile.am9
-rw-r--r--ndb/src/kernel/blocks/trix/Makefile_old (renamed from ndb/src/kernel/blocks/trix/Makefile)0
-rw-r--r--ndb/src/kernel/blocks/trix/Trix.hpp17
-rw-r--r--ndb/src/kernel/error/ErrorReporter.cpp30
-rw-r--r--ndb/src/kernel/error/ErrorReporter.hpp10
-rw-r--r--ndb/src/kernel/error/Makefile.am11
-rw-r--r--ndb/src/kernel/error/Makefile_old (renamed from ndb/src/kernel/error/Makefile)0
-rw-r--r--ndb/src/kernel/ndb-main/Main.cpp301
-rw-r--r--ndb/src/kernel/ndb-main/Makefile42
-rw-r--r--ndb/src/kernel/ndb-main/SimBlockList.cpp111
-rw-r--r--ndb/src/kernel/vm/Configuration.cpp439
-rw-r--r--ndb/src/kernel/vm/Configuration.hpp28
-rw-r--r--ndb/src/kernel/vm/Emulator.cpp10
-rw-r--r--ndb/src/kernel/vm/Emulator.hpp19
-rw-r--r--ndb/src/kernel/vm/FastScheduler.cpp14
-rw-r--r--ndb/src/kernel/vm/FastScheduler.hpp14
-rw-r--r--ndb/src/kernel/vm/Makefile29
-rw-r--r--ndb/src/kernel/vm/Makefile.am29
-rw-r--r--ndb/src/kernel/vm/Makefile_old30
-rw-r--r--ndb/src/kernel/vm/SignalCounter.hpp2
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.cpp59
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.hpp15
-rw-r--r--ndb/src/kernel/vm/TransporterCallback.cpp7
-rw-r--r--ndb/src/kernel/vm/VMSignal.hpp9
-rw-r--r--ndb/src/kernel/vm/pc.hpp21
-rw-r--r--ndb/src/kernel/vm/testLongSig/testLongSig.cpp40
-rw-r--r--ndb/src/mgmapi/Makefile27
-rw-r--r--ndb/src/mgmapi/Makefile.am13
-rw-r--r--ndb/src/mgmapi/Makefile_old27
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp152
-rw-r--r--ndb/src/mgmapi/mgmapi_configuration.cpp157
-rw-r--r--ndb/src/mgmapi/mgmapi_configuration.hpp32
-rw-r--r--ndb/src/mgmapi/test/keso.c14
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.cpp28
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.hpp2
-rw-r--r--ndb/src/mgmclient/Makefile25
-rw-r--r--ndb/src/mgmclient/Makefile.am21
-rw-r--r--ndb/src/mgmclient/Makefile_old25
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.cpp10
-rw-r--r--ndb/src/mgmsrv/Makefile40
-rw-r--r--ndb/src/mgmsrv/Makefile.am30
-rw-r--r--ndb/src/mgmsrv/Makefile_old41
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp152
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.hpp12
-rw-r--r--ndb/src/mgmsrv/MgmtSrvrConfig.cpp27
-rw-r--r--ndb/src/mgmsrv/Services.cpp184
-rw-r--r--ndb/src/mgmsrv/main.cpp57
-rw-r--r--ndb/src/mgmsrv/mkconfig/Makefile5
-rw-r--r--ndb/src/mgmsrv/mkconfig/mkconfig.cpp20
-rw-r--r--ndb/src/ndbapi/ClusterMgr.cpp124
-rw-r--r--ndb/src/ndbapi/ClusterMgr.hpp4
-rw-r--r--ndb/src/ndbapi/DictCache.hpp3
-rw-r--r--ndb/src/ndbapi/Makefile63
-rw-r--r--ndb/src/ndbapi/Makefile.am50
-rw-r--r--ndb/src/ndbapi/Makefile_old67
-rw-r--r--ndb/src/ndbapi/Ndb.cpp126
-rw-r--r--ndb/src/ndbapi/NdbApiSignal.cpp1
-rw-r--r--ndb/src/ndbapi/NdbApiSignal.hpp1
-rw-r--r--ndb/src/ndbapi/NdbBlob.cpp1349
-rw-r--r--ndb/src/ndbapi/NdbConnection.cpp150
-rw-r--r--ndb/src/ndbapi/NdbDictionary.cpp81
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp124
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.hpp32
-rw-r--r--ndb/src/ndbapi/NdbEventOperationImpl.cpp51
-rw-r--r--ndb/src/ndbapi/NdbEventOperationImpl.hpp1
-rw-r--r--ndb/src/ndbapi/NdbIndexOperation.cpp17
-rw-r--r--ndb/src/ndbapi/NdbOperation.cpp37
-rw-r--r--ndb/src/ndbapi/NdbOperationDefine.cpp34
-rw-r--r--ndb/src/ndbapi/NdbOperationExec.cpp2
-rw-r--r--ndb/src/ndbapi/NdbOperationInt.cpp13
-rw-r--r--ndb/src/ndbapi/NdbOperationScan.cpp39
-rw-r--r--ndb/src/ndbapi/NdbOperationSearch.cpp35
-rw-r--r--ndb/src/ndbapi/NdbRecAttr.cpp97
-rw-r--r--ndb/src/ndbapi/NdbResultSet.cpp12
-rw-r--r--ndb/src/ndbapi/NdbScanOperation.cpp30
-rw-r--r--ndb/src/ndbapi/NdbSchemaCon.cpp163
-rw-r--r--ndb/src/ndbapi/NdbSchemaOp.cpp205
-rw-r--r--ndb/src/ndbapi/NdbUtil.hpp1
-rw-r--r--ndb/src/ndbapi/Ndberr.cpp8
-rw-r--r--ndb/src/ndbapi/Ndbif.cpp96
-rw-r--r--ndb/src/ndbapi/Ndbinit.cpp49
-rw-r--r--ndb/src/ndbapi/Ndblist.cpp38
-rw-r--r--ndb/src/ndbapi/TransporterFacade.cpp118
-rw-r--r--ndb/src/ndbapi/TransporterFacade.hpp22
-rw-r--r--ndb/src/ndbapi/ndberror.c10
-rw-r--r--ndb/src/ndbapi/signal-sender/SignalSender.cpp2
-rw-r--r--ndb/src/newtonapi/dba_schema.cpp149
-rw-r--r--ndb/src/old_files/client/Makefile (renamed from ndb/src/client/Makefile)0
-rw-r--r--ndb/src/old_files/client/odbc/Extra.mk (renamed from ndb/src/client/odbc/Extra.mk)0
-rw-r--r--ndb/src/old_files/client/odbc/Makefile (renamed from ndb/src/client/odbc/Makefile)0
-rwxr-xr-xndb/src/old_files/client/odbc/NdbOdbc.cpp (renamed from ndb/src/client/odbc/NdbOdbc.cpp)0
-rwxr-xr-xndb/src/old_files/client/odbc/NdbOdbc.def (renamed from ndb/src/client/odbc/NdbOdbc.def)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/CodeGen.cpp (renamed from ndb/src/client/odbc/codegen/CodeGen.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/CodeGen.hpp (renamed from ndb/src/client/odbc/codegen/CodeGen.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_base.cpp (renamed from ndb/src/client/odbc/codegen/Code_base.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_base.hpp (renamed from ndb/src/client/odbc/codegen/Code_base.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_column.cpp (renamed from ndb/src/client/odbc/codegen/Code_column.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_column.hpp (renamed from ndb/src/client/odbc/codegen/Code_column.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_comp_op.cpp (renamed from ndb/src/client/odbc/codegen/Code_comp_op.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_comp_op.hpp (renamed from ndb/src/client/odbc/codegen/Code_comp_op.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_create_index.cpp (renamed from ndb/src/client/odbc/codegen/Code_create_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_create_index.hpp (renamed from ndb/src/client/odbc/codegen/Code_create_index.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_create_row.cpp (renamed from ndb/src/client/odbc/codegen/Code_create_row.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_create_row.hpp (renamed from ndb/src/client/odbc/codegen/Code_create_row.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_create_table.cpp (renamed from ndb/src/client/odbc/codegen/Code_create_table.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_create_table.hpp (renamed from ndb/src/client/odbc/codegen/Code_create_table.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_data_type.cpp (renamed from ndb/src/client/odbc/codegen/Code_data_type.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_data_type.hpp (renamed from ndb/src/client/odbc/codegen/Code_data_type.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_ddl.cpp (renamed from ndb/src/client/odbc/codegen/Code_ddl.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_ddl.hpp (renamed from ndb/src/client/odbc/codegen/Code_ddl.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_ddl_column.cpp (renamed from ndb/src/client/odbc/codegen/Code_ddl_column.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_ddl_column.hpp (renamed from ndb/src/client/odbc/codegen/Code_ddl_column.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.cpp (renamed from ndb/src/client/odbc/codegen/Code_ddl_constr.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.hpp (renamed from ndb/src/client/odbc/codegen/Code_ddl_constr.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_ddl_row.cpp (renamed from ndb/src/client/odbc/codegen/Code_ddl_row.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_ddl_row.hpp (renamed from ndb/src/client/odbc/codegen/Code_ddl_row.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_delete.cpp (renamed from ndb/src/client/odbc/codegen/Code_delete.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_delete.hpp (renamed from ndb/src/client/odbc/codegen/Code_delete.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_delete_index.cpp (renamed from ndb/src/client/odbc/codegen/Code_delete_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_delete_index.hpp (renamed from ndb/src/client/odbc/codegen/Code_delete_index.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.cpp (renamed from ndb/src/client/odbc/codegen/Code_delete_lookup.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.hpp (renamed from ndb/src/client/odbc/codegen/Code_delete_lookup.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_delete_scan.cpp (renamed from ndb/src/client/odbc/codegen/Code_delete_scan.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_delete_scan.hpp (renamed from ndb/src/client/odbc/codegen/Code_delete_scan.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_dml.cpp (renamed from ndb/src/client/odbc/codegen/Code_dml.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_dml.hpp (renamed from ndb/src/client/odbc/codegen/Code_dml.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_dml_column.cpp (renamed from ndb/src/client/odbc/codegen/Code_dml_column.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_dml_column.hpp (renamed from ndb/src/client/odbc/codegen/Code_dml_column.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_dml_row.cpp (renamed from ndb/src/client/odbc/codegen/Code_dml_row.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_dml_row.hpp (renamed from ndb/src/client/odbc/codegen/Code_dml_row.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_drop_index.cpp (renamed from ndb/src/client/odbc/codegen/Code_drop_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_drop_index.hpp (renamed from ndb/src/client/odbc/codegen/Code_drop_index.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_drop_table.cpp (renamed from ndb/src/client/odbc/codegen/Code_drop_table.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_drop_table.hpp (renamed from ndb/src/client/odbc/codegen/Code_drop_table.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr.cpp (renamed from ndb/src/client/odbc/codegen/Code_expr.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr.hpp (renamed from ndb/src/client/odbc/codegen/Code_expr.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_column.cpp (renamed from ndb/src/client/odbc/codegen/Code_expr_column.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_column.hpp (renamed from ndb/src/client/odbc/codegen/Code_expr_column.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_const.cpp (renamed from ndb/src/client/odbc/codegen/Code_expr_const.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_const.hpp (renamed from ndb/src/client/odbc/codegen/Code_expr_const.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_conv.cpp (renamed from ndb/src/client/odbc/codegen/Code_expr_conv.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_conv.hpp (renamed from ndb/src/client/odbc/codegen/Code_expr_conv.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_func.cpp (renamed from ndb/src/client/odbc/codegen/Code_expr_func.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_func.hpp (renamed from ndb/src/client/odbc/codegen/Code_expr_func.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_op.cpp (renamed from ndb/src/client/odbc/codegen/Code_expr_op.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_op.hpp (renamed from ndb/src/client/odbc/codegen/Code_expr_op.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_param.cpp (renamed from ndb/src/client/odbc/codegen/Code_expr_param.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_param.hpp (renamed from ndb/src/client/odbc/codegen/Code_expr_param.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_row.cpp (renamed from ndb/src/client/odbc/codegen/Code_expr_row.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_expr_row.hpp (renamed from ndb/src/client/odbc/codegen/Code_expr_row.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_idx_column.cpp (renamed from ndb/src/client/odbc/codegen/Code_idx_column.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_idx_column.hpp (renamed from ndb/src/client/odbc/codegen/Code_idx_column.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_insert.cpp (renamed from ndb/src/client/odbc/codegen/Code_insert.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_insert.hpp (renamed from ndb/src/client/odbc/codegen/Code_insert.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_pred.cpp (renamed from ndb/src/client/odbc/codegen/Code_pred.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_pred.hpp (renamed from ndb/src/client/odbc/codegen/Code_pred.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_pred_op.cpp (renamed from ndb/src/client/odbc/codegen/Code_pred_op.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_pred_op.hpp (renamed from ndb/src/client/odbc/codegen/Code_pred_op.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query.cpp (renamed from ndb/src/client/odbc/codegen/Code_query.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query.hpp (renamed from ndb/src/client/odbc/codegen/Code_query.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_count.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_count.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_count.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_count.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_distinct.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_distinct.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_distinct.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_distinct.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_filter.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_filter.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_filter.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_filter.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_group.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_group.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_group.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_group.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_index.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_index.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_index.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_join.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_join.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_join.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_join.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_lookup.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_lookup.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_lookup.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_lookup.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_project.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_project.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_project.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_project.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_range.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_range.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_range.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_range.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_repeat.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_repeat.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_repeat.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_repeat.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_scan.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_scan.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_scan.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_scan.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_sort.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_sort.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_sort.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_sort.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_sys.cpp (renamed from ndb/src/client/odbc/codegen/Code_query_sys.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_query_sys.hpp (renamed from ndb/src/client/odbc/codegen/Code_query_sys.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_root.cpp (renamed from ndb/src/client/odbc/codegen/Code_root.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_root.hpp (renamed from ndb/src/client/odbc/codegen/Code_root.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_select.cpp (renamed from ndb/src/client/odbc/codegen/Code_select.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_select.hpp (renamed from ndb/src/client/odbc/codegen/Code_select.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_set_row.cpp (renamed from ndb/src/client/odbc/codegen/Code_set_row.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_set_row.hpp (renamed from ndb/src/client/odbc/codegen/Code_set_row.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_stmt.cpp (renamed from ndb/src/client/odbc/codegen/Code_stmt.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_stmt.hpp (renamed from ndb/src/client/odbc/codegen/Code_stmt.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_table.cpp (renamed from ndb/src/client/odbc/codegen/Code_table.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_table.hpp (renamed from ndb/src/client/odbc/codegen/Code_table.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_table_list.cpp (renamed from ndb/src/client/odbc/codegen/Code_table_list.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_table_list.hpp (renamed from ndb/src/client/odbc/codegen/Code_table_list.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_update.cpp (renamed from ndb/src/client/odbc/codegen/Code_update.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_update.hpp (renamed from ndb/src/client/odbc/codegen/Code_update.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_update_index.cpp (renamed from ndb/src/client/odbc/codegen/Code_update_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_update_index.hpp (renamed from ndb/src/client/odbc/codegen/Code_update_index.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_update_lookup.cpp (renamed from ndb/src/client/odbc/codegen/Code_update_lookup.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_update_lookup.hpp (renamed from ndb/src/client/odbc/codegen/Code_update_lookup.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_update_scan.cpp (renamed from ndb/src/client/odbc/codegen/Code_update_scan.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Code_update_scan.hpp (renamed from ndb/src/client/odbc/codegen/Code_update_scan.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/Makefile (renamed from ndb/src/client/odbc/codegen/Makefile)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/SimpleGram.ypp1649
-rw-r--r--ndb/src/old_files/client/odbc/codegen/SimpleParser.cpp96
-rw-r--r--ndb/src/old_files/client/odbc/codegen/SimpleParser.hpp (renamed from ndb/src/client/odbc/codegen/SimpleParser.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/codegen/SimpleScan.lpp243
-rw-r--r--ndb/src/old_files/client/odbc/common/AttrArea.cpp (renamed from ndb/src/client/odbc/common/AttrArea.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/AttrArea.hpp (renamed from ndb/src/client/odbc/common/AttrArea.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/CodeTree.cpp (renamed from ndb/src/client/odbc/common/CodeTree.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/CodeTree.hpp (renamed from ndb/src/client/odbc/common/CodeTree.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/ConnArea.cpp (renamed from ndb/src/client/odbc/common/ConnArea.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/ConnArea.hpp (renamed from ndb/src/client/odbc/common/ConnArea.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/Ctx.cpp355
-rw-r--r--ndb/src/old_files/client/odbc/common/Ctx.hpp (renamed from ndb/src/client/odbc/common/Ctx.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/DataField.cpp3023
-rw-r--r--ndb/src/old_files/client/odbc/common/DataField.hpp (renamed from ndb/src/client/odbc/common/DataField.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/DataRow.cpp (renamed from ndb/src/client/odbc/common/DataRow.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/DataRow.hpp (renamed from ndb/src/client/odbc/common/DataRow.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/DataType.cpp551
-rw-r--r--ndb/src/old_files/client/odbc/common/DataType.hpp293
-rw-r--r--ndb/src/old_files/client/odbc/common/DescArea.cpp (renamed from ndb/src/client/odbc/common/DescArea.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/DescArea.hpp (renamed from ndb/src/client/odbc/common/DescArea.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/DiagArea.cpp (renamed from ndb/src/client/odbc/common/DiagArea.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/DiagArea.hpp (renamed from ndb/src/client/odbc/common/DiagArea.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/Makefile (renamed from ndb/src/client/odbc/common/Makefile)0
-rw-r--r--ndb/src/old_files/client/odbc/common/OdbcData.cpp560
-rw-r--r--ndb/src/old_files/client/odbc/common/OdbcData.hpp (renamed from ndb/src/client/odbc/common/OdbcData.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/ResultArea.cpp (renamed from ndb/src/client/odbc/common/ResultArea.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/ResultArea.hpp (renamed from ndb/src/client/odbc/common/ResultArea.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/Sqlstate.cpp (renamed from ndb/src/client/odbc/common/Sqlstate.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/Sqlstate.hpp (renamed from ndb/src/client/odbc/common/Sqlstate.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/StmtArea.cpp (renamed from ndb/src/client/odbc/common/StmtArea.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/StmtArea.hpp (renamed from ndb/src/client/odbc/common/StmtArea.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/StmtInfo.cpp (renamed from ndb/src/client/odbc/common/StmtInfo.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/StmtInfo.hpp (renamed from ndb/src/client/odbc/common/StmtInfo.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/common.cpp (renamed from ndb/src/client/odbc/common/common.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/common/common.hpp124
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictCatalog.cpp (renamed from ndb/src/client/odbc/dictionary/DictCatalog.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictCatalog.hpp (renamed from ndb/src/client/odbc/dictionary/DictCatalog.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictColumn.cpp (renamed from ndb/src/client/odbc/dictionary/DictColumn.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictColumn.hpp (renamed from ndb/src/client/odbc/dictionary/DictColumn.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictIndex.cpp (renamed from ndb/src/client/odbc/dictionary/DictIndex.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictIndex.hpp (renamed from ndb/src/client/odbc/dictionary/DictIndex.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictSchema.cpp (renamed from ndb/src/client/odbc/dictionary/DictSchema.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictSchema.hpp (renamed from ndb/src/client/odbc/dictionary/DictSchema.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictSys.cpp (renamed from ndb/src/client/odbc/dictionary/DictSys.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictSys.hpp (renamed from ndb/src/client/odbc/dictionary/DictSys.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictTable.cpp (renamed from ndb/src/client/odbc/dictionary/DictTable.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/DictTable.hpp (renamed from ndb/src/client/odbc/dictionary/DictTable.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/dictionary/Makefile (renamed from ndb/src/client/odbc/dictionary/Makefile)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/class.fig (renamed from ndb/src/client/odbc/docs/class.fig)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/descfield.pl (renamed from ndb/src/client/odbc/docs/descfield.pl)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/diag.txt (renamed from ndb/src/client/odbc/docs/diag.txt)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/getinfo.pl (renamed from ndb/src/client/odbc/docs/getinfo.pl)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/gettypeinfo.pl (renamed from ndb/src/client/odbc/docs/gettypeinfo.pl)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/handleattr.pl (renamed from ndb/src/client/odbc/docs/handleattr.pl)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/main.hpp (renamed from ndb/src/client/odbc/docs/main.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/ndbodbc.html (renamed from ndb/src/client/odbc/docs/ndbodbc.html)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/select.fig (renamed from ndb/src/client/odbc/docs/select.fig)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/systables.pl (renamed from ndb/src/client/odbc/docs/systables.pl)0
-rw-r--r--ndb/src/old_files/client/odbc/docs/type.txt (renamed from ndb/src/client/odbc/docs/type.txt)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/Func.data (renamed from ndb/src/client/odbc/driver/Func.data)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/Func.pl (renamed from ndb/src/client/odbc/driver/Func.pl)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/Makefile (renamed from ndb/src/client/odbc/driver/Makefile)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLAllocConnect.cpp (renamed from ndb/src/client/odbc/driver/SQLAllocConnect.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLAllocEnv.cpp (renamed from ndb/src/client/odbc/driver/SQLAllocEnv.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLAllocHandle.cpp (renamed from ndb/src/client/odbc/driver/SQLAllocHandle.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLAllocHandleStd.cpp (renamed from ndb/src/client/odbc/driver/SQLAllocHandleStd.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLAllocStmt.cpp (renamed from ndb/src/client/odbc/driver/SQLAllocStmt.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLBindCol.cpp (renamed from ndb/src/client/odbc/driver/SQLBindCol.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLBindParam.cpp (renamed from ndb/src/client/odbc/driver/SQLBindParam.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLBindParameter.cpp (renamed from ndb/src/client/odbc/driver/SQLBindParameter.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLBrowseConnect.cpp (renamed from ndb/src/client/odbc/driver/SQLBrowseConnect.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLBulkOperations.cpp (renamed from ndb/src/client/odbc/driver/SQLBulkOperations.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLCancel.cpp (renamed from ndb/src/client/odbc/driver/SQLCancel.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLCloseCursor.cpp (renamed from ndb/src/client/odbc/driver/SQLCloseCursor.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLColAttribute.cpp (renamed from ndb/src/client/odbc/driver/SQLColAttribute.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLColAttributes.cpp (renamed from ndb/src/client/odbc/driver/SQLColAttributes.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLColumnPrivileges.cpp (renamed from ndb/src/client/odbc/driver/SQLColumnPrivileges.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLColumns.cpp (renamed from ndb/src/client/odbc/driver/SQLColumns.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLConnect.cpp (renamed from ndb/src/client/odbc/driver/SQLConnect.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLCopyDesc.cpp (renamed from ndb/src/client/odbc/driver/SQLCopyDesc.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLDataSources.cpp (renamed from ndb/src/client/odbc/driver/SQLDataSources.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLDescribeCol.cpp (renamed from ndb/src/client/odbc/driver/SQLDescribeCol.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLDescribeParam.cpp (renamed from ndb/src/client/odbc/driver/SQLDescribeParam.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLDisconnect.cpp (renamed from ndb/src/client/odbc/driver/SQLDisconnect.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLDriverConnect.cpp (renamed from ndb/src/client/odbc/driver/SQLDriverConnect.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLDrivers.cpp (renamed from ndb/src/client/odbc/driver/SQLDrivers.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLEndTran.cpp (renamed from ndb/src/client/odbc/driver/SQLEndTran.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLError.cpp (renamed from ndb/src/client/odbc/driver/SQLError.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLExecDirect.cpp (renamed from ndb/src/client/odbc/driver/SQLExecDirect.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLExecute.cpp (renamed from ndb/src/client/odbc/driver/SQLExecute.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLExtendedFetch.cpp (renamed from ndb/src/client/odbc/driver/SQLExtendedFetch.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLFetch.cpp (renamed from ndb/src/client/odbc/driver/SQLFetch.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLFetchScroll.cpp (renamed from ndb/src/client/odbc/driver/SQLFetchScroll.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLForeignKeys.cpp (renamed from ndb/src/client/odbc/driver/SQLForeignKeys.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLFreeConnect.cpp (renamed from ndb/src/client/odbc/driver/SQLFreeConnect.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLFreeEnv.cpp (renamed from ndb/src/client/odbc/driver/SQLFreeEnv.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLFreeHandle.cpp (renamed from ndb/src/client/odbc/driver/SQLFreeHandle.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLFreeStmt.cpp (renamed from ndb/src/client/odbc/driver/SQLFreeStmt.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetConnectAttr.cpp (renamed from ndb/src/client/odbc/driver/SQLGetConnectAttr.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetConnectOption.cpp (renamed from ndb/src/client/odbc/driver/SQLGetConnectOption.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetCursorName.cpp (renamed from ndb/src/client/odbc/driver/SQLGetCursorName.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetData.cpp (renamed from ndb/src/client/odbc/driver/SQLGetData.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetDescField.cpp (renamed from ndb/src/client/odbc/driver/SQLGetDescField.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetDescRec.cpp (renamed from ndb/src/client/odbc/driver/SQLGetDescRec.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetDiagField.cpp (renamed from ndb/src/client/odbc/driver/SQLGetDiagField.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetDiagRec.cpp (renamed from ndb/src/client/odbc/driver/SQLGetDiagRec.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetEnvAttr.cpp (renamed from ndb/src/client/odbc/driver/SQLGetEnvAttr.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetFunctions.cpp (renamed from ndb/src/client/odbc/driver/SQLGetFunctions.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetInfo.cpp (renamed from ndb/src/client/odbc/driver/SQLGetInfo.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetStmtAttr.cpp (renamed from ndb/src/client/odbc/driver/SQLGetStmtAttr.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetStmtOption.cpp (renamed from ndb/src/client/odbc/driver/SQLGetStmtOption.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLGetTypeInfo.cpp (renamed from ndb/src/client/odbc/driver/SQLGetTypeInfo.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLMoreResults.cpp (renamed from ndb/src/client/odbc/driver/SQLMoreResults.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLNativeSql.cpp (renamed from ndb/src/client/odbc/driver/SQLNativeSql.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLNumParams.cpp (renamed from ndb/src/client/odbc/driver/SQLNumParams.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLNumResultCols.cpp (renamed from ndb/src/client/odbc/driver/SQLNumResultCols.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLParamData.cpp (renamed from ndb/src/client/odbc/driver/SQLParamData.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLParamOptions.cpp (renamed from ndb/src/client/odbc/driver/SQLParamOptions.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLPrepare.cpp (renamed from ndb/src/client/odbc/driver/SQLPrepare.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLPrimaryKeys.cpp (renamed from ndb/src/client/odbc/driver/SQLPrimaryKeys.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLProcedureColumns.cpp (renamed from ndb/src/client/odbc/driver/SQLProcedureColumns.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLProcedures.cpp (renamed from ndb/src/client/odbc/driver/SQLProcedures.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLPutData.cpp (renamed from ndb/src/client/odbc/driver/SQLPutData.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLRowCount.cpp (renamed from ndb/src/client/odbc/driver/SQLRowCount.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetConnectAttr.cpp (renamed from ndb/src/client/odbc/driver/SQLSetConnectAttr.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetConnectOption.cpp (renamed from ndb/src/client/odbc/driver/SQLSetConnectOption.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetCursorName.cpp (renamed from ndb/src/client/odbc/driver/SQLSetCursorName.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetDescField.cpp (renamed from ndb/src/client/odbc/driver/SQLSetDescField.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetDescRec.cpp (renamed from ndb/src/client/odbc/driver/SQLSetDescRec.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetEnvAttr.cpp (renamed from ndb/src/client/odbc/driver/SQLSetEnvAttr.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetParam.cpp (renamed from ndb/src/client/odbc/driver/SQLSetParam.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetPos.cpp (renamed from ndb/src/client/odbc/driver/SQLSetPos.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetScrollOptions.cpp (renamed from ndb/src/client/odbc/driver/SQLSetScrollOptions.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetStmtAttr.cpp (renamed from ndb/src/client/odbc/driver/SQLSetStmtAttr.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSetStmtOption.cpp (renamed from ndb/src/client/odbc/driver/SQLSetStmtOption.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLSpecialColumns.cpp (renamed from ndb/src/client/odbc/driver/SQLSpecialColumns.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLStatistics.cpp (renamed from ndb/src/client/odbc/driver/SQLStatistics.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLTablePrivileges.cpp (renamed from ndb/src/client/odbc/driver/SQLTablePrivileges.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLTables.cpp (renamed from ndb/src/client/odbc/driver/SQLTables.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/SQLTransact.cpp (renamed from ndb/src/client/odbc/driver/SQLTransact.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/driver/driver.cpp150
-rw-r--r--ndb/src/old_files/client/odbc/driver/driver.hpp (renamed from ndb/src/client/odbc/driver/driver.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_comp_op.cpp (renamed from ndb/src/client/odbc/executor/Exec_comp_op.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_create_index.cpp (renamed from ndb/src/client/odbc/executor/Exec_create_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_create_table.cpp (renamed from ndb/src/client/odbc/executor/Exec_create_table.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_delete_index.cpp (renamed from ndb/src/client/odbc/executor/Exec_delete_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_delete_lookup.cpp (renamed from ndb/src/client/odbc/executor/Exec_delete_lookup.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_delete_scan.cpp (renamed from ndb/src/client/odbc/executor/Exec_delete_scan.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_drop_index.cpp (renamed from ndb/src/client/odbc/executor/Exec_drop_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_drop_table.cpp (renamed from ndb/src/client/odbc/executor/Exec_drop_table.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_expr_conv.cpp (renamed from ndb/src/client/odbc/executor/Exec_expr_conv.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_expr_func.cpp (renamed from ndb/src/client/odbc/executor/Exec_expr_func.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_expr_op.cpp (renamed from ndb/src/client/odbc/executor/Exec_expr_op.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_insert.cpp (renamed from ndb/src/client/odbc/executor/Exec_insert.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_pred_op.cpp (renamed from ndb/src/client/odbc/executor/Exec_pred_op.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_query_index.cpp (renamed from ndb/src/client/odbc/executor/Exec_query_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_query_lookup.cpp (renamed from ndb/src/client/odbc/executor/Exec_query_lookup.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_query_range.cpp (renamed from ndb/src/client/odbc/executor/Exec_query_range.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_query_scan.cpp (renamed from ndb/src/client/odbc/executor/Exec_query_scan.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_query_sys.cpp (renamed from ndb/src/client/odbc/executor/Exec_query_sys.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_update_index.cpp (renamed from ndb/src/client/odbc/executor/Exec_update_index.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_update_lookup.cpp (renamed from ndb/src/client/odbc/executor/Exec_update_lookup.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Exec_update_scan.cpp (renamed from ndb/src/client/odbc/executor/Exec_update_scan.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Executor.cpp (renamed from ndb/src/client/odbc/executor/Executor.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Executor.hpp (renamed from ndb/src/client/odbc/executor/Executor.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/executor/Makefile (renamed from ndb/src/client/odbc/executor/Makefile)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/AttrDbc.cpp (renamed from ndb/src/client/odbc/handles/AttrDbc.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/AttrEnv.cpp (renamed from ndb/src/client/odbc/handles/AttrEnv.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/AttrRoot.cpp (renamed from ndb/src/client/odbc/handles/AttrRoot.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/AttrStmt.cpp (renamed from ndb/src/client/odbc/handles/AttrStmt.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/DescSpec.cpp (renamed from ndb/src/client/odbc/handles/DescSpec.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/FuncTab.cpp (renamed from ndb/src/client/odbc/handles/FuncTab.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleBase.cpp (renamed from ndb/src/client/odbc/handles/HandleBase.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleBase.hpp (renamed from ndb/src/client/odbc/handles/HandleBase.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleDbc.cpp (renamed from ndb/src/client/odbc/handles/HandleDbc.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleDbc.hpp (renamed from ndb/src/client/odbc/handles/HandleDbc.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleDesc.cpp (renamed from ndb/src/client/odbc/handles/HandleDesc.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleDesc.hpp (renamed from ndb/src/client/odbc/handles/HandleDesc.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleEnv.cpp (renamed from ndb/src/client/odbc/handles/HandleEnv.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleEnv.hpp (renamed from ndb/src/client/odbc/handles/HandleEnv.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleRoot.cpp271
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleRoot.hpp (renamed from ndb/src/client/odbc/handles/HandleRoot.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleStmt.cpp (renamed from ndb/src/client/odbc/handles/HandleStmt.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/HandleStmt.hpp (renamed from ndb/src/client/odbc/handles/HandleStmt.hpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/InfoTab.cpp (renamed from ndb/src/client/odbc/handles/InfoTab.cpp)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/Makefile (renamed from ndb/src/client/odbc/handles/Makefile)0
-rw-r--r--ndb/src/old_files/client/odbc/handles/PoolNdb.cpp81
-rw-r--r--ndb/src/old_files/client/odbc/handles/PoolNdb.hpp44
-rw-r--r--ndb/src/old_files/client/odbc/handles/handles.hpp (renamed from ndb/src/client/odbc/handles/handles.hpp)0
-rw-r--r--ndb/src/old_files/ndbbaseclient/Makefile (renamed from ndb/src/ndbbaseclient/Makefile)0
-rw-r--r--ndb/src/old_files/ndbbaseclient/ndbbaseclient_dummy.cpp (renamed from ndb/src/ndbbaseclient/ndbbaseclient_dummy.cpp)0
-rw-r--r--ndb/src/old_files/ndbclient/Makefile (renamed from ndb/src/ndbclient/Makefile)0
-rw-r--r--ndb/src/old_files/ndbclient/ndbclient_dummy.cpp (renamed from ndb/src/ndbclient/ndbclient_dummy.cpp)0
-rw-r--r--ndb/src/old_files/newtonapi/Makefile (renamed from ndb/src/newtonapi/Makefile)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_binding.cpp (renamed from ndb/src/newtonapi/dba_binding.cpp)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_bulkread.cpp (renamed from ndb/src/newtonapi/dba_bulkread.cpp)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_config.cpp (renamed from ndb/src/newtonapi/dba_config.cpp)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_dac.cpp (renamed from ndb/src/newtonapi/dba_dac.cpp)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_error.cpp (renamed from ndb/src/newtonapi/dba_error.cpp)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_init.cpp (renamed from ndb/src/newtonapi/dba_init.cpp)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_internal.hpp (renamed from ndb/src/newtonapi/dba_internal.hpp)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_process.cpp (renamed from ndb/src/newtonapi/dba_process.cpp)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_process.hpp (renamed from ndb/src/newtonapi/dba_process.hpp)0
-rw-r--r--ndb/src/old_files/newtonapi/dba_schema.cpp150
-rw-r--r--ndb/src/old_files/rep/ExtSender.cpp (renamed from ndb/src/rep/ExtSender.cpp)0
-rw-r--r--ndb/src/old_files/rep/ExtSender.hpp (renamed from ndb/src/rep/ExtSender.hpp)0
-rw-r--r--ndb/src/old_files/rep/Makefile (renamed from ndb/src/rep/Makefile)0
-rw-r--r--ndb/src/old_files/rep/NodeConnectInfo.hpp (renamed from ndb/src/rep/NodeConnectInfo.hpp)0
-rw-r--r--ndb/src/old_files/rep/README (renamed from ndb/src/rep/README)0
-rw-r--r--ndb/src/old_files/rep/RepApiInterpreter.cpp (renamed from ndb/src/rep/RepApiInterpreter.cpp)0
-rw-r--r--ndb/src/old_files/rep/RepApiInterpreter.hpp (renamed from ndb/src/rep/RepApiInterpreter.hpp)0
-rw-r--r--ndb/src/old_files/rep/RepApiService.cpp (renamed from ndb/src/rep/RepApiService.cpp)0
-rw-r--r--ndb/src/old_files/rep/RepApiService.hpp (renamed from ndb/src/rep/RepApiService.hpp)0
-rw-r--r--ndb/src/old_files/rep/RepCommandInterpreter.cpp (renamed from ndb/src/rep/RepCommandInterpreter.cpp)0
-rw-r--r--ndb/src/old_files/rep/RepCommandInterpreter.hpp (renamed from ndb/src/rep/RepCommandInterpreter.hpp)0
-rw-r--r--ndb/src/old_files/rep/RepComponents.cpp (renamed from ndb/src/rep/RepComponents.cpp)0
-rw-r--r--ndb/src/old_files/rep/RepComponents.hpp (renamed from ndb/src/rep/RepComponents.hpp)0
-rw-r--r--ndb/src/old_files/rep/RepMain.cpp (renamed from ndb/src/rep/RepMain.cpp)0
-rw-r--r--ndb/src/old_files/rep/Requestor.cpp (renamed from ndb/src/rep/Requestor.cpp)0
-rw-r--r--ndb/src/old_files/rep/Requestor.hpp (renamed from ndb/src/rep/Requestor.hpp)0
-rw-r--r--ndb/src/old_files/rep/RequestorSubscriptions.cpp (renamed from ndb/src/rep/RequestorSubscriptions.cpp)0
-rw-r--r--ndb/src/old_files/rep/SignalQueue.cpp (renamed from ndb/src/rep/SignalQueue.cpp)0
-rw-r--r--ndb/src/old_files/rep/SignalQueue.hpp117
-rw-r--r--ndb/src/old_files/rep/TODO (renamed from ndb/src/rep/TODO)0
-rw-r--r--ndb/src/old_files/rep/adapters/AppNDB.cpp583
-rw-r--r--ndb/src/old_files/rep/adapters/AppNDB.hpp (renamed from ndb/src/rep/adapters/AppNDB.hpp)0
-rw-r--r--ndb/src/old_files/rep/adapters/ExtAPI.cpp (renamed from ndb/src/rep/adapters/ExtAPI.cpp)0
-rw-r--r--ndb/src/old_files/rep/adapters/ExtAPI.hpp (renamed from ndb/src/rep/adapters/ExtAPI.hpp)0
-rw-r--r--ndb/src/old_files/rep/adapters/ExtNDB.cpp559
-rw-r--r--ndb/src/old_files/rep/adapters/ExtNDB.hpp118
-rw-r--r--ndb/src/old_files/rep/adapters/Makefile (renamed from ndb/src/rep/adapters/Makefile)0
-rw-r--r--ndb/src/old_files/rep/adapters/TableInfoPs.hpp (renamed from ndb/src/rep/adapters/TableInfoPs.hpp)0
-rw-r--r--ndb/src/old_files/rep/dbug_hack.cpp (renamed from ndb/src/rep/dbug_hack.cpp)0
-rw-r--r--ndb/src/old_files/rep/rep_version.hpp (renamed from ndb/src/rep/rep_version.hpp)0
-rw-r--r--ndb/src/old_files/rep/repapi/Makefile (renamed from ndb/src/rep/repapi/Makefile)0
-rw-r--r--ndb/src/old_files/rep/repapi/repapi.cpp (renamed from ndb/src/rep/repapi/repapi.cpp)0
-rw-r--r--ndb/src/old_files/rep/repapi/repapi.h (renamed from ndb/src/rep/repapi/repapi.h)0
-rw-r--r--ndb/src/old_files/rep/state/Channel.cpp487
-rw-r--r--ndb/src/old_files/rep/state/Channel.hpp (renamed from ndb/src/rep/state/Channel.hpp)0
-rw-r--r--ndb/src/old_files/rep/state/Interval.cpp (renamed from ndb/src/rep/state/Interval.cpp)0
-rw-r--r--ndb/src/old_files/rep/state/Interval.hpp (renamed from ndb/src/rep/state/Interval.hpp)0
-rw-r--r--ndb/src/old_files/rep/state/Makefile (renamed from ndb/src/rep/state/Makefile)0
-rw-r--r--ndb/src/old_files/rep/state/RepState.cpp (renamed from ndb/src/rep/state/RepState.cpp)0
-rw-r--r--ndb/src/old_files/rep/state/RepState.hpp276
-rw-r--r--ndb/src/old_files/rep/state/RepStateEvent.cpp (renamed from ndb/src/rep/state/RepStateEvent.cpp)0
-rw-r--r--ndb/src/old_files/rep/state/RepStateRequests.cpp (renamed from ndb/src/rep/state/RepStateRequests.cpp)0
-rw-r--r--ndb/src/old_files/rep/state/testInterval/Makefile (renamed from ndb/src/rep/state/testInterval/Makefile)0
-rw-r--r--ndb/src/old_files/rep/state/testInterval/testInterval.cpp (renamed from ndb/src/rep/state/testInterval/testInterval.cpp)0
-rw-r--r--ndb/src/old_files/rep/state/testRepState/Makefile (renamed from ndb/src/rep/state/testRepState/Makefile)0
-rw-r--r--ndb/src/old_files/rep/state/testRepState/testRequestor.cpp (renamed from ndb/src/rep/state/testRepState/testRequestor.cpp)0
-rw-r--r--ndb/src/old_files/rep/state/testRepState/testRequestor.hpp (renamed from ndb/src/rep/state/testRepState/testRequestor.hpp)0
-rw-r--r--ndb/src/old_files/rep/storage/GCIBuffer.cpp (renamed from ndb/src/rep/storage/GCIBuffer.cpp)0
-rw-r--r--ndb/src/old_files/rep/storage/GCIBuffer.hpp (renamed from ndb/src/rep/storage/GCIBuffer.hpp)0
-rw-r--r--ndb/src/old_files/rep/storage/GCIContainer.cpp (renamed from ndb/src/rep/storage/GCIContainer.cpp)0
-rw-r--r--ndb/src/old_files/rep/storage/GCIContainer.hpp (renamed from ndb/src/rep/storage/GCIContainer.hpp)0
-rw-r--r--ndb/src/old_files/rep/storage/GCIContainerPS.cpp (renamed from ndb/src/rep/storage/GCIContainerPS.cpp)0
-rw-r--r--ndb/src/old_files/rep/storage/GCIContainerPS.hpp (renamed from ndb/src/rep/storage/GCIContainerPS.hpp)0
-rw-r--r--ndb/src/old_files/rep/storage/GCIPage.cpp (renamed from ndb/src/rep/storage/GCIPage.cpp)0
-rw-r--r--ndb/src/old_files/rep/storage/GCIPage.hpp (renamed from ndb/src/rep/storage/GCIPage.hpp)0
-rw-r--r--ndb/src/old_files/rep/storage/LogRecord.hpp (renamed from ndb/src/rep/storage/LogRecord.hpp)0
-rw-r--r--ndb/src/old_files/rep/storage/Makefile (renamed from ndb/src/rep/storage/Makefile)0
-rw-r--r--ndb/src/old_files/rep/storage/NodeConnectInfo.hpp (renamed from ndb/src/rep/storage/NodeConnectInfo.hpp)0
-rw-r--r--ndb/src/old_files/rep/storage/NodeGroup.cpp (renamed from ndb/src/rep/storage/NodeGroup.cpp)0
-rw-r--r--ndb/src/old_files/rep/storage/NodeGroup.hpp (renamed from ndb/src/rep/storage/NodeGroup.hpp)0
-rw-r--r--ndb/src/old_files/rep/storage/NodeGroupInfo.cpp (renamed from ndb/src/rep/storage/NodeGroupInfo.cpp)0
-rw-r--r--ndb/src/old_files/rep/storage/NodeGroupInfo.hpp (renamed from ndb/src/rep/storage/NodeGroupInfo.hpp)0
-rw-r--r--ndb/src/old_files/rep/transfer/Makefile (renamed from ndb/src/rep/transfer/Makefile)0
-rw-r--r--ndb/src/old_files/rep/transfer/TransPS.cpp553
-rw-r--r--ndb/src/old_files/rep/transfer/TransPS.hpp136
-rw-r--r--ndb/src/old_files/rep/transfer/TransSS.cpp653
-rw-r--r--ndb/src/old_files/rep/transfer/TransSS.hpp145
-rw-r--r--ndb/src/old_files/rep/transfer/TransSSSubscriptions.cpp (renamed from ndb/src/rep/transfer/TransSSSubscriptions.cpp)0
-rw-r--r--ndb/src/rep/SignalQueue.hpp117
-rw-r--r--ndb/src/rep/adapters/AppNDB.cpp581
-rw-r--r--ndb/src/rep/adapters/ExtNDB.cpp551
-rw-r--r--ndb/src/rep/adapters/ExtNDB.hpp114
-rw-r--r--ndb/src/rep/state/Channel.cpp487
-rw-r--r--ndb/src/rep/state/RepState.hpp275
-rw-r--r--ndb/src/rep/transfer/TransPS.cpp549
-rw-r--r--ndb/src/rep/transfer/TransPS.hpp130
-rw-r--r--ndb/src/rep/transfer/TransSS.cpp649
-rw-r--r--ndb/src/rep/transfer/TransSS.hpp141
-rw-r--r--ndb/src/scripts/Makefile5
-rw-r--r--ndb/test/Makefile19
-rw-r--r--ndb/test/Makefile.am6
-rw-r--r--ndb/test/include/NDBT_Table.hpp69
-rw-r--r--ndb/test/include/NdbConfig.hpp19
-rw-r--r--ndb/test/include/NdbRestarter.hpp4
-rw-r--r--ndb/test/include/NdbSchemaCon.hpp147
-rw-r--r--ndb/test/include/NdbSchemaOp.hpp587
-rw-r--r--ndb/test/ndbapi/InsertRecs.cpp (renamed from ndb/test/ndbapi/telco/InsertRecs.cpp)0
-rw-r--r--ndb/test/ndbapi/Makefile50
-rw-r--r--ndb/test/ndbapi/Makefile.am81
-rw-r--r--ndb/test/ndbapi/Makefile_old51
-rw-r--r--ndb/test/ndbapi/ScanFilter.hpp (renamed from ndb/test/ndbapi/testScanInterpreter/ScanFilter.hpp)0
-rw-r--r--ndb/test/ndbapi/ScanFunctions.hpp (renamed from ndb/test/ndbapi/testScan/ScanFunctions.hpp)0
-rw-r--r--ndb/test/ndbapi/ScanInterpretTest.hpp (renamed from ndb/test/ndbapi/testScanInterpreter/ScanInterpretTest.hpp)0
-rw-r--r--ndb/test/ndbapi/TraceNdbApi.cpp (renamed from ndb/test/ndbapi/acid2/TraceNdbApi.cpp)0
-rw-r--r--ndb/test/ndbapi/VerifyNdbApi.cpp (renamed from ndb/test/ndbapi/acid2/VerifyNdbApi.cpp)0
-rw-r--r--ndb/test/ndbapi/acid.cpp558
-rw-r--r--ndb/test/ndbapi/acid/acid.cpp561
-rw-r--r--ndb/test/ndbapi/acid2.cpp (renamed from ndb/test/ndbapi/acid2/acid2.cpp)0
-rw-r--r--ndb/test/ndbapi/adoInsertRecs.cpp (renamed from ndb/test/ndbapi/telco/adoInsertRecs.cpp)0
-rw-r--r--ndb/test/ndbapi/asyncGenerator.cpp (renamed from ndb/test/ndbapi/lmc-bench/async-src/generator/asyncGenerator.cpp)0
-rw-r--r--ndb/test/ndbapi/bank/Bank.cpp2458
-rw-r--r--ndb/test/ndbapi/bank/BankLoad.cpp582
-rw-r--r--ndb/test/ndbapi/bank/Makefile.am22
-rw-r--r--ndb/test/ndbapi/bank/Makefile_old (renamed from ndb/test/ndbapi/bank/Makefile)0
-rw-r--r--ndb/test/ndbapi/bank/bankCreator.cpp54
-rw-r--r--ndb/test/ndbapi/bank/bankCreator/bankCreator.cpp54
-rw-r--r--ndb/test/ndbapi/bank/bankMakeGL.cpp55
-rw-r--r--ndb/test/ndbapi/bank/bankMakeGL/bankMakeGL.cpp55
-rw-r--r--ndb/test/ndbapi/bank/bankSumAccounts.cpp55
-rw-r--r--ndb/test/ndbapi/bank/bankSumAccounts/bankSumAccounts.cpp55
-rw-r--r--ndb/test/ndbapi/bank/bankTimer.cpp58
-rw-r--r--ndb/test/ndbapi/bank/bankTimer/bankTimer.cpp58
-rw-r--r--ndb/test/ndbapi/bank/bankTransactionMaker.cpp58
-rw-r--r--ndb/test/ndbapi/bank/bankTransactionMaker/bankTransactionMaker.cpp58
-rw-r--r--ndb/test/ndbapi/bank/bankValidateAllGLs.cpp56
-rw-r--r--ndb/test/ndbapi/bank/bankValidateAllGLs/bankValidateAllGLs.cpp56
-rw-r--r--ndb/test/ndbapi/bank/old_dirs/bankCreator/Makefile (renamed from ndb/test/ndbapi/bank/bankCreator/Makefile)0
-rw-r--r--ndb/test/ndbapi/bank/old_dirs/bankMakeGL/Makefile (renamed from ndb/test/ndbapi/bank/bankMakeGL/Makefile)0
-rw-r--r--ndb/test/ndbapi/bank/old_dirs/bankSumAccounts/Makefile (renamed from ndb/test/ndbapi/bank/bankSumAccounts/Makefile)0
-rw-r--r--ndb/test/ndbapi/bank/old_dirs/bankTimer/Makefile (renamed from ndb/test/ndbapi/bank/bankTimer/Makefile)0
-rw-r--r--ndb/test/ndbapi/bank/old_dirs/bankTransactionMaker/Makefile (renamed from ndb/test/ndbapi/bank/bankTransactionMaker/Makefile)0
-rw-r--r--ndb/test/ndbapi/bank/old_dirs/bankValidateAllGLs/Makefile (renamed from ndb/test/ndbapi/bank/bankValidateAllGLs/Makefile)0
-rw-r--r--ndb/test/ndbapi/bank/old_dirs/src/Makefile (renamed from ndb/test/ndbapi/bank/src/Makefile)0
-rw-r--r--ndb/test/ndbapi/bank/old_dirs/testBank/Makefile (renamed from ndb/test/ndbapi/bank/testBank/Makefile)0
-rw-r--r--ndb/test/ndbapi/bank/src/Bank.cpp2458
-rw-r--r--ndb/test/ndbapi/bank/src/BankLoad.cpp582
-rw-r--r--ndb/test/ndbapi/bank/testBank.cpp150
-rw-r--r--ndb/test/ndbapi/bank/testBank/testBank.cpp150
-rw-r--r--ndb/test/ndbapi/benchronja.cpp (renamed from ndb/test/ndbapi/ronja/benchronja/benchronja.cpp)0
-rw-r--r--ndb/test/ndbapi/bulk_copy.cpp (renamed from ndb/test/ndbapi/bulk_copy/bulk_copy.cpp)0
-rw-r--r--ndb/test/ndbapi/cdrserver.cpp (renamed from ndb/test/ndbapi/vw_test/cdrserver.cpp)0
-rw-r--r--ndb/test/ndbapi/celloDb.cpp (renamed from ndb/test/ndbapi/cello-sessionDb/celloDb.cpp)0
-rw-r--r--ndb/test/ndbapi/create_all_tabs.cpp (renamed from ndb/test/ndbapi/create_all_tabs/create_all_tabs.cpp)0
-rw-r--r--ndb/test/ndbapi/create_tab.cpp (renamed from ndb/test/ndbapi/create_tab/create_tab.cpp)0
-rw-r--r--ndb/test/ndbapi/drop_all_tabs.cpp (renamed from ndb/test/ndbapi/drop_all_tabs/drop_all_tabs.cpp)0
-rw-r--r--ndb/test/ndbapi/flexAsynch.cpp985
-rw-r--r--ndb/test/ndbapi/flexAsynch/flexAsynch.cpp982
-rw-r--r--ndb/test/ndbapi/flexBench.cpp (renamed from ndb/test/ndbapi/flexBench/flexBench.cpp)0
-rw-r--r--ndb/test/ndbapi/flexHammer.cpp890
-rw-r--r--ndb/test/ndbapi/flexHammer/flexHammer.cpp889
-rw-r--r--ndb/test/ndbapi/flexScan.cpp1667
-rw-r--r--ndb/test/ndbapi/flexScan/flexScan.cpp1674
-rw-r--r--ndb/test/ndbapi/flexTT.cpp928
-rw-r--r--ndb/test/ndbapi/flexTT/flexTT.cpp927
-rw-r--r--ndb/test/ndbapi/flexTimedAsynch.cpp (renamed from ndb/test/ndbapi/flexTimedAsynch/flexTimedAsynch.cpp)0
-rw-r--r--ndb/test/ndbapi/flex_bench_mysql.cpp (renamed from ndb/test/ndbapi/flex_bench_mysql/flex_bench_mysql.cpp)0
-rw-r--r--ndb/test/ndbapi/index.cpp (renamed from ndb/test/ndbapi/indexTest/index.cpp)0
-rw-r--r--ndb/test/ndbapi/index2.cpp (renamed from ndb/test/ndbapi/indexTest2/index2.cpp)0
-rw-r--r--ndb/test/ndbapi/initronja.cpp350
-rw-r--r--ndb/test/ndbapi/interpreterInTup.cpp1517
-rw-r--r--ndb/test/ndbapi/interpreterInTup/interpreterInTup.cpp1524
-rw-r--r--ndb/test/ndbapi/lmc-bench/src/user/userInterface.cpp740
-rw-r--r--ndb/test/ndbapi/mainAsyncGenerator.cpp (renamed from ndb/test/ndbapi/lmc-bench/async-src/generator/mainAsyncGenerator.cpp)0
-rw-r--r--ndb/test/ndbapi/msa.cpp1205
-rw-r--r--ndb/test/ndbapi/ndb_async1.cpp (renamed from ndb/test/ndbapi/lmc-bench/async-src/user/ndb_async1.cpp)0
-rw-r--r--ndb/test/ndbapi/ndb_async2.cpp (renamed from ndb/test/ndbapi/lmc-bench/async-src/user/ndb_async2.cpp)0
-rw-r--r--ndb/test/ndbapi/ndb_user_populate.cpp (renamed from ndb/test/ndbapi/lmc-bench/src/user/ndb_user_populate.cpp)0
-rw-r--r--ndb/test/ndbapi/ndb_user_transaction.cpp (renamed from ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction.cpp)0
-rw-r--r--ndb/test/ndbapi/ndb_user_transaction2.cpp (renamed from ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction2.cpp)0
-rw-r--r--ndb/test/ndbapi/ndb_user_transaction3.cpp (renamed from ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction3.cpp)0
-rw-r--r--ndb/test/ndbapi/ndb_user_transaction4.cpp (renamed from ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction4.cpp)0
-rw-r--r--ndb/test/ndbapi/ndb_user_transaction5.cpp (renamed from ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction5.cpp)0
-rw-r--r--ndb/test/ndbapi/ndb_user_transaction6.cpp (renamed from ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction6.cpp)0
-rw-r--r--ndb/test/ndbapi/old_dirs/acid/Makefile (renamed from ndb/test/ndbapi/acid/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/acid2/Makefile (renamed from ndb/test/ndbapi/acid2/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/acid2/TraceNdbApi.hpp (renamed from ndb/test/ndbapi/acid2/TraceNdbApi.hpp)0
-rw-r--r--ndb/test/ndbapi/old_dirs/acid2/VerifyNdbApi.hpp (renamed from ndb/test/ndbapi/acid2/VerifyNdbApi.hpp)0
-rwxr-xr-xndb/test/ndbapi/old_dirs/basicAsynch/Makefile (renamed from ndb/test/ndbapi/basicAsynch/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/bulk_copy/Makefile (renamed from ndb/test/ndbapi/bulk_copy/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/create_all_tabs/Makefile (renamed from ndb/test/ndbapi/create_all_tabs/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/create_tab/Makefile (renamed from ndb/test/ndbapi/create_tab/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/drop_all_tabs/Makefile (renamed from ndb/test/ndbapi/drop_all_tabs/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/flexAsynch/Makefile (renamed from ndb/test/ndbapi/flexAsynch/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/flexBench/Makefile.am10
-rw-r--r--ndb/test/ndbapi/old_dirs/flexBench/Makefile_old (renamed from ndb/test/ndbapi/flexBench/Makefile)0
-rwxr-xr-xndb/test/ndbapi/old_dirs/flexBench/ndbplot.pl (renamed from ndb/test/ndbapi/flexBench/ndbplot.pl)0
-rw-r--r--ndb/test/ndbapi/old_dirs/flexHammer/Makefile (renamed from ndb/test/ndbapi/flexHammer/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/flexHammer/README (renamed from ndb/test/ndbapi/flexHammer/README)0
-rw-r--r--ndb/test/ndbapi/old_dirs/flexScan/Makefile (renamed from ndb/test/ndbapi/flexScan/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/flexScan/README (renamed from ndb/test/ndbapi/flexScan/README)0
-rw-r--r--ndb/test/ndbapi/old_dirs/flexTT/Makefile (renamed from ndb/test/ndbapi/flexTT/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/flexTimedAsynch/Makefile (renamed from ndb/test/ndbapi/flexTimedAsynch/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/flex_bench_mysql/Makefile (renamed from ndb/test/ndbapi/flex_bench_mysql/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/indexTest/Makefile (renamed from ndb/test/ndbapi/indexTest/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/indexTest2/Makefile (renamed from ndb/test/ndbapi/indexTest2/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/interpreterInTup/Makefile (renamed from ndb/test/ndbapi/interpreterInTup/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/Makefile (renamed from ndb/test/ndbapi/lmc-bench/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/async-src/Makefile (renamed from ndb/test/ndbapi/lmc-bench/async-src/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/async-src/generator/Makefile (renamed from ndb/test/ndbapi/lmc-bench/async-src/generator/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/dbGenerator.h (renamed from ndb/test/ndbapi/lmc-bench/async-src/include/dbGenerator.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/testData.h (renamed from ndb/test/ndbapi/lmc-bench/async-src/include/testData.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/userInterface.h (renamed from ndb/test/ndbapi/lmc-bench/async-src/include/userInterface.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/Makefile (renamed from ndb/test/ndbapi/lmc-bench/async-src/user/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/macros.h (renamed from ndb/test/ndbapi/lmc-bench/async-src/user/macros.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/ndb_error.hpp (renamed from ndb/test/ndbapi/lmc-bench/async-src/user/ndb_error.hpp)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/bin/.empty (renamed from ndb/test/ndbapi/lmc-bench/bin/.empty)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/include/ndb_schema.hpp (renamed from ndb/test/ndbapi/lmc-bench/include/ndb_schema.hpp)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/include/testDefinitions.h (renamed from ndb/test/ndbapi/lmc-bench/include/testDefinitions.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/lib/.empty (renamed from ndb/test/ndbapi/lmc-bench/lib/.empty)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/script/Makefile (renamed from ndb/test/ndbapi/lmc-bench/script/Makefile)0
-rwxr-xr-xndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench-l-p10.sh (renamed from ndb/test/ndbapi/lmc-bench/script/async-lmc-bench-l-p10.sh)0
-rwxr-xr-xndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench-l.sh (renamed from ndb/test/ndbapi/lmc-bench/script/async-lmc-bench-l.sh)0
-rwxr-xr-xndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench-p10.sh (renamed from ndb/test/ndbapi/lmc-bench/script/async-lmc-bench-p10.sh)0
-rwxr-xr-xndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench.sh (renamed from ndb/test/ndbapi/lmc-bench/script/async-lmc-bench.sh)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/Makefile (renamed from ndb/test/ndbapi/lmc-bench/src/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/README (renamed from ndb/test/ndbapi/lmc-bench/src/README)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/Makefile (renamed from ndb/test/ndbapi/lmc-bench/src/generator/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/dbGenerator.c (renamed from ndb/test/ndbapi/lmc-bench/src/generator/dbGenerator.c)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/dbGenerator.h (renamed from ndb/test/ndbapi/lmc-bench/src/generator/dbGenerator.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/mainGenerator.c (renamed from ndb/test/ndbapi/lmc-bench/src/generator/mainGenerator.c)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/include/testData.h (renamed from ndb/test/ndbapi/lmc-bench/src/include/testData.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/include/userInterface.h (renamed from ndb/test/ndbapi/lmc-bench/src/include/userInterface.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/makevars.linux (renamed from ndb/test/ndbapi/lmc-bench/src/makevars.linux)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/makevars.sparc (renamed from ndb/test/ndbapi/lmc-bench/src/makevars.sparc)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/Makefile (renamed from ndb/test/ndbapi/lmc-bench/src/populator/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/dbPopulate.c (renamed from ndb/test/ndbapi/lmc-bench/src/populator/dbPopulate.c)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/dbPopulate.h (renamed from ndb/test/ndbapi/lmc-bench/src/populator/dbPopulate.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/mainPopulate.c (renamed from ndb/test/ndbapi/lmc-bench/src/populator/mainPopulate.c)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/Makefile (renamed from ndb/test/ndbapi/lmc-bench/src/user/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/localDbPrepare.c (renamed from ndb/test/ndbapi/lmc-bench/src/user/localDbPrepare.c)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/macros.h (renamed from ndb/test/ndbapi/lmc-bench/src/user/macros.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/ndb_error.hpp (renamed from ndb/test/ndbapi/lmc-bench/src/user/ndb_error.hpp)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/Makefile (renamed from ndb/test/ndbapi/lmc-bench/src/user/old/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userHandle.h (renamed from ndb/test/ndbapi/lmc-bench/src/user/old/userHandle.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userInterface.c (renamed from ndb/test/ndbapi/lmc-bench/src/user/old/userInterface.c)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userTransaction.c (renamed from ndb/test/ndbapi/lmc-bench/src/user/old/userTransaction.c)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userHandle.h (renamed from ndb/test/ndbapi/lmc-bench/src/user/userHandle.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userInterface.cpp739
-rw-r--r--ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userTransaction.c (renamed from ndb/test/ndbapi/lmc-bench/src/user/userTransaction.c)0
-rw-r--r--ndb/test/ndbapi/old_dirs/restarter/Makefile (renamed from ndb/test/ndbapi/restarter/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/restarter2/Makefile (renamed from ndb/test/ndbapi/restarter2/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/restarts/Makefile (renamed from ndb/test/ndbapi/restarts/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/ronja/Makefile (renamed from ndb/test/ndbapi/ronja/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/ronja/benchronja/Makefile (renamed from ndb/test/ndbapi/ronja/benchronja/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/ronja/initronja/Makefile (renamed from ndb/test/ndbapi/ronja/initronja/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/telco/Makefile (renamed from ndb/test/ndbapi/telco/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/telco/readme (renamed from ndb/test/ndbapi/telco/readme)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testBackup/Makefile (renamed from ndb/test/ndbapi/testBackup/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testBasic/Makefile (renamed from ndb/test/ndbapi/testBasic/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testBlobs/Makefile (renamed from ndb/test/ndbapi/testBlobs/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testDataBuffers/Makefile (renamed from ndb/test/ndbapi/testDataBuffers/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testDict/Makefile (renamed from ndb/test/ndbapi/testDict/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testGrep/Makefile (renamed from ndb/test/ndbapi/testGrep/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile (renamed from ndb/test/ndbapi/testGrep/verify/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testIndex/Makefile (renamed from ndb/test/ndbapi/testIndex/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testInterpreter/Makefile (renamed from ndb/test/ndbapi/testInterpreter/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testMgm/Makefile (renamed from ndb/test/ndbapi/testMgm/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testNdbApi/Makefile (renamed from ndb/test/ndbapi/testNdbApi/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testNodeRestart/Makefile (renamed from ndb/test/ndbapi/testNodeRestart/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testOIBasic/Makefile (renamed from ndb/test/ndbapi/testOIBasic/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testOIBasic/times.txt (renamed from ndb/test/ndbapi/testOIBasic/times.txt)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testOperations/Makefile (renamed from ndb/test/ndbapi/testOperations/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testOrderedIndex/Makefile (renamed from ndb/test/ndbapi/testOrderedIndex/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testRestartGci/Makefile (renamed from ndb/test/ndbapi/testRestartGci/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testScan/Makefile (renamed from ndb/test/ndbapi/testScan/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testScanInterpreter/Makefile (renamed from ndb/test/ndbapi/testScanInterpreter/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testSystemRestart/Makefile (renamed from ndb/test/ndbapi/testSystemRestart/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testTimeout/Makefile (renamed from ndb/test/ndbapi/testTimeout/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/testTransactions/Makefile (renamed from ndb/test/ndbapi/testTransactions/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/test_event/Makefile (renamed from ndb/test/ndbapi/test_event/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/vw_test/Makefile (renamed from ndb/test/ndbapi/vw_test/Makefile)0
-rw-r--r--ndb/test/ndbapi/old_dirs/vw_test/bcd.h (renamed from ndb/test/ndbapi/vw_test/bcd.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/vw_test/script/client_start (renamed from ndb/test/ndbapi/vw_test/script/client_start)0
-rw-r--r--ndb/test/ndbapi/old_dirs/vw_test/utv.h (renamed from ndb/test/ndbapi/vw_test/utv.h)0
-rw-r--r--ndb/test/ndbapi/old_dirs/vw_test/vcdrfunc.h (renamed from ndb/test/ndbapi/vw_test/vcdrfunc.h)0
-rw-r--r--ndb/test/ndbapi/restarter.cpp (renamed from ndb/test/ndbapi/restarter/restarter.cpp)0
-rw-r--r--ndb/test/ndbapi/restarter2.cpp (renamed from ndb/test/ndbapi/restarter2/restarter2.cpp)0
-rw-r--r--ndb/test/ndbapi/restarts.cpp (renamed from ndb/test/ndbapi/restarts/restarts.cpp)0
-rw-r--r--ndb/test/ndbapi/ronja/initronja/initronja.cpp349
-rw-r--r--ndb/test/ndbapi/size.cpp (renamed from ndb/test/ndbapi/vw_test/size.cpp)0
-rw-r--r--ndb/test/ndbapi/telco/msa.cpp1203
-rw-r--r--ndb/test/ndbapi/testBackup.cpp475
-rw-r--r--ndb/test/ndbapi/testBackup/testBackup.cpp476
-rw-r--r--ndb/test/ndbapi/testBasic.cpp (renamed from ndb/test/ndbapi/testBasic/testBasic.cpp)0
-rw-r--r--[-rwxr-xr-x]ndb/test/ndbapi/testBasicAsynch.cpp (renamed from ndb/test/ndbapi/basicAsynch/testBasicAsynch.cpp)0
-rw-r--r--ndb/test/ndbapi/testBlobs.cpp1213
-rw-r--r--ndb/test/ndbapi/testBlobs/testBlobs.cpp195
-rw-r--r--ndb/test/ndbapi/testDataBuffers.cpp616
-rw-r--r--ndb/test/ndbapi/testDataBuffers/testDataBuffers.cpp616
-rw-r--r--ndb/test/ndbapi/testDict.cpp1578
-rw-r--r--ndb/test/ndbapi/testDict/testDict.cpp1578
-rw-r--r--ndb/test/ndbapi/testGrep.cpp (renamed from ndb/test/ndbapi/testGrep/testGrep.cpp)0
-rw-r--r--ndb/test/ndbapi/testGrep/verify/testGrepVerify.cpp120
-rw-r--r--ndb/test/ndbapi/testGrepVerify.cpp117
-rw-r--r--ndb/test/ndbapi/testIndex.cpp (renamed from ndb/test/ndbapi/testIndex/testIndex.cpp)0
-rw-r--r--ndb/test/ndbapi/testInterpreter.cpp (renamed from ndb/test/ndbapi/testInterpreter/testInterpreter.cpp)0
-rw-r--r--ndb/test/ndbapi/testMgm.cpp (renamed from ndb/test/ndbapi/testMgm/testMgm.cpp)0
-rw-r--r--ndb/test/ndbapi/testNdbApi.cpp1013
-rw-r--r--ndb/test/ndbapi/testNdbApi/testNdbApi.cpp1013
-rw-r--r--ndb/test/ndbapi/testNodeRestart.cpp (renamed from ndb/test/ndbapi/testNodeRestart/testNodeRestart.cpp)0
-rw-r--r--ndb/test/ndbapi/testOIBasic.cpp2808
-rw-r--r--ndb/test/ndbapi/testOIBasic/testOIBasic.cpp2767
-rw-r--r--ndb/test/ndbapi/testOperations.cpp (renamed from ndb/test/ndbapi/testOperations/testOperations.cpp)0
-rw-r--r--ndb/test/ndbapi/testOrderedIndex.cpp (renamed from ndb/test/ndbapi/testOrderedIndex/testOrderedIndex.cpp)0
-rw-r--r--ndb/test/ndbapi/testRestartGci.cpp218
-rw-r--r--ndb/test/ndbapi/testRestartGci/testRestartGci.cpp218
-rw-r--r--ndb/test/ndbapi/testScan.cpp1402
-rw-r--r--ndb/test/ndbapi/testScan/testScan.cpp1311
-rw-r--r--ndb/test/ndbapi/testScanInterpreter.cpp280
-rw-r--r--ndb/test/ndbapi/testScanInterpreter/testScanInterpreter.cpp280
-rw-r--r--ndb/test/ndbapi/testScanPerf/Makefile9
-rw-r--r--ndb/test/ndbapi/testScanPerf/testScanPerf.cpp368
-rw-r--r--ndb/test/ndbapi/testSystemRestart.cpp1185
-rw-r--r--ndb/test/ndbapi/testSystemRestart/testSystemRestart.cpp942
-rw-r--r--ndb/test/ndbapi/testTimeout.cpp261
-rw-r--r--ndb/test/ndbapi/testTimeout/testTimeout.cpp261
-rw-r--r--ndb/test/ndbapi/testTransactions.cpp (renamed from ndb/test/ndbapi/testTransactions/testTransactions.cpp)0
-rw-r--r--ndb/test/ndbapi/test_event.cpp (renamed from ndb/test/ndbapi/test_event/test_event.cpp)0
-rw-r--r--ndb/test/ndbapi/userInterface.cpp (renamed from ndb/test/ndbapi/lmc-bench/async-src/user/userInterface.cpp)0
-rw-r--r--ndb/test/newtonapi/Makefile8
-rw-r--r--ndb/test/odbc/Makefile13
-rw-r--r--ndb/test/odbc/driver/testOdbcDriver.cpp2
-rw-r--r--ndb/test/run-test/Makefile.am18
-rw-r--r--ndb/test/run-test/Makefile_old (renamed from ndb/test/run-test/Makefile)0
-rw-r--r--ndb/test/run-test/README43
-rw-r--r--ndb/test/run-test/atrt-example.tgzbin0 -> 2196 bytes
-rw-r--r--ndb/test/run-test/basic.txt763
-rw-r--r--ndb/test/run-test/main.cpp150
-rwxr-xr-xndb/test/run-test/make-html-reports.sh406
-rw-r--r--ndb/test/src/Makefile31
-rw-r--r--ndb/test/src/Makefile.am20
-rw-r--r--ndb/test/src/Makefile_old33
-rw-r--r--ndb/test/src/NDBT_ResultRow.cpp74
-rw-r--r--ndb/test/src/NDBT_Table.cpp128
-rw-r--r--ndb/test/src/NdbBackup.cpp33
-rw-r--r--ndb/test/src/NdbConfig.cpp131
-rw-r--r--ndb/test/src/NdbRestarter.cpp13
-rw-r--r--ndb/test/src/NdbSchemaCon.cpp169
-rw-r--r--ndb/test/src/NdbSchemaOp.cpp220
-rw-r--r--ndb/test/src/UtilTransactions.cpp4
-rw-r--r--ndb/test/tools/Makefile.am31
-rw-r--r--ndb/test/tools/Makefile_old (renamed from ndb/test/tools/Makefile)0
-rw-r--r--ndb/test/tools/copy_tab.cpp (renamed from ndb/tools/copy_tab/copy_tab.cpp)0
-rw-r--r--ndb/test/tools/cpcc.cpp (renamed from ndb/tools/cpcc/cpcc.cpp)0
-rw-r--r--ndb/test/tools/create_index.cpp (renamed from ndb/tools/create_index/create_index.cpp)0
-rw-r--r--ndb/test/tools/hugoCalculator.cpp (renamed from ndb/test/tools/hugoCalculator/hugoCalculator.cpp)0
-rw-r--r--ndb/test/tools/hugoFill.cpp (renamed from ndb/test/tools/hugoFill/hugoFill.cpp)0
-rw-r--r--ndb/test/tools/hugoLoad.cpp (renamed from ndb/test/tools/hugoLoad/hugoLoad.cpp)0
-rw-r--r--ndb/test/tools/hugoLockRecords.cpp (renamed from ndb/test/tools/hugoLockRecords/hugoLockRecords.cpp)0
-rw-r--r--ndb/test/tools/hugoPkDelete.cpp (renamed from ndb/test/tools/hugoPkDelete/hugoPkDel.cpp)0
-rw-r--r--ndb/test/tools/hugoPkRead.cpp (renamed from ndb/test/tools/hugoPkRead/hugoPkRead.cpp)0
-rw-r--r--ndb/test/tools/hugoPkReadRecord.cpp (renamed from ndb/test/tools/hugoPkReadRecord/hugoPkReadRecord.cpp)0
-rw-r--r--ndb/test/tools/hugoPkUpdate.cpp (renamed from ndb/test/tools/hugoPkUpdate/hugoPkUpd.cpp)0
-rw-r--r--ndb/test/tools/hugoScanRead.cpp (renamed from ndb/test/tools/hugoScanRead/hugoScanRead.cpp)0
-rw-r--r--ndb/test/tools/hugoScanUpdate.cpp (renamed from ndb/test/tools/hugoScanUpdate/hugoScanUpd.cpp)0
-rw-r--r--ndb/test/tools/old_dirs/hugoCalculator/Makefile (renamed from ndb/test/tools/hugoCalculator/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoFill/Makefile (renamed from ndb/test/tools/hugoFill/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoLoad/Makefile (renamed from ndb/test/tools/hugoLoad/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoLockRecords/Makefile (renamed from ndb/test/tools/hugoLockRecords/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoPkDelete/Makefile (renamed from ndb/test/tools/hugoPkDelete/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoPkRead/Makefile (renamed from ndb/test/tools/hugoPkRead/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoPkReadRecord/Makefile (renamed from ndb/test/tools/hugoPkReadRecord/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoPkUpdate/Makefile (renamed from ndb/test/tools/hugoPkUpdate/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoScanRead/Makefile (renamed from ndb/test/tools/hugoScanRead/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoScanUpdate/Makefile (renamed from ndb/test/tools/hugoScanUpdate/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/restart/Makefile (renamed from ndb/test/tools/restart/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/transproxy/Makefile (renamed from ndb/tools/transproxy/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/verify_index/Makefile (renamed from ndb/tools/verify_index/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/waiter/Makefile_old (renamed from ndb/test/tools/waiter/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/waiter/waiter.cpp (renamed from ndb/test/tools/waiter/waiter.cpp)0
-rw-r--r--ndb/test/tools/restart.cpp (renamed from ndb/test/tools/restart/restart.cpp)0
-rw-r--r--ndb/test/tools/transproxy.cpp (renamed from ndb/tools/transproxy/transproxy.cpp)0
-rw-r--r--ndb/test/tools/verify_index.cpp (renamed from ndb/tools/verify_index/verify_index.cpp)0
-rw-r--r--ndb/tools/Makefile.am36
-rw-r--r--ndb/tools/Makefile_old (renamed from ndb/tools/Makefile)0
-rw-r--r--ndb/tools/delete_all.cpp181
-rw-r--r--ndb/tools/delete_all/delete_all.cpp93
-rw-r--r--ndb/tools/desc.cpp103
-rw-r--r--ndb/tools/desc/desc.cpp78
-rw-r--r--ndb/tools/drop_index.cpp (renamed from ndb/tools/drop_index/drop_index.cpp)0
-rw-r--r--ndb/tools/drop_tab.cpp (renamed from ndb/tools/drop_tab/drop_tab.cpp)0
-rw-r--r--ndb/tools/listTables.cpp195
-rw-r--r--ndb/tools/list_tables/listTables.cpp195
-rw-r--r--ndb/tools/ndbsql.cpp956
-rw-r--r--ndb/tools/ndbsql/ndbsql.cpp947
-rw-r--r--ndb/tools/old_dirs/copy_tab/Makefile (renamed from ndb/tools/copy_tab/Makefile)0
-rw-r--r--ndb/tools/old_dirs/cpcc/Makefile (renamed from ndb/tools/cpcc/Makefile)0
-rw-r--r--ndb/tools/old_dirs/create_index/Makefile (renamed from ndb/tools/create_index/Makefile)0
-rw-r--r--ndb/tools/old_dirs/delete_all/Makefile (renamed from ndb/tools/delete_all/Makefile)0
-rw-r--r--ndb/tools/old_dirs/desc/Makefile (renamed from ndb/tools/desc/Makefile)0
-rw-r--r--ndb/tools/old_dirs/drop_index/Makefile (renamed from ndb/tools/drop_index/Makefile)0
-rw-r--r--ndb/tools/old_dirs/drop_tab/Makefile (renamed from ndb/tools/drop_tab/Makefile)0
-rw-r--r--ndb/tools/old_dirs/list_tables/Makefile (renamed from ndb/tools/list_tables/Makefile)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/Makefile.PL (renamed from ndb/tools/ndbnet/Makefile.PL)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Base.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/Base.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Client.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/Client.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Command.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/Command.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Config.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/Config.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Database.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/Database.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Env.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/Env.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Node.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/Node.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/NodeApi.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/NodeApi.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/NodeDb.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/NodeDb.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/NodeMgmt.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/NodeMgmt.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Server.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/Server.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/ServerINET.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/ServerINET.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Net/ServerUNIX.pm (renamed from ndb/tools/ndbnet/lib/NDB/Net/ServerUNIX.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Run.pm (renamed from ndb/tools/ndbnet/lib/NDB/Run.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Base.pm (renamed from ndb/tools/ndbnet/lib/NDB/Run/Base.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Database.pm (renamed from ndb/tools/ndbnet/lib/NDB/Run/Database.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Env.pm (renamed from ndb/tools/ndbnet/lib/NDB/Run/Env.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Node.pm (renamed from ndb/tools/ndbnet/lib/NDB/Run/Node.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Base.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/Base.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Dir.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/Dir.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Event.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/Event.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/File.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/File.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/IO.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/IO.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Lock.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/Lock.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Log.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/Log.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Socket.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/Socket.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/SocketINET.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/SocketINET.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/lib/NDB/Util/SocketUNIX.pm (renamed from ndb/tools/ndbnet/lib/NDB/Util/SocketUNIX.pm)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/ndbnet.pl (renamed from ndb/tools/ndbnet/ndbnet.pl)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/ndbnetd.pl (renamed from ndb/tools/ndbnet/ndbnetd.pl)0
-rw-r--r--ndb/tools/old_dirs/ndbnet/ndbrun (renamed from ndb/tools/ndbnet/ndbrun)0
-rw-r--r--ndb/tools/old_dirs/ndbsql/Makefile (renamed from ndb/tools/ndbsql/Makefile)0
-rw-r--r--ndb/tools/old_dirs/select_all/Makefile (renamed from ndb/tools/select_all/Makefile)0
-rw-r--r--ndb/tools/old_dirs/select_count/Makefile (renamed from ndb/tools/select_count/Makefile)0
-rw-r--r--ndb/tools/old_dirs/src/counterviewer/CounterViewer.java (renamed from ndb/tools/src/counterviewer/CounterViewer.java)0
-rw-r--r--ndb/tools/select_all.cpp (renamed from ndb/tools/select_all/select_all.cpp)0
-rw-r--r--ndb/tools/select_count.cpp199
-rw-r--r--ndb/tools/select_count/select_count.cpp90
-rw-r--r--ndb/tools/waiter.cpp299
-rwxr-xr-xnetware/BUILD/compile-linux-tools4
-rwxr-xr-xnetware/BUILD/compile-netware-standard1
-rwxr-xr-xnetware/BUILD/mwenv13
-rwxr-xr-xnetware/BUILD/nwbootstrap12
-rw-r--r--netware/Makefile.am29
-rw-r--r--netware/init_db.sql13
-rw-r--r--netware/my_manage.c5
-rw-r--r--netware/mysql_fix_privilege_tables.pl121
-rw-r--r--netware/mysql_test_run.c293
-rw-r--r--netware/mysqld_safe.c616
-rw-r--r--netware/static_init_db.sql4
-rw-r--r--regex/regcomp.c2
-rw-r--r--[-rwxr-xr-x]scripts/fill_func_tables.sh0
-rw-r--r--scripts/make_binary_distribution.sh50
-rw-r--r--scripts/make_win_binary_distribution.sh5
-rw-r--r--[-rwxr-xr-x]scripts/make_win_src_distribution.sh30
-rw-r--r--scripts/mysql_create_system_tables.sh346
-rw-r--r--scripts/mysql_find_rows.sh2
-rw-r--r--scripts/mysql_fix_privilege_tables.sh7
-rw-r--r--scripts/mysql_fix_privilege_tables.sql41
-rw-r--r--scripts/mysql_install_db.sh15
-rw-r--r--scripts/mysqld_safe.sh8
-rw-r--r--sql-bench/server-cfg.sh8
-rw-r--r--sql-common/Makefile.am2
-rw-r--r--sql-common/client.c123
-rw-r--r--sql-common/my_time.c561
-rw-r--r--sql/Makefile.am21
-rw-r--r--sql/examples/ha_archive.cc586
-rw-r--r--sql/examples/ha_archive.h120
-rw-r--r--sql/examples/ha_example.cc129
-rw-r--r--sql/examples/ha_example.h87
-rw-r--r--sql/field.cc847
-rw-r--r--sql/field.h35
-rw-r--r--sql/field_conv.cc12
-rw-r--r--sql/filesort.cc11
-rw-r--r--sql/ha_berkeley.cc51
-rw-r--r--sql/ha_berkeley.h29
-rw-r--r--sql/ha_heap.cc6
-rw-r--r--sql/ha_heap.h19
-rw-r--r--sql/ha_innodb.cc123
-rw-r--r--sql/ha_innodb.h41
-rw-r--r--sql/ha_isam.h18
-rw-r--r--sql/ha_isammrg.h12
-rw-r--r--sql/ha_myisam.cc29
-rw-r--r--sql/ha_myisam.h27
-rw-r--r--sql/ha_myisammrg.h26
-rw-r--r--sql/ha_ndbcluster.cc1027
-rw-r--r--sql/ha_ndbcluster.h55
-rw-r--r--sql/handler.cc205
-rw-r--r--sql/handler.h299
-rw-r--r--sql/item.cc142
-rw-r--r--sql/item.h93
-rw-r--r--sql/item_cmpfunc.cc97
-rw-r--r--sql/item_cmpfunc.h8
-rw-r--r--sql/item_create.cc9
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_func.cc89
-rw-r--r--sql/item_func.h10
-rw-r--r--sql/item_strfunc.cc36
-rw-r--r--sql/item_subselect.cc14
-rw-r--r--sql/item_sum.cc39
-rw-r--r--sql/item_sum.h3
-rw-r--r--sql/item_timefunc.cc360
-rw-r--r--sql/item_timefunc.h56
-rw-r--r--sql/lex.h6
-rw-r--r--sql/log.cc259
-rw-r--r--sql/log_event.cc101
-rw-r--r--sql/mysql_priv.h45
-rw-r--r--sql/mysqld.cc219
-rw-r--r--sql/net_serv.cc12
-rw-r--r--sql/opt_range.cc84
-rw-r--r--sql/opt_sum.cc26
-rw-r--r--sql/password.c6
-rw-r--r--sql/protocol.cc24
-rw-r--r--sql/protocol.h5
-rw-r--r--sql/records.cc10
-rw-r--r--sql/repl_failsafe.cc5
-rw-r--r--sql/set_var.cc238
-rw-r--r--sql/set_var.h92
-rw-r--r--sql/share/czech/errmsg.txt88
-rw-r--r--sql/share/danish/errmsg.txt64
-rw-r--r--sql/share/dutch/errmsg.txt48
-rw-r--r--sql/share/english/errmsg.txt150
-rw-r--r--sql/share/estonian/errmsg.txt62
-rw-r--r--sql/share/french/errmsg.txt56
-rw-r--r--sql/share/german/errmsg.txt20
-rw-r--r--sql/share/greek/errmsg.txt88
-rw-r--r--sql/share/hungarian/errmsg.txt76
-rw-r--r--sql/share/italian/errmsg.txt48
-rw-r--r--sql/share/japanese/errmsg.txt100
-rw-r--r--sql/share/korean/errmsg.txt82
-rw-r--r--sql/share/norwegian-ny/errmsg.txt102
-rw-r--r--sql/share/norwegian/errmsg.txt102
-rw-r--r--sql/share/polish/errmsg.txt110
-rw-r--r--sql/share/portuguese/errmsg.txt24
-rw-r--r--sql/share/romanian/errmsg.txt78
-rw-r--r--sql/share/russian/errmsg.txt44
-rw-r--r--sql/share/serbian/errmsg.txt54
-rw-r--r--sql/share/slovak/errmsg.txt86
-rw-r--r--sql/slave.cc107
-rw-r--r--sql/spatial.cc11
-rw-r--r--sql/spatial.h3
-rw-r--r--sql/sql_acl.cc40
-rw-r--r--sql/sql_base.cc21
-rw-r--r--sql/sql_bitmap.h17
-rw-r--r--sql/sql_cache.cc19
-rw-r--r--sql/sql_class.cc52
-rw-r--r--sql/sql_class.h49
-rw-r--r--sql/sql_db.cc71
-rw-r--r--sql/sql_delete.cc16
-rw-r--r--sql/sql_derived.cc1
-rw-r--r--sql/sql_handler.cc192
-rw-r--r--sql/sql_help.cc238
-rw-r--r--sql/sql_insert.cc14
-rw-r--r--sql/sql_lex.cc42
-rw-r--r--sql/sql_lex.h23
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_parse.cc290
-rw-r--r--sql/sql_prepare.cc508
-rw-r--r--sql/sql_select.cc223
-rw-r--r--sql/sql_show.cc22
-rw-r--r--sql/sql_string.cc3
-rw-r--r--sql/sql_table.cc137
-rw-r--r--sql/sql_update.cc27
-rw-r--r--sql/sql_yacc.yy163
-rw-r--r--sql/structs.h25
-rw-r--r--sql/table.cc17
-rw-r--r--sql/table.h3
-rw-r--r--sql/time.cc742
-rw-r--r--sql/tzfile.h137
-rw-r--r--sql/tztime.cc2581
-rw-r--r--sql/tztime.h79
-rw-r--r--sql/unireg.cc2
-rw-r--r--strings/ctype-big5.c26
-rw-r--r--strings/ctype-bin.c28
-rw-r--r--strings/ctype-czech.c14
-rw-r--r--strings/ctype-euc_kr.c18
-rw-r--r--strings/ctype-extra.c27
-rw-r--r--strings/ctype-gb2312.c22
-rw-r--r--strings/ctype-gbk.c29
-rw-r--r--strings/ctype-latin1.c29
-rw-r--r--strings/ctype-mb.c20
-rw-r--r--strings/ctype-simple.c134
-rw-r--r--strings/ctype-sjis.c27
-rw-r--r--strings/ctype-tis620.c26
-rw-r--r--strings/ctype-uca.c1785
-rw-r--r--strings/ctype-ucs2.c52
-rw-r--r--strings/ctype-ujis.c26
-rw-r--r--strings/ctype-utf8.c56
-rw-r--r--strings/ctype-win1250ch.c21
-rw-r--r--strings/ctype.c55
-rw-r--r--strings/int2str.c139
-rw-r--r--strings/longlong2str-x86.s4
-rw-r--r--strings/longlong2str.c10
-rw-r--r--strings/my_strtoll10.c2
-rw-r--r--strings/my_vsnprintf.c3
-rw-r--r--support-files/my-huge.cnf.sh8
-rw-r--r--support-files/my-innodb-heavy-4G.cnf.sh4
-rw-r--r--support-files/my-large.cnf.sh8
-rw-r--r--support-files/my-medium.cnf.sh6
-rw-r--r--support-files/my-small.cnf.sh6
-rw-r--r--support-files/mysql.spec.sh15
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/client_test.c7302
-rw-r--r--tools/mysqlmanager.c4
-rw-r--r--vio/test-sslserver.c5
1802 files changed, 99865 insertions, 76131 deletions
diff --git a/.bzrignore b/.bzrignore
index 08ef076d278..e653a6f4343 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -272,11 +272,13 @@ emacs.h
extra/comp_err
extra/my_print_defaults
extra/mysql_install
+extra/mysql_tzinfo_to_sql
extra/mysql_waitpid
extra/perror
extra/replace
extra/resolve_stack_dump
extra/resolveip
+extra/tztime.cc
fcns.c
fcns.h
gmon.out
@@ -316,6 +318,7 @@ isam/test3
libmysql/*.c
libmysql/conf_to_src
libmysql/my_static.h
+libmysql/my_time.c
libmysql/mysys_priv.h
libmysql/net.c
libmysql/vio_priv.h
@@ -382,6 +385,7 @@ libmysqld/log_event.cc
libmysqld/md5.c
libmysqld/mf_iocache.cc
libmysqld/mini_client.cc
+libmysqld/my_time.c
libmysqld/net_pkg.cc
libmysqld/net_serv.cc
libmysqld/opt_ft.cc
@@ -443,6 +447,7 @@ libmysqld/strfunc.cc
libmysqld/table.cc
libmysqld/thr_malloc.cc
libmysqld/time.cc
+libmysqld/tztime.cc
libmysqld/uniques.cc
libmysqld/unireg.cc
libtool
@@ -496,6 +501,7 @@ mysql-max-4.0.2-alpha-pc-linux-gnu-i686.tar.gz
mysql-test/gmon.out
mysql-test/install_test_db
mysql-test/mysql-test-run
+mysql-test/ndb/ndbcluster
mysql-test/r/*.reject
mysql-test/r/rpl000001.eval
mysql-test/r/rpl000002.eval
@@ -721,6 +727,10 @@ sql/gen_lex_hash
sql/gmon.out
sql/lex_hash.h
sql/mini_client_errors.c
+sql/my_time.c
+sql/mysql_tzinfo_to_sql
+sql/mysql_tzinfo_to_sql.cc
+sql/mysql_tzinfo_to_sql_tztime.cc
sql/mysqlbinlog
sql/mysqld
sql/mysqld-purecov
@@ -740,6 +750,7 @@ sql/sql_yacc.cc
sql/sql_yacc.h
sql/sql_yacc.output
sql/sql_yacc.yy.orig
+sql/test_time
sql/udf_example.so
sql_error.cc
sql_prepare.cc
diff --git a/BUILD/compile-pentium-maintainer b/BUILD/compile-pentium-maintainer
deleted file mode 100755
index 1265154dc76..00000000000
--- a/BUILD/compile-pentium-maintainer
+++ /dev/null
@@ -1,13 +0,0 @@
-#! /bin/sh
-
-path=`dirname $0`
-. "$path/SETUP.sh"
-
-extra_flags="$pentium_cflags $debug_cflags"
-c_warnings="$c_warnings $debug_extra_warnings"
-cxx_warnings="$cxx_warnings $debug_extra_warnings"
-extra_configs="$pentium_configs $debug_configs "
-
-extra_configs="$extra_configs --enable-maintainer-mode"
-
-. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-max b/BUILD/compile-pentium-max
index caf657a2049..6eb71fcebb6 100755
--- a/BUILD/compile-pentium-max
+++ b/BUILD/compile-pentium-max
@@ -7,6 +7,11 @@ extra_flags="$pentium_cflags $fast_cflags -g"
extra_configs="$pentium_configs"
#strip=yes
+#extra_configs="$extra_configs --with-innodb --with-berkeley-db \
+# --with-embedded-server --enable-thread-safe-client \
+# --with-openssl --with-vio --with-raid --with-ndbcluster"
+# removed per discussion with Brian and Sanja because it makes Bootstrap
+# fail
extra_configs="$extra_configs --with-innodb --with-berkeley-db \
--with-embedded-server --enable-thread-safe-client \
--with-openssl --with-vio --with-raid --with-ndbcluster"
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index b2409deb9f4..802dc53452d 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -16,15 +16,18 @@ arjen@bitbike.com
arjen@co3064164-a.bitbike.com
arjen@fred.bitbike.com
arjen@george.bitbike.com
+autotest@mc01.ndb.mysql.com
bar@bar.intranet.mysql.r18.ru
bar@bar.mysql.r18.ru
bar@bar.udmsearch.izhnet.ru
bar@deer.(none)
bar@gw.udmsearch.izhnet.ru
+bar@mysql.com
bell@laptop.sanja.is.com.ua
bell@sanja.is.com.ua
bk@admin.bk
bk@mysql.r18.ru
+brian@avenger.(none)
brian@brian-akers-computer.local
carsten@tsort.bitbybit.dk
davida@isil.mysql.com
@@ -37,6 +40,7 @@ georg@beethoven.local
gerberb@ou800.zenez.com
gluh@gluh.(none)
gluh@gluh.mysql.r18.ru
+gordon@zero.local.lan
greg@gcw.ath.cx
greg@mysql.com
guilhem@mysql.com
@@ -77,6 +81,7 @@ jcole@sarvik.tfr.cafe.ee
jcole@tetra.spaceapes.com
joreland@mysql.com
jorge@linux.jorge.mysql.com
+jplindst@t41.(none)
kaj@work.mysql.com
konstantin@mysql.com
kostja@oak.local
@@ -87,9 +92,11 @@ marko@hundin.mysql.fi
miguel@hegel.(none)
miguel@hegel.br
miguel@hegel.local
+miguel@hegel.txg
miguel@light.
miguel@light.local
miguel@sartre.local
+mikron@mikael-ronstr-ms-dator.local
mmatthew@markslaptop.
monty@bitch.mysql.fi
monty@butch.
@@ -107,13 +114,17 @@ monty@tik.
monty@tik.mysql.fi
monty@tramp.mysql.fi
monty@work.mysql.com
+mronstrom@mysql.com
+mskold@mysql.com
msvensson@build.mysql.com
mwagner@cash.mwagner.org
mwagner@evoq.mwagner.org
+mwagner@here.mwagner.org
mwagner@work.mysql.com
mydev@mysql.com
mysql@home.(none)
mysqldev@build.mysql2.com
+mysqldev@mysql.com
ndbdev@ndbmaster.mysql.com
nick@mysql.com
nick@nick.leippe.com
@@ -124,6 +135,7 @@ paul@ice.local
paul@ice.snake.net
paul@kite-hub.kitebird.com
paul@teton.kitebird.com
+pekka@mysql.com
pem@mysql.com
pem@per-erik-martins-dator.local
peter@linux.local
@@ -169,6 +181,9 @@ timour@mysql.com
tom@basil-firewall.home.com
tomas@mc05.(none)
tomas@poseidon.(none)
+tomas@poseidon.bredbandsbolaget.se
+tomas@poseidon.elisa-laajakaista.fi
+tomas@poseidon.ndb.mysql.com
tonu@hundin.mysql.fi
tonu@volk.internalnet
tonu@x153.internalnet
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile
index 03571593f77..cf466ef5848 100755
--- a/Build-tools/Do-compile
+++ b/Build-tools/Do-compile
@@ -7,16 +7,17 @@ use Sys::Hostname;
@config_options= ();
@make_options= ();
-$opt_distribution=$opt_user=$opt_config_env="";
+$opt_distribution=$opt_user=$opt_config_env=$opt_config_extra_env="";
$opt_dbd_options=$opt_perl_options=$opt_config_options=$opt_make_options=$opt_suffix="";
$opt_tmp=$opt_version_suffix="";
$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_cluster=$opt_with_debug=$opt_no_benchmark=$opt_no_mysqltest=$opt_without_embedded=$opt_readline=0;
-$opt_innodb=$opt_bdb=$opt_raid=$opt_libwrap=$opt_clearlogs=$opt_without_ndbcluster=0;
+$opt_innodb=$opt_bdb=$opt_raid=$opt_libwrap=$opt_clearlogs=0;
GetOptions(
"bdb",
"build-thread=i",
"config-env=s" => \@config_env,
+ "config-extra-env=s" => \@config_extra_env,
"config-options=s" => \@config_options,
"dbd-options=s",
"debug",
@@ -56,8 +57,7 @@ GetOptions(
"with-other-libc=s",
"with-small-disk",
"without-embedded",
- "clearlogs",
- "without-ndbcluster",
+ "clearlogs",
) || usage();
usage() if ($opt_help);
@@ -81,6 +81,12 @@ if (@config_env > 0)
$opt_config_env= join(" ", @config_env);
}
+if (@config_extra_env > 0)
+{
+ chomp(@config_extra_env);
+ $opt_config_extra_env= join(" ", @config_extra_env);
+}
+
$host= hostname();
chomp($uname=`uname`);
$full_host_name=$host;
@@ -91,6 +97,7 @@ $email="$opt_user\@mysql.com";
chomp($pwd = `pwd`);
$VER= basename($opt_distribution);
$VER=~ /mysql.*-([1-9]\.[0-9]{1,2}\.[0-9]{1,2}.*)\.tar*/; $version=$1;
+$release=""; # Shut up perl
($major, $minor, $release) = split(/\./,$version);
$log="$pwd/Logs/$host-$major.$minor$opt_version_suffix.log";
$opt_distribution =~ /(mysql[^\/]*)\.tar/;
@@ -113,6 +120,8 @@ if (defined($gcc_version) && ! $opt_config_env)
}
}
+$opt_config_env.=" $opt_config_extra_env";
+
$new_opt_tmp=0;
if ($opt_tmp)
{
@@ -139,6 +148,7 @@ $ENV{'MYSQL_TCP_PORT'}= $mysql_tcp_port= 3334 + $opt_build_thread*2;
$ENV{'MYSQL_UNIX_PORT'}=$mysql_unix_port="$opt_tmp/mysql$opt_suffix.build";
$ENV{"PERL5LIB"}="$pwd/$host/perl5:$pwd/$host/perl5/site_perl";
$slave_port=$mysql_tcp_port+16;
+$ndbcluster_port= 9350 + $opt_build_thread*2;
$manager_port=$mysql_tcp_port+1;
$mysqladmin_args="--no-defaults -u root --connect_timeout=5 --shutdown_timeout=20";
@@ -156,6 +166,9 @@ select STDOUT;
$|=1;
info("Compiling MySQL$opt_version_suffix at $host$opt_suffix, stage: $opt_stage\n");
+info("LD_LIBRARY_PATH is $ENV{LD_LIBRARY_PATH}");
+info("PATH is $ENV{PATH}");
+
log_timestamp();
if (-x "$host/bin/mysqladmin")
@@ -237,9 +250,15 @@ if ($opt_stage <= 1)
$opt_config_options.= " --with-low-memory" if ($opt_with_low_memory);
$opt_config_options.= " --with-mysqld-ldflags=-all-static" if ($opt_static_server);
$opt_config_options.= " --with-raid" if ($opt_raid);
- $opt_config_options.= " --with-readline" if ($opt_readline);
+ if ($opt_readline)
+ {
+ $opt_config_options.= " --with-readline";
+ }
+ else
+ {
+ $opt_config_options.= " --with-libedit";
+ }
$opt_config_options.= " --with-embedded-server" unless ($opt_without_embedded);
- $opt_config_options.= " --without-ndbcluster" if ($opt_without_ndbcluster);
$opt_config_options.= " --with-ndbcluster" if ($opt_with_cluster);
# Only enable InnoDB when requested (required to be able to
@@ -295,7 +314,7 @@ if ($opt_stage <= 3)
}
$flags.= " --no-strip" if ($opt_no_strip || $opt_with_debug);
- $flags.= " --with-ndbcluster" if ($opt__with_ndbcluster);
+ $flags.= " --with-ndbcluster" if ($opt_with_cluster);
check_system("scripts/make_binary_distribution --tmp=$opt_tmp --suffix=$opt_suffix $flags",".tar.gz created");
safe_system("mv mysql*.t*gz $pwd/$host");
if (-f "client/.libs/mysqladmin")
@@ -334,10 +353,12 @@ $ENV{"LD_LIBRARY_PATH"}= ("$test_dir/lib" .
#
if ($opt_stage <= 5 && !$opt_no_test && !$opt_no_mysqltest)
{
+ my $flags= "";
+ $flags.= " --with-ndbcluster" if ($opt_with_cluster);
log_timestamp();
system("mkdir $bench_tmpdir") if (! -d $bench_tmpdir);
safe_cd("${test_dir}/mysql-test");
- check_system("./mysql-test-run --warnings --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful");
+ check_system("./mysql-test-run $flags --warnings --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --ndbcluster_port=$ndbcluster_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful");
}
#
@@ -448,16 +469,25 @@ exit 0;
sub usage
{
print <<EOF;
-$0 version 1.5
+$0 version 1.6
$0 takes the following options:
--bdb
Compile with support for Berkeley DB tables
+--build-thread=<1,2,3...>
+When running several Do-compile runs in parallel, each build
+should have its own thread ID, so running the test suites
+does not cause conflicts with duplicate TCP port numbers.
+
--config-env=<environment for configure>
To set up the environment, like 'CC=cc CXX=gcc CXXFLAGS=-O3'
+--config-extra-env <environment for configure>
+Additional flags for environment (not CC or CXX). Should be used when one
+wants Do-compile to propose proper CC and CXX flags.
+
--config-options=<options>
To add some extra options to configure (e.g. '--with-perl=yes')
@@ -554,7 +584,7 @@ If user is empty then no mail is sent.
Set name suffix (e.g. 'com' or '-max') for a distribution
--with cluster
-Compile with NDB Cluster
+Compile and test with NDB Cluster enabled
--with-debug
Build binaries with debug information (implies "--no-strip")
diff --git a/Build-tools/Do-rpm b/Build-tools/Do-rpm
index 7da8b022031..da06e1f58e4 100755
--- a/Build-tools/Do-rpm
+++ b/Build-tools/Do-rpm
@@ -22,6 +22,7 @@ use Getopt::Long;
Getopt::Long::Configure ("bundling");
use Sys::Hostname;
+$opt_nobuild = undef;
$opt_cc= undef;
$opt_cflags= undef;
$opt_clean= undef;
@@ -48,6 +49,7 @@ GetOptions(
"help|h",
"log|l:s",
"mail|m=s",
+ "nobuild",
"verbose|v",
) || &print_help;
@@ -79,7 +81,10 @@ foreach (@spec)
if (m/^%define\s*mysql_version\s*(.*)/)
{
$VERSION= $1;
+ $VERSION_SRPM=$VERSION;
($MAJOR, $MINOR, $RELEASE)= split(/\./,$VERSION);
+ $VERSION_SRPM= $MAJOR . '.' . $MINOR . '.' . $RELEASE;
+ $VERSION_SRPM =~ s/\-\w+$//;
($RELEASE, $SUFFIX)= split(/\-/,$RELEASE);
$SUFFIX= "-" . $SUFFIX if ($SUFFIX);
}
@@ -143,60 +148,64 @@ chomp($SRCRPMDIR= `$RPM --eval "%{_srcrpmdir}" 2> /dev/null`);
$SOURCEFILE= glob "mysql*-$VERSION.tar.gz";
-&logger("Starting RPM build of MySQL-$VERSION on $HOST");
+unless($opt_nobuild) {
-foreach $file ($SOURCEFILE, $SPECFILE)
-{
- &abort("Unable to find $file!") unless (-f "$file");
-}
+ &logger("Starting RPM build of MySQL-$VERSION on $HOST");
+
+ foreach $file ($SOURCEFILE, $SPECFILE)
+ {
+ &abort("Unable to find $file!") unless (-f "$file");
+ }
#
# Install source and spec file
#
-&logger("Copying SOURCE and SPEC file to build directories.");
-unless ($opt_dry_run)
-{
- copy($SOURCEFILE, $SOURCEDIR)
- or &abort("Unable to copy $SOURCEFILE to $SOURCEDIR!");
- copy($SPECFILE, $SPECDIR)
- or &abort("Unable to copy $SPECFILE to $SPECDIR!");
-}
+ &logger("Copying SOURCE and SPEC file to build directories.");
+ unless ($opt_dry_run)
+ {
+ copy($SOURCEFILE, $SOURCEDIR)
+ or &abort("Unable to copy $SOURCEFILE to $SOURCEDIR!");
+ copy($SPECFILE, $SPECDIR)
+ or &abort("Unable to copy $SPECFILE to $SPECDIR!");
+ }
#
# Set environment variables - these are being used in the
# official MySQL RPM spec file
#
-&logger("Setting special build environment variables")
-if ($opt_cc) or ($opt_cflags) or ($opt_cxxflags) or ($opt_cxx);
-$ENV{MYSQL_BUILD_CC}=$opt_cc if ($opt_cc);
-$ENV{MYSQL_BUILD_CFLAGS}=$opt_cflags if ($opt_cflags);
-$ENV{MYSQL_BUILD_CXXFLAGS}=$opt_cxxflags if ($opt_cxxflags);
-$ENV{MYSQL_BUILD_CXX}=$opt_cxx if ($opt_cxx);
+ &logger("Setting special build environment variables")
+ if ($opt_cc) or ($opt_cflags) or ($opt_cxxflags) or ($opt_cxx);
+ $ENV{MYSQL_BUILD_CC}=$opt_cc if ($opt_cc);
+ $ENV{MYSQL_BUILD_CFLAGS}=$opt_cflags if ($opt_cflags);
+ $ENV{MYSQL_BUILD_CXXFLAGS}=$opt_cxxflags if ($opt_cxxflags);
+ $ENV{MYSQL_BUILD_CXX}=$opt_cxx if ($opt_cxx);
#
# Build the RPMs
#
-$command= "$RPM";
-$command.= " -v" if ($opt_verbose);
-$command.= " -ba";
-$command.= " --clean $RMSOURCE" if $opt_clean;
-$command.= " $SPECDIR/";
-$command.= basename($SPECFILE);
-&logger("Building RPM.");
-&run_command($command, "Error while building the RPMs!");
+ $command= "$RPM";
+ $command.= " -v" if ($opt_verbose);
+ $command.= " -ba";
+ $command.= " --clean $RMSOURCE" if $opt_clean;
+ $command.= " $SPECDIR/";
+ $command.= basename($SPECFILE);
+ &logger("Building RPM.");
+ &run_command($command, "Error while building the RPMs!");
+}
#
# Move the resulting RPMs into the pwd
#
$command= "mv";
$command.= " -v " if ($opt_verbose);
-$command.= " $SRCRPMDIR/MySQL*$VERSION*.src.rpm $PWD";
+$command.= " $SRCRPMDIR/MySQL*$VERSION_SRPM*.src.rpm $PWD";
&logger("Moving source RPM to current dir.");
&run_command($command, "Error moving source RPM!");
$command= "mv";
$command.= " -v " if ($opt_verbose);
-$command.= " $RPMDIR/$RPMARCH/MySQL*$VERSION*.$RPMARCH.rpm $PWD";
+# $command.= " $RPMDIR/$RPMARCH/MySQL*$VERSION*.$RPMARCH.rpm $PWD";
+$command.= " $RPMDIR/$RPMARCH/MySQL*$VERSION_SRPM*.$RPMARCH.rpm $PWD";
&logger("Moving binary RPMs to current dir.");
&run_command($command, "Error moving binary RPMs!");
diff --git a/Build-tools/my_md5sum b/Build-tools/my_md5sum
new file mode 100755
index 00000000000..20742ee2ed0
--- /dev/null
+++ b/Build-tools/my_md5sum
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+#
+# my_md5sum
+#
+# Script to clone the 'md5sum' command found on modern systems, since that
+# command is not always found on all systems.
+#
+# Use the "--help" option for more info!
+#
+# Written by Matt Wagner <matt@mysql.com>
+#
+use strict;
+use Digest::MD5;
+use Getopt::Long;
+
+my $VER= "1.1";
+
+#
+# Strip the leading path info off the program name ($0). We want 'my_md5sum'
+# not './my_md5sum'.
+#
+$0=~ s/^.*\/(.+)$/$1/;
+
+my ($opt_check, $opt_help)= undef;
+
+GetOptions(
+ "check|c" => \$opt_check,
+ "help|h" => \$opt_help,
+ ) || usage();
+
+#
+# Put all the [file1 file2 file3 ...]'s into an array
+#
+my @files = @ARGV;
+
+#
+# Give the "--help" text if:
+# - "--help|-h" was specified
+# - The number of files given as arguments is nil
+# - The "--check|-c" option is used with more than one [file] argument
+#
+usage() if $opt_help || $#files == -1 || ($opt_check && $#files > 0);
+
+# If "--check|-c", then go into checking
+if ($opt_check)
+{
+ open (CHECKFILE, $files[0]) or die "$files[0]: $!";
+
+ while (<CHECKFILE>)
+ {
+ #
+ # Goto the next line in the file if it does not match a typical
+ # digest line like:
+ #
+ # f1007efa2c72daa693981ec764cdeaca Bootstrap
+ #
+ next if $_!~ m/^([a-z0-9]{32})\s+(.+)$/;
+
+ # Collect the trappings from the above regex
+ my $checksum= $1;
+ my $checkfile= $2;
+
+ # Generate a fresh MD5 for the file in question
+ my $digest= &mkmd5($checkfile);
+
+ # Check the fresh MD5 against what is recorded in the file
+ # Print an error message if they don't match, else print OK
+ print "$checkfile: FAILED\n" if $digest ne $checksum;
+ print "$checkfile: OK\n" if $digest eq $checksum;
+ }
+}
+# Else generate the MD5 digest to STDOUT
+else
+{
+ foreach my $file (@files)
+ {
+ my $digest= &mkmd5($file);
+
+ print "$digest $file\n";
+ }
+}
+
+
+#
+# This routine generates the MD5 digest of a file
+#
+sub mkmd5
+{
+ my $file= shift;
+
+ open (FILE, $file) or die "$file: $!";
+ binmode(FILE);
+
+ my $digest= Digest::MD5->new->addfile(*FILE)->hexdigest;
+
+ close FILE;
+
+ return $digest;
+}
+
+#
+# Print the help text
+#
+sub usage
+{
+ print <<EOF;
+
+$0 version $VER by Matt Wagner <matt\@mysql.com>
+
+Usage:
+$0 [-c [file]] | [file1...]
+Generates or checks MD5 message digests.
+
+Options:
+-c, --check Check message digests (default is generate)
+-h, --help Display this text and exit
+
+The input for -c should be the list of message digests and file names that is
+printed on STDOUT by this program when it generates digests.
+
+EOF
+
+ exit(0);
+}
diff --git a/Build-tools/mysql-copyright b/Build-tools/mysql-copyright
index 004476ff92c..f2da3cdf447 100755
--- a/Build-tools/mysql-copyright
+++ b/Build-tools/mysql-copyright
@@ -12,15 +12,17 @@ use Getopt::Long;
$opt_help = 0;
$opt_version = 0;
+$opt_verbose = 0;
$opt_target = "mysql-copyright-target-";
$opt_target .= `date +%d%m%y-%H%M%S`;
chop $opt_target;
-GetOptions("help","version","target=s") || error();
+GetOptions("help","version","target=s", "verbose") || error();
# fix the directory prefix for target dir
$WD= cwd();
+my $win_flag = 0;
$opt_target= $WD . '/' . $opt_target;
&main();
@@ -50,6 +52,7 @@ sub main
for ($i=0; $ARGV[$i]; $i++)
{
my $distfile= $ARGV[$i];
+ $win_flag = ($distfile =~ /win-src/) ? 1 : 0;
my $dir;
$dir= "mysql-copyright-";
@@ -66,20 +69,19 @@ sub main
}
# if the distfile is mysql-3.22.22-alpha.tar.gz, then
# distname is 'mysql-3.22.22-alpha' and suffix '.tar.gz'
- if ($distfile =~ m/^($REG_BASENAME)([\-\_])
- ($REG_VERSION){1}([\.\-\+])
- (.*)?$/xo)
+ if ($distfile =~
+ m/^($REG_BASENAME)([\-\_])($REG_VERSION){1}([\.\-\+]\w+\-\w+)?[\.\-\+](.*)?$/xo)
{
$distname= $1.$2.$3;
- $suffix= $5.$6;
+ $suffix= $5;
+ $fileext = $6;
$newdistname= $1."com".$2.$3;
+ $newdistname .= $suffix if $win_flag;
}
# find out the extract path (should be same as distname!)
chomp($destdir= `tar ztf ../$distfile | head -1`);
# remove slash from the end
$destdir= substr($destdir, 0, -1);
- print "destdir: $destdir\n";
- print "distname: $distname\n";
if ("$destdir" ne "$distname")
{
@@ -100,45 +102,92 @@ sub main
# exist in the new mysql distributions, but let's be sure..
unlink("$destdir/PUBLIC", "$destdir/README");
copy("$WD/Docs/MySQLEULA.txt", "$destdir");
-
- # remove readline subdir and update configure accordingly
- system("rm -rf $destdir/cmd-line-utils/readline");
- unlink ("$destdir/configure") or die "Can't delete $destdir/configure: $!\n";
- `(cd $destdir ; sed -e 's!\ cmd-line-utils\/readline\/Makefile\ dnl!!g' < configure.in > configure.in.new)`;
- rename ("$destdir/configure.in.new","$destdir/configure.in") or die "Can't rename $destdir/configure.in.new: $!\n";;
- `(cd $destdir ; autoconf)`;
+
+ # remove readline, bdb subdirs and update 'configure'
+ my @extra_fat= ('bdb', 'cmd-line-utils/readline');
+
+ foreach my $fat (@extra_fat)
+ {
+ &trim_the_fat($fat);
+ }
# fix file copyrights
&fix_usage_copyright();
&add_copyright();
# rename the directory with new distribution name
+ chdir("$WD/$dir");
+ print "renaming $destdir $newdistname\n" if $opt_verbose;
rename($destdir, $newdistname);
# tar the new distribution
- `tar cz -f $opt_target/$newdistname.tar.gz *`;
+ `tar cz -f $WD/$newdistname.tar.gz $newdistname`;
$pec= $? >> 8;
abort($dir, "Making new tar archive failed!\n") if ($pec);
# remove temporary directory
- chdir "..";
- `rm -rf $dir/`;
+ chdir($WD) or print "$! Unable to move up one dir\n";
+ `cd $WD`;
+ my $cwd = getcwd();
+ print "current dir is $cwd\n" if $opt_verbose ;
+ if (-e $dir) {
+ print "Trying to delete $dir\n" if $opt_verbose;
+ if ( system("rm -rf $dir")){
+ print "$! Unable to delete $dir!\n";
+ }
+ }
}
exit(0);
}
####
+#### This function will remove unwanted parts of a src tree for the mysqlcom
+#### distributions.
+####
+sub trim_the_fat
+{
+ my $the_fat= shift;
+ my $cwd= getcwd();
+
+ system("rm -rf $destdir/${the_fat}");
+ if ($win_flag)
+ {
+ chdir("$destdir") or die "Unable to change directory to $destdir!: $!\n";
+ }
+ else
+ {
+ chdir("$destdir");
+ unlink ("configure") or die "Can't delete $destdir/configure: $!\n";
+ open(CONFIGURE,"<configure.in") or die "Unable to open configure.in for read: $!\n";
+ undef $/;
+ my $configure= <CONFIGURE>;
+ close(CONFIGURE);
+ $configure=~ s|${the_fat}/Makefile dnl\n?||g;
+ open(CONFIGURE,">configure.in") or die "Unable to open configure.in for write: $!\n";
+ print CONFIGURE $configure;
+ close(CONFIGURE);
+ `autoconf`;
+ die "'./configure' was not produced!" unless (-f "configure");
+ chdir("$cwd");
+ }
+}
+
+
+####
#### mysqld and MySQL client programs have a usage printed with --help.
#### This usage includes a copyright, which needs to be modified
####
-
sub fix_usage_copyright
{
- my @Cfiles = `find . -type f -name \"*.c*\"`;
- foreach my $Cfile (@Cfiles)
+ my $findlist = `find . -type f -name \"*.c*\"`;
+ my @files = split("\n", $findlist);
+ my $cwd = getcwd();
+
+ foreach my $file (@files)
{
- chop $Cfile;
- `replace "This is free software," "This is commercial software," "and you are welcome to modify and redistribute it under the GPL license" "please see the file MySQLEULA.txt for details" -- $Cfile`;
+ next if ! -f $file;
+ print "processing file $file in cwd $cwd\n" if $opt_verbose;
+ `replace "This is free software," "This is commercial software," "and you are welcome to modify and redistribute it under the GPL license" "please see the file MySQLEULA.txt for details" -- "$file"` ;
}
}
@@ -148,11 +197,16 @@ sub fix_usage_copyright
sub add_copyright
{
- my @files = `find . -type f -name "*"`;
+ my $findlist = `find . -type f -name "*"`;
+ my @files = split("\n", $findlist);
+ my $cwd = getcwd();
+
foreach my $file (@files)
{
- chop $file;
- `$WD/Build-tools/mysql-copyright-2 $file`;
+ next if ! -f $file;
+ next if -B $file;
+ print "processing file $file in cwd $cwd\n" if $opt_verbose;
+ `$WD/Build-tools/mysql-copyright-2 "$file"`;
}
}
diff --git a/Build-tools/mysql-copyright-2 b/Build-tools/mysql-copyright-2
index e946ed217d1..a1a870526da 100755
--- a/Build-tools/mysql-copyright-2
+++ b/Build-tools/mysql-copyright-2
@@ -89,6 +89,7 @@ sub add_copyright
elsif ($ARGV =~ /\.c$/ ||
$ARGV =~ /\.cc$/ ||
$ARGV =~ /\.h$/ ||
+ $ARGV =~ /\.cpp$/ ||
$ARGV =~ /\.yy$/)
{
$start_copyright="/* ";
diff --git a/Docs/manual_toc.html b/Docs/manual_toc.html
new file mode 100644
index 00000000000..b9014e5efb9
--- /dev/null
+++ b/Docs/manual_toc.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>Place holder for manual_toc.html</title>
+</head>
+<body>
+This is just a place holder for the autogenerated manual_toc.html
+to make "make dist" happy.
+</body>
+</html>
diff --git a/Makefile.am b/Makefile.am
index 4e4c2da8082..f8efb247c95 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,7 +24,7 @@ SUBDIRS = . include @docs_dirs@ \
@readline_topdir@ sql-common \
@thread_dirs@ pstack @sql_client_dirs@ \
@sql_server_dirs@ scripts man tests SSL\
- BUILD @netware_dir@ os2 @libmysqld_dirs@ \
+ BUILD netware os2 @libmysqld_dirs@ \
@bench_dirs@ support-files @fs_dirs@ @tools_dirs@
# Relink after clean
@@ -36,7 +36,7 @@ linked_sources = linked_client_sources linked_server_sources \
CLEANFILES = $(linked_sources)
# This is just so that the linking is done early.
-config.h: $(linked_sources)
+all-local: $(linked_sources)
linked_include_sources:
cd include; $(MAKE) link_sources
@@ -71,7 +71,8 @@ linked_server_sources:
cd sql; rm -f mini_client_errors.c;\
@LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c;\
rm -f pack.c;@LN_CP_F@ ../sql-common/pack.c pack.c;\
- rm -f client.c;@LN_CP_F@ ../sql-common/client.c client.c
+ rm -f client.c;@LN_CP_F@ ../sql-common/client.c client.c;\
+ rm -f my_time.c;@LN_CP_F@ ../sql-common/my_time.c my_time.c
echo timestamp > linked_server_sources
# Create permission databases
diff --git a/VC++Files/InstallShield/4.0.XX-classic/4.0.XX-classic.ipr b/VC++Files/InstallShield/4.0.XX-classic/4.0.XX-classic.ipr
deleted file mode 100755
index ef8404545fb..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/4.0.XX-classic.ipr
+++ /dev/null
@@ -1,51 +0,0 @@
-[Language]
-LanguageSupport0=0009
-
-[OperatingSystem]
-OSSupport=0000000000010010
-
-[Data]
-CurrentMedia=
-CurrentComponentDef=Default.cdf
-ProductName=MySQL Servers and Clients
-set_mifserial=
-DevEnvironment=Microsoft Visual C++ 6
-AppExe=
-set_dlldebug=No
-EmailAddresss=
-Instructions=Instructions.txt
-set_testmode=No
-set_mif=No
-SummaryText=
-Department=
-HomeURL=
-Author=
-Type=Database Application
-InstallRoot=D:\MySQL-Install\4.0.xcom-clas
-Version=1.00.000
-InstallationGUID=40744a4d-efed-4cff-84a9-9e6389550f5c
-set_level=Level 3
-CurrentFileGroupDef=Default.fdf
-Notes=Notes.txt
-set_maxerr=50
-set_args=
-set_miffile=Status.mif
-set_dllcmdline=
-Copyright=
-set_warnaserr=No
-CurrentPlatform=
-Category=
-set_preproc=
-CurrentLanguage=English
-CompanyName=MySQL
-Description=Description.txt
-set_maxwarn=50
-set_crc=Yes
-set_compileb4build=No
-
-[MediaInfo]
-
-[General]
-Type=INSTALLMAIN
-Version=1.10.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Component Definitions/Default.cdf b/VC++Files/InstallShield/4.0.XX-classic/Component Definitions/Default.cdf
deleted file mode 100755
index 48d37800cd1..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Component Definitions/Default.cdf
+++ /dev/null
@@ -1,192 +0,0 @@
-[Development]
-required0=Servers
-SELECTED=Yes
-FILENEED=STANDARD
-required1=Grant Tables
-HTTPLOCATION=
-STATUS=Examples, Libraries, Includes and Script files
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=Examples, Libraries, Includes and Script files
-DISPLAYTEXT=Examples, Libraries, Includes and Script files
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Development
-COMMENT=
-INCLUDEINBUILD=Yes
-INSTALLATION=ALWAYSOVERWRITE
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[Grant Tables]
-required0=Servers
-SELECTED=Yes
-FILENEED=CRITICAL
-HTTPLOCATION=
-STATUS=The Grant Tables and Core Files
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The Grant Tables and Core Files
-DISPLAYTEXT=The Grant Tables and Core Files
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Grant Tables
-requiredby0=Development
-COMMENT=
-INCLUDEINBUILD=Yes
-requiredby1=Clients and Tools
-INSTALLATION=NEVEROVERWRITE
-requiredby2=Documentation
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[Components]
-component0=Development
-component1=Grant Tables
-component2=Servers
-component3=Clients and Tools
-component4=Documentation
-
-[TopComponents]
-component0=Servers
-component1=Clients and Tools
-component2=Documentation
-component3=Development
-component4=Grant Tables
-
-[SetupType]
-setuptype0=Compact
-setuptype1=Typical
-setuptype2=Custom
-
-[Clients and Tools]
-required0=Servers
-SELECTED=Yes
-FILENEED=HIGHLYRECOMMENDED
-required1=Grant Tables
-HTTPLOCATION=
-STATUS=The MySQL clients and Maintenance Tools
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The MySQL clients and Maintenance Tools
-DISPLAYTEXT=The MySQL clients and Maintenance Tools
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Clients and Tools
-COMMENT=
-INCLUDEINBUILD=Yes
-INSTALLATION=NEWERDATE
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[Servers]
-SELECTED=Yes
-FILENEED=CRITICAL
-HTTPLOCATION=
-STATUS=The MySQL Servers
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The MySQL Servers
-DISPLAYTEXT=The MySQL Servers
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Servers
-requiredby0=Development
-COMMENT=
-INCLUDEINBUILD=Yes
-requiredby1=Grant Tables
-INSTALLATION=ALWAYSOVERWRITE
-requiredby2=Clients and Tools
-requiredby3=Documentation
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[SetupTypeItem-Compact]
-Comment=
-item0=Grant Tables
-item1=Servers
-item2=Clients and Tools
-item3=Documentation
-Descrip=
-DisplayText=
-
-[SetupTypeItem-Custom]
-Comment=
-item0=Development
-item1=Grant Tables
-item2=Servers
-item3=Clients and Tools
-Descrip=
-item4=Documentation
-DisplayText=
-
-[Info]
-Type=CompDef
-Version=1.00.000
-Name=
-
-[SetupTypeItem-Typical]
-Comment=
-item0=Development
-item1=Grant Tables
-item2=Servers
-item3=Clients and Tools
-Descrip=
-item4=Documentation
-DisplayText=
-
-[Documentation]
-required0=Servers
-SELECTED=Yes
-FILENEED=HIGHLYRECOMMENDED
-required1=Grant Tables
-HTTPLOCATION=
-STATUS=The MySQL Documentation with different formats
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The MySQL Documentation with different formats
-DISPLAYTEXT=The MySQL Documentation with different formats
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Documentation
-COMMENT=
-INCLUDEINBUILD=Yes
-INSTALLATION=ALWAYSOVERWRITE
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Component Definitions/Default.fgl b/VC++Files/InstallShield/4.0.XX-classic/Component Definitions/Default.fgl
deleted file mode 100755
index 4e20dcea4ab..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Component Definitions/Default.fgl
+++ /dev/null
@@ -1,42 +0,0 @@
-[<PROGRAMFILES>\<COMMONFILES>]
-DISPLAYTEXT=Common Files Folder
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[<WINDIR>\<WINSYSDIR>]
-DISPLAYTEXT=Windows System Folder
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[USERDEFINED]
-DISPLAYTEXT=Script-defined Folders
-TYPE=USERSTART
-fulldirectory=
-
-[<PROGRAMFILES>]
-DISPLAYTEXT=Program Files Folder
-SubDir0=<PROGRAMFILES>\<COMMONFILES>
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[<TARGETDIR>]
-DISPLAYTEXT=General Application Destination
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[<WINDIR>]
-DISPLAYTEXT=Windows Operating System
-SubDir0=<WINDIR>\<WINSYSDIR>
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[TopDir]
-SubDir0=<WINDIR>
-SubDir1=<PROGRAMFILES>
-SubDir2=<TARGETDIR>
-SubDir3=USERDEFINED
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Clients and Tools.fgl b/VC++Files/InstallShield/4.0.XX-classic/File Groups/Clients and Tools.fgl
deleted file mode 100755
index ed1e42e65b6..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Clients and Tools.fgl
+++ /dev/null
@@ -1,32 +0,0 @@
-[bin]
-file15=C:\mysql\bin\replace.exe
-file16=C:\mysql\bin\winmysqladmin.cnt
-file0=C:\mysql\bin\isamchk.exe
-file17=C:\mysql\bin\WINMYSQLADMIN.HLP
-file1=C:\mysql\bin\myisamchk.exe
-file18=C:\mysql\bin\comp-err.exe
-file2=C:\mysql\bin\myisamlog.exe
-file19=C:\mysql\bin\my_print_defaults.exe
-file3=C:\mysql\bin\myisampack.exe
-file4=C:\mysql\bin\mysql.exe
-file5=C:\mysql\bin\mysqladmin.exe
-file6=C:\mysql\bin\mysqlbinlog.exe
-file7=C:\mysql\bin\mysqlc.exe
-file8=C:\mysql\bin\mysqlcheck.exe
-file9=C:\mysql\bin\mysqldump.exe
-file20=C:\mysql\bin\winmysqladmin.exe
-file21=C:\mysql\bin\myisam_ftdump.exe
-file10=C:\mysql\bin\mysqlimport.exe
-fulldirectory=
-file11=C:\mysql\bin\mysqlshow.exe
-file12=C:\mysql\bin\mysqlwatch.exe
-file13=C:\mysql\bin\pack_isam.exe
-file14=C:\mysql\bin\perror.exe
-
-[TopDir]
-SubDir0=bin
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Default.fdf b/VC++Files/InstallShield/4.0.XX-classic/File Groups/Default.fdf
deleted file mode 100755
index 8096a4b74bf..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Default.fdf
+++ /dev/null
@@ -1,82 +0,0 @@
-[FileGroups]
-group0=Development
-group1=Grant Tables
-group2=Servers
-group3=Clients and Tools
-group4=Documentation
-
-[Development]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Grant Tables]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Clients and Tools]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=0000000000000000
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Servers]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Info]
-Type=FileGrp
-Version=1.00.000
-Name=
-
-[Documentation]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Development.fgl b/VC++Files/InstallShield/4.0.XX-classic/File Groups/Development.fgl
deleted file mode 100755
index f56c51fce05..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Development.fgl
+++ /dev/null
@@ -1,240 +0,0 @@
-[bench\Data\Wisconsin]
-file0=C:\mysql\bench\Data\Wisconsin\onek.data
-file1=C:\mysql\bench\Data\Wisconsin\tenk.data
-fulldirectory=
-
-[lib\debug]
-file0=C:\mysql\lib\debug\libmySQL.dll
-file1=C:\mysql\lib\debug\libmySQL.lib
-file2=C:\mysql\lib\debug\mysqlclient.lib
-file3=C:\mysql\lib\debug\zlib.lib
-file4=C:\mysql\lib\debug\mysys.lib
-file5=C:\mysql\lib\debug\regex.lib
-file6=C:\mysql\lib\debug\strings.lib
-fulldirectory=
-
-[bench\output]
-fulldirectory=
-
-[examples\libmysqltest]
-file0=C:\mysql\examples\libmysqltest\myTest.c
-file1=C:\mysql\examples\libmysqltest\myTest.dsp
-file2=C:\mysql\examples\libmysqltest\myTest.dsw
-file3=C:\mysql\examples\libmysqltest\myTest.exe
-file4=C:\mysql\examples\libmysqltest\myTest.mak
-file5=C:\mysql\examples\libmysqltest\myTest.ncb
-file6=C:\mysql\examples\libmysqltest\myTest.opt
-file7=C:\mysql\examples\libmysqltest\readme
-fulldirectory=
-
-[include]
-file15=C:\mysql\include\libmysqld.def
-file16=C:\mysql\include\my_alloc.h
-file0=C:\mysql\include\raid.h
-file17=C:\mysql\include\my_getopt.h
-file1=C:\mysql\include\errmsg.h
-file2=C:\mysql\include\Libmysql.def
-file3=C:\mysql\include\m_ctype.h
-file4=C:\mysql\include\m_string.h
-file5=C:\mysql\include\my_list.h
-file6=C:\mysql\include\my_pthread.h
-file7=C:\mysql\include\my_sys.h
-file8=C:\mysql\include\mysql.h
-file9=C:\mysql\include\mysql_com.h
-file10=C:\mysql\include\mysql_version.h
-fulldirectory=
-file11=C:\mysql\include\mysqld_error.h
-file12=C:\mysql\include\dbug.h
-file13=C:\mysql\include\config-win.h
-file14=C:\mysql\include\my_global.h
-
-[examples]
-SubDir0=examples\libmysqltest
-SubDir1=examples\tests
-fulldirectory=
-
-[lib\opt]
-file0=C:\mysql\lib\opt\libmySQL.dll
-file1=C:\mysql\lib\opt\libmySQL.lib
-file2=C:\mysql\lib\opt\mysqlclient.lib
-file3=C:\mysql\lib\opt\zlib.lib
-file4=C:\mysql\lib\opt\mysys.lib
-file5=C:\mysql\lib\opt\regex.lib
-file6=C:\mysql\lib\opt\strings.lib
-fulldirectory=
-
-[bench\Data]
-SubDir0=bench\Data\ATIS
-SubDir1=bench\Data\Wisconsin
-fulldirectory=
-
-[bench\limits]
-file15=C:\mysql\bench\limits\pg.comment
-file16=C:\mysql\bench\limits\solid.cfg
-file0=C:\mysql\bench\limits\access.cfg
-file17=C:\mysql\bench\limits\solid-nt4.cfg
-file1=C:\mysql\bench\limits\access.comment
-file18=C:\mysql\bench\limits\sybase.cfg
-file2=C:\mysql\bench\limits\Adabas.cfg
-file3=C:\mysql\bench\limits\Adabas.comment
-file4=C:\mysql\bench\limits\Db2.cfg
-file5=C:\mysql\bench\limits\empress.cfg
-file6=C:\mysql\bench\limits\empress.comment
-file7=C:\mysql\bench\limits\Informix.cfg
-file8=C:\mysql\bench\limits\Informix.comment
-file9=C:\mysql\bench\limits\msql.cfg
-file10=C:\mysql\bench\limits\ms-sql.cfg
-fulldirectory=
-file11=C:\mysql\bench\limits\Ms-sql65.cfg
-file12=C:\mysql\bench\limits\mysql.cfg
-file13=C:\mysql\bench\limits\oracle.cfg
-file14=C:\mysql\bench\limits\pg.cfg
-
-[TopDir]
-SubDir0=bench
-SubDir1=examples
-SubDir2=include
-SubDir3=lib
-SubDir4=scripts
-
-[bench]
-file15=C:\mysql\bench\test-create
-file16=C:\mysql\bench\test-insert
-file0=C:\mysql\bench\uname.bat
-file17=C:\mysql\bench\test-select
-file1=C:\mysql\bench\compare-results
-file18=C:\mysql\bench\test-wisconsin
-file2=C:\mysql\bench\copy-db
-file19=C:\mysql\bench\bench-init.pl
-file3=C:\mysql\bench\crash-me
-file4=C:\mysql\bench\example.bat
-file5=C:\mysql\bench\print-limit-table
-file6=C:\mysql\bench\pwd.bat
-file7=C:\mysql\bench\Readme
-SubDir0=bench\Data
-file8=C:\mysql\bench\run.bat
-SubDir1=bench\limits
-file9=C:\mysql\bench\run-all-tests
-SubDir2=bench\output
-file10=C:\mysql\bench\server-cfg
-fulldirectory=
-file11=C:\mysql\bench\test-alter-table
-file12=C:\mysql\bench\test-ATIS
-file13=C:\mysql\bench\test-big-tables
-file14=C:\mysql\bench\test-connect
-
-[examples\tests]
-file15=C:\mysql\examples\tests\lock_test.res
-file16=C:\mysql\examples\tests\mail_to_db.pl
-file0=C:\mysql\examples\tests\unique_users.tst
-file17=C:\mysql\examples\tests\table_types.pl
-file1=C:\mysql\examples\tests\auto_increment.tst
-file18=C:\mysql\examples\tests\test_delayed_insert.pl
-file2=C:\mysql\examples\tests\big_record.pl
-file19=C:\mysql\examples\tests\udf_test
-file3=C:\mysql\examples\tests\big_record.res
-file4=C:\mysql\examples\tests\czech-sorting
-file5=C:\mysql\examples\tests\deadlock-script.pl
-file6=C:\mysql\examples\tests\export.pl
-file7=C:\mysql\examples\tests\fork_test.pl
-file8=C:\mysql\examples\tests\fork2_test.pl
-file9=C:\mysql\examples\tests\fork3_test.pl
-file20=C:\mysql\examples\tests\udf_test.res
-file21=C:\mysql\examples\tests\auto_increment.res
-file10=C:\mysql\examples\tests\function.res
-fulldirectory=
-file11=C:\mysql\examples\tests\function.tst
-file12=C:\mysql\examples\tests\grant.pl
-file13=C:\mysql\examples\tests\grant.res
-file14=C:\mysql\examples\tests\lock_test.pl
-
-[bench\Data\ATIS]
-file26=C:\mysql\bench\Data\ATIS\stop1.txt
-file15=C:\mysql\bench\Data\ATIS\flight_class.txt
-file27=C:\mysql\bench\Data\ATIS\time_interval.txt
-file16=C:\mysql\bench\Data\ATIS\flight_day.txt
-file0=C:\mysql\bench\Data\ATIS\transport.txt
-file28=C:\mysql\bench\Data\ATIS\time_zone.txt
-file17=C:\mysql\bench\Data\ATIS\flight_fare.txt
-file1=C:\mysql\bench\Data\ATIS\airline.txt
-file29=C:\mysql\bench\Data\ATIS\aircraft.txt
-file18=C:\mysql\bench\Data\ATIS\food_service.txt
-file2=C:\mysql\bench\Data\ATIS\airport.txt
-file19=C:\mysql\bench\Data\ATIS\ground_service.txt
-file3=C:\mysql\bench\Data\ATIS\airport_service.txt
-file4=C:\mysql\bench\Data\ATIS\city.txt
-file5=C:\mysql\bench\Data\ATIS\class_of_service.txt
-file6=C:\mysql\bench\Data\ATIS\code_description.txt
-file7=C:\mysql\bench\Data\ATIS\compound_class.txt
-file8=C:\mysql\bench\Data\ATIS\connect_leg.txt
-file9=C:\mysql\bench\Data\ATIS\date_day.txt
-file20=C:\mysql\bench\Data\ATIS\month_name.txt
-file21=C:\mysql\bench\Data\ATIS\restrict_carrier.txt
-file10=C:\mysql\bench\Data\ATIS\day_name.txt
-fulldirectory=
-file22=C:\mysql\bench\Data\ATIS\restrict_class.txt
-file11=C:\mysql\bench\Data\ATIS\dual_carrier.txt
-file23=C:\mysql\bench\Data\ATIS\restriction.txt
-file12=C:\mysql\bench\Data\ATIS\fare.txt
-file24=C:\mysql\bench\Data\ATIS\state.txt
-file13=C:\mysql\bench\Data\ATIS\fconnection.txt
-file25=C:\mysql\bench\Data\ATIS\stop.txt
-file14=C:\mysql\bench\Data\ATIS\flight.txt
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
-[scripts]
-file37=C:\mysql\scripts\mysqld_safe-watch.sh
-file26=C:\mysql\scripts\mysql_zap
-file15=C:\mysql\scripts\mysql_fix_privilege_tables
-file38=C:\mysql\scripts\mysqldumpslow
-file27=C:\mysql\scripts\mysql_zap.sh
-file16=C:\mysql\scripts\mysql_fix_privilege_tables.sh
-file0=C:\mysql\scripts\Readme
-file39=C:\mysql\scripts\mysqldumpslow.sh
-file28=C:\mysql\scripts\mysqlaccess
-file17=C:\mysql\scripts\mysql_install_db
-file1=C:\mysql\scripts\make_binary_distribution.sh
-file29=C:\mysql\scripts\mysqlaccess.conf
-file18=C:\mysql\scripts\mysql_install_db.sh
-file2=C:\mysql\scripts\msql2mysql
-file19=C:\mysql\scripts\mysql_secure_installation
-file3=C:\mysql\scripts\msql2mysql.sh
-file4=C:\mysql\scripts\mysql_config
-file5=C:\mysql\scripts\mysql_config.sh
-file6=C:\mysql\scripts\mysql_convert_table_format
-file7=C:\mysql\scripts\mysql_convert_table_format.sh
-file40=C:\mysql\scripts\mysqlhotcopy
-file8=C:\mysql\scripts\mysql_explain_log
-file41=C:\mysql\scripts\mysqlhotcopy.pl
-file30=C:\mysql\scripts\mysqlaccess.sh
-file9=C:\mysql\scripts\mysql_explain_log.sh
-file42=C:\mysql\scripts\mysqlhotcopy.sh
-file31=C:\mysql\scripts\mysqlbug
-file20=C:\mysql\scripts\mysql_secure_installation.sh
-file43=C:\mysql\scripts\make_binary_distribution
-file32=C:\mysql\scripts\mysqlbug.sh
-file21=C:\mysql\scripts\mysql_setpermission
-file10=C:\mysql\scripts\mysql_find_rows
-fulldirectory=
-file44=C:\mysql\scripts\mysql_fix_privilege_tables.sql
-file33=C:\mysql\scripts\mysqld_multi
-file22=C:\mysql\scripts\mysql_setpermission.pl
-file11=C:\mysql\scripts\mysql_find_rows.pl
-file34=C:\mysql\scripts\mysqld_multi.sh
-file23=C:\mysql\scripts\mysql_setpermission.sh
-file12=C:\mysql\scripts\mysql_find_rows.sh
-file35=C:\mysql\scripts\mysqld_safe
-file24=C:\mysql\scripts\mysql_tableinfo
-file13=C:\mysql\scripts\mysql_fix_extensions
-file36=C:\mysql\scripts\mysqld_safe.sh
-file25=C:\mysql\scripts\mysql_tableinfo.sh
-file14=C:\mysql\scripts\mysql_fix_extensions.sh
-
-[lib]
-SubDir0=lib\debug
-SubDir1=lib\opt
-fulldirectory=
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Documentation.fgl b/VC++Files/InstallShield/4.0.XX-classic/File Groups/Documentation.fgl
deleted file mode 100755
index 80fe777cf0f..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Documentation.fgl
+++ /dev/null
@@ -1,99 +0,0 @@
-[Docs\Flags]
-file59=C:\mysql\Docs\Flags\romania.gif
-file48=C:\mysql\Docs\Flags\kroatia.eps
-file37=C:\mysql\Docs\Flags\iceland.gif
-file26=C:\mysql\Docs\Flags\france.eps
-file15=C:\mysql\Docs\Flags\china.gif
-file49=C:\mysql\Docs\Flags\kroatia.gif
-file38=C:\mysql\Docs\Flags\ireland.eps
-file27=C:\mysql\Docs\Flags\france.gif
-file16=C:\mysql\Docs\Flags\croatia.eps
-file0=C:\mysql\Docs\Flags\usa.gif
-file39=C:\mysql\Docs\Flags\ireland.gif
-file28=C:\mysql\Docs\Flags\germany.eps
-file17=C:\mysql\Docs\Flags\croatia.gif
-file1=C:\mysql\Docs\Flags\argentina.gif
-file29=C:\mysql\Docs\Flags\germany.gif
-file18=C:\mysql\Docs\Flags\czech-republic.eps
-file2=C:\mysql\Docs\Flags\australia.eps
-file19=C:\mysql\Docs\Flags\czech-republic.gif
-file3=C:\mysql\Docs\Flags\australia.gif
-file80=C:\mysql\Docs\Flags\usa.eps
-file4=C:\mysql\Docs\Flags\austria.eps
-file81=C:\mysql\Docs\Flags\argentina.eps
-file70=C:\mysql\Docs\Flags\spain.eps
-file5=C:\mysql\Docs\Flags\austria.gif
-file71=C:\mysql\Docs\Flags\spain.gif
-file60=C:\mysql\Docs\Flags\russia.eps
-file6=C:\mysql\Docs\Flags\brazil.eps
-file72=C:\mysql\Docs\Flags\sweden.eps
-file61=C:\mysql\Docs\Flags\russia.gif
-file50=C:\mysql\Docs\Flags\latvia.eps
-file7=C:\mysql\Docs\Flags\brazil.gif
-file73=C:\mysql\Docs\Flags\sweden.gif
-file62=C:\mysql\Docs\Flags\singapore.eps
-file51=C:\mysql\Docs\Flags\latvia.gif
-file40=C:\mysql\Docs\Flags\island.eps
-file8=C:\mysql\Docs\Flags\bulgaria.eps
-file74=C:\mysql\Docs\Flags\switzerland.eps
-file63=C:\mysql\Docs\Flags\singapore.gif
-file52=C:\mysql\Docs\Flags\netherlands.eps
-file41=C:\mysql\Docs\Flags\island.gif
-file30=C:\mysql\Docs\Flags\great-britain.eps
-file9=C:\mysql\Docs\Flags\bulgaria.gif
-file75=C:\mysql\Docs\Flags\switzerland.gif
-file64=C:\mysql\Docs\Flags\south-africa.eps
-file53=C:\mysql\Docs\Flags\netherlands.gif
-file42=C:\mysql\Docs\Flags\israel.eps
-file31=C:\mysql\Docs\Flags\great-britain.gif
-file20=C:\mysql\Docs\Flags\denmark.eps
-file76=C:\mysql\Docs\Flags\taiwan.eps
-file65=C:\mysql\Docs\Flags\south-africa.gif
-file54=C:\mysql\Docs\Flags\poland.eps
-file43=C:\mysql\Docs\Flags\israel.gif
-file32=C:\mysql\Docs\Flags\greece.eps
-file21=C:\mysql\Docs\Flags\denmark.gif
-file10=C:\mysql\Docs\Flags\canada.eps
-fulldirectory=
-file77=C:\mysql\Docs\Flags\taiwan.gif
-file66=C:\mysql\Docs\Flags\south-africa1.eps
-file55=C:\mysql\Docs\Flags\poland.gif
-file44=C:\mysql\Docs\Flags\italy.eps
-file33=C:\mysql\Docs\Flags\greece.gif
-file22=C:\mysql\Docs\Flags\estonia.eps
-file11=C:\mysql\Docs\Flags\canada.gif
-file78=C:\mysql\Docs\Flags\ukraine.eps
-file67=C:\mysql\Docs\Flags\south-africa1.gif
-file56=C:\mysql\Docs\Flags\portugal.eps
-file45=C:\mysql\Docs\Flags\italy.gif
-file34=C:\mysql\Docs\Flags\hungary.eps
-file23=C:\mysql\Docs\Flags\estonia.gif
-file12=C:\mysql\Docs\Flags\chile.eps
-file79=C:\mysql\Docs\Flags\ukraine.gif
-file68=C:\mysql\Docs\Flags\south-korea.eps
-file57=C:\mysql\Docs\Flags\portugal.gif
-file46=C:\mysql\Docs\Flags\japan.eps
-file35=C:\mysql\Docs\Flags\hungary.gif
-file24=C:\mysql\Docs\Flags\finland.eps
-file13=C:\mysql\Docs\Flags\chile.gif
-file69=C:\mysql\Docs\Flags\south-korea.gif
-file58=C:\mysql\Docs\Flags\romania.eps
-file47=C:\mysql\Docs\Flags\japan.gif
-file36=C:\mysql\Docs\Flags\iceland.eps
-file25=C:\mysql\Docs\Flags\finland.gif
-file14=C:\mysql\Docs\Flags\china.eps
-
-[Docs]
-file0=C:\mysql\Docs\manual_toc.html
-file1=C:\mysql\Docs\manual.html
-file2=C:\mysql\Docs\manual.txt
-SubDir0=Docs\Flags
-fulldirectory=
-
-[TopDir]
-SubDir0=Docs
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Grant Tables.fgl b/VC++Files/InstallShield/4.0.XX-classic/File Groups/Grant Tables.fgl
deleted file mode 100755
index 178065a7003..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Grant Tables.fgl
+++ /dev/null
@@ -1,36 +0,0 @@
-[data\test]
-fulldirectory=
-
-[data\mysql]
-file15=C:\mysql\data\mysql\func.frm
-file16=C:\mysql\data\mysql\func.MYD
-file0=C:\mysql\data\mysql\columns_priv.frm
-file17=C:\mysql\data\mysql\func.MYI
-file1=C:\mysql\data\mysql\columns_priv.MYD
-file2=C:\mysql\data\mysql\columns_priv.MYI
-file3=C:\mysql\data\mysql\db.frm
-file4=C:\mysql\data\mysql\db.MYD
-file5=C:\mysql\data\mysql\db.MYI
-file6=C:\mysql\data\mysql\host.frm
-file7=C:\mysql\data\mysql\host.MYD
-file8=C:\mysql\data\mysql\host.MYI
-file9=C:\mysql\data\mysql\tables_priv.frm
-file10=C:\mysql\data\mysql\tables_priv.MYD
-fulldirectory=
-file11=C:\mysql\data\mysql\tables_priv.MYI
-file12=C:\mysql\data\mysql\user.frm
-file13=C:\mysql\data\mysql\user.MYD
-file14=C:\mysql\data\mysql\user.MYI
-
-[TopDir]
-SubDir0=data
-
-[data]
-SubDir0=data\mysql
-SubDir1=data\test
-fulldirectory=
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Servers.fgl b/VC++Files/InstallShield/4.0.XX-classic/File Groups/Servers.fgl
deleted file mode 100755
index 8a626c56253..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/File Groups/Servers.fgl
+++ /dev/null
@@ -1,227 +0,0 @@
-[Embedded\Static\release]
-file0=C:\mysql\embedded\Static\release\test_stc.dsp
-file1=C:\mysql\embedded\Static\release\ReadMe.txt
-file2=C:\mysql\embedded\Static\release\StdAfx.cpp
-file3=C:\mysql\embedded\Static\release\StdAfx.h
-file4=C:\mysql\embedded\Static\release\test_stc.cpp
-file5=C:\mysql\embedded\Static\release\mysqlserver.lib
-fulldirectory=
-
-[share\polish]
-file0=C:\mysql\share\polish\errmsg.sys
-file1=C:\mysql\share\polish\errmsg.txt
-fulldirectory=
-
-[share\dutch]
-file0=C:\mysql\share\dutch\errmsg.sys
-file1=C:\mysql\share\dutch\errmsg.txt
-fulldirectory=
-
-[share\spanish]
-file0=C:\mysql\share\spanish\errmsg.sys
-file1=C:\mysql\share\spanish\errmsg.txt
-fulldirectory=
-
-[share\english]
-file0=C:\mysql\share\english\errmsg.sys
-file1=C:\mysql\share\english\errmsg.txt
-fulldirectory=
-
-[bin]
-file0=C:\mysql\bin\mysqld-opt.exe
-file1=C:\mysql\bin\mysqld-nt.exe
-file2=C:\mysql\bin\mysqld.exe
-file3=C:\mysql\bin\cygwinb19.dll
-file4=C:\mysql\bin\libmySQL.dll
-fulldirectory=
-
-[share\korean]
-file0=C:\mysql\share\korean\errmsg.sys
-file1=C:\mysql\share\korean\errmsg.txt
-fulldirectory=
-
-[share\charsets]
-file15=C:\mysql\share\charsets\latin1.conf
-file16=C:\mysql\share\charsets\latin2.conf
-file0=C:\mysql\share\charsets\win1251ukr.conf
-file17=C:\mysql\share\charsets\latin5.conf
-file1=C:\mysql\share\charsets\cp1257.conf
-file18=C:\mysql\share\charsets\Readme
-file2=C:\mysql\share\charsets\croat.conf
-file19=C:\mysql\share\charsets\swe7.conf
-file3=C:\mysql\share\charsets\danish.conf
-file4=C:\mysql\share\charsets\dec8.conf
-file5=C:\mysql\share\charsets\dos.conf
-file6=C:\mysql\share\charsets\estonia.conf
-file7=C:\mysql\share\charsets\german1.conf
-file8=C:\mysql\share\charsets\greek.conf
-file9=C:\mysql\share\charsets\hebrew.conf
-file20=C:\mysql\share\charsets\usa7.conf
-file21=C:\mysql\share\charsets\win1250.conf
-file10=C:\mysql\share\charsets\hp8.conf
-fulldirectory=
-file22=C:\mysql\share\charsets\win1251.conf
-file11=C:\mysql\share\charsets\hungarian.conf
-file23=C:\mysql\share\charsets\cp1251.conf
-file12=C:\mysql\share\charsets\Index
-file13=C:\mysql\share\charsets\koi8_ru.conf
-file14=C:\mysql\share\charsets\koi8_ukr.conf
-
-[Embedded\DLL\debug]
-file0=C:\mysql\embedded\DLL\debug\libmysqld.dll
-file1=C:\mysql\embedded\DLL\debug\libmysqld.exp
-file2=C:\mysql\embedded\DLL\debug\libmysqld.lib
-fulldirectory=
-
-[Embedded]
-file0=C:\mysql\embedded\embedded.dsw
-SubDir0=Embedded\DLL
-SubDir1=Embedded\Static
-fulldirectory=
-
-[share\ukrainian]
-file0=C:\mysql\share\ukrainian\errmsg.sys
-file1=C:\mysql\share\ukrainian\errmsg.txt
-fulldirectory=
-
-[share\hungarian]
-file0=C:\mysql\share\hungarian\errmsg.sys
-file1=C:\mysql\share\hungarian\errmsg.txt
-fulldirectory=
-
-[share\german]
-file0=C:\mysql\share\german\errmsg.sys
-file1=C:\mysql\share\german\errmsg.txt
-fulldirectory=
-
-[share\portuguese]
-file0=C:\mysql\share\portuguese\errmsg.sys
-file1=C:\mysql\share\portuguese\errmsg.txt
-fulldirectory=
-
-[share\estonian]
-file0=C:\mysql\share\estonian\errmsg.sys
-file1=C:\mysql\share\estonian\errmsg.txt
-fulldirectory=
-
-[share\romanian]
-file0=C:\mysql\share\romanian\errmsg.sys
-file1=C:\mysql\share\romanian\errmsg.txt
-fulldirectory=
-
-[share\french]
-file0=C:\mysql\share\french\errmsg.sys
-file1=C:\mysql\share\french\errmsg.txt
-fulldirectory=
-
-[share\swedish]
-file0=C:\mysql\share\swedish\errmsg.sys
-file1=C:\mysql\share\swedish\errmsg.txt
-fulldirectory=
-
-[share\slovak]
-file0=C:\mysql\share\slovak\errmsg.sys
-file1=C:\mysql\share\slovak\errmsg.txt
-fulldirectory=
-
-[share\greek]
-file0=C:\mysql\share\greek\errmsg.sys
-file1=C:\mysql\share\greek\errmsg.txt
-fulldirectory=
-
-[TopDir]
-file0=C:\mysql\my-huge.cnf
-file1=C:\mysql\my-large.cnf
-file2=C:\mysql\my-medium.cnf
-file3=C:\mysql\my-small.cnf
-file4=C:\mysql\MySQLEULA.txt
-file5=C:\mysql\README.txt
-SubDir0=bin
-SubDir1=share
-SubDir2=Embedded
-
-[share]
-SubDir8=share\hungarian
-SubDir9=share\charsets
-SubDir20=share\spanish
-SubDir21=share\swedish
-SubDir10=share\italian
-SubDir22=share\ukrainian
-SubDir11=share\japanese
-SubDir12=share\korean
-SubDir13=share\norwegian
-SubDir14=share\norwegian-ny
-SubDir15=share\polish
-SubDir16=share\portuguese
-SubDir0=share\czech
-SubDir17=share\romanian
-SubDir1=share\danish
-SubDir18=share\russian
-SubDir2=share\dutch
-SubDir19=share\slovak
-SubDir3=share\english
-fulldirectory=
-SubDir4=share\estonian
-SubDir5=share\french
-SubDir6=share\german
-SubDir7=share\greek
-
-[share\norwegian-ny]
-file0=C:\mysql\share\norwegian-ny\errmsg.sys
-file1=C:\mysql\share\norwegian-ny\errmsg.txt
-fulldirectory=
-
-[Embedded\DLL]
-file0=C:\mysql\embedded\DLL\test_dll.dsp
-file1=C:\mysql\embedded\DLL\StdAfx.h
-file2=C:\mysql\embedded\DLL\test_dll.cpp
-file3=C:\mysql\embedded\DLL\StdAfx.cpp
-SubDir0=Embedded\DLL\debug
-SubDir1=Embedded\DLL\release
-fulldirectory=
-
-[Embedded\Static]
-SubDir0=Embedded\Static\release
-fulldirectory=
-
-[Embedded\DLL\release]
-file0=C:\mysql\embedded\DLL\release\libmysqld.dll
-file1=C:\mysql\embedded\DLL\release\libmysqld.exp
-file2=C:\mysql\embedded\DLL\release\libmysqld.lib
-file3=C:\mysql\embedded\DLL\release\mysql-server.exe
-fulldirectory=
-
-[share\danish]
-file0=C:\mysql\share\danish\errmsg.sys
-file1=C:\mysql\share\danish\errmsg.txt
-fulldirectory=
-
-[share\czech]
-file0=C:\mysql\share\czech\errmsg.sys
-file1=C:\mysql\share\czech\errmsg.txt
-fulldirectory=
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
-[share\russian]
-file0=C:\mysql\share\russian\errmsg.sys
-file1=C:\mysql\share\russian\errmsg.txt
-fulldirectory=
-
-[share\norwegian]
-file0=C:\mysql\share\norwegian\errmsg.sys
-file1=C:\mysql\share\norwegian\errmsg.txt
-fulldirectory=
-
-[share\japanese]
-file0=C:\mysql\share\japanese\errmsg.sys
-file1=C:\mysql\share\japanese\errmsg.txt
-fulldirectory=
-
-[share\italian]
-file0=C:\mysql\share\italian\errmsg.sys
-file1=C:\mysql\share\italian\errmsg.txt
-fulldirectory=
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Registry Entries/Default.rge b/VC++Files/InstallShield/4.0.XX-classic/Registry Entries/Default.rge
deleted file mode 100755
index 537dfd82e48..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Registry Entries/Default.rge
+++ /dev/null
@@ -1,4 +0,0 @@
-[General]
-Type=REGISTRYDATA
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.dbg b/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.dbg
deleted file mode 100755
index 0c6d4e6b708..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.dbg
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.ino b/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.ino
deleted file mode 100755
index 204d8ea0f36..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.ino
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.ins b/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.ins
deleted file mode 100755
index 759009b5c84..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.ins
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.obs b/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.obs
deleted file mode 100755
index 5fcfcb62c4e..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.obs
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.rul.old b/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.rul.old
deleted file mode 100755
index df143b493c4..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Script Files/Setup.rul.old
+++ /dev/null
@@ -1,640 +0,0 @@
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// IIIIIII SSSSSS
-// II SS InstallShield (R)
-// II SSSSSS (c) 1996-1997, InstallShield Software Corporation
-// II SS (c) 1990-1996, InstallShield Corporation
-// IIIIIII SSSSSS All Rights Reserved.
-//
-//
-// This code is generated as a starting setup template. You should
-// modify it to provide all necessary steps for your setup.
-//
-//
-// File Name: Setup.rul
-//
-// Description: InstallShield script
-//
-// Comments: This template script performs a basic setup on a
-// Windows 95 or Windows NT 4.0 platform. With minor
-// modifications, this template can be adapted to create
-// new, customized setups.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
- // Include header file
-#include "sdlang.h"
-#include "sddialog.h"
-
-////////////////////// string defines ////////////////////////////
-
-#define UNINST_LOGFILE_NAME "Uninst.isu"
-
-//////////////////// installation declarations ///////////////////
-
- // ----- DLL prototypes -----
-
-
- // your DLL prototypes
-
-
- // ---- script prototypes -----
-
- // generated
- prototype ShowDialogs();
- prototype MoveFileData();
- prototype HandleMoveDataError( NUMBER );
- prototype ProcessBeforeDataMove();
- prototype ProcessAfterDataMove();
- prototype SetupRegistry();
- prototype SetupFolders();
- prototype CleanUpInstall();
- prototype SetupInstall();
- prototype SetupScreen();
- prototype CheckRequirements();
- prototype DialogShowSdWelcome();
- prototype DialogShowSdShowInfoList();
- prototype DialogShowSdAskDestPath();
- prototype DialogShowSdSetupType();
- prototype DialogShowSdComponentDialog2();
- prototype DialogShowSdFinishReboot();
-
- // your prototypes
-
-
- // ----- global variables ------
-
- // generated
- BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
- STRING svDir;
- STRING svName, svCompany, svSerial;
- STRING szAppPath;
- STRING svSetupType;
-
-
- // your global variables
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// MAIN PROGRAM
-//
-// The setup begins here by hiding the visible setup
-// window. This is done to allow all the titles, images, etc. to
-// be established before showing the main window. The following
-// logic then performs the setup in a series of steps.
-//
-///////////////////////////////////////////////////////////////////////////////
-program
- Disable( BACKGROUND );
-
- CheckRequirements();
-
- SetupInstall();
-
- SetupScreen();
-
- if (ShowDialogs()<0) goto end_install;
-
- if (ProcessBeforeDataMove()<0) goto end_install;
-
- if (MoveFileData()<0) goto end_install;
-
- if (ProcessAfterDataMove()<0) goto end_install;
-
- if (SetupRegistry()<0) goto end_install;
-
- if (SetupFolders()<0) goto end_install;
-
-
- end_install:
-
- CleanUpInstall();
-
- // If an unrecoverable error occurred, clean up the partial installation.
- // Otherwise, exit normally.
-
- if (bInstallAborted) then
- abort;
- endif;
-
-endprogram
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ShowDialogs //
-// //
-// Purpose: This function manages the display and navigation //
-// the standard dialogs that exist in a setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ShowDialogs()
- NUMBER nResult;
- begin
-
- Dlg_Start:
- // beginning of dialogs label
-
- Dlg_SdWelcome:
- nResult = DialogShowSdWelcome();
- if (nResult = BACK) goto Dlg_Start;
-
- Dlg_SdShowInfoList:
- nResult = DialogShowSdShowInfoList();
- if (nResult = BACK) goto Dlg_SdWelcome;
-
- Dlg_SdAskDestPath:
- nResult = DialogShowSdAskDestPath();
- if (nResult = BACK) goto Dlg_SdShowInfoList;
-
- Dlg_SdSetupType:
- nResult = DialogShowSdSetupType();
- if (nResult = BACK) goto Dlg_SdAskDestPath;
-
- Dlg_SdComponentDialog2:
- if ((nResult = BACK) && (svSetupType != "Custom") && (svSetupType != "")) then
- goto Dlg_SdSetupType;
- endif;
- nResult = DialogShowSdComponentDialog2();
- if (nResult = BACK) goto Dlg_SdSetupType;
-
- return 0;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessBeforeDataMove //
-// //
-// Purpose: This function performs any necessary operations prior to the //
-// actual data move operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessBeforeDataMove()
- STRING svLogFile;
- NUMBER nResult;
- begin
-
- InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
-
- svLogFile = UNINST_LOGFILE_NAME;
-
- nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
- if (nResult < 0) then
- MessageBox( @ERROR_UNINSTSETUP, WARNING );
- endif;
-
- szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir
-
- if ((bIs32BitSetup) && (bIsShellExplorer)) then
- RegDBSetItem( REGDB_APPPATH, szAppPath );
- RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
- RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
- endif;
-
- // TODO : update any items you want to process before moving the data
- //
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: MoveFileData //
-// //
-// Purpose: This function handles the data movement for //
-// the setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function MoveFileData()
- NUMBER nResult, nDisk;
- begin
-
- nDisk = 1;
- SetStatusWindow( 0, "" );
- Disable( DIALOGCACHE );
- Enable( STATUS );
- StatusUpdate( ON, 100 );
- nResult = ComponentMoveData( MEDIA, nDisk, 0 );
-
- HandleMoveDataError( nResult );
-
- Disable( STATUS );
-
- return nResult;
-
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: HandleMoveDataError //
-// //
-// Purpose: This function handles the error (if any) during the move data //
-// operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function HandleMoveDataError( nResult )
- STRING szErrMsg, svComponent , svFileGroup , svFile;
- begin
-
- svComponent = "";
- svFileGroup = "";
- svFile = "";
-
- switch (nResult)
- case 0:
- return 0;
- default:
- ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
- szErrMsg = @ERROR_MOVEDATA + "\n\n" +
- @ERROR_COMPONENT + " " + svComponent + "\n" +
- @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
- @ERROR_FILE + " " + svFile;
- SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
- bInstallAborted = TRUE;
- return nResult;
- endswitch;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessAfterDataMove //
-// //
-// Purpose: This function performs any necessary operations needed after //
-// all data has been moved. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessAfterDataMove()
- begin
-
- // TODO : update self-registered files and other processes that
- // should be performed after the data has been moved.
-
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupRegistry //
-// //
-// Purpose: This function makes the registry entries for this setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupRegistry()
- NUMBER nResult;
-
- begin
-
- // TODO : Add all your registry entry keys here
- //
- //
- // RegDBCreateKeyEx, RegDBSetKeyValueEx....
- //
-
- nResult = CreateRegistrySet( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// Function: SetupFolders
-//
-// Purpose: This function creates all the folders and shortcuts for the
-// setup. This includes program groups and items for Windows 3.1.
-//
-///////////////////////////////////////////////////////////////////////////////
-function SetupFolders()
- NUMBER nResult;
-
- begin
-
-
- // TODO : Add all your folder (program group) along with shortcuts (program items)
- //
- //
- // CreateProgramFolder, AddFolderIcon....
- //
-
- nResult = CreateShellObjects( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CleanUpInstall //
-// //
-// Purpose: This cleans up the setup. Anything that should //
-// be released or deleted at the end of the setup should //
-// be done here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CleanUpInstall()
- begin
-
-
- if (bInstallAborted) then
- return 0;
- endif;
-
- DialogShowSdFinishReboot();
-
- if (BATCH_INSTALL) then // ensure locked files are properly written
- CommitSharedFiles(0);
- endif;
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupInstall //
-// //
-// Purpose: This will setup the installation. Any general initialization //
-// needed for the installation should be performed here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupInstall()
- begin
-
- Enable( CORECOMPONENTHANDLING );
-
- bInstallAborted = FALSE;
-
- if (bIs32BitSetup) then
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME ^ @PRODUCT_NAME;
- else
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME16 ^ @PRODUCT_NAME16; // use shorten names
- endif;
-
- TARGETDIR = svDir;
-
- SdProductName( @PRODUCT_NAME );
-
- Enable( DIALOGCACHE );
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupScreen //
-// //
-// Purpose: This function establishes the screen look. This includes //
-// colors, fonts, and text to be displayed. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupScreen()
- begin
-
- Enable( FULLWINDOWMODE );
- Enable( INDVFILESTATUS );
- SetTitle( @TITLE_MAIN, 24, WHITE );
-
- SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
-
- Enable( BACKGROUND );
-
- Delay( 1 );
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CheckRequirements //
-// //
-// Purpose: This function checks all minimum requirements for the //
-// application being installed. If any fail, then the user //
-// is informed and the setup is terminated. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CheckRequirements()
- NUMBER nvDx, nvDy, nvResult;
- STRING svResult;
-
- begin
-
- bWinNT = FALSE;
- bIsShellExplorer = FALSE;
-
- // Check screen resolution.
- GetExtents( nvDx, nvDy );
-
- if (nvDy < 480) then
- MessageBox( @ERROR_VGARESOLUTION, WARNING );
- abort;
- endif;
-
- // set 'setup' operation mode
- bIs32BitSetup = TRUE;
- GetSystemInfo( ISTYPE, nvResult, svResult );
- if (nvResult = 16) then
- bIs32BitSetup = FALSE; // running 16-bit setup
- return 0; // no additional information required
- endif;
-
- // --- 32-bit testing after this point ---
-
- // Determine the target system's operating system.
- GetSystemInfo( OS, nvResult, svResult );
-
- if (nvResult = IS_WINDOWSNT) then
- // Running Windows NT.
- bWinNT = TRUE;
-
- // Check to see if the shell being used is EXPLORER shell.
- if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
- if (nvResult >= 4) then
- bIsShellExplorer = TRUE;
- endif;
- endif;
-
- elseif (nvResult = IS_WINDOWS95 ) then
- bIsShellExplorer = TRUE;
-
- endif;
-
-end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdWelcome //
-// //
-// Purpose: This function handles the standard welcome dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdWelcome()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdWelcome( szTitle, szMsg );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdShowInfoList //
-// //
-// Purpose: This function displays the general information list dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdShowInfoList()
- NUMBER nResult;
- LIST list;
- STRING szTitle, szMsg, szFile;
- begin
-
- szFile = SUPPORTDIR ^ "infolist.txt";
-
- list = ListCreate( STRINGLIST );
- ListReadFromFile( list, szFile );
- szTitle = "";
- szMsg = " ";
- nResult = SdShowInfoList( szTitle, szMsg, list );
-
- ListDestroy( list );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdAskDestPath //
-// //
-// Purpose: This function asks the user for the destination directory. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdAskDestPath()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
-
- TARGETDIR = svDir;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdSetupType //
-// //
-// Purpose: This function displays the standard setup type dialog. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdSetupType()
- NUMBER nResult, nType;
- STRING szTitle, szMsg;
- begin
-
- switch (svSetupType)
- case "Typical":
- nType = TYPICAL;
- case "Custom":
- nType = CUSTOM;
- case "Compact":
- nType = COMPACT;
- case "":
- svSetupType = "Typical";
- nType = TYPICAL;
- endswitch;
-
- szTitle = "";
- szMsg = "";
- nResult = SetupType( szTitle, szMsg, "", nType, 0 );
-
- switch (nResult)
- case COMPACT:
- svSetupType = "Compact";
- case TYPICAL:
- svSetupType = "Typical";
- case CUSTOM:
- svSetupType = "Custom";
- endswitch;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdComponentDialog2 //
-// //
-// Purpose: This function displays the custom component dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdComponentDialog2()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- if ((svSetupType != "Custom") && (svSetupType != "")) then
- return 0;
- endif;
-
- szTitle = "";
- szMsg = "";
- nResult = SdComponentDialog2( szTitle, szMsg, svDir, "" );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdFinishReboot //
-// //
-// Purpose: This function will show the last dialog of the product. //
-// It will allow the user to reboot and/or show some readme text. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdFinishReboot()
- NUMBER nResult, nDefOptions;
- STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
- NUMBER bOpt1, bOpt2;
- begin
-
- if (!BATCH_INSTALL) then
- bOpt1 = FALSE;
- bOpt2 = FALSE;
- szMsg1 = "";
- szMsg2 = "";
- szOption1 = "";
- szOption2 = "";
- nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
- return 0;
- endif;
-
- nDefOptions = SYS_BOOTMACHINE;
- szTitle = "";
- szMsg1 = "";
- szMsg2 = "";
- nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );
-
- return nResult;
- end;
-
- // --- include script file section ---
-
-#include "sddialog.rul"
-
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Script Files/setup.rul b/VC++Files/InstallShield/4.0.XX-classic/Script Files/setup.rul
deleted file mode 100755
index 73d61114075..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Script Files/setup.rul
+++ /dev/null
@@ -1,641 +0,0 @@
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// IIIIIII SSSSSS
-// II SS InstallShield (R)
-// II SSSSSS (c) 1996-1997, InstallShield Software Corporation
-// II SS (c) 1990-1996, InstallShield Corporation
-// IIIIIII SSSSSS All Rights Reserved.
-//
-//
-// This code is generated as a starting setup template. You should
-// modify it to provide all necessary steps for your setup.
-//
-//
-// File Name: Setup.rul
-//
-// Description: InstallShield script
-//
-// Comments: This template script performs a basic setup on a
-// Windows 95 or Windows NT 4.0 platform. With minor
-// modifications, this template can be adapted to create
-// new, customized setups.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
- // Include header file
-#include "sdlang.h"
-#include "sddialog.h"
-
-////////////////////// string defines ////////////////////////////
-
-#define UNINST_LOGFILE_NAME "Uninst.isu"
-
-//////////////////// installation declarations ///////////////////
-
- // ----- DLL prototypes -----
-
-
- // your DLL prototypes
-
-
- // ---- script prototypes -----
-
- // generated
- prototype ShowDialogs();
- prototype MoveFileData();
- prototype HandleMoveDataError( NUMBER );
- prototype ProcessBeforeDataMove();
- prototype ProcessAfterDataMove();
- prototype SetupRegistry();
- prototype SetupFolders();
- prototype CleanUpInstall();
- prototype SetupInstall();
- prototype SetupScreen();
- prototype CheckRequirements();
- prototype DialogShowSdWelcome();
- prototype DialogShowSdShowInfoList();
- prototype DialogShowSdAskDestPath();
- prototype DialogShowSdSetupType();
- prototype DialogShowSdComponentDialog2();
- prototype DialogShowSdFinishReboot();
-
- // your prototypes
-
-
- // ----- global variables ------
-
- // generated
- BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
- STRING svDir;
- STRING svName, svCompany, svSerial;
- STRING szAppPath;
- STRING svSetupType;
-
-
- // your global variables
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// MAIN PROGRAM
-//
-// The setup begins here by hiding the visible setup
-// window. This is done to allow all the titles, images, etc. to
-// be established before showing the main window. The following
-// logic then performs the setup in a series of steps.
-//
-///////////////////////////////////////////////////////////////////////////////
-program
- Disable( BACKGROUND );
-
- CheckRequirements();
-
- SetupInstall();
-
- SetupScreen();
-
- if (ShowDialogs()<0) goto end_install;
-
- if (ProcessBeforeDataMove()<0) goto end_install;
-
- if (MoveFileData()<0) goto end_install;
-
- if (ProcessAfterDataMove()<0) goto end_install;
-
- if (SetupRegistry()<0) goto end_install;
-
- if (SetupFolders()<0) goto end_install;
-
-
- end_install:
-
- CleanUpInstall();
-
- // If an unrecoverable error occurred, clean up the partial installation.
- // Otherwise, exit normally.
-
- if (bInstallAborted) then
- abort;
- endif;
-
-endprogram
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ShowDialogs //
-// //
-// Purpose: This function manages the display and navigation //
-// the standard dialogs that exist in a setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ShowDialogs()
- NUMBER nResult;
- begin
-
- Dlg_Start:
- // beginning of dialogs label
-
- Dlg_SdWelcome:
- nResult = DialogShowSdWelcome();
- if (nResult = BACK) goto Dlg_Start;
-
- Dlg_SdShowInfoList:
- nResult = DialogShowSdShowInfoList();
- if (nResult = BACK) goto Dlg_SdWelcome;
-
- Dlg_SdAskDestPath:
- nResult = DialogShowSdAskDestPath();
- if (nResult = BACK) goto Dlg_SdShowInfoList;
-
- Dlg_SdSetupType:
- nResult = DialogShowSdSetupType();
- if (nResult = BACK) goto Dlg_SdAskDestPath;
-
- Dlg_SdComponentDialog2:
- if ((nResult = BACK) && (svSetupType != "Custom") && (svSetupType != "")) then
- goto Dlg_SdSetupType;
- endif;
- nResult = DialogShowSdComponentDialog2();
- if (nResult = BACK) goto Dlg_SdSetupType;
-
- return 0;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessBeforeDataMove //
-// //
-// Purpose: This function performs any necessary operations prior to the //
-// actual data move operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessBeforeDataMove()
- STRING svLogFile;
- NUMBER nResult;
- begin
-
- InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
-
- svLogFile = UNINST_LOGFILE_NAME;
-
- nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
- if (nResult < 0) then
- MessageBox( @ERROR_UNINSTSETUP, WARNING );
- endif;
-
- szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir
-
- if ((bIs32BitSetup) && (bIsShellExplorer)) then
-// RegDBSetItem( REGDB_APPPATH, szAppPath );
-// RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
- RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
- endif;
-
- // TODO : update any items you want to process before moving the data
- //
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: MoveFileData //
-// //
-// Purpose: This function handles the data movement for //
-// the setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function MoveFileData()
- NUMBER nResult, nDisk;
- begin
-
- nDisk = 1;
- SetStatusWindow( 0, "" );
- Disable( DIALOGCACHE );
- Enable( STATUS );
- StatusUpdate( ON, 100 );
- nResult = ComponentMoveData( MEDIA, nDisk, 0 );
-
- HandleMoveDataError( nResult );
-
- Disable( STATUS );
-
- return nResult;
-
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: HandleMoveDataError //
-// //
-// Purpose: This function handles the error (if any) during the move data //
-// operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function HandleMoveDataError( nResult )
- STRING szErrMsg, svComponent , svFileGroup , svFile;
- begin
-
- svComponent = "";
- svFileGroup = "";
- svFile = "";
-
- switch (nResult)
- case 0:
- return 0;
- default:
- ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
- szErrMsg = @ERROR_MOVEDATA + "\n\n" +
- @ERROR_COMPONENT + " " + svComponent + "\n" +
- @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
- @ERROR_FILE + " " + svFile;
- SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
- bInstallAborted = TRUE;
- return nResult;
- endswitch;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessAfterDataMove //
-// //
-// Purpose: This function performs any necessary operations needed after //
-// all data has been moved. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessAfterDataMove()
- begin
-
- // TODO : update self-registered files and other processes that
- // should be performed after the data has been moved.
-
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupRegistry //
-// //
-// Purpose: This function makes the registry entries for this setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupRegistry()
- NUMBER nResult;
-
- begin
-
- // TODO : Add all your registry entry keys here
- //
- //
- // RegDBCreateKeyEx, RegDBSetKeyValueEx....
- //
-
- nResult = CreateRegistrySet( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// Function: SetupFolders
-//
-// Purpose: This function creates all the folders and shortcuts for the
-// setup. This includes program groups and items for Windows 3.1.
-//
-///////////////////////////////////////////////////////////////////////////////
-function SetupFolders()
- NUMBER nResult;
-
- begin
-
-
- // TODO : Add all your folder (program group) along with shortcuts (program items)
- //
- //
- // CreateProgramFolder, AddFolderIcon....
- //
-
- nResult = CreateShellObjects( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CleanUpInstall //
-// //
-// Purpose: This cleans up the setup. Anything that should //
-// be released or deleted at the end of the setup should //
-// be done here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CleanUpInstall()
- begin
-
-
- if (bInstallAborted) then
- return 0;
- endif;
-
- DialogShowSdFinishReboot();
-
- if (BATCH_INSTALL) then // ensure locked files are properly written
- CommitSharedFiles(0);
- endif;
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupInstall //
-// //
-// Purpose: This will setup the installation. Any general initialization //
-// needed for the installation should be performed here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupInstall()
- begin
-
- Enable( CORECOMPONENTHANDLING );
-
- bInstallAborted = FALSE;
-
- if (bIs32BitSetup) then
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME ^ @PRODUCT_NAME;
- else
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME16 ^ @PRODUCT_NAME16; // use shorten names
- endif;
-
- TARGETDIR = svDir;
-
- SdProductName( @PRODUCT_NAME );
-
- Enable( DIALOGCACHE );
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupScreen //
-// //
-// Purpose: This function establishes the screen look. This includes //
-// colors, fonts, and text to be displayed. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupScreen()
- begin
-
- Enable( FULLWINDOWMODE );
- Enable( INDVFILESTATUS );
- SetTitle( @TITLE_MAIN, 24, WHITE );
-
- SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
-
- Enable( BACKGROUND );
-
- Delay( 1 );
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CheckRequirements //
-// //
-// Purpose: This function checks all minimum requirements for the //
-// application being installed. If any fail, then the user //
-// is informed and the setup is terminated. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CheckRequirements()
- NUMBER nvDx, nvDy, nvResult;
- STRING svResult;
-
- begin
-
- bWinNT = FALSE;
- bIsShellExplorer = FALSE;
-
- // Check screen resolution.
- GetExtents( nvDx, nvDy );
-
- if (nvDy < 480) then
- MessageBox( @ERROR_VGARESOLUTION, WARNING );
- abort;
- endif;
-
- // set 'setup' operation mode
- bIs32BitSetup = TRUE;
- GetSystemInfo( ISTYPE, nvResult, svResult );
- if (nvResult = 16) then
- bIs32BitSetup = FALSE; // running 16-bit setup
- return 0; // no additional information required
- endif;
-
- // --- 32-bit testing after this point ---
-
- // Determine the target system's operating system.
- GetSystemInfo( OS, nvResult, svResult );
-
- if (nvResult = IS_WINDOWSNT) then
- // Running Windows NT.
- bWinNT = TRUE;
-
- // Check to see if the shell being used is EXPLORER shell.
- if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
- if (nvResult >= 4) then
- bIsShellExplorer = TRUE;
- endif;
- endif;
-
- elseif (nvResult = IS_WINDOWS95 ) then
- bIsShellExplorer = TRUE;
-
- endif;
-
-end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdWelcome //
-// //
-// Purpose: This function handles the standard welcome dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdWelcome()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdWelcome( szTitle, szMsg );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdShowInfoList //
-// //
-// Purpose: This function displays the general information list dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdShowInfoList()
- NUMBER nResult;
- LIST list;
- STRING szTitle, szMsg, szFile;
- begin
-
- szFile = SUPPORTDIR ^ "infolist.txt";
-
- list = ListCreate( STRINGLIST );
- ListReadFromFile( list, szFile );
- szTitle = "";
- szMsg = " ";
- nResult = SdShowInfoList( szTitle, szMsg, list );
-
- ListDestroy( list );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdAskDestPath //
-// //
-// Purpose: This function asks the user for the destination directory. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdAskDestPath()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
-
- TARGETDIR = svDir;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdSetupType //
-// //
-// Purpose: This function displays the standard setup type dialog. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdSetupType()
- NUMBER nResult, nType;
- STRING szTitle, szMsg;
- begin
-
- switch (svSetupType)
- case "Typical":
- nType = TYPICAL;
- case "Custom":
- nType = CUSTOM;
- case "Compact":
- nType = COMPACT;
- case "":
- svSetupType = "Typical";
- nType = TYPICAL;
- endswitch;
-
- szTitle = "";
- szMsg = "";
- nResult = SetupType( szTitle, szMsg, "", nType, 0 );
-
- switch (nResult)
- case COMPACT:
- svSetupType = "Compact";
- case TYPICAL:
- svSetupType = "Typical";
- case CUSTOM:
- svSetupType = "Custom";
- endswitch;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdComponentDialog2 //
-// //
-// Purpose: This function displays the custom component dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdComponentDialog2()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- if ((svSetupType != "Custom") && (svSetupType != "")) then
- return 0;
- endif;
-
- szTitle = "";
- szMsg = "";
- nResult = SdComponentDialog2( szTitle, szMsg, svDir, "" );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdFinishReboot //
-// //
-// Purpose: This function will show the last dialog of the product. //
-// It will allow the user to reboot and/or show some readme text. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdFinishReboot()
- NUMBER nResult, nDefOptions;
- STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
- NUMBER bOpt1, bOpt2;
- begin
-
- if (!BATCH_INSTALL) then
- bOpt1 = FALSE;
- bOpt2 = FALSE;
- szMsg1 = "";
- szMsg2 = "";
- szOption1 = "";
- szOption2 = "";
- nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
- return 0;
- endif;
-
- nDefOptions = SYS_BOOTMACHINE;
- szTitle = "";
- szMsg1 = "";
- szMsg2 = "";
- nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );
-
- return nResult;
- end;
-
- // --- include script file section ---
-
-#include "sddialog.rul"
-
-
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt b/VC++Files/InstallShield/4.0.XX-classic/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt
deleted file mode 100755
index e5a6f6ac433..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-This is a release of MySQL Classic @VERSION@ for Win32.
-
-NOTE: If you install MySQL in a folder other than
-C:\MYSQL or you intend to start MySQL on NT/Win2000
-as a service, you must create a file named C:\MY.CNF
-or \Windows\my.ini or \winnt\my.ini with the following
-information::
-
-[mysqld]
-basedir=E:/installation-path/
-datadir=E:/data-path/
-
-After your have installed MySQL, the installation
-directory will contain 4 files named 'my-small.cnf,
-my-medium.cnf, my-large.cnf, my-huge.cnf'.
-You can use this as a starting point for your own
-C:\my.cnf file.
-
-If you have any problems, you can mail them to
-win32@lists.mysql.com after you have consulted the
-MySQL manual and the MySQL mailing list archive
-(http://www.mysql.com/documentation/index.html)
-
-On behalf of the MySQL AB gang,
-Michael Widenius
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmp b/VC++Files/InstallShield/4.0.XX-classic/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmp
deleted file mode 100755
index 3229d50c9bf..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Shell Objects/Default.shl b/VC++Files/InstallShield/4.0.XX-classic/Shell Objects/Default.shl
deleted file mode 100755
index 187cb651307..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Shell Objects/Default.shl
+++ /dev/null
@@ -1,12 +0,0 @@
-[Data]
-Folder3=<FOLDER_STARTUP>
-Group0=Main
-Group1=Startup
-Folder0=<FOLDER_DESKTOP>
-Folder1=<FOLDER_STARTMENU>
-Folder2=<FOLDER_PROGRAMS>
-
-[Info]
-Type=ShellObject
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl b/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl
deleted file mode 100755
index 868c801c68c..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl
+++ /dev/null
@@ -1,23 +0,0 @@
-[Data]
-TITLE_MAIN=MySQL Classic Servers and Clients @VERSION@
-COMPANY_NAME=MySQL AB
-ERROR_COMPONENT=Component:
-COMPANY_NAME16=Company
-PRODUCT_VERSION=MySQL Classic Servers and Clients @VERSION@
-ERROR_MOVEDATA=An error occurred during the move data process: %d
-ERROR_FILEGROUP=File Group:
-UNINST_KEY=MySQL Classic Servers and Clients @VERSION@
-TITLE_CAPTIONBAR=MySQL Classic Servers and Clients @VERSION@
-PRODUCT_NAME16=Product
-ERROR_VGARESOLUTION=This program requires VGA or better resolution.
-ERROR_FILE=File:
-UNINST_DISPLAY_NAME=MySQL Classic Servers and Clients @VERSION@
-PRODUCT_KEY=yourapp.Exe
-PRODUCT_NAME=MySQL Classic Servers and Clients @VERSION@
-ERROR_UNINSTSETUP=unInstaller setup failed to initialize. You may not be able to uninstall this product.
-
-[General]
-Language=0009
-Type=STRINGTABLESPECIFIC
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/String Tables/Default.shl b/VC++Files/InstallShield/4.0.XX-classic/String Tables/Default.shl
deleted file mode 100755
index d4dc4925ab1..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/String Tables/Default.shl
+++ /dev/null
@@ -1,74 +0,0 @@
-[TITLE_MAIN]
-Comment=
-
-[COMPANY_NAME]
-Comment=
-
-[ERROR_COMPONENT]
-Comment=
-
-[COMPANY_NAME16]
-Comment=
-
-[PRODUCT_VERSION]
-Comment=
-
-[ERROR_MOVEDATA]
-Comment=
-
-[ERROR_FILEGROUP]
-Comment=
-
-[Language]
-Lang0=0009
-CurrentLang=0
-
-[UNINST_KEY]
-Comment=
-
-[TITLE_CAPTIONBAR]
-Comment=
-
-[Data]
-Entry0=ERROR_VGARESOLUTION
-Entry1=TITLE_MAIN
-Entry2=TITLE_CAPTIONBAR
-Entry3=UNINST_KEY
-Entry4=UNINST_DISPLAY_NAME
-Entry5=COMPANY_NAME
-Entry6=PRODUCT_NAME
-Entry7=PRODUCT_VERSION
-Entry8=PRODUCT_KEY
-Entry9=ERROR_MOVEDATA
-Entry10=ERROR_UNINSTSETUP
-Entry11=COMPANY_NAME16
-Entry12=PRODUCT_NAME16
-Entry13=ERROR_COMPONENT
-Entry14=ERROR_FILEGROUP
-Entry15=ERROR_FILE
-
-[PRODUCT_NAME16]
-Comment=
-
-[ERROR_VGARESOLUTION]
-Comment=
-
-[ERROR_FILE]
-Comment=
-
-[General]
-Type=STRINGTABLE
-Version=1.00.000
-
-[UNINST_DISPLAY_NAME]
-Comment=
-
-[PRODUCT_KEY]
-Comment=
-
-[PRODUCT_NAME]
-Comment=
-
-[ERROR_UNINSTSETUP]
-Comment=
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Text Substitutions/Build.tsb b/VC++Files/InstallShield/4.0.XX-classic/Text Substitutions/Build.tsb
deleted file mode 100755
index 3949bd4c066..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Text Substitutions/Build.tsb
+++ /dev/null
@@ -1,56 +0,0 @@
-[<HKUS>]
-Value=
-KeyType=4
-
-[<HKCR>]
-Value=
-KeyType=4
-
-[<PROGRAMFILES>]
-Value=
-KeyType=4
-
-[<WINSYSDIR>]
-Value=
-KeyType=4
-
-[<COMMONFILES>]
-Value=
-KeyType=4
-
-[<WINDIR>]
-Value=
-KeyType=4
-
-[Data]
-Key0=<PROGRAMFILES>
-Key1=<COMMONFILES>
-Key2=<WINDIR>
-Key3=<WINSYSDIR>
-Key4=<HKLM>
-Key5=<HKCU>
-Key6=<HKCC>
-Key7=<HKDD>
-Key8=<HKUS>
-Key9=<HKCR>
-
-[General]
-Type=TEXTSUB
-Version=1.00.000
-
-[<HKLM>]
-Value=
-KeyType=4
-
-[<HKCU>]
-Value=
-KeyType=4
-
-[<HKCC>]
-Value=
-KeyType=4
-
-[<HKDD>]
-Value=
-KeyType=4
-
diff --git a/VC++Files/InstallShield/4.0.XX-classic/Text Substitutions/Setup.tsb b/VC++Files/InstallShield/4.0.XX-classic/Text Substitutions/Setup.tsb
deleted file mode 100755
index b0c5a509f0b..00000000000
--- a/VC++Files/InstallShield/4.0.XX-classic/Text Substitutions/Setup.tsb
+++ /dev/null
@@ -1,76 +0,0 @@
-[<SRCDIR>]
-Value=
-KeyType=4
-
-[<HKUS>]
-Value=
-KeyType=4
-
-[<HKCR>]
-Value=
-KeyType=4
-
-[<PROGRAMFILES>]
-Value=
-KeyType=4
-
-[<TARGETDIR>]
-Value=
-KeyType=4
-
-[<WINSYSDIR>]
-Value=
-KeyType=4
-
-[<COMMONFILES>]
-Value=
-KeyType=4
-
-[<WINDIR>]
-Value=
-KeyType=4
-
-[Data]
-Key0=<PROGRAMFILES>
-Key1=<COMMONFILES>
-Key2=<WINDIR>
-Key3=<WINSYSDIR>
-Key4=<TARGETDIR>
-Key5=<SUPPORTDIR>
-Key10=<HKDD>
-Key6=<SRCDIR>
-Key11=<HKUS>
-Key7=<HKLM>
-Key12=<HKCR>
-Key8=<HKCU>
-Key13=<SHELL_OBJECT_FOLDER>
-Key9=<HKCC>
-
-[<SUPPORTDIR>]
-Value=
-KeyType=4
-
-[<SHELL_OBJECT_FOLDER>]
-Value=
-KeyType=4
-
-[General]
-Type=TEXTSUB
-Version=1.00.000
-
-[<HKLM>]
-Value=
-KeyType=4
-
-[<HKCU>]
-Value=
-KeyType=4
-
-[<HKCC>]
-Value=
-KeyType=4
-
-[<HKDD>]
-Value=
-KeyType=4
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/4.0.XX-gpl.ipr b/VC++Files/InstallShield/4.0.XX-gpl/4.0.XX-gpl.ipr
deleted file mode 100755
index c415a03a315..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/4.0.XX-gpl.ipr
+++ /dev/null
@@ -1,51 +0,0 @@
-[Language]
-LanguageSupport0=0009
-
-[OperatingSystem]
-OSSupport=0000000000010010
-
-[Data]
-CurrentMedia=
-CurrentComponentDef=Default.cdf
-ProductName=MySQL Servers and Clients
-set_mifserial=
-DevEnvironment=Microsoft Visual C++ 6
-AppExe=
-set_dlldebug=No
-EmailAddresss=
-Instructions=Instructions.txt
-set_testmode=No
-set_mif=No
-SummaryText=
-Department=
-HomeURL=
-Author=
-Type=Database Application
-InstallRoot=D:\MySQL-Install\mysql-4\MySQL Servers and Clients
-Version=1.00.000
-InstallationGUID=40744a4d-efed-4cff-84a9-9e6389550f5c
-set_level=Level 3
-CurrentFileGroupDef=Default.fdf
-Notes=Notes.txt
-set_maxerr=50
-set_args=
-set_miffile=Status.mif
-set_dllcmdline=
-Copyright=
-set_warnaserr=No
-CurrentPlatform=
-Category=
-set_preproc=
-CurrentLanguage=English
-CompanyName=MySQL
-Description=Description.txt
-set_maxwarn=50
-set_crc=Yes
-set_compileb4build=No
-
-[MediaInfo]
-
-[General]
-Type=INSTALLMAIN
-Version=1.10.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Component Definitions/Default.cdf b/VC++Files/InstallShield/4.0.XX-gpl/Component Definitions/Default.cdf
deleted file mode 100755
index 48d37800cd1..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Component Definitions/Default.cdf
+++ /dev/null
@@ -1,192 +0,0 @@
-[Development]
-required0=Servers
-SELECTED=Yes
-FILENEED=STANDARD
-required1=Grant Tables
-HTTPLOCATION=
-STATUS=Examples, Libraries, Includes and Script files
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=Examples, Libraries, Includes and Script files
-DISPLAYTEXT=Examples, Libraries, Includes and Script files
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Development
-COMMENT=
-INCLUDEINBUILD=Yes
-INSTALLATION=ALWAYSOVERWRITE
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[Grant Tables]
-required0=Servers
-SELECTED=Yes
-FILENEED=CRITICAL
-HTTPLOCATION=
-STATUS=The Grant Tables and Core Files
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The Grant Tables and Core Files
-DISPLAYTEXT=The Grant Tables and Core Files
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Grant Tables
-requiredby0=Development
-COMMENT=
-INCLUDEINBUILD=Yes
-requiredby1=Clients and Tools
-INSTALLATION=NEVEROVERWRITE
-requiredby2=Documentation
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[Components]
-component0=Development
-component1=Grant Tables
-component2=Servers
-component3=Clients and Tools
-component4=Documentation
-
-[TopComponents]
-component0=Servers
-component1=Clients and Tools
-component2=Documentation
-component3=Development
-component4=Grant Tables
-
-[SetupType]
-setuptype0=Compact
-setuptype1=Typical
-setuptype2=Custom
-
-[Clients and Tools]
-required0=Servers
-SELECTED=Yes
-FILENEED=HIGHLYRECOMMENDED
-required1=Grant Tables
-HTTPLOCATION=
-STATUS=The MySQL clients and Maintenance Tools
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The MySQL clients and Maintenance Tools
-DISPLAYTEXT=The MySQL clients and Maintenance Tools
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Clients and Tools
-COMMENT=
-INCLUDEINBUILD=Yes
-INSTALLATION=NEWERDATE
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[Servers]
-SELECTED=Yes
-FILENEED=CRITICAL
-HTTPLOCATION=
-STATUS=The MySQL Servers
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The MySQL Servers
-DISPLAYTEXT=The MySQL Servers
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Servers
-requiredby0=Development
-COMMENT=
-INCLUDEINBUILD=Yes
-requiredby1=Grant Tables
-INSTALLATION=ALWAYSOVERWRITE
-requiredby2=Clients and Tools
-requiredby3=Documentation
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[SetupTypeItem-Compact]
-Comment=
-item0=Grant Tables
-item1=Servers
-item2=Clients and Tools
-item3=Documentation
-Descrip=
-DisplayText=
-
-[SetupTypeItem-Custom]
-Comment=
-item0=Development
-item1=Grant Tables
-item2=Servers
-item3=Clients and Tools
-Descrip=
-item4=Documentation
-DisplayText=
-
-[Info]
-Type=CompDef
-Version=1.00.000
-Name=
-
-[SetupTypeItem-Typical]
-Comment=
-item0=Development
-item1=Grant Tables
-item2=Servers
-item3=Clients and Tools
-Descrip=
-item4=Documentation
-DisplayText=
-
-[Documentation]
-required0=Servers
-SELECTED=Yes
-FILENEED=HIGHLYRECOMMENDED
-required1=Grant Tables
-HTTPLOCATION=
-STATUS=The MySQL Documentation with different formats
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The MySQL Documentation with different formats
-DISPLAYTEXT=The MySQL Documentation with different formats
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Documentation
-COMMENT=
-INCLUDEINBUILD=Yes
-INSTALLATION=ALWAYSOVERWRITE
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Component Definitions/Default.fgl b/VC++Files/InstallShield/4.0.XX-gpl/Component Definitions/Default.fgl
deleted file mode 100755
index 4e20dcea4ab..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Component Definitions/Default.fgl
+++ /dev/null
@@ -1,42 +0,0 @@
-[<PROGRAMFILES>\<COMMONFILES>]
-DISPLAYTEXT=Common Files Folder
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[<WINDIR>\<WINSYSDIR>]
-DISPLAYTEXT=Windows System Folder
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[USERDEFINED]
-DISPLAYTEXT=Script-defined Folders
-TYPE=USERSTART
-fulldirectory=
-
-[<PROGRAMFILES>]
-DISPLAYTEXT=Program Files Folder
-SubDir0=<PROGRAMFILES>\<COMMONFILES>
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[<TARGETDIR>]
-DISPLAYTEXT=General Application Destination
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[<WINDIR>]
-DISPLAYTEXT=Windows Operating System
-SubDir0=<WINDIR>\<WINSYSDIR>
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[TopDir]
-SubDir0=<WINDIR>
-SubDir1=<PROGRAMFILES>
-SubDir2=<TARGETDIR>
-SubDir3=USERDEFINED
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Clients and Tools.fgl b/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Clients and Tools.fgl
deleted file mode 100755
index ed1e42e65b6..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Clients and Tools.fgl
+++ /dev/null
@@ -1,32 +0,0 @@
-[bin]
-file15=C:\mysql\bin\replace.exe
-file16=C:\mysql\bin\winmysqladmin.cnt
-file0=C:\mysql\bin\isamchk.exe
-file17=C:\mysql\bin\WINMYSQLADMIN.HLP
-file1=C:\mysql\bin\myisamchk.exe
-file18=C:\mysql\bin\comp-err.exe
-file2=C:\mysql\bin\myisamlog.exe
-file19=C:\mysql\bin\my_print_defaults.exe
-file3=C:\mysql\bin\myisampack.exe
-file4=C:\mysql\bin\mysql.exe
-file5=C:\mysql\bin\mysqladmin.exe
-file6=C:\mysql\bin\mysqlbinlog.exe
-file7=C:\mysql\bin\mysqlc.exe
-file8=C:\mysql\bin\mysqlcheck.exe
-file9=C:\mysql\bin\mysqldump.exe
-file20=C:\mysql\bin\winmysqladmin.exe
-file21=C:\mysql\bin\myisam_ftdump.exe
-file10=C:\mysql\bin\mysqlimport.exe
-fulldirectory=
-file11=C:\mysql\bin\mysqlshow.exe
-file12=C:\mysql\bin\mysqlwatch.exe
-file13=C:\mysql\bin\pack_isam.exe
-file14=C:\mysql\bin\perror.exe
-
-[TopDir]
-SubDir0=bin
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Default.fdf b/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Default.fdf
deleted file mode 100755
index 8096a4b74bf..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Default.fdf
+++ /dev/null
@@ -1,82 +0,0 @@
-[FileGroups]
-group0=Development
-group1=Grant Tables
-group2=Servers
-group3=Clients and Tools
-group4=Documentation
-
-[Development]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Grant Tables]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Clients and Tools]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=0000000000000000
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Servers]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Info]
-Type=FileGrp
-Version=1.00.000
-Name=
-
-[Documentation]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Development.fgl b/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Development.fgl
deleted file mode 100755
index 02e01d564aa..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Development.fgl
+++ /dev/null
@@ -1,242 +0,0 @@
-[bench\Data\Wisconsin]
-file0=C:\mysql\bench\Data\Wisconsin\onek.data
-file1=C:\mysql\bench\Data\Wisconsin\tenk.data
-fulldirectory=
-
-[lib\debug]
-file0=C:\mysql\lib\debug\libmySQL.dll
-file1=C:\mysql\lib\debug\libmySQL.lib
-file2=C:\mysql\lib\debug\mysqlclient.lib
-file3=C:\mysql\lib\debug\zlib.lib
-file4=C:\mysql\lib\debug\regex.lib
-file5=C:\mysql\lib\debug\mysys.lib
-file6=C:\mysql\lib\debug\strings.lib
-fulldirectory=
-
-[bench\output]
-fulldirectory=
-
-[examples\libmysqltest]
-file0=C:\mysql\examples\libmysqltest\myTest.c
-file1=C:\mysql\examples\libmysqltest\myTest.dsp
-file2=C:\mysql\examples\libmysqltest\myTest.dsw
-file3=C:\mysql\examples\libmysqltest\myTest.exe
-file4=C:\mysql\examples\libmysqltest\myTest.mak
-file5=C:\mysql\examples\libmysqltest\myTest.ncb
-file6=C:\mysql\examples\libmysqltest\myTest.opt
-file7=C:\mysql\examples\libmysqltest\readme
-fulldirectory=
-
-[include]
-file15=C:\mysql\include\libmysqld.def
-file16=C:\mysql\include\my_alloc.h
-file0=C:\mysql\include\raid.h
-file17=C:\mysql\include\my_getopt.h
-file1=C:\mysql\include\errmsg.h
-file2=C:\mysql\include\Libmysql.def
-file3=C:\mysql\include\m_ctype.h
-file4=C:\mysql\include\m_string.h
-file5=C:\mysql\include\my_list.h
-file6=C:\mysql\include\my_pthread.h
-file7=C:\mysql\include\my_sys.h
-file8=C:\mysql\include\mysql.h
-file9=C:\mysql\include\mysql_com.h
-file10=C:\mysql\include\mysql_version.h
-fulldirectory=
-file11=C:\mysql\include\mysqld_error.h
-file12=C:\mysql\include\dbug.h
-file13=C:\mysql\include\config-win.h
-file14=C:\mysql\include\my_global.h
-
-[examples]
-SubDir0=examples\libmysqltest
-SubDir1=examples\tests
-fulldirectory=
-
-[lib\opt]
-file0=C:\mysql\lib\opt\libmySQL.dll
-file1=C:\mysql\lib\opt\libmySQL.lib
-file2=C:\mysql\lib\opt\mysqlclient.lib
-file3=C:\mysql\lib\opt\zlib.lib
-file4=C:\mysql\lib\opt\strings.lib
-file5=C:\mysql\lib\opt\mysys-max.lib
-file6=C:\mysql\lib\opt\regex.lib
-file7=C:\mysql\lib\opt\mysys.lib
-fulldirectory=
-
-[bench\Data]
-SubDir0=bench\Data\ATIS
-SubDir1=bench\Data\Wisconsin
-fulldirectory=
-
-[bench\limits]
-file15=C:\mysql\bench\limits\pg.comment
-file16=C:\mysql\bench\limits\solid.cfg
-file0=C:\mysql\bench\limits\access.cfg
-file17=C:\mysql\bench\limits\solid-nt4.cfg
-file1=C:\mysql\bench\limits\access.comment
-file18=C:\mysql\bench\limits\sybase.cfg
-file2=C:\mysql\bench\limits\Adabas.cfg
-file3=C:\mysql\bench\limits\Adabas.comment
-file4=C:\mysql\bench\limits\Db2.cfg
-file5=C:\mysql\bench\limits\empress.cfg
-file6=C:\mysql\bench\limits\empress.comment
-file7=C:\mysql\bench\limits\Informix.cfg
-file8=C:\mysql\bench\limits\Informix.comment
-file9=C:\mysql\bench\limits\msql.cfg
-file10=C:\mysql\bench\limits\ms-sql.cfg
-fulldirectory=
-file11=C:\mysql\bench\limits\Ms-sql65.cfg
-file12=C:\mysql\bench\limits\mysql.cfg
-file13=C:\mysql\bench\limits\oracle.cfg
-file14=C:\mysql\bench\limits\pg.cfg
-
-[TopDir]
-SubDir0=bench
-SubDir1=examples
-SubDir2=include
-SubDir3=lib
-SubDir4=scripts
-
-[bench]
-file15=C:\mysql\bench\test-create
-file16=C:\mysql\bench\test-insert
-file0=C:\mysql\bench\uname.bat
-file17=C:\mysql\bench\test-select
-file1=C:\mysql\bench\compare-results
-file18=C:\mysql\bench\test-wisconsin
-file2=C:\mysql\bench\copy-db
-file19=C:\mysql\bench\bench-init.pl
-file3=C:\mysql\bench\crash-me
-file4=C:\mysql\bench\example.bat
-file5=C:\mysql\bench\print-limit-table
-file6=C:\mysql\bench\pwd.bat
-file7=C:\mysql\bench\Readme
-SubDir0=bench\Data
-file8=C:\mysql\bench\run.bat
-SubDir1=bench\limits
-file9=C:\mysql\bench\run-all-tests
-SubDir2=bench\output
-file10=C:\mysql\bench\server-cfg
-fulldirectory=
-file11=C:\mysql\bench\test-alter-table
-file12=C:\mysql\bench\test-ATIS
-file13=C:\mysql\bench\test-big-tables
-file14=C:\mysql\bench\test-connect
-
-[examples\tests]
-file15=C:\mysql\examples\tests\lock_test.res
-file16=C:\mysql\examples\tests\mail_to_db.pl
-file0=C:\mysql\examples\tests\unique_users.tst
-file17=C:\mysql\examples\tests\table_types.pl
-file1=C:\mysql\examples\tests\auto_increment.tst
-file18=C:\mysql\examples\tests\test_delayed_insert.pl
-file2=C:\mysql\examples\tests\big_record.pl
-file19=C:\mysql\examples\tests\udf_test
-file3=C:\mysql\examples\tests\big_record.res
-file4=C:\mysql\examples\tests\czech-sorting
-file5=C:\mysql\examples\tests\deadlock-script.pl
-file6=C:\mysql\examples\tests\export.pl
-file7=C:\mysql\examples\tests\fork_test.pl
-file8=C:\mysql\examples\tests\fork2_test.pl
-file9=C:\mysql\examples\tests\fork3_test.pl
-file20=C:\mysql\examples\tests\udf_test.res
-file21=C:\mysql\examples\tests\auto_increment.res
-file10=C:\mysql\examples\tests\function.res
-fulldirectory=
-file11=C:\mysql\examples\tests\function.tst
-file12=C:\mysql\examples\tests\grant.pl
-file13=C:\mysql\examples\tests\grant.res
-file14=C:\mysql\examples\tests\lock_test.pl
-
-[bench\Data\ATIS]
-file26=C:\mysql\bench\Data\ATIS\stop1.txt
-file15=C:\mysql\bench\Data\ATIS\flight_class.txt
-file27=C:\mysql\bench\Data\ATIS\time_interval.txt
-file16=C:\mysql\bench\Data\ATIS\flight_day.txt
-file0=C:\mysql\bench\Data\ATIS\transport.txt
-file28=C:\mysql\bench\Data\ATIS\time_zone.txt
-file17=C:\mysql\bench\Data\ATIS\flight_fare.txt
-file1=C:\mysql\bench\Data\ATIS\airline.txt
-file29=C:\mysql\bench\Data\ATIS\aircraft.txt
-file18=C:\mysql\bench\Data\ATIS\food_service.txt
-file2=C:\mysql\bench\Data\ATIS\airport.txt
-file19=C:\mysql\bench\Data\ATIS\ground_service.txt
-file3=C:\mysql\bench\Data\ATIS\airport_service.txt
-file4=C:\mysql\bench\Data\ATIS\city.txt
-file5=C:\mysql\bench\Data\ATIS\class_of_service.txt
-file6=C:\mysql\bench\Data\ATIS\code_description.txt
-file7=C:\mysql\bench\Data\ATIS\compound_class.txt
-file8=C:\mysql\bench\Data\ATIS\connect_leg.txt
-file9=C:\mysql\bench\Data\ATIS\date_day.txt
-file20=C:\mysql\bench\Data\ATIS\month_name.txt
-file21=C:\mysql\bench\Data\ATIS\restrict_carrier.txt
-file10=C:\mysql\bench\Data\ATIS\day_name.txt
-fulldirectory=
-file22=C:\mysql\bench\Data\ATIS\restrict_class.txt
-file11=C:\mysql\bench\Data\ATIS\dual_carrier.txt
-file23=C:\mysql\bench\Data\ATIS\restriction.txt
-file12=C:\mysql\bench\Data\ATIS\fare.txt
-file24=C:\mysql\bench\Data\ATIS\state.txt
-file13=C:\mysql\bench\Data\ATIS\fconnection.txt
-file25=C:\mysql\bench\Data\ATIS\stop.txt
-file14=C:\mysql\bench\Data\ATIS\flight.txt
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
-[scripts]
-file37=C:\mysql\scripts\mysqld_safe-watch.sh
-file26=C:\mysql\scripts\mysql_zap
-file15=C:\mysql\scripts\mysql_fix_privilege_tables
-file38=C:\mysql\scripts\mysqldumpslow
-file27=C:\mysql\scripts\mysql_zap.sh
-file16=C:\mysql\scripts\mysql_fix_privilege_tables.sh
-file0=C:\mysql\scripts\Readme
-file39=C:\mysql\scripts\mysqldumpslow.sh
-file28=C:\mysql\scripts\mysqlaccess
-file17=C:\mysql\scripts\mysql_install_db
-file1=C:\mysql\scripts\make_binary_distribution.sh
-file29=C:\mysql\scripts\mysqlaccess.conf
-file18=C:\mysql\scripts\mysql_install_db.sh
-file2=C:\mysql\scripts\msql2mysql
-file19=C:\mysql\scripts\mysql_secure_installation
-file3=C:\mysql\scripts\msql2mysql.sh
-file4=C:\mysql\scripts\mysql_config
-file5=C:\mysql\scripts\mysql_config.sh
-file6=C:\mysql\scripts\mysql_convert_table_format
-file7=C:\mysql\scripts\mysql_convert_table_format.sh
-file40=C:\mysql\scripts\mysqlhotcopy
-file8=C:\mysql\scripts\mysql_explain_log
-file41=C:\mysql\scripts\mysqlhotcopy.pl
-file30=C:\mysql\scripts\mysqlaccess.sh
-file9=C:\mysql\scripts\mysql_explain_log.sh
-file42=C:\mysql\scripts\mysqlhotcopy.sh
-file31=C:\mysql\scripts\mysqlbug
-file20=C:\mysql\scripts\mysql_secure_installation.sh
-file43=C:\mysql\scripts\make_binary_distribution
-file32=C:\mysql\scripts\mysqlbug.sh
-file21=C:\mysql\scripts\mysql_setpermission
-file10=C:\mysql\scripts\mysql_find_rows
-fulldirectory=
-file44=C:\mysql\scripts\mysql_fix_privilege_tables.sql
-file33=C:\mysql\scripts\mysqld_multi
-file22=C:\mysql\scripts\mysql_setpermission.pl
-file11=C:\mysql\scripts\mysql_find_rows.pl
-file34=C:\mysql\scripts\mysqld_multi.sh
-file23=C:\mysql\scripts\mysql_setpermission.sh
-file12=C:\mysql\scripts\mysql_find_rows.sh
-file35=C:\mysql\scripts\mysqld_safe
-file24=C:\mysql\scripts\mysql_tableinfo
-file13=C:\mysql\scripts\mysql_fix_extensions
-file36=C:\mysql\scripts\mysqld_safe.sh
-file25=C:\mysql\scripts\mysql_tableinfo.sh
-file14=C:\mysql\scripts\mysql_fix_extensions.sh
-
-[lib]
-file0=C:\mysql\lib\Readme
-SubDir0=lib\debug
-SubDir1=lib\opt
-fulldirectory=
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Documentation.fgl b/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Documentation.fgl
deleted file mode 100755
index 107ebd1afb7..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Documentation.fgl
+++ /dev/null
@@ -1,101 +0,0 @@
-[Docs\Flags]
-file59=C:\mysql\Docs\Flags\romania.gif
-file48=C:\mysql\Docs\Flags\kroatia.eps
-file37=C:\mysql\Docs\Flags\iceland.gif
-file26=C:\mysql\Docs\Flags\france.eps
-file15=C:\mysql\Docs\Flags\china.gif
-file49=C:\mysql\Docs\Flags\kroatia.gif
-file38=C:\mysql\Docs\Flags\ireland.eps
-file27=C:\mysql\Docs\Flags\france.gif
-file16=C:\mysql\Docs\Flags\croatia.eps
-file0=C:\mysql\Docs\Flags\usa.gif
-file39=C:\mysql\Docs\Flags\ireland.gif
-file28=C:\mysql\Docs\Flags\germany.eps
-file17=C:\mysql\Docs\Flags\croatia.gif
-file1=C:\mysql\Docs\Flags\argentina.gif
-file29=C:\mysql\Docs\Flags\germany.gif
-file18=C:\mysql\Docs\Flags\czech-republic.eps
-file2=C:\mysql\Docs\Flags\australia.eps
-file19=C:\mysql\Docs\Flags\czech-republic.gif
-file3=C:\mysql\Docs\Flags\australia.gif
-file80=C:\mysql\Docs\Flags\usa.eps
-file4=C:\mysql\Docs\Flags\austria.eps
-file81=C:\mysql\Docs\Flags\argentina.eps
-file70=C:\mysql\Docs\Flags\spain.eps
-file5=C:\mysql\Docs\Flags\austria.gif
-file71=C:\mysql\Docs\Flags\spain.gif
-file60=C:\mysql\Docs\Flags\russia.eps
-file6=C:\mysql\Docs\Flags\brazil.eps
-file72=C:\mysql\Docs\Flags\sweden.eps
-file61=C:\mysql\Docs\Flags\russia.gif
-file50=C:\mysql\Docs\Flags\latvia.eps
-file7=C:\mysql\Docs\Flags\brazil.gif
-file73=C:\mysql\Docs\Flags\sweden.gif
-file62=C:\mysql\Docs\Flags\singapore.eps
-file51=C:\mysql\Docs\Flags\latvia.gif
-file40=C:\mysql\Docs\Flags\island.eps
-file8=C:\mysql\Docs\Flags\bulgaria.eps
-file74=C:\mysql\Docs\Flags\switzerland.eps
-file63=C:\mysql\Docs\Flags\singapore.gif
-file52=C:\mysql\Docs\Flags\netherlands.eps
-file41=C:\mysql\Docs\Flags\island.gif
-file30=C:\mysql\Docs\Flags\great-britain.eps
-file9=C:\mysql\Docs\Flags\bulgaria.gif
-file75=C:\mysql\Docs\Flags\switzerland.gif
-file64=C:\mysql\Docs\Flags\south-africa.eps
-file53=C:\mysql\Docs\Flags\netherlands.gif
-file42=C:\mysql\Docs\Flags\israel.eps
-file31=C:\mysql\Docs\Flags\great-britain.gif
-file20=C:\mysql\Docs\Flags\denmark.eps
-file76=C:\mysql\Docs\Flags\taiwan.eps
-file65=C:\mysql\Docs\Flags\south-africa.gif
-file54=C:\mysql\Docs\Flags\poland.eps
-file43=C:\mysql\Docs\Flags\israel.gif
-file32=C:\mysql\Docs\Flags\greece.eps
-file21=C:\mysql\Docs\Flags\denmark.gif
-file10=C:\mysql\Docs\Flags\canada.eps
-fulldirectory=
-file77=C:\mysql\Docs\Flags\taiwan.gif
-file66=C:\mysql\Docs\Flags\south-africa1.eps
-file55=C:\mysql\Docs\Flags\poland.gif
-file44=C:\mysql\Docs\Flags\italy.eps
-file33=C:\mysql\Docs\Flags\greece.gif
-file22=C:\mysql\Docs\Flags\estonia.eps
-file11=C:\mysql\Docs\Flags\canada.gif
-file78=C:\mysql\Docs\Flags\ukraine.eps
-file67=C:\mysql\Docs\Flags\south-africa1.gif
-file56=C:\mysql\Docs\Flags\portugal.eps
-file45=C:\mysql\Docs\Flags\italy.gif
-file34=C:\mysql\Docs\Flags\hungary.eps
-file23=C:\mysql\Docs\Flags\estonia.gif
-file12=C:\mysql\Docs\Flags\chile.eps
-file79=C:\mysql\Docs\Flags\ukraine.gif
-file68=C:\mysql\Docs\Flags\south-korea.eps
-file57=C:\mysql\Docs\Flags\portugal.gif
-file46=C:\mysql\Docs\Flags\japan.eps
-file35=C:\mysql\Docs\Flags\hungary.gif
-file24=C:\mysql\Docs\Flags\finland.eps
-file13=C:\mysql\Docs\Flags\chile.gif
-file69=C:\mysql\Docs\Flags\south-korea.gif
-file58=C:\mysql\Docs\Flags\romania.eps
-file47=C:\mysql\Docs\Flags\japan.gif
-file36=C:\mysql\Docs\Flags\iceland.eps
-file25=C:\mysql\Docs\Flags\finland.gif
-file14=C:\mysql\Docs\Flags\china.eps
-
-[Docs]
-file0=C:\mysql\Docs\manual_toc.html
-file1=C:\mysql\Docs\Copying
-file2=C:\mysql\Docs\Copying.lib
-file3=C:\mysql\Docs\manual.html
-file4=C:\mysql\Docs\manual.txt
-SubDir0=Docs\Flags
-fulldirectory=
-
-[TopDir]
-SubDir0=Docs
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Grant Tables.fgl b/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Grant Tables.fgl
deleted file mode 100755
index 178065a7003..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Grant Tables.fgl
+++ /dev/null
@@ -1,36 +0,0 @@
-[data\test]
-fulldirectory=
-
-[data\mysql]
-file15=C:\mysql\data\mysql\func.frm
-file16=C:\mysql\data\mysql\func.MYD
-file0=C:\mysql\data\mysql\columns_priv.frm
-file17=C:\mysql\data\mysql\func.MYI
-file1=C:\mysql\data\mysql\columns_priv.MYD
-file2=C:\mysql\data\mysql\columns_priv.MYI
-file3=C:\mysql\data\mysql\db.frm
-file4=C:\mysql\data\mysql\db.MYD
-file5=C:\mysql\data\mysql\db.MYI
-file6=C:\mysql\data\mysql\host.frm
-file7=C:\mysql\data\mysql\host.MYD
-file8=C:\mysql\data\mysql\host.MYI
-file9=C:\mysql\data\mysql\tables_priv.frm
-file10=C:\mysql\data\mysql\tables_priv.MYD
-fulldirectory=
-file11=C:\mysql\data\mysql\tables_priv.MYI
-file12=C:\mysql\data\mysql\user.frm
-file13=C:\mysql\data\mysql\user.MYD
-file14=C:\mysql\data\mysql\user.MYI
-
-[TopDir]
-SubDir0=data
-
-[data]
-SubDir0=data\mysql
-SubDir1=data\test
-fulldirectory=
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Servers.fgl b/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Servers.fgl
deleted file mode 100755
index c54ff378a55..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/File Groups/Servers.fgl
+++ /dev/null
@@ -1,229 +0,0 @@
-[Embedded\Static\release]
-file0=C:\mysql\embedded\Static\release\test_stc.dsp
-file1=C:\mysql\embedded\Static\release\ReadMe.txt
-file2=C:\mysql\embedded\Static\release\StdAfx.cpp
-file3=C:\mysql\embedded\Static\release\StdAfx.h
-file4=C:\mysql\embedded\Static\release\test_stc.cpp
-file5=C:\mysql\embedded\Static\release\mysqlserver.lib
-fulldirectory=
-
-[share\polish]
-file0=C:\mysql\share\polish\errmsg.sys
-file1=C:\mysql\share\polish\errmsg.txt
-fulldirectory=
-
-[share\dutch]
-file0=C:\mysql\share\dutch\errmsg.sys
-file1=C:\mysql\share\dutch\errmsg.txt
-fulldirectory=
-
-[share\spanish]
-file0=C:\mysql\share\spanish\errmsg.sys
-file1=C:\mysql\share\spanish\errmsg.txt
-fulldirectory=
-
-[share\english]
-file0=C:\mysql\share\english\errmsg.sys
-file1=C:\mysql\share\english\errmsg.txt
-fulldirectory=
-
-[bin]
-file0=C:\mysql\bin\mysqld-opt.exe
-file1=C:\mysql\bin\mysqld-max.exe
-file2=C:\mysql\bin\mysqld-max-nt.exe
-file3=C:\mysql\bin\mysqld-nt.exe
-file4=C:\mysql\bin\mysqld.exe
-file5=C:\mysql\bin\cygwinb19.dll
-file6=C:\mysql\bin\libmySQL.dll
-fulldirectory=
-
-[share\korean]
-file0=C:\mysql\share\korean\errmsg.sys
-file1=C:\mysql\share\korean\errmsg.txt
-fulldirectory=
-
-[share\charsets]
-file15=C:\mysql\share\charsets\latin1.conf
-file16=C:\mysql\share\charsets\latin2.conf
-file0=C:\mysql\share\charsets\win1251ukr.conf
-file17=C:\mysql\share\charsets\latin5.conf
-file1=C:\mysql\share\charsets\cp1257.conf
-file18=C:\mysql\share\charsets\Readme
-file2=C:\mysql\share\charsets\croat.conf
-file19=C:\mysql\share\charsets\swe7.conf
-file3=C:\mysql\share\charsets\danish.conf
-file4=C:\mysql\share\charsets\dec8.conf
-file5=C:\mysql\share\charsets\dos.conf
-file6=C:\mysql\share\charsets\estonia.conf
-file7=C:\mysql\share\charsets\german1.conf
-file8=C:\mysql\share\charsets\greek.conf
-file9=C:\mysql\share\charsets\hebrew.conf
-file20=C:\mysql\share\charsets\usa7.conf
-file21=C:\mysql\share\charsets\win1250.conf
-file10=C:\mysql\share\charsets\hp8.conf
-fulldirectory=
-file22=C:\mysql\share\charsets\win1251.conf
-file11=C:\mysql\share\charsets\hungarian.conf
-file23=C:\mysql\share\charsets\cp1251.conf
-file12=C:\mysql\share\charsets\Index
-file13=C:\mysql\share\charsets\koi8_ru.conf
-file14=C:\mysql\share\charsets\koi8_ukr.conf
-
-[Embedded\DLL\debug]
-file0=C:\mysql\embedded\DLL\debug\libmysqld.dll
-file1=C:\mysql\embedded\DLL\debug\libmysqld.exp
-file2=C:\mysql\embedded\DLL\debug\libmysqld.lib
-fulldirectory=
-
-[Embedded]
-file0=C:\mysql\embedded\embedded.dsw
-SubDir0=Embedded\DLL
-SubDir1=Embedded\Static
-fulldirectory=
-
-[share\ukrainian]
-file0=C:\mysql\share\ukrainian\errmsg.sys
-file1=C:\mysql\share\ukrainian\errmsg.txt
-fulldirectory=
-
-[share\hungarian]
-file0=C:\mysql\share\hungarian\errmsg.sys
-file1=C:\mysql\share\hungarian\errmsg.txt
-fulldirectory=
-
-[share\german]
-file0=C:\mysql\share\german\errmsg.sys
-file1=C:\mysql\share\german\errmsg.txt
-fulldirectory=
-
-[share\portuguese]
-file0=C:\mysql\share\portuguese\errmsg.sys
-file1=C:\mysql\share\portuguese\errmsg.txt
-fulldirectory=
-
-[share\estonian]
-file0=C:\mysql\share\estonian\errmsg.sys
-file1=C:\mysql\share\estonian\errmsg.txt
-fulldirectory=
-
-[share\romanian]
-file0=C:\mysql\share\romanian\errmsg.sys
-file1=C:\mysql\share\romanian\errmsg.txt
-fulldirectory=
-
-[share\french]
-file0=C:\mysql\share\french\errmsg.sys
-file1=C:\mysql\share\french\errmsg.txt
-fulldirectory=
-
-[share\swedish]
-file0=C:\mysql\share\swedish\errmsg.sys
-file1=C:\mysql\share\swedish\errmsg.txt
-fulldirectory=
-
-[share\slovak]
-file0=C:\mysql\share\slovak\errmsg.sys
-file1=C:\mysql\share\slovak\errmsg.txt
-fulldirectory=
-
-[share\greek]
-file0=C:\mysql\share\greek\errmsg.sys
-file1=C:\mysql\share\greek\errmsg.txt
-fulldirectory=
-
-[TopDir]
-file0=C:\mysql\mysqlbug.txt
-file1=C:\mysql\my-huge.cnf
-file2=C:\mysql\my-large.cnf
-file3=C:\mysql\my-medium.cnf
-file4=C:\mysql\my-small.cnf
-file5=C:\mysql\README.txt
-SubDir0=bin
-SubDir1=share
-SubDir2=Embedded
-
-[share]
-SubDir8=share\hungarian
-SubDir9=share\charsets
-SubDir20=share\spanish
-SubDir21=share\swedish
-SubDir10=share\italian
-SubDir22=share\ukrainian
-SubDir11=share\japanese
-SubDir12=share\korean
-SubDir13=share\norwegian
-SubDir14=share\norwegian-ny
-SubDir15=share\polish
-SubDir16=share\portuguese
-SubDir0=share\czech
-SubDir17=share\romanian
-SubDir1=share\danish
-SubDir18=share\russian
-SubDir2=share\dutch
-SubDir19=share\slovak
-SubDir3=share\english
-fulldirectory=
-SubDir4=share\estonian
-SubDir5=share\french
-SubDir6=share\german
-SubDir7=share\greek
-
-[share\norwegian-ny]
-file0=C:\mysql\share\norwegian-ny\errmsg.sys
-file1=C:\mysql\share\norwegian-ny\errmsg.txt
-fulldirectory=
-
-[Embedded\DLL]
-file0=C:\mysql\embedded\DLL\test_dll.dsp
-file1=C:\mysql\embedded\DLL\StdAfx.h
-file2=C:\mysql\embedded\DLL\test_dll.cpp
-file3=C:\mysql\embedded\DLL\StdAfx.cpp
-SubDir0=Embedded\DLL\debug
-SubDir1=Embedded\DLL\release
-fulldirectory=
-
-[Embedded\Static]
-SubDir0=Embedded\Static\release
-fulldirectory=
-
-[Embedded\DLL\release]
-file0=C:\mysql\embedded\DLL\release\libmysqld.dll
-file1=C:\mysql\embedded\DLL\release\libmysqld.exp
-file2=C:\mysql\embedded\DLL\release\libmysqld.lib
-file3=C:\mysql\embedded\DLL\release\mysql-server.exe
-fulldirectory=
-
-[share\danish]
-file0=C:\mysql\share\danish\errmsg.sys
-file1=C:\mysql\share\danish\errmsg.txt
-fulldirectory=
-
-[share\czech]
-file0=C:\mysql\share\czech\errmsg.sys
-file1=C:\mysql\share\czech\errmsg.txt
-fulldirectory=
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
-[share\russian]
-file0=C:\mysql\share\russian\errmsg.sys
-file1=C:\mysql\share\russian\errmsg.txt
-fulldirectory=
-
-[share\norwegian]
-file0=C:\mysql\share\norwegian\errmsg.sys
-file1=C:\mysql\share\norwegian\errmsg.txt
-fulldirectory=
-
-[share\japanese]
-file0=C:\mysql\share\japanese\errmsg.sys
-file1=C:\mysql\share\japanese\errmsg.txt
-fulldirectory=
-
-[share\italian]
-file0=C:\mysql\share\italian\errmsg.sys
-file1=C:\mysql\share\italian\errmsg.txt
-fulldirectory=
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Registry Entries/Default.rge b/VC++Files/InstallShield/4.0.XX-gpl/Registry Entries/Default.rge
deleted file mode 100755
index 537dfd82e48..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Registry Entries/Default.rge
+++ /dev/null
@@ -1,4 +0,0 @@
-[General]
-Type=REGISTRYDATA
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.dbg b/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.dbg
deleted file mode 100755
index 0c6d4e6b708..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.dbg
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.ino b/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.ino
deleted file mode 100755
index 204d8ea0f36..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.ino
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.ins b/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.ins
deleted file mode 100755
index 759009b5c84..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.ins
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.obs b/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.obs
deleted file mode 100755
index 5fcfcb62c4e..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.obs
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.rul.old b/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.rul.old
deleted file mode 100755
index df143b493c4..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/Setup.rul.old
+++ /dev/null
@@ -1,640 +0,0 @@
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// IIIIIII SSSSSS
-// II SS InstallShield (R)
-// II SSSSSS (c) 1996-1997, InstallShield Software Corporation
-// II SS (c) 1990-1996, InstallShield Corporation
-// IIIIIII SSSSSS All Rights Reserved.
-//
-//
-// This code is generated as a starting setup template. You should
-// modify it to provide all necessary steps for your setup.
-//
-//
-// File Name: Setup.rul
-//
-// Description: InstallShield script
-//
-// Comments: This template script performs a basic setup on a
-// Windows 95 or Windows NT 4.0 platform. With minor
-// modifications, this template can be adapted to create
-// new, customized setups.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
- // Include header file
-#include "sdlang.h"
-#include "sddialog.h"
-
-////////////////////// string defines ////////////////////////////
-
-#define UNINST_LOGFILE_NAME "Uninst.isu"
-
-//////////////////// installation declarations ///////////////////
-
- // ----- DLL prototypes -----
-
-
- // your DLL prototypes
-
-
- // ---- script prototypes -----
-
- // generated
- prototype ShowDialogs();
- prototype MoveFileData();
- prototype HandleMoveDataError( NUMBER );
- prototype ProcessBeforeDataMove();
- prototype ProcessAfterDataMove();
- prototype SetupRegistry();
- prototype SetupFolders();
- prototype CleanUpInstall();
- prototype SetupInstall();
- prototype SetupScreen();
- prototype CheckRequirements();
- prototype DialogShowSdWelcome();
- prototype DialogShowSdShowInfoList();
- prototype DialogShowSdAskDestPath();
- prototype DialogShowSdSetupType();
- prototype DialogShowSdComponentDialog2();
- prototype DialogShowSdFinishReboot();
-
- // your prototypes
-
-
- // ----- global variables ------
-
- // generated
- BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
- STRING svDir;
- STRING svName, svCompany, svSerial;
- STRING szAppPath;
- STRING svSetupType;
-
-
- // your global variables
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// MAIN PROGRAM
-//
-// The setup begins here by hiding the visible setup
-// window. This is done to allow all the titles, images, etc. to
-// be established before showing the main window. The following
-// logic then performs the setup in a series of steps.
-//
-///////////////////////////////////////////////////////////////////////////////
-program
- Disable( BACKGROUND );
-
- CheckRequirements();
-
- SetupInstall();
-
- SetupScreen();
-
- if (ShowDialogs()<0) goto end_install;
-
- if (ProcessBeforeDataMove()<0) goto end_install;
-
- if (MoveFileData()<0) goto end_install;
-
- if (ProcessAfterDataMove()<0) goto end_install;
-
- if (SetupRegistry()<0) goto end_install;
-
- if (SetupFolders()<0) goto end_install;
-
-
- end_install:
-
- CleanUpInstall();
-
- // If an unrecoverable error occurred, clean up the partial installation.
- // Otherwise, exit normally.
-
- if (bInstallAborted) then
- abort;
- endif;
-
-endprogram
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ShowDialogs //
-// //
-// Purpose: This function manages the display and navigation //
-// the standard dialogs that exist in a setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ShowDialogs()
- NUMBER nResult;
- begin
-
- Dlg_Start:
- // beginning of dialogs label
-
- Dlg_SdWelcome:
- nResult = DialogShowSdWelcome();
- if (nResult = BACK) goto Dlg_Start;
-
- Dlg_SdShowInfoList:
- nResult = DialogShowSdShowInfoList();
- if (nResult = BACK) goto Dlg_SdWelcome;
-
- Dlg_SdAskDestPath:
- nResult = DialogShowSdAskDestPath();
- if (nResult = BACK) goto Dlg_SdShowInfoList;
-
- Dlg_SdSetupType:
- nResult = DialogShowSdSetupType();
- if (nResult = BACK) goto Dlg_SdAskDestPath;
-
- Dlg_SdComponentDialog2:
- if ((nResult = BACK) && (svSetupType != "Custom") && (svSetupType != "")) then
- goto Dlg_SdSetupType;
- endif;
- nResult = DialogShowSdComponentDialog2();
- if (nResult = BACK) goto Dlg_SdSetupType;
-
- return 0;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessBeforeDataMove //
-// //
-// Purpose: This function performs any necessary operations prior to the //
-// actual data move operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessBeforeDataMove()
- STRING svLogFile;
- NUMBER nResult;
- begin
-
- InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
-
- svLogFile = UNINST_LOGFILE_NAME;
-
- nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
- if (nResult < 0) then
- MessageBox( @ERROR_UNINSTSETUP, WARNING );
- endif;
-
- szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir
-
- if ((bIs32BitSetup) && (bIsShellExplorer)) then
- RegDBSetItem( REGDB_APPPATH, szAppPath );
- RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
- RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
- endif;
-
- // TODO : update any items you want to process before moving the data
- //
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: MoveFileData //
-// //
-// Purpose: This function handles the data movement for //
-// the setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function MoveFileData()
- NUMBER nResult, nDisk;
- begin
-
- nDisk = 1;
- SetStatusWindow( 0, "" );
- Disable( DIALOGCACHE );
- Enable( STATUS );
- StatusUpdate( ON, 100 );
- nResult = ComponentMoveData( MEDIA, nDisk, 0 );
-
- HandleMoveDataError( nResult );
-
- Disable( STATUS );
-
- return nResult;
-
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: HandleMoveDataError //
-// //
-// Purpose: This function handles the error (if any) during the move data //
-// operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function HandleMoveDataError( nResult )
- STRING szErrMsg, svComponent , svFileGroup , svFile;
- begin
-
- svComponent = "";
- svFileGroup = "";
- svFile = "";
-
- switch (nResult)
- case 0:
- return 0;
- default:
- ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
- szErrMsg = @ERROR_MOVEDATA + "\n\n" +
- @ERROR_COMPONENT + " " + svComponent + "\n" +
- @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
- @ERROR_FILE + " " + svFile;
- SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
- bInstallAborted = TRUE;
- return nResult;
- endswitch;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessAfterDataMove //
-// //
-// Purpose: This function performs any necessary operations needed after //
-// all data has been moved. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessAfterDataMove()
- begin
-
- // TODO : update self-registered files and other processes that
- // should be performed after the data has been moved.
-
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupRegistry //
-// //
-// Purpose: This function makes the registry entries for this setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupRegistry()
- NUMBER nResult;
-
- begin
-
- // TODO : Add all your registry entry keys here
- //
- //
- // RegDBCreateKeyEx, RegDBSetKeyValueEx....
- //
-
- nResult = CreateRegistrySet( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// Function: SetupFolders
-//
-// Purpose: This function creates all the folders and shortcuts for the
-// setup. This includes program groups and items for Windows 3.1.
-//
-///////////////////////////////////////////////////////////////////////////////
-function SetupFolders()
- NUMBER nResult;
-
- begin
-
-
- // TODO : Add all your folder (program group) along with shortcuts (program items)
- //
- //
- // CreateProgramFolder, AddFolderIcon....
- //
-
- nResult = CreateShellObjects( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CleanUpInstall //
-// //
-// Purpose: This cleans up the setup. Anything that should //
-// be released or deleted at the end of the setup should //
-// be done here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CleanUpInstall()
- begin
-
-
- if (bInstallAborted) then
- return 0;
- endif;
-
- DialogShowSdFinishReboot();
-
- if (BATCH_INSTALL) then // ensure locked files are properly written
- CommitSharedFiles(0);
- endif;
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupInstall //
-// //
-// Purpose: This will setup the installation. Any general initialization //
-// needed for the installation should be performed here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupInstall()
- begin
-
- Enable( CORECOMPONENTHANDLING );
-
- bInstallAborted = FALSE;
-
- if (bIs32BitSetup) then
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME ^ @PRODUCT_NAME;
- else
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME16 ^ @PRODUCT_NAME16; // use shorten names
- endif;
-
- TARGETDIR = svDir;
-
- SdProductName( @PRODUCT_NAME );
-
- Enable( DIALOGCACHE );
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupScreen //
-// //
-// Purpose: This function establishes the screen look. This includes //
-// colors, fonts, and text to be displayed. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupScreen()
- begin
-
- Enable( FULLWINDOWMODE );
- Enable( INDVFILESTATUS );
- SetTitle( @TITLE_MAIN, 24, WHITE );
-
- SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
-
- Enable( BACKGROUND );
-
- Delay( 1 );
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CheckRequirements //
-// //
-// Purpose: This function checks all minimum requirements for the //
-// application being installed. If any fail, then the user //
-// is informed and the setup is terminated. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CheckRequirements()
- NUMBER nvDx, nvDy, nvResult;
- STRING svResult;
-
- begin
-
- bWinNT = FALSE;
- bIsShellExplorer = FALSE;
-
- // Check screen resolution.
- GetExtents( nvDx, nvDy );
-
- if (nvDy < 480) then
- MessageBox( @ERROR_VGARESOLUTION, WARNING );
- abort;
- endif;
-
- // set 'setup' operation mode
- bIs32BitSetup = TRUE;
- GetSystemInfo( ISTYPE, nvResult, svResult );
- if (nvResult = 16) then
- bIs32BitSetup = FALSE; // running 16-bit setup
- return 0; // no additional information required
- endif;
-
- // --- 32-bit testing after this point ---
-
- // Determine the target system's operating system.
- GetSystemInfo( OS, nvResult, svResult );
-
- if (nvResult = IS_WINDOWSNT) then
- // Running Windows NT.
- bWinNT = TRUE;
-
- // Check to see if the shell being used is EXPLORER shell.
- if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
- if (nvResult >= 4) then
- bIsShellExplorer = TRUE;
- endif;
- endif;
-
- elseif (nvResult = IS_WINDOWS95 ) then
- bIsShellExplorer = TRUE;
-
- endif;
-
-end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdWelcome //
-// //
-// Purpose: This function handles the standard welcome dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdWelcome()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdWelcome( szTitle, szMsg );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdShowInfoList //
-// //
-// Purpose: This function displays the general information list dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdShowInfoList()
- NUMBER nResult;
- LIST list;
- STRING szTitle, szMsg, szFile;
- begin
-
- szFile = SUPPORTDIR ^ "infolist.txt";
-
- list = ListCreate( STRINGLIST );
- ListReadFromFile( list, szFile );
- szTitle = "";
- szMsg = " ";
- nResult = SdShowInfoList( szTitle, szMsg, list );
-
- ListDestroy( list );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdAskDestPath //
-// //
-// Purpose: This function asks the user for the destination directory. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdAskDestPath()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
-
- TARGETDIR = svDir;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdSetupType //
-// //
-// Purpose: This function displays the standard setup type dialog. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdSetupType()
- NUMBER nResult, nType;
- STRING szTitle, szMsg;
- begin
-
- switch (svSetupType)
- case "Typical":
- nType = TYPICAL;
- case "Custom":
- nType = CUSTOM;
- case "Compact":
- nType = COMPACT;
- case "":
- svSetupType = "Typical";
- nType = TYPICAL;
- endswitch;
-
- szTitle = "";
- szMsg = "";
- nResult = SetupType( szTitle, szMsg, "", nType, 0 );
-
- switch (nResult)
- case COMPACT:
- svSetupType = "Compact";
- case TYPICAL:
- svSetupType = "Typical";
- case CUSTOM:
- svSetupType = "Custom";
- endswitch;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdComponentDialog2 //
-// //
-// Purpose: This function displays the custom component dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdComponentDialog2()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- if ((svSetupType != "Custom") && (svSetupType != "")) then
- return 0;
- endif;
-
- szTitle = "";
- szMsg = "";
- nResult = SdComponentDialog2( szTitle, szMsg, svDir, "" );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdFinishReboot //
-// //
-// Purpose: This function will show the last dialog of the product. //
-// It will allow the user to reboot and/or show some readme text. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdFinishReboot()
- NUMBER nResult, nDefOptions;
- STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
- NUMBER bOpt1, bOpt2;
- begin
-
- if (!BATCH_INSTALL) then
- bOpt1 = FALSE;
- bOpt2 = FALSE;
- szMsg1 = "";
- szMsg2 = "";
- szOption1 = "";
- szOption2 = "";
- nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
- return 0;
- endif;
-
- nDefOptions = SYS_BOOTMACHINE;
- szTitle = "";
- szMsg1 = "";
- szMsg2 = "";
- nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );
-
- return nResult;
- end;
-
- // --- include script file section ---
-
-#include "sddialog.rul"
-
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/setup.rul b/VC++Files/InstallShield/4.0.XX-gpl/Script Files/setup.rul
deleted file mode 100755
index 73d61114075..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Script Files/setup.rul
+++ /dev/null
@@ -1,641 +0,0 @@
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// IIIIIII SSSSSS
-// II SS InstallShield (R)
-// II SSSSSS (c) 1996-1997, InstallShield Software Corporation
-// II SS (c) 1990-1996, InstallShield Corporation
-// IIIIIII SSSSSS All Rights Reserved.
-//
-//
-// This code is generated as a starting setup template. You should
-// modify it to provide all necessary steps for your setup.
-//
-//
-// File Name: Setup.rul
-//
-// Description: InstallShield script
-//
-// Comments: This template script performs a basic setup on a
-// Windows 95 or Windows NT 4.0 platform. With minor
-// modifications, this template can be adapted to create
-// new, customized setups.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
- // Include header file
-#include "sdlang.h"
-#include "sddialog.h"
-
-////////////////////// string defines ////////////////////////////
-
-#define UNINST_LOGFILE_NAME "Uninst.isu"
-
-//////////////////// installation declarations ///////////////////
-
- // ----- DLL prototypes -----
-
-
- // your DLL prototypes
-
-
- // ---- script prototypes -----
-
- // generated
- prototype ShowDialogs();
- prototype MoveFileData();
- prototype HandleMoveDataError( NUMBER );
- prototype ProcessBeforeDataMove();
- prototype ProcessAfterDataMove();
- prototype SetupRegistry();
- prototype SetupFolders();
- prototype CleanUpInstall();
- prototype SetupInstall();
- prototype SetupScreen();
- prototype CheckRequirements();
- prototype DialogShowSdWelcome();
- prototype DialogShowSdShowInfoList();
- prototype DialogShowSdAskDestPath();
- prototype DialogShowSdSetupType();
- prototype DialogShowSdComponentDialog2();
- prototype DialogShowSdFinishReboot();
-
- // your prototypes
-
-
- // ----- global variables ------
-
- // generated
- BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
- STRING svDir;
- STRING svName, svCompany, svSerial;
- STRING szAppPath;
- STRING svSetupType;
-
-
- // your global variables
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// MAIN PROGRAM
-//
-// The setup begins here by hiding the visible setup
-// window. This is done to allow all the titles, images, etc. to
-// be established before showing the main window. The following
-// logic then performs the setup in a series of steps.
-//
-///////////////////////////////////////////////////////////////////////////////
-program
- Disable( BACKGROUND );
-
- CheckRequirements();
-
- SetupInstall();
-
- SetupScreen();
-
- if (ShowDialogs()<0) goto end_install;
-
- if (ProcessBeforeDataMove()<0) goto end_install;
-
- if (MoveFileData()<0) goto end_install;
-
- if (ProcessAfterDataMove()<0) goto end_install;
-
- if (SetupRegistry()<0) goto end_install;
-
- if (SetupFolders()<0) goto end_install;
-
-
- end_install:
-
- CleanUpInstall();
-
- // If an unrecoverable error occurred, clean up the partial installation.
- // Otherwise, exit normally.
-
- if (bInstallAborted) then
- abort;
- endif;
-
-endprogram
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ShowDialogs //
-// //
-// Purpose: This function manages the display and navigation //
-// the standard dialogs that exist in a setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ShowDialogs()
- NUMBER nResult;
- begin
-
- Dlg_Start:
- // beginning of dialogs label
-
- Dlg_SdWelcome:
- nResult = DialogShowSdWelcome();
- if (nResult = BACK) goto Dlg_Start;
-
- Dlg_SdShowInfoList:
- nResult = DialogShowSdShowInfoList();
- if (nResult = BACK) goto Dlg_SdWelcome;
-
- Dlg_SdAskDestPath:
- nResult = DialogShowSdAskDestPath();
- if (nResult = BACK) goto Dlg_SdShowInfoList;
-
- Dlg_SdSetupType:
- nResult = DialogShowSdSetupType();
- if (nResult = BACK) goto Dlg_SdAskDestPath;
-
- Dlg_SdComponentDialog2:
- if ((nResult = BACK) && (svSetupType != "Custom") && (svSetupType != "")) then
- goto Dlg_SdSetupType;
- endif;
- nResult = DialogShowSdComponentDialog2();
- if (nResult = BACK) goto Dlg_SdSetupType;
-
- return 0;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessBeforeDataMove //
-// //
-// Purpose: This function performs any necessary operations prior to the //
-// actual data move operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessBeforeDataMove()
- STRING svLogFile;
- NUMBER nResult;
- begin
-
- InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
-
- svLogFile = UNINST_LOGFILE_NAME;
-
- nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
- if (nResult < 0) then
- MessageBox( @ERROR_UNINSTSETUP, WARNING );
- endif;
-
- szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir
-
- if ((bIs32BitSetup) && (bIsShellExplorer)) then
-// RegDBSetItem( REGDB_APPPATH, szAppPath );
-// RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
- RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
- endif;
-
- // TODO : update any items you want to process before moving the data
- //
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: MoveFileData //
-// //
-// Purpose: This function handles the data movement for //
-// the setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function MoveFileData()
- NUMBER nResult, nDisk;
- begin
-
- nDisk = 1;
- SetStatusWindow( 0, "" );
- Disable( DIALOGCACHE );
- Enable( STATUS );
- StatusUpdate( ON, 100 );
- nResult = ComponentMoveData( MEDIA, nDisk, 0 );
-
- HandleMoveDataError( nResult );
-
- Disable( STATUS );
-
- return nResult;
-
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: HandleMoveDataError //
-// //
-// Purpose: This function handles the error (if any) during the move data //
-// operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function HandleMoveDataError( nResult )
- STRING szErrMsg, svComponent , svFileGroup , svFile;
- begin
-
- svComponent = "";
- svFileGroup = "";
- svFile = "";
-
- switch (nResult)
- case 0:
- return 0;
- default:
- ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
- szErrMsg = @ERROR_MOVEDATA + "\n\n" +
- @ERROR_COMPONENT + " " + svComponent + "\n" +
- @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
- @ERROR_FILE + " " + svFile;
- SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
- bInstallAborted = TRUE;
- return nResult;
- endswitch;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessAfterDataMove //
-// //
-// Purpose: This function performs any necessary operations needed after //
-// all data has been moved. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessAfterDataMove()
- begin
-
- // TODO : update self-registered files and other processes that
- // should be performed after the data has been moved.
-
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupRegistry //
-// //
-// Purpose: This function makes the registry entries for this setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupRegistry()
- NUMBER nResult;
-
- begin
-
- // TODO : Add all your registry entry keys here
- //
- //
- // RegDBCreateKeyEx, RegDBSetKeyValueEx....
- //
-
- nResult = CreateRegistrySet( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// Function: SetupFolders
-//
-// Purpose: This function creates all the folders and shortcuts for the
-// setup. This includes program groups and items for Windows 3.1.
-//
-///////////////////////////////////////////////////////////////////////////////
-function SetupFolders()
- NUMBER nResult;
-
- begin
-
-
- // TODO : Add all your folder (program group) along with shortcuts (program items)
- //
- //
- // CreateProgramFolder, AddFolderIcon....
- //
-
- nResult = CreateShellObjects( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CleanUpInstall //
-// //
-// Purpose: This cleans up the setup. Anything that should //
-// be released or deleted at the end of the setup should //
-// be done here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CleanUpInstall()
- begin
-
-
- if (bInstallAborted) then
- return 0;
- endif;
-
- DialogShowSdFinishReboot();
-
- if (BATCH_INSTALL) then // ensure locked files are properly written
- CommitSharedFiles(0);
- endif;
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupInstall //
-// //
-// Purpose: This will setup the installation. Any general initialization //
-// needed for the installation should be performed here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupInstall()
- begin
-
- Enable( CORECOMPONENTHANDLING );
-
- bInstallAborted = FALSE;
-
- if (bIs32BitSetup) then
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME ^ @PRODUCT_NAME;
- else
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME16 ^ @PRODUCT_NAME16; // use shorten names
- endif;
-
- TARGETDIR = svDir;
-
- SdProductName( @PRODUCT_NAME );
-
- Enable( DIALOGCACHE );
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupScreen //
-// //
-// Purpose: This function establishes the screen look. This includes //
-// colors, fonts, and text to be displayed. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupScreen()
- begin
-
- Enable( FULLWINDOWMODE );
- Enable( INDVFILESTATUS );
- SetTitle( @TITLE_MAIN, 24, WHITE );
-
- SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
-
- Enable( BACKGROUND );
-
- Delay( 1 );
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CheckRequirements //
-// //
-// Purpose: This function checks all minimum requirements for the //
-// application being installed. If any fail, then the user //
-// is informed and the setup is terminated. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CheckRequirements()
- NUMBER nvDx, nvDy, nvResult;
- STRING svResult;
-
- begin
-
- bWinNT = FALSE;
- bIsShellExplorer = FALSE;
-
- // Check screen resolution.
- GetExtents( nvDx, nvDy );
-
- if (nvDy < 480) then
- MessageBox( @ERROR_VGARESOLUTION, WARNING );
- abort;
- endif;
-
- // set 'setup' operation mode
- bIs32BitSetup = TRUE;
- GetSystemInfo( ISTYPE, nvResult, svResult );
- if (nvResult = 16) then
- bIs32BitSetup = FALSE; // running 16-bit setup
- return 0; // no additional information required
- endif;
-
- // --- 32-bit testing after this point ---
-
- // Determine the target system's operating system.
- GetSystemInfo( OS, nvResult, svResult );
-
- if (nvResult = IS_WINDOWSNT) then
- // Running Windows NT.
- bWinNT = TRUE;
-
- // Check to see if the shell being used is EXPLORER shell.
- if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
- if (nvResult >= 4) then
- bIsShellExplorer = TRUE;
- endif;
- endif;
-
- elseif (nvResult = IS_WINDOWS95 ) then
- bIsShellExplorer = TRUE;
-
- endif;
-
-end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdWelcome //
-// //
-// Purpose: This function handles the standard welcome dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdWelcome()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdWelcome( szTitle, szMsg );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdShowInfoList //
-// //
-// Purpose: This function displays the general information list dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdShowInfoList()
- NUMBER nResult;
- LIST list;
- STRING szTitle, szMsg, szFile;
- begin
-
- szFile = SUPPORTDIR ^ "infolist.txt";
-
- list = ListCreate( STRINGLIST );
- ListReadFromFile( list, szFile );
- szTitle = "";
- szMsg = " ";
- nResult = SdShowInfoList( szTitle, szMsg, list );
-
- ListDestroy( list );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdAskDestPath //
-// //
-// Purpose: This function asks the user for the destination directory. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdAskDestPath()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
-
- TARGETDIR = svDir;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdSetupType //
-// //
-// Purpose: This function displays the standard setup type dialog. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdSetupType()
- NUMBER nResult, nType;
- STRING szTitle, szMsg;
- begin
-
- switch (svSetupType)
- case "Typical":
- nType = TYPICAL;
- case "Custom":
- nType = CUSTOM;
- case "Compact":
- nType = COMPACT;
- case "":
- svSetupType = "Typical";
- nType = TYPICAL;
- endswitch;
-
- szTitle = "";
- szMsg = "";
- nResult = SetupType( szTitle, szMsg, "", nType, 0 );
-
- switch (nResult)
- case COMPACT:
- svSetupType = "Compact";
- case TYPICAL:
- svSetupType = "Typical";
- case CUSTOM:
- svSetupType = "Custom";
- endswitch;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdComponentDialog2 //
-// //
-// Purpose: This function displays the custom component dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdComponentDialog2()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- if ((svSetupType != "Custom") && (svSetupType != "")) then
- return 0;
- endif;
-
- szTitle = "";
- szMsg = "";
- nResult = SdComponentDialog2( szTitle, szMsg, svDir, "" );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdFinishReboot //
-// //
-// Purpose: This function will show the last dialog of the product. //
-// It will allow the user to reboot and/or show some readme text. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdFinishReboot()
- NUMBER nResult, nDefOptions;
- STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
- NUMBER bOpt1, bOpt2;
- begin
-
- if (!BATCH_INSTALL) then
- bOpt1 = FALSE;
- bOpt2 = FALSE;
- szMsg1 = "";
- szMsg2 = "";
- szOption1 = "";
- szOption2 = "";
- nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
- return 0;
- endif;
-
- nDefOptions = SYS_BOOTMACHINE;
- szTitle = "";
- szMsg1 = "";
- szMsg2 = "";
- nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );
-
- return nResult;
- end;
-
- // --- include script file section ---
-
-#include "sddialog.rul"
-
-
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt b/VC++Files/InstallShield/4.0.XX-gpl/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt
deleted file mode 100755
index acdf4f48618..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-This is a release of MySQL @VERSION@ for Win32.
-
-NOTE: If you install MySQL in a folder other than
-C:\MYSQL or you intend to start MySQL on NT/Win2000
-as a service, you must create a file named C:\MY.CNF
-or \Windows\my.ini or \winnt\my.ini with the following
-information::
-
-[mysqld]
-basedir=E:/installation-path/
-datadir=E:/data-path/
-
-After your have installed MySQL, the installation
-directory will contain 4 files named 'my-small.cnf,
-my-medium.cnf, my-large.cnf, my-huge.cnf'.
-You can use this as a starting point for your own
-C:\my.cnf file.
-
-If you have any problems, you can mail them to
-win32@lists.mysql.com after you have consulted the
-MySQL manual and the MySQL mailing list archive
-(http://www.mysql.com/documentation/index.html)
-
-On behalf of the MySQL AB gang,
-Michael Widenius
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmp b/VC++Files/InstallShield/4.0.XX-gpl/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmp
deleted file mode 100755
index 3229d50c9bf..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Shell Objects/Default.shl b/VC++Files/InstallShield/4.0.XX-gpl/Shell Objects/Default.shl
deleted file mode 100755
index 187cb651307..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Shell Objects/Default.shl
+++ /dev/null
@@ -1,12 +0,0 @@
-[Data]
-Folder3=<FOLDER_STARTUP>
-Group0=Main
-Group1=Startup
-Folder0=<FOLDER_DESKTOP>
-Folder1=<FOLDER_STARTMENU>
-Folder2=<FOLDER_PROGRAMS>
-
-[Info]
-Type=ShellObject
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl b/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl
deleted file mode 100755
index 35e7c278cc9..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl
+++ /dev/null
@@ -1,23 +0,0 @@
-[Data]
-TITLE_MAIN=MySQL Servers and Clients @VERSION@
-COMPANY_NAME=MySQL AB
-ERROR_COMPONENT=Component:
-COMPANY_NAME16=Company
-PRODUCT_VERSION=MySQL Servers and Clients @VERSION@
-ERROR_MOVEDATA=An error occurred during the move data process: %d
-ERROR_FILEGROUP=File Group:
-UNINST_KEY=MySQL Servers and Clients @VERSION@
-TITLE_CAPTIONBAR=MySQL Servers and Clients @VERSION@
-PRODUCT_NAME16=Product
-ERROR_VGARESOLUTION=This program requires VGA or better resolution.
-ERROR_FILE=File:
-UNINST_DISPLAY_NAME=MySQL Servers and Clients @VERSION@
-PRODUCT_KEY=yourapp.Exe
-PRODUCT_NAME=MySQL Servers and Clients @VERSION@
-ERROR_UNINSTSETUP=unInstaller setup failed to initialize. You may not be able to uninstall this product.
-
-[General]
-Language=0009
-Type=STRINGTABLESPECIFIC
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/String Tables/Default.shl b/VC++Files/InstallShield/4.0.XX-gpl/String Tables/Default.shl
deleted file mode 100755
index d4dc4925ab1..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/String Tables/Default.shl
+++ /dev/null
@@ -1,74 +0,0 @@
-[TITLE_MAIN]
-Comment=
-
-[COMPANY_NAME]
-Comment=
-
-[ERROR_COMPONENT]
-Comment=
-
-[COMPANY_NAME16]
-Comment=
-
-[PRODUCT_VERSION]
-Comment=
-
-[ERROR_MOVEDATA]
-Comment=
-
-[ERROR_FILEGROUP]
-Comment=
-
-[Language]
-Lang0=0009
-CurrentLang=0
-
-[UNINST_KEY]
-Comment=
-
-[TITLE_CAPTIONBAR]
-Comment=
-
-[Data]
-Entry0=ERROR_VGARESOLUTION
-Entry1=TITLE_MAIN
-Entry2=TITLE_CAPTIONBAR
-Entry3=UNINST_KEY
-Entry4=UNINST_DISPLAY_NAME
-Entry5=COMPANY_NAME
-Entry6=PRODUCT_NAME
-Entry7=PRODUCT_VERSION
-Entry8=PRODUCT_KEY
-Entry9=ERROR_MOVEDATA
-Entry10=ERROR_UNINSTSETUP
-Entry11=COMPANY_NAME16
-Entry12=PRODUCT_NAME16
-Entry13=ERROR_COMPONENT
-Entry14=ERROR_FILEGROUP
-Entry15=ERROR_FILE
-
-[PRODUCT_NAME16]
-Comment=
-
-[ERROR_VGARESOLUTION]
-Comment=
-
-[ERROR_FILE]
-Comment=
-
-[General]
-Type=STRINGTABLE
-Version=1.00.000
-
-[UNINST_DISPLAY_NAME]
-Comment=
-
-[PRODUCT_KEY]
-Comment=
-
-[PRODUCT_NAME]
-Comment=
-
-[ERROR_UNINSTSETUP]
-Comment=
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Text Substitutions/Build.tsb b/VC++Files/InstallShield/4.0.XX-gpl/Text Substitutions/Build.tsb
deleted file mode 100755
index 3949bd4c066..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Text Substitutions/Build.tsb
+++ /dev/null
@@ -1,56 +0,0 @@
-[<HKUS>]
-Value=
-KeyType=4
-
-[<HKCR>]
-Value=
-KeyType=4
-
-[<PROGRAMFILES>]
-Value=
-KeyType=4
-
-[<WINSYSDIR>]
-Value=
-KeyType=4
-
-[<COMMONFILES>]
-Value=
-KeyType=4
-
-[<WINDIR>]
-Value=
-KeyType=4
-
-[Data]
-Key0=<PROGRAMFILES>
-Key1=<COMMONFILES>
-Key2=<WINDIR>
-Key3=<WINSYSDIR>
-Key4=<HKLM>
-Key5=<HKCU>
-Key6=<HKCC>
-Key7=<HKDD>
-Key8=<HKUS>
-Key9=<HKCR>
-
-[General]
-Type=TEXTSUB
-Version=1.00.000
-
-[<HKLM>]
-Value=
-KeyType=4
-
-[<HKCU>]
-Value=
-KeyType=4
-
-[<HKCC>]
-Value=
-KeyType=4
-
-[<HKDD>]
-Value=
-KeyType=4
-
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/Text Substitutions/Setup.tsb b/VC++Files/InstallShield/4.0.XX-gpl/Text Substitutions/Setup.tsb
deleted file mode 100755
index b0c5a509f0b..00000000000
--- a/VC++Files/InstallShield/4.0.XX-gpl/Text Substitutions/Setup.tsb
+++ /dev/null
@@ -1,76 +0,0 @@
-[<SRCDIR>]
-Value=
-KeyType=4
-
-[<HKUS>]
-Value=
-KeyType=4
-
-[<HKCR>]
-Value=
-KeyType=4
-
-[<PROGRAMFILES>]
-Value=
-KeyType=4
-
-[<TARGETDIR>]
-Value=
-KeyType=4
-
-[<WINSYSDIR>]
-Value=
-KeyType=4
-
-[<COMMONFILES>]
-Value=
-KeyType=4
-
-[<WINDIR>]
-Value=
-KeyType=4
-
-[Data]
-Key0=<PROGRAMFILES>
-Key1=<COMMONFILES>
-Key2=<WINDIR>
-Key3=<WINSYSDIR>
-Key4=<TARGETDIR>
-Key5=<SUPPORTDIR>
-Key10=<HKDD>
-Key6=<SRCDIR>
-Key11=<HKUS>
-Key7=<HKLM>
-Key12=<HKCR>
-Key8=<HKCU>
-Key13=<SHELL_OBJECT_FOLDER>
-Key9=<HKCC>
-
-[<SUPPORTDIR>]
-Value=
-KeyType=4
-
-[<SHELL_OBJECT_FOLDER>]
-Value=
-KeyType=4
-
-[General]
-Type=TEXTSUB
-Version=1.00.000
-
-[<HKLM>]
-Value=
-KeyType=4
-
-[<HKCU>]
-Value=
-KeyType=4
-
-[<HKCC>]
-Value=
-KeyType=4
-
-[<HKDD>]
-Value=
-KeyType=4
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/4.0.XX-pro.ipr b/VC++Files/InstallShield/4.0.XX-pro/4.0.XX-pro.ipr
deleted file mode 100755
index bfa7a082873..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/4.0.XX-pro.ipr
+++ /dev/null
@@ -1,52 +0,0 @@
-[Language]
-LanguageSupport0=0009
-
-[OperatingSystem]
-OSSupport=0000000000010010
-
-[Data]
-CurrentMedia=New Media
-CurrentComponentDef=Default.cdf
-ProductName=MySQL Servers and Clients
-set_mifserial=
-DevEnvironment=Microsoft Visual C++ 6
-AppExe=
-set_dlldebug=No
-EmailAddresss=
-Instructions=Instructions.txt
-set_testmode=No
-set_mif=No
-SummaryText=
-Department=
-HomeURL=
-Author=
-Type=Database Application
-InstallRoot=D:\MySQL-Install\4.0.xpro
-Version=1.00.000
-InstallationGUID=40744a4d-efed-4cff-84a9-9e6389550f5c
-set_level=Level 3
-CurrentFileGroupDef=Default.fdf
-Notes=Notes.txt
-set_maxerr=50
-set_args=
-set_miffile=Status.mif
-set_dllcmdline=
-Copyright=
-set_warnaserr=No
-CurrentPlatform=
-Category=
-set_preproc=
-CurrentLanguage=English
-CompanyName=MySQL
-Description=Description.txt
-set_maxwarn=50
-set_crc=Yes
-set_compileb4build=No
-
-[MediaInfo]
-mediadata0=New Media/
-
-[General]
-Type=INSTALLMAIN
-Version=1.10.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Component Definitions/Default.cdf b/VC++Files/InstallShield/4.0.XX-pro/Component Definitions/Default.cdf
deleted file mode 100755
index 48d37800cd1..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Component Definitions/Default.cdf
+++ /dev/null
@@ -1,192 +0,0 @@
-[Development]
-required0=Servers
-SELECTED=Yes
-FILENEED=STANDARD
-required1=Grant Tables
-HTTPLOCATION=
-STATUS=Examples, Libraries, Includes and Script files
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=Examples, Libraries, Includes and Script files
-DISPLAYTEXT=Examples, Libraries, Includes and Script files
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Development
-COMMENT=
-INCLUDEINBUILD=Yes
-INSTALLATION=ALWAYSOVERWRITE
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[Grant Tables]
-required0=Servers
-SELECTED=Yes
-FILENEED=CRITICAL
-HTTPLOCATION=
-STATUS=The Grant Tables and Core Files
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The Grant Tables and Core Files
-DISPLAYTEXT=The Grant Tables and Core Files
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Grant Tables
-requiredby0=Development
-COMMENT=
-INCLUDEINBUILD=Yes
-requiredby1=Clients and Tools
-INSTALLATION=NEVEROVERWRITE
-requiredby2=Documentation
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[Components]
-component0=Development
-component1=Grant Tables
-component2=Servers
-component3=Clients and Tools
-component4=Documentation
-
-[TopComponents]
-component0=Servers
-component1=Clients and Tools
-component2=Documentation
-component3=Development
-component4=Grant Tables
-
-[SetupType]
-setuptype0=Compact
-setuptype1=Typical
-setuptype2=Custom
-
-[Clients and Tools]
-required0=Servers
-SELECTED=Yes
-FILENEED=HIGHLYRECOMMENDED
-required1=Grant Tables
-HTTPLOCATION=
-STATUS=The MySQL clients and Maintenance Tools
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The MySQL clients and Maintenance Tools
-DISPLAYTEXT=The MySQL clients and Maintenance Tools
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Clients and Tools
-COMMENT=
-INCLUDEINBUILD=Yes
-INSTALLATION=NEWERDATE
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[Servers]
-SELECTED=Yes
-FILENEED=CRITICAL
-HTTPLOCATION=
-STATUS=The MySQL Servers
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The MySQL Servers
-DISPLAYTEXT=The MySQL Servers
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Servers
-requiredby0=Development
-COMMENT=
-INCLUDEINBUILD=Yes
-requiredby1=Grant Tables
-INSTALLATION=ALWAYSOVERWRITE
-requiredby2=Clients and Tools
-requiredby3=Documentation
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
-[SetupTypeItem-Compact]
-Comment=
-item0=Grant Tables
-item1=Servers
-item2=Clients and Tools
-item3=Documentation
-Descrip=
-DisplayText=
-
-[SetupTypeItem-Custom]
-Comment=
-item0=Development
-item1=Grant Tables
-item2=Servers
-item3=Clients and Tools
-Descrip=
-item4=Documentation
-DisplayText=
-
-[Info]
-Type=CompDef
-Version=1.00.000
-Name=
-
-[SetupTypeItem-Typical]
-Comment=
-item0=Development
-item1=Grant Tables
-item2=Servers
-item3=Clients and Tools
-Descrip=
-item4=Documentation
-DisplayText=
-
-[Documentation]
-required0=Servers
-SELECTED=Yes
-FILENEED=HIGHLYRECOMMENDED
-required1=Grant Tables
-HTTPLOCATION=
-STATUS=The MySQL Documentation with different formats
-UNINSTALLABLE=Yes
-TARGET=<TARGETDIR>
-FTPLOCATION=
-VISIBLE=Yes
-DESCRIPTION=The MySQL Documentation with different formats
-DISPLAYTEXT=The MySQL Documentation with different formats
-IMAGE=
-DEFSELECTION=Yes
-filegroup0=Documentation
-COMMENT=
-INCLUDEINBUILD=Yes
-INSTALLATION=ALWAYSOVERWRITE
-COMPRESSIFSEPARATE=No
-MISC=
-ENCRYPT=No
-DISK=ANYDISK
-TARGETDIRCDROM=
-PASSWORD=
-TARGETHIDDEN=General Application Destination
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Component Definitions/Default.fgl b/VC++Files/InstallShield/4.0.XX-pro/Component Definitions/Default.fgl
deleted file mode 100755
index 4e20dcea4ab..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Component Definitions/Default.fgl
+++ /dev/null
@@ -1,42 +0,0 @@
-[<PROGRAMFILES>\<COMMONFILES>]
-DISPLAYTEXT=Common Files Folder
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[<WINDIR>\<WINSYSDIR>]
-DISPLAYTEXT=Windows System Folder
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[USERDEFINED]
-DISPLAYTEXT=Script-defined Folders
-TYPE=USERSTART
-fulldirectory=
-
-[<PROGRAMFILES>]
-DISPLAYTEXT=Program Files Folder
-SubDir0=<PROGRAMFILES>\<COMMONFILES>
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[<TARGETDIR>]
-DISPLAYTEXT=General Application Destination
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[<WINDIR>]
-DISPLAYTEXT=Windows Operating System
-SubDir0=<WINDIR>\<WINSYSDIR>
-TYPE=TEXTSUBFIXED
-fulldirectory=
-
-[TopDir]
-SubDir0=<WINDIR>
-SubDir1=<PROGRAMFILES>
-SubDir2=<TARGETDIR>
-SubDir3=USERDEFINED
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Clients and Tools.fgl b/VC++Files/InstallShield/4.0.XX-pro/File Groups/Clients and Tools.fgl
deleted file mode 100755
index ed1e42e65b6..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Clients and Tools.fgl
+++ /dev/null
@@ -1,32 +0,0 @@
-[bin]
-file15=C:\mysql\bin\replace.exe
-file16=C:\mysql\bin\winmysqladmin.cnt
-file0=C:\mysql\bin\isamchk.exe
-file17=C:\mysql\bin\WINMYSQLADMIN.HLP
-file1=C:\mysql\bin\myisamchk.exe
-file18=C:\mysql\bin\comp-err.exe
-file2=C:\mysql\bin\myisamlog.exe
-file19=C:\mysql\bin\my_print_defaults.exe
-file3=C:\mysql\bin\myisampack.exe
-file4=C:\mysql\bin\mysql.exe
-file5=C:\mysql\bin\mysqladmin.exe
-file6=C:\mysql\bin\mysqlbinlog.exe
-file7=C:\mysql\bin\mysqlc.exe
-file8=C:\mysql\bin\mysqlcheck.exe
-file9=C:\mysql\bin\mysqldump.exe
-file20=C:\mysql\bin\winmysqladmin.exe
-file21=C:\mysql\bin\myisam_ftdump.exe
-file10=C:\mysql\bin\mysqlimport.exe
-fulldirectory=
-file11=C:\mysql\bin\mysqlshow.exe
-file12=C:\mysql\bin\mysqlwatch.exe
-file13=C:\mysql\bin\pack_isam.exe
-file14=C:\mysql\bin\perror.exe
-
-[TopDir]
-SubDir0=bin
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Default.fdf b/VC++Files/InstallShield/4.0.XX-pro/File Groups/Default.fdf
deleted file mode 100755
index 8096a4b74bf..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Default.fdf
+++ /dev/null
@@ -1,82 +0,0 @@
-[FileGroups]
-group0=Development
-group1=Grant Tables
-group2=Servers
-group3=Clients and Tools
-group4=Documentation
-
-[Development]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Grant Tables]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Clients and Tools]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=0000000000000000
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Servers]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
-[Info]
-Type=FileGrp
-Version=1.00.000
-Name=
-
-[Documentation]
-SELFREGISTERING=No
-HTTPLOCATION=
-LANGUAGE=
-OPERATINGSYSTEM=
-FTPLOCATION=
-FILETYPE=No
-INFOTYPE=Standard
-COMMENT=
-COMPRESS=Yes
-COMPRESSDLL=
-POTENTIALLY=No
-MISC=
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Development.fgl b/VC++Files/InstallShield/4.0.XX-pro/File Groups/Development.fgl
deleted file mode 100755
index 292cc867909..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Development.fgl
+++ /dev/null
@@ -1,240 +0,0 @@
-[bench\Data\Wisconsin]
-file0=C:\mysql\bench\Data\Wisconsin\onek.data
-file1=C:\mysql\bench\Data\Wisconsin\tenk.data
-fulldirectory=
-
-[lib\debug]
-file0=C:\mysql\lib\debug\libmySQL.dll
-file1=C:\mysql\lib\debug\libmySQL.lib
-file2=C:\mysql\lib\debug\mysqlclient.lib
-file3=C:\mysql\lib\debug\zlib.lib
-file4=C:\mysql\lib\debug\mysys.lib
-file5=C:\mysql\lib\debug\regex.lib
-file6=C:\mysql\lib\debug\strings.lib
-fulldirectory=
-
-[bench\output]
-fulldirectory=
-
-[examples\libmysqltest]
-file0=C:\mysql\examples\libmysqltest\myTest.c
-file1=C:\mysql\examples\libmysqltest\myTest.dsp
-file2=C:\mysql\examples\libmysqltest\myTest.dsw
-file3=C:\mysql\examples\libmysqltest\myTest.exe
-file4=C:\mysql\examples\libmysqltest\myTest.mak
-file5=C:\mysql\examples\libmysqltest\myTest.ncb
-file6=C:\mysql\examples\libmysqltest\myTest.opt
-file7=C:\mysql\examples\libmysqltest\readme
-fulldirectory=
-
-[include]
-file15=C:\mysql\include\libmysqld.def
-file16=C:\mysql\include\my_alloc.h
-file0=C:\mysql\include\raid.h
-file17=C:\mysql\include\my_getopt.h
-file1=C:\mysql\include\errmsg.h
-file2=C:\mysql\include\Libmysql.def
-file3=C:\mysql\include\m_ctype.h
-file4=C:\mysql\include\m_string.h
-file5=C:\mysql\include\my_list.h
-file6=C:\mysql\include\my_pthread.h
-file7=C:\mysql\include\my_sys.h
-file8=C:\mysql\include\mysql.h
-file9=C:\mysql\include\mysql_com.h
-file10=C:\mysql\include\mysql_version.h
-fulldirectory=
-file11=C:\mysql\include\mysqld_error.h
-file12=C:\mysql\include\dbug.h
-file13=C:\mysql\include\config-win.h
-file14=C:\mysql\include\my_global.h
-
-[examples]
-SubDir0=examples\libmysqltest
-SubDir1=examples\tests
-fulldirectory=
-
-[lib\opt]
-file0=C:\mysql\lib\opt\libmySQL.dll
-file1=C:\mysql\lib\opt\libmySQL.lib
-file2=C:\mysql\lib\opt\mysqlclient.lib
-file3=C:\mysql\lib\opt\zlib.lib
-file4=C:\mysql\lib\opt\strings.lib
-file5=C:\mysql\lib\opt\regex.lib
-file6=C:\mysql\lib\opt\mysys.lib
-fulldirectory=
-
-[bench\Data]
-SubDir0=bench\Data\ATIS
-SubDir1=bench\Data\Wisconsin
-fulldirectory=
-
-[bench\limits]
-file15=C:\mysql\bench\limits\pg.comment
-file16=C:\mysql\bench\limits\solid.cfg
-file0=C:\mysql\bench\limits\access.cfg
-file17=C:\mysql\bench\limits\solid-nt4.cfg
-file1=C:\mysql\bench\limits\access.comment
-file18=C:\mysql\bench\limits\sybase.cfg
-file2=C:\mysql\bench\limits\Adabas.cfg
-file3=C:\mysql\bench\limits\Adabas.comment
-file4=C:\mysql\bench\limits\Db2.cfg
-file5=C:\mysql\bench\limits\empress.cfg
-file6=C:\mysql\bench\limits\empress.comment
-file7=C:\mysql\bench\limits\Informix.cfg
-file8=C:\mysql\bench\limits\Informix.comment
-file9=C:\mysql\bench\limits\msql.cfg
-file10=C:\mysql\bench\limits\ms-sql.cfg
-fulldirectory=
-file11=C:\mysql\bench\limits\Ms-sql65.cfg
-file12=C:\mysql\bench\limits\mysql.cfg
-file13=C:\mysql\bench\limits\oracle.cfg
-file14=C:\mysql\bench\limits\pg.cfg
-
-[TopDir]
-SubDir0=bench
-SubDir1=examples
-SubDir2=include
-SubDir3=lib
-SubDir4=scripts
-
-[bench]
-file15=C:\mysql\bench\test-create
-file16=C:\mysql\bench\test-insert
-file0=C:\mysql\bench\uname.bat
-file17=C:\mysql\bench\test-select
-file1=C:\mysql\bench\compare-results
-file18=C:\mysql\bench\test-wisconsin
-file2=C:\mysql\bench\copy-db
-file19=C:\mysql\bench\bench-init.pl
-file3=C:\mysql\bench\crash-me
-file4=C:\mysql\bench\example.bat
-file5=C:\mysql\bench\print-limit-table
-file6=C:\mysql\bench\pwd.bat
-file7=C:\mysql\bench\Readme
-SubDir0=bench\Data
-file8=C:\mysql\bench\run.bat
-SubDir1=bench\limits
-file9=C:\mysql\bench\run-all-tests
-SubDir2=bench\output
-file10=C:\mysql\bench\server-cfg
-fulldirectory=
-file11=C:\mysql\bench\test-alter-table
-file12=C:\mysql\bench\test-ATIS
-file13=C:\mysql\bench\test-big-tables
-file14=C:\mysql\bench\test-connect
-
-[examples\tests]
-file15=C:\mysql\examples\tests\lock_test.res
-file16=C:\mysql\examples\tests\mail_to_db.pl
-file0=C:\mysql\examples\tests\unique_users.tst
-file17=C:\mysql\examples\tests\table_types.pl
-file1=C:\mysql\examples\tests\auto_increment.tst
-file18=C:\mysql\examples\tests\test_delayed_insert.pl
-file2=C:\mysql\examples\tests\big_record.pl
-file19=C:\mysql\examples\tests\udf_test
-file3=C:\mysql\examples\tests\big_record.res
-file4=C:\mysql\examples\tests\czech-sorting
-file5=C:\mysql\examples\tests\deadlock-script.pl
-file6=C:\mysql\examples\tests\export.pl
-file7=C:\mysql\examples\tests\fork_test.pl
-file8=C:\mysql\examples\tests\fork2_test.pl
-file9=C:\mysql\examples\tests\fork3_test.pl
-file20=C:\mysql\examples\tests\udf_test.res
-file21=C:\mysql\examples\tests\auto_increment.res
-file10=C:\mysql\examples\tests\function.res
-fulldirectory=
-file11=C:\mysql\examples\tests\function.tst
-file12=C:\mysql\examples\tests\grant.pl
-file13=C:\mysql\examples\tests\grant.res
-file14=C:\mysql\examples\tests\lock_test.pl
-
-[bench\Data\ATIS]
-file26=C:\mysql\bench\Data\ATIS\stop1.txt
-file15=C:\mysql\bench\Data\ATIS\flight_class.txt
-file27=C:\mysql\bench\Data\ATIS\time_interval.txt
-file16=C:\mysql\bench\Data\ATIS\flight_day.txt
-file0=C:\mysql\bench\Data\ATIS\transport.txt
-file28=C:\mysql\bench\Data\ATIS\time_zone.txt
-file17=C:\mysql\bench\Data\ATIS\flight_fare.txt
-file1=C:\mysql\bench\Data\ATIS\airline.txt
-file29=C:\mysql\bench\Data\ATIS\aircraft.txt
-file18=C:\mysql\bench\Data\ATIS\food_service.txt
-file2=C:\mysql\bench\Data\ATIS\airport.txt
-file19=C:\mysql\bench\Data\ATIS\ground_service.txt
-file3=C:\mysql\bench\Data\ATIS\airport_service.txt
-file4=C:\mysql\bench\Data\ATIS\city.txt
-file5=C:\mysql\bench\Data\ATIS\class_of_service.txt
-file6=C:\mysql\bench\Data\ATIS\code_description.txt
-file7=C:\mysql\bench\Data\ATIS\compound_class.txt
-file8=C:\mysql\bench\Data\ATIS\connect_leg.txt
-file9=C:\mysql\bench\Data\ATIS\date_day.txt
-file20=C:\mysql\bench\Data\ATIS\month_name.txt
-file21=C:\mysql\bench\Data\ATIS\restrict_carrier.txt
-file10=C:\mysql\bench\Data\ATIS\day_name.txt
-fulldirectory=
-file22=C:\mysql\bench\Data\ATIS\restrict_class.txt
-file11=C:\mysql\bench\Data\ATIS\dual_carrier.txt
-file23=C:\mysql\bench\Data\ATIS\restriction.txt
-file12=C:\mysql\bench\Data\ATIS\fare.txt
-file24=C:\mysql\bench\Data\ATIS\state.txt
-file13=C:\mysql\bench\Data\ATIS\fconnection.txt
-file25=C:\mysql\bench\Data\ATIS\stop.txt
-file14=C:\mysql\bench\Data\ATIS\flight.txt
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
-[scripts]
-file37=C:\mysql\scripts\mysqld_safe-watch.sh
-file26=C:\mysql\scripts\mysql_zap
-file15=C:\mysql\scripts\mysql_fix_privilege_tables
-file38=C:\mysql\scripts\mysqldumpslow
-file27=C:\mysql\scripts\mysql_zap.sh
-file16=C:\mysql\scripts\mysql_fix_privilege_tables.sh
-file0=C:\mysql\scripts\Readme
-file39=C:\mysql\scripts\mysqldumpslow.sh
-file28=C:\mysql\scripts\mysqlaccess
-file17=C:\mysql\scripts\mysql_install_db
-file1=C:\mysql\scripts\make_binary_distribution.sh
-file29=C:\mysql\scripts\mysqlaccess.conf
-file18=C:\mysql\scripts\mysql_install_db.sh
-file2=C:\mysql\scripts\msql2mysql
-file19=C:\mysql\scripts\mysql_secure_installation
-file3=C:\mysql\scripts\msql2mysql.sh
-file4=C:\mysql\scripts\mysql_config
-file5=C:\mysql\scripts\mysql_config.sh
-file6=C:\mysql\scripts\mysql_convert_table_format
-file7=C:\mysql\scripts\mysql_convert_table_format.sh
-file40=C:\mysql\scripts\mysqlhotcopy
-file8=C:\mysql\scripts\mysql_explain_log
-file41=C:\mysql\scripts\mysqlhotcopy.pl
-file30=C:\mysql\scripts\mysqlaccess.sh
-file9=C:\mysql\scripts\mysql_explain_log.sh
-file42=C:\mysql\scripts\mysqlhotcopy.sh
-file31=C:\mysql\scripts\mysqlbug
-file20=C:\mysql\scripts\mysql_secure_installation.sh
-file43=C:\mysql\scripts\make_binary_distribution
-file32=C:\mysql\scripts\mysqlbug.sh
-file21=C:\mysql\scripts\mysql_setpermission
-file10=C:\mysql\scripts\mysql_find_rows
-fulldirectory=
-file44=C:\mysql\scripts\mysql_fix_privilege_tables.sql
-file33=C:\mysql\scripts\mysqld_multi
-file22=C:\mysql\scripts\mysql_setpermission.pl
-file11=C:\mysql\scripts\mysql_find_rows.pl
-file34=C:\mysql\scripts\mysqld_multi.sh
-file23=C:\mysql\scripts\mysql_setpermission.sh
-file12=C:\mysql\scripts\mysql_find_rows.sh
-file35=C:\mysql\scripts\mysqld_safe
-file24=C:\mysql\scripts\mysql_tableinfo
-file13=C:\mysql\scripts\mysql_fix_extensions
-file36=C:\mysql\scripts\mysqld_safe.sh
-file25=C:\mysql\scripts\mysql_tableinfo.sh
-file14=C:\mysql\scripts\mysql_fix_extensions.sh
-
-[lib]
-SubDir0=lib\debug
-SubDir1=lib\opt
-fulldirectory=
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Documentation.fgl b/VC++Files/InstallShield/4.0.XX-pro/File Groups/Documentation.fgl
deleted file mode 100755
index 80fe777cf0f..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Documentation.fgl
+++ /dev/null
@@ -1,99 +0,0 @@
-[Docs\Flags]
-file59=C:\mysql\Docs\Flags\romania.gif
-file48=C:\mysql\Docs\Flags\kroatia.eps
-file37=C:\mysql\Docs\Flags\iceland.gif
-file26=C:\mysql\Docs\Flags\france.eps
-file15=C:\mysql\Docs\Flags\china.gif
-file49=C:\mysql\Docs\Flags\kroatia.gif
-file38=C:\mysql\Docs\Flags\ireland.eps
-file27=C:\mysql\Docs\Flags\france.gif
-file16=C:\mysql\Docs\Flags\croatia.eps
-file0=C:\mysql\Docs\Flags\usa.gif
-file39=C:\mysql\Docs\Flags\ireland.gif
-file28=C:\mysql\Docs\Flags\germany.eps
-file17=C:\mysql\Docs\Flags\croatia.gif
-file1=C:\mysql\Docs\Flags\argentina.gif
-file29=C:\mysql\Docs\Flags\germany.gif
-file18=C:\mysql\Docs\Flags\czech-republic.eps
-file2=C:\mysql\Docs\Flags\australia.eps
-file19=C:\mysql\Docs\Flags\czech-republic.gif
-file3=C:\mysql\Docs\Flags\australia.gif
-file80=C:\mysql\Docs\Flags\usa.eps
-file4=C:\mysql\Docs\Flags\austria.eps
-file81=C:\mysql\Docs\Flags\argentina.eps
-file70=C:\mysql\Docs\Flags\spain.eps
-file5=C:\mysql\Docs\Flags\austria.gif
-file71=C:\mysql\Docs\Flags\spain.gif
-file60=C:\mysql\Docs\Flags\russia.eps
-file6=C:\mysql\Docs\Flags\brazil.eps
-file72=C:\mysql\Docs\Flags\sweden.eps
-file61=C:\mysql\Docs\Flags\russia.gif
-file50=C:\mysql\Docs\Flags\latvia.eps
-file7=C:\mysql\Docs\Flags\brazil.gif
-file73=C:\mysql\Docs\Flags\sweden.gif
-file62=C:\mysql\Docs\Flags\singapore.eps
-file51=C:\mysql\Docs\Flags\latvia.gif
-file40=C:\mysql\Docs\Flags\island.eps
-file8=C:\mysql\Docs\Flags\bulgaria.eps
-file74=C:\mysql\Docs\Flags\switzerland.eps
-file63=C:\mysql\Docs\Flags\singapore.gif
-file52=C:\mysql\Docs\Flags\netherlands.eps
-file41=C:\mysql\Docs\Flags\island.gif
-file30=C:\mysql\Docs\Flags\great-britain.eps
-file9=C:\mysql\Docs\Flags\bulgaria.gif
-file75=C:\mysql\Docs\Flags\switzerland.gif
-file64=C:\mysql\Docs\Flags\south-africa.eps
-file53=C:\mysql\Docs\Flags\netherlands.gif
-file42=C:\mysql\Docs\Flags\israel.eps
-file31=C:\mysql\Docs\Flags\great-britain.gif
-file20=C:\mysql\Docs\Flags\denmark.eps
-file76=C:\mysql\Docs\Flags\taiwan.eps
-file65=C:\mysql\Docs\Flags\south-africa.gif
-file54=C:\mysql\Docs\Flags\poland.eps
-file43=C:\mysql\Docs\Flags\israel.gif
-file32=C:\mysql\Docs\Flags\greece.eps
-file21=C:\mysql\Docs\Flags\denmark.gif
-file10=C:\mysql\Docs\Flags\canada.eps
-fulldirectory=
-file77=C:\mysql\Docs\Flags\taiwan.gif
-file66=C:\mysql\Docs\Flags\south-africa1.eps
-file55=C:\mysql\Docs\Flags\poland.gif
-file44=C:\mysql\Docs\Flags\italy.eps
-file33=C:\mysql\Docs\Flags\greece.gif
-file22=C:\mysql\Docs\Flags\estonia.eps
-file11=C:\mysql\Docs\Flags\canada.gif
-file78=C:\mysql\Docs\Flags\ukraine.eps
-file67=C:\mysql\Docs\Flags\south-africa1.gif
-file56=C:\mysql\Docs\Flags\portugal.eps
-file45=C:\mysql\Docs\Flags\italy.gif
-file34=C:\mysql\Docs\Flags\hungary.eps
-file23=C:\mysql\Docs\Flags\estonia.gif
-file12=C:\mysql\Docs\Flags\chile.eps
-file79=C:\mysql\Docs\Flags\ukraine.gif
-file68=C:\mysql\Docs\Flags\south-korea.eps
-file57=C:\mysql\Docs\Flags\portugal.gif
-file46=C:\mysql\Docs\Flags\japan.eps
-file35=C:\mysql\Docs\Flags\hungary.gif
-file24=C:\mysql\Docs\Flags\finland.eps
-file13=C:\mysql\Docs\Flags\chile.gif
-file69=C:\mysql\Docs\Flags\south-korea.gif
-file58=C:\mysql\Docs\Flags\romania.eps
-file47=C:\mysql\Docs\Flags\japan.gif
-file36=C:\mysql\Docs\Flags\iceland.eps
-file25=C:\mysql\Docs\Flags\finland.gif
-file14=C:\mysql\Docs\Flags\china.eps
-
-[Docs]
-file0=C:\mysql\Docs\manual_toc.html
-file1=C:\mysql\Docs\manual.html
-file2=C:\mysql\Docs\manual.txt
-SubDir0=Docs\Flags
-fulldirectory=
-
-[TopDir]
-SubDir0=Docs
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Grant Tables.fgl b/VC++Files/InstallShield/4.0.XX-pro/File Groups/Grant Tables.fgl
deleted file mode 100755
index 178065a7003..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Grant Tables.fgl
+++ /dev/null
@@ -1,36 +0,0 @@
-[data\test]
-fulldirectory=
-
-[data\mysql]
-file15=C:\mysql\data\mysql\func.frm
-file16=C:\mysql\data\mysql\func.MYD
-file0=C:\mysql\data\mysql\columns_priv.frm
-file17=C:\mysql\data\mysql\func.MYI
-file1=C:\mysql\data\mysql\columns_priv.MYD
-file2=C:\mysql\data\mysql\columns_priv.MYI
-file3=C:\mysql\data\mysql\db.frm
-file4=C:\mysql\data\mysql\db.MYD
-file5=C:\mysql\data\mysql\db.MYI
-file6=C:\mysql\data\mysql\host.frm
-file7=C:\mysql\data\mysql\host.MYD
-file8=C:\mysql\data\mysql\host.MYI
-file9=C:\mysql\data\mysql\tables_priv.frm
-file10=C:\mysql\data\mysql\tables_priv.MYD
-fulldirectory=
-file11=C:\mysql\data\mysql\tables_priv.MYI
-file12=C:\mysql\data\mysql\user.frm
-file13=C:\mysql\data\mysql\user.MYD
-file14=C:\mysql\data\mysql\user.MYI
-
-[TopDir]
-SubDir0=data
-
-[data]
-SubDir0=data\mysql
-SubDir1=data\test
-fulldirectory=
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Servers.fgl b/VC++Files/InstallShield/4.0.XX-pro/File Groups/Servers.fgl
deleted file mode 100755
index 8a626c56253..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/File Groups/Servers.fgl
+++ /dev/null
@@ -1,227 +0,0 @@
-[Embedded\Static\release]
-file0=C:\mysql\embedded\Static\release\test_stc.dsp
-file1=C:\mysql\embedded\Static\release\ReadMe.txt
-file2=C:\mysql\embedded\Static\release\StdAfx.cpp
-file3=C:\mysql\embedded\Static\release\StdAfx.h
-file4=C:\mysql\embedded\Static\release\test_stc.cpp
-file5=C:\mysql\embedded\Static\release\mysqlserver.lib
-fulldirectory=
-
-[share\polish]
-file0=C:\mysql\share\polish\errmsg.sys
-file1=C:\mysql\share\polish\errmsg.txt
-fulldirectory=
-
-[share\dutch]
-file0=C:\mysql\share\dutch\errmsg.sys
-file1=C:\mysql\share\dutch\errmsg.txt
-fulldirectory=
-
-[share\spanish]
-file0=C:\mysql\share\spanish\errmsg.sys
-file1=C:\mysql\share\spanish\errmsg.txt
-fulldirectory=
-
-[share\english]
-file0=C:\mysql\share\english\errmsg.sys
-file1=C:\mysql\share\english\errmsg.txt
-fulldirectory=
-
-[bin]
-file0=C:\mysql\bin\mysqld-opt.exe
-file1=C:\mysql\bin\mysqld-nt.exe
-file2=C:\mysql\bin\mysqld.exe
-file3=C:\mysql\bin\cygwinb19.dll
-file4=C:\mysql\bin\libmySQL.dll
-fulldirectory=
-
-[share\korean]
-file0=C:\mysql\share\korean\errmsg.sys
-file1=C:\mysql\share\korean\errmsg.txt
-fulldirectory=
-
-[share\charsets]
-file15=C:\mysql\share\charsets\latin1.conf
-file16=C:\mysql\share\charsets\latin2.conf
-file0=C:\mysql\share\charsets\win1251ukr.conf
-file17=C:\mysql\share\charsets\latin5.conf
-file1=C:\mysql\share\charsets\cp1257.conf
-file18=C:\mysql\share\charsets\Readme
-file2=C:\mysql\share\charsets\croat.conf
-file19=C:\mysql\share\charsets\swe7.conf
-file3=C:\mysql\share\charsets\danish.conf
-file4=C:\mysql\share\charsets\dec8.conf
-file5=C:\mysql\share\charsets\dos.conf
-file6=C:\mysql\share\charsets\estonia.conf
-file7=C:\mysql\share\charsets\german1.conf
-file8=C:\mysql\share\charsets\greek.conf
-file9=C:\mysql\share\charsets\hebrew.conf
-file20=C:\mysql\share\charsets\usa7.conf
-file21=C:\mysql\share\charsets\win1250.conf
-file10=C:\mysql\share\charsets\hp8.conf
-fulldirectory=
-file22=C:\mysql\share\charsets\win1251.conf
-file11=C:\mysql\share\charsets\hungarian.conf
-file23=C:\mysql\share\charsets\cp1251.conf
-file12=C:\mysql\share\charsets\Index
-file13=C:\mysql\share\charsets\koi8_ru.conf
-file14=C:\mysql\share\charsets\koi8_ukr.conf
-
-[Embedded\DLL\debug]
-file0=C:\mysql\embedded\DLL\debug\libmysqld.dll
-file1=C:\mysql\embedded\DLL\debug\libmysqld.exp
-file2=C:\mysql\embedded\DLL\debug\libmysqld.lib
-fulldirectory=
-
-[Embedded]
-file0=C:\mysql\embedded\embedded.dsw
-SubDir0=Embedded\DLL
-SubDir1=Embedded\Static
-fulldirectory=
-
-[share\ukrainian]
-file0=C:\mysql\share\ukrainian\errmsg.sys
-file1=C:\mysql\share\ukrainian\errmsg.txt
-fulldirectory=
-
-[share\hungarian]
-file0=C:\mysql\share\hungarian\errmsg.sys
-file1=C:\mysql\share\hungarian\errmsg.txt
-fulldirectory=
-
-[share\german]
-file0=C:\mysql\share\german\errmsg.sys
-file1=C:\mysql\share\german\errmsg.txt
-fulldirectory=
-
-[share\portuguese]
-file0=C:\mysql\share\portuguese\errmsg.sys
-file1=C:\mysql\share\portuguese\errmsg.txt
-fulldirectory=
-
-[share\estonian]
-file0=C:\mysql\share\estonian\errmsg.sys
-file1=C:\mysql\share\estonian\errmsg.txt
-fulldirectory=
-
-[share\romanian]
-file0=C:\mysql\share\romanian\errmsg.sys
-file1=C:\mysql\share\romanian\errmsg.txt
-fulldirectory=
-
-[share\french]
-file0=C:\mysql\share\french\errmsg.sys
-file1=C:\mysql\share\french\errmsg.txt
-fulldirectory=
-
-[share\swedish]
-file0=C:\mysql\share\swedish\errmsg.sys
-file1=C:\mysql\share\swedish\errmsg.txt
-fulldirectory=
-
-[share\slovak]
-file0=C:\mysql\share\slovak\errmsg.sys
-file1=C:\mysql\share\slovak\errmsg.txt
-fulldirectory=
-
-[share\greek]
-file0=C:\mysql\share\greek\errmsg.sys
-file1=C:\mysql\share\greek\errmsg.txt
-fulldirectory=
-
-[TopDir]
-file0=C:\mysql\my-huge.cnf
-file1=C:\mysql\my-large.cnf
-file2=C:\mysql\my-medium.cnf
-file3=C:\mysql\my-small.cnf
-file4=C:\mysql\MySQLEULA.txt
-file5=C:\mysql\README.txt
-SubDir0=bin
-SubDir1=share
-SubDir2=Embedded
-
-[share]
-SubDir8=share\hungarian
-SubDir9=share\charsets
-SubDir20=share\spanish
-SubDir21=share\swedish
-SubDir10=share\italian
-SubDir22=share\ukrainian
-SubDir11=share\japanese
-SubDir12=share\korean
-SubDir13=share\norwegian
-SubDir14=share\norwegian-ny
-SubDir15=share\polish
-SubDir16=share\portuguese
-SubDir0=share\czech
-SubDir17=share\romanian
-SubDir1=share\danish
-SubDir18=share\russian
-SubDir2=share\dutch
-SubDir19=share\slovak
-SubDir3=share\english
-fulldirectory=
-SubDir4=share\estonian
-SubDir5=share\french
-SubDir6=share\german
-SubDir7=share\greek
-
-[share\norwegian-ny]
-file0=C:\mysql\share\norwegian-ny\errmsg.sys
-file1=C:\mysql\share\norwegian-ny\errmsg.txt
-fulldirectory=
-
-[Embedded\DLL]
-file0=C:\mysql\embedded\DLL\test_dll.dsp
-file1=C:\mysql\embedded\DLL\StdAfx.h
-file2=C:\mysql\embedded\DLL\test_dll.cpp
-file3=C:\mysql\embedded\DLL\StdAfx.cpp
-SubDir0=Embedded\DLL\debug
-SubDir1=Embedded\DLL\release
-fulldirectory=
-
-[Embedded\Static]
-SubDir0=Embedded\Static\release
-fulldirectory=
-
-[Embedded\DLL\release]
-file0=C:\mysql\embedded\DLL\release\libmysqld.dll
-file1=C:\mysql\embedded\DLL\release\libmysqld.exp
-file2=C:\mysql\embedded\DLL\release\libmysqld.lib
-file3=C:\mysql\embedded\DLL\release\mysql-server.exe
-fulldirectory=
-
-[share\danish]
-file0=C:\mysql\share\danish\errmsg.sys
-file1=C:\mysql\share\danish\errmsg.txt
-fulldirectory=
-
-[share\czech]
-file0=C:\mysql\share\czech\errmsg.sys
-file1=C:\mysql\share\czech\errmsg.txt
-fulldirectory=
-
-[General]
-Type=FILELIST
-Version=1.00.000
-
-[share\russian]
-file0=C:\mysql\share\russian\errmsg.sys
-file1=C:\mysql\share\russian\errmsg.txt
-fulldirectory=
-
-[share\norwegian]
-file0=C:\mysql\share\norwegian\errmsg.sys
-file1=C:\mysql\share\norwegian\errmsg.txt
-fulldirectory=
-
-[share\japanese]
-file0=C:\mysql\share\japanese\errmsg.sys
-file1=C:\mysql\share\japanese\errmsg.txt
-fulldirectory=
-
-[share\italian]
-file0=C:\mysql\share\italian\errmsg.sys
-file1=C:\mysql\share\italian\errmsg.txt
-fulldirectory=
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Registry Entries/Default.rge b/VC++Files/InstallShield/4.0.XX-pro/Registry Entries/Default.rge
deleted file mode 100755
index 537dfd82e48..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Registry Entries/Default.rge
+++ /dev/null
@@ -1,4 +0,0 @@
-[General]
-Type=REGISTRYDATA
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.dbg b/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.dbg
deleted file mode 100755
index 0c6d4e6b708..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.dbg
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.ino b/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.ino
deleted file mode 100755
index 204d8ea0f36..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.ino
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.ins b/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.ins
deleted file mode 100755
index 759009b5c84..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.ins
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.obs b/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.obs
deleted file mode 100755
index 5fcfcb62c4e..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.obs
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.rul.old b/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.rul.old
deleted file mode 100755
index df143b493c4..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Script Files/Setup.rul.old
+++ /dev/null
@@ -1,640 +0,0 @@
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// IIIIIII SSSSSS
-// II SS InstallShield (R)
-// II SSSSSS (c) 1996-1997, InstallShield Software Corporation
-// II SS (c) 1990-1996, InstallShield Corporation
-// IIIIIII SSSSSS All Rights Reserved.
-//
-//
-// This code is generated as a starting setup template. You should
-// modify it to provide all necessary steps for your setup.
-//
-//
-// File Name: Setup.rul
-//
-// Description: InstallShield script
-//
-// Comments: This template script performs a basic setup on a
-// Windows 95 or Windows NT 4.0 platform. With minor
-// modifications, this template can be adapted to create
-// new, customized setups.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
- // Include header file
-#include "sdlang.h"
-#include "sddialog.h"
-
-////////////////////// string defines ////////////////////////////
-
-#define UNINST_LOGFILE_NAME "Uninst.isu"
-
-//////////////////// installation declarations ///////////////////
-
- // ----- DLL prototypes -----
-
-
- // your DLL prototypes
-
-
- // ---- script prototypes -----
-
- // generated
- prototype ShowDialogs();
- prototype MoveFileData();
- prototype HandleMoveDataError( NUMBER );
- prototype ProcessBeforeDataMove();
- prototype ProcessAfterDataMove();
- prototype SetupRegistry();
- prototype SetupFolders();
- prototype CleanUpInstall();
- prototype SetupInstall();
- prototype SetupScreen();
- prototype CheckRequirements();
- prototype DialogShowSdWelcome();
- prototype DialogShowSdShowInfoList();
- prototype DialogShowSdAskDestPath();
- prototype DialogShowSdSetupType();
- prototype DialogShowSdComponentDialog2();
- prototype DialogShowSdFinishReboot();
-
- // your prototypes
-
-
- // ----- global variables ------
-
- // generated
- BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
- STRING svDir;
- STRING svName, svCompany, svSerial;
- STRING szAppPath;
- STRING svSetupType;
-
-
- // your global variables
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// MAIN PROGRAM
-//
-// The setup begins here by hiding the visible setup
-// window. This is done to allow all the titles, images, etc. to
-// be established before showing the main window. The following
-// logic then performs the setup in a series of steps.
-//
-///////////////////////////////////////////////////////////////////////////////
-program
- Disable( BACKGROUND );
-
- CheckRequirements();
-
- SetupInstall();
-
- SetupScreen();
-
- if (ShowDialogs()<0) goto end_install;
-
- if (ProcessBeforeDataMove()<0) goto end_install;
-
- if (MoveFileData()<0) goto end_install;
-
- if (ProcessAfterDataMove()<0) goto end_install;
-
- if (SetupRegistry()<0) goto end_install;
-
- if (SetupFolders()<0) goto end_install;
-
-
- end_install:
-
- CleanUpInstall();
-
- // If an unrecoverable error occurred, clean up the partial installation.
- // Otherwise, exit normally.
-
- if (bInstallAborted) then
- abort;
- endif;
-
-endprogram
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ShowDialogs //
-// //
-// Purpose: This function manages the display and navigation //
-// the standard dialogs that exist in a setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ShowDialogs()
- NUMBER nResult;
- begin
-
- Dlg_Start:
- // beginning of dialogs label
-
- Dlg_SdWelcome:
- nResult = DialogShowSdWelcome();
- if (nResult = BACK) goto Dlg_Start;
-
- Dlg_SdShowInfoList:
- nResult = DialogShowSdShowInfoList();
- if (nResult = BACK) goto Dlg_SdWelcome;
-
- Dlg_SdAskDestPath:
- nResult = DialogShowSdAskDestPath();
- if (nResult = BACK) goto Dlg_SdShowInfoList;
-
- Dlg_SdSetupType:
- nResult = DialogShowSdSetupType();
- if (nResult = BACK) goto Dlg_SdAskDestPath;
-
- Dlg_SdComponentDialog2:
- if ((nResult = BACK) && (svSetupType != "Custom") && (svSetupType != "")) then
- goto Dlg_SdSetupType;
- endif;
- nResult = DialogShowSdComponentDialog2();
- if (nResult = BACK) goto Dlg_SdSetupType;
-
- return 0;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessBeforeDataMove //
-// //
-// Purpose: This function performs any necessary operations prior to the //
-// actual data move operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessBeforeDataMove()
- STRING svLogFile;
- NUMBER nResult;
- begin
-
- InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
-
- svLogFile = UNINST_LOGFILE_NAME;
-
- nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
- if (nResult < 0) then
- MessageBox( @ERROR_UNINSTSETUP, WARNING );
- endif;
-
- szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir
-
- if ((bIs32BitSetup) && (bIsShellExplorer)) then
- RegDBSetItem( REGDB_APPPATH, szAppPath );
- RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
- RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
- endif;
-
- // TODO : update any items you want to process before moving the data
- //
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: MoveFileData //
-// //
-// Purpose: This function handles the data movement for //
-// the setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function MoveFileData()
- NUMBER nResult, nDisk;
- begin
-
- nDisk = 1;
- SetStatusWindow( 0, "" );
- Disable( DIALOGCACHE );
- Enable( STATUS );
- StatusUpdate( ON, 100 );
- nResult = ComponentMoveData( MEDIA, nDisk, 0 );
-
- HandleMoveDataError( nResult );
-
- Disable( STATUS );
-
- return nResult;
-
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: HandleMoveDataError //
-// //
-// Purpose: This function handles the error (if any) during the move data //
-// operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function HandleMoveDataError( nResult )
- STRING szErrMsg, svComponent , svFileGroup , svFile;
- begin
-
- svComponent = "";
- svFileGroup = "";
- svFile = "";
-
- switch (nResult)
- case 0:
- return 0;
- default:
- ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
- szErrMsg = @ERROR_MOVEDATA + "\n\n" +
- @ERROR_COMPONENT + " " + svComponent + "\n" +
- @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
- @ERROR_FILE + " " + svFile;
- SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
- bInstallAborted = TRUE;
- return nResult;
- endswitch;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessAfterDataMove //
-// //
-// Purpose: This function performs any necessary operations needed after //
-// all data has been moved. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessAfterDataMove()
- begin
-
- // TODO : update self-registered files and other processes that
- // should be performed after the data has been moved.
-
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupRegistry //
-// //
-// Purpose: This function makes the registry entries for this setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupRegistry()
- NUMBER nResult;
-
- begin
-
- // TODO : Add all your registry entry keys here
- //
- //
- // RegDBCreateKeyEx, RegDBSetKeyValueEx....
- //
-
- nResult = CreateRegistrySet( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// Function: SetupFolders
-//
-// Purpose: This function creates all the folders and shortcuts for the
-// setup. This includes program groups and items for Windows 3.1.
-//
-///////////////////////////////////////////////////////////////////////////////
-function SetupFolders()
- NUMBER nResult;
-
- begin
-
-
- // TODO : Add all your folder (program group) along with shortcuts (program items)
- //
- //
- // CreateProgramFolder, AddFolderIcon....
- //
-
- nResult = CreateShellObjects( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CleanUpInstall //
-// //
-// Purpose: This cleans up the setup. Anything that should //
-// be released or deleted at the end of the setup should //
-// be done here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CleanUpInstall()
- begin
-
-
- if (bInstallAborted) then
- return 0;
- endif;
-
- DialogShowSdFinishReboot();
-
- if (BATCH_INSTALL) then // ensure locked files are properly written
- CommitSharedFiles(0);
- endif;
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupInstall //
-// //
-// Purpose: This will setup the installation. Any general initialization //
-// needed for the installation should be performed here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupInstall()
- begin
-
- Enable( CORECOMPONENTHANDLING );
-
- bInstallAborted = FALSE;
-
- if (bIs32BitSetup) then
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME ^ @PRODUCT_NAME;
- else
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME16 ^ @PRODUCT_NAME16; // use shorten names
- endif;
-
- TARGETDIR = svDir;
-
- SdProductName( @PRODUCT_NAME );
-
- Enable( DIALOGCACHE );
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupScreen //
-// //
-// Purpose: This function establishes the screen look. This includes //
-// colors, fonts, and text to be displayed. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupScreen()
- begin
-
- Enable( FULLWINDOWMODE );
- Enable( INDVFILESTATUS );
- SetTitle( @TITLE_MAIN, 24, WHITE );
-
- SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
-
- Enable( BACKGROUND );
-
- Delay( 1 );
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CheckRequirements //
-// //
-// Purpose: This function checks all minimum requirements for the //
-// application being installed. If any fail, then the user //
-// is informed and the setup is terminated. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CheckRequirements()
- NUMBER nvDx, nvDy, nvResult;
- STRING svResult;
-
- begin
-
- bWinNT = FALSE;
- bIsShellExplorer = FALSE;
-
- // Check screen resolution.
- GetExtents( nvDx, nvDy );
-
- if (nvDy < 480) then
- MessageBox( @ERROR_VGARESOLUTION, WARNING );
- abort;
- endif;
-
- // set 'setup' operation mode
- bIs32BitSetup = TRUE;
- GetSystemInfo( ISTYPE, nvResult, svResult );
- if (nvResult = 16) then
- bIs32BitSetup = FALSE; // running 16-bit setup
- return 0; // no additional information required
- endif;
-
- // --- 32-bit testing after this point ---
-
- // Determine the target system's operating system.
- GetSystemInfo( OS, nvResult, svResult );
-
- if (nvResult = IS_WINDOWSNT) then
- // Running Windows NT.
- bWinNT = TRUE;
-
- // Check to see if the shell being used is EXPLORER shell.
- if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
- if (nvResult >= 4) then
- bIsShellExplorer = TRUE;
- endif;
- endif;
-
- elseif (nvResult = IS_WINDOWS95 ) then
- bIsShellExplorer = TRUE;
-
- endif;
-
-end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdWelcome //
-// //
-// Purpose: This function handles the standard welcome dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdWelcome()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdWelcome( szTitle, szMsg );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdShowInfoList //
-// //
-// Purpose: This function displays the general information list dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdShowInfoList()
- NUMBER nResult;
- LIST list;
- STRING szTitle, szMsg, szFile;
- begin
-
- szFile = SUPPORTDIR ^ "infolist.txt";
-
- list = ListCreate( STRINGLIST );
- ListReadFromFile( list, szFile );
- szTitle = "";
- szMsg = " ";
- nResult = SdShowInfoList( szTitle, szMsg, list );
-
- ListDestroy( list );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdAskDestPath //
-// //
-// Purpose: This function asks the user for the destination directory. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdAskDestPath()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
-
- TARGETDIR = svDir;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdSetupType //
-// //
-// Purpose: This function displays the standard setup type dialog. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdSetupType()
- NUMBER nResult, nType;
- STRING szTitle, szMsg;
- begin
-
- switch (svSetupType)
- case "Typical":
- nType = TYPICAL;
- case "Custom":
- nType = CUSTOM;
- case "Compact":
- nType = COMPACT;
- case "":
- svSetupType = "Typical";
- nType = TYPICAL;
- endswitch;
-
- szTitle = "";
- szMsg = "";
- nResult = SetupType( szTitle, szMsg, "", nType, 0 );
-
- switch (nResult)
- case COMPACT:
- svSetupType = "Compact";
- case TYPICAL:
- svSetupType = "Typical";
- case CUSTOM:
- svSetupType = "Custom";
- endswitch;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdComponentDialog2 //
-// //
-// Purpose: This function displays the custom component dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdComponentDialog2()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- if ((svSetupType != "Custom") && (svSetupType != "")) then
- return 0;
- endif;
-
- szTitle = "";
- szMsg = "";
- nResult = SdComponentDialog2( szTitle, szMsg, svDir, "" );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdFinishReboot //
-// //
-// Purpose: This function will show the last dialog of the product. //
-// It will allow the user to reboot and/or show some readme text. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdFinishReboot()
- NUMBER nResult, nDefOptions;
- STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
- NUMBER bOpt1, bOpt2;
- begin
-
- if (!BATCH_INSTALL) then
- bOpt1 = FALSE;
- bOpt2 = FALSE;
- szMsg1 = "";
- szMsg2 = "";
- szOption1 = "";
- szOption2 = "";
- nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
- return 0;
- endif;
-
- nDefOptions = SYS_BOOTMACHINE;
- szTitle = "";
- szMsg1 = "";
- szMsg2 = "";
- nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );
-
- return nResult;
- end;
-
- // --- include script file section ---
-
-#include "sddialog.rul"
-
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Script Files/setup.rul b/VC++Files/InstallShield/4.0.XX-pro/Script Files/setup.rul
deleted file mode 100755
index 73d61114075..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Script Files/setup.rul
+++ /dev/null
@@ -1,641 +0,0 @@
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// IIIIIII SSSSSS
-// II SS InstallShield (R)
-// II SSSSSS (c) 1996-1997, InstallShield Software Corporation
-// II SS (c) 1990-1996, InstallShield Corporation
-// IIIIIII SSSSSS All Rights Reserved.
-//
-//
-// This code is generated as a starting setup template. You should
-// modify it to provide all necessary steps for your setup.
-//
-//
-// File Name: Setup.rul
-//
-// Description: InstallShield script
-//
-// Comments: This template script performs a basic setup on a
-// Windows 95 or Windows NT 4.0 platform. With minor
-// modifications, this template can be adapted to create
-// new, customized setups.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
- // Include header file
-#include "sdlang.h"
-#include "sddialog.h"
-
-////////////////////// string defines ////////////////////////////
-
-#define UNINST_LOGFILE_NAME "Uninst.isu"
-
-//////////////////// installation declarations ///////////////////
-
- // ----- DLL prototypes -----
-
-
- // your DLL prototypes
-
-
- // ---- script prototypes -----
-
- // generated
- prototype ShowDialogs();
- prototype MoveFileData();
- prototype HandleMoveDataError( NUMBER );
- prototype ProcessBeforeDataMove();
- prototype ProcessAfterDataMove();
- prototype SetupRegistry();
- prototype SetupFolders();
- prototype CleanUpInstall();
- prototype SetupInstall();
- prototype SetupScreen();
- prototype CheckRequirements();
- prototype DialogShowSdWelcome();
- prototype DialogShowSdShowInfoList();
- prototype DialogShowSdAskDestPath();
- prototype DialogShowSdSetupType();
- prototype DialogShowSdComponentDialog2();
- prototype DialogShowSdFinishReboot();
-
- // your prototypes
-
-
- // ----- global variables ------
-
- // generated
- BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
- STRING svDir;
- STRING svName, svCompany, svSerial;
- STRING szAppPath;
- STRING svSetupType;
-
-
- // your global variables
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// MAIN PROGRAM
-//
-// The setup begins here by hiding the visible setup
-// window. This is done to allow all the titles, images, etc. to
-// be established before showing the main window. The following
-// logic then performs the setup in a series of steps.
-//
-///////////////////////////////////////////////////////////////////////////////
-program
- Disable( BACKGROUND );
-
- CheckRequirements();
-
- SetupInstall();
-
- SetupScreen();
-
- if (ShowDialogs()<0) goto end_install;
-
- if (ProcessBeforeDataMove()<0) goto end_install;
-
- if (MoveFileData()<0) goto end_install;
-
- if (ProcessAfterDataMove()<0) goto end_install;
-
- if (SetupRegistry()<0) goto end_install;
-
- if (SetupFolders()<0) goto end_install;
-
-
- end_install:
-
- CleanUpInstall();
-
- // If an unrecoverable error occurred, clean up the partial installation.
- // Otherwise, exit normally.
-
- if (bInstallAborted) then
- abort;
- endif;
-
-endprogram
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ShowDialogs //
-// //
-// Purpose: This function manages the display and navigation //
-// the standard dialogs that exist in a setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ShowDialogs()
- NUMBER nResult;
- begin
-
- Dlg_Start:
- // beginning of dialogs label
-
- Dlg_SdWelcome:
- nResult = DialogShowSdWelcome();
- if (nResult = BACK) goto Dlg_Start;
-
- Dlg_SdShowInfoList:
- nResult = DialogShowSdShowInfoList();
- if (nResult = BACK) goto Dlg_SdWelcome;
-
- Dlg_SdAskDestPath:
- nResult = DialogShowSdAskDestPath();
- if (nResult = BACK) goto Dlg_SdShowInfoList;
-
- Dlg_SdSetupType:
- nResult = DialogShowSdSetupType();
- if (nResult = BACK) goto Dlg_SdAskDestPath;
-
- Dlg_SdComponentDialog2:
- if ((nResult = BACK) && (svSetupType != "Custom") && (svSetupType != "")) then
- goto Dlg_SdSetupType;
- endif;
- nResult = DialogShowSdComponentDialog2();
- if (nResult = BACK) goto Dlg_SdSetupType;
-
- return 0;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessBeforeDataMove //
-// //
-// Purpose: This function performs any necessary operations prior to the //
-// actual data move operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessBeforeDataMove()
- STRING svLogFile;
- NUMBER nResult;
- begin
-
- InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
-
- svLogFile = UNINST_LOGFILE_NAME;
-
- nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
- if (nResult < 0) then
- MessageBox( @ERROR_UNINSTSETUP, WARNING );
- endif;
-
- szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir
-
- if ((bIs32BitSetup) && (bIsShellExplorer)) then
-// RegDBSetItem( REGDB_APPPATH, szAppPath );
-// RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
- RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
- endif;
-
- // TODO : update any items you want to process before moving the data
- //
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: MoveFileData //
-// //
-// Purpose: This function handles the data movement for //
-// the setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function MoveFileData()
- NUMBER nResult, nDisk;
- begin
-
- nDisk = 1;
- SetStatusWindow( 0, "" );
- Disable( DIALOGCACHE );
- Enable( STATUS );
- StatusUpdate( ON, 100 );
- nResult = ComponentMoveData( MEDIA, nDisk, 0 );
-
- HandleMoveDataError( nResult );
-
- Disable( STATUS );
-
- return nResult;
-
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: HandleMoveDataError //
-// //
-// Purpose: This function handles the error (if any) during the move data //
-// operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function HandleMoveDataError( nResult )
- STRING szErrMsg, svComponent , svFileGroup , svFile;
- begin
-
- svComponent = "";
- svFileGroup = "";
- svFile = "";
-
- switch (nResult)
- case 0:
- return 0;
- default:
- ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
- szErrMsg = @ERROR_MOVEDATA + "\n\n" +
- @ERROR_COMPONENT + " " + svComponent + "\n" +
- @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
- @ERROR_FILE + " " + svFile;
- SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
- bInstallAborted = TRUE;
- return nResult;
- endswitch;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessAfterDataMove //
-// //
-// Purpose: This function performs any necessary operations needed after //
-// all data has been moved. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessAfterDataMove()
- begin
-
- // TODO : update self-registered files and other processes that
- // should be performed after the data has been moved.
-
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupRegistry //
-// //
-// Purpose: This function makes the registry entries for this setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupRegistry()
- NUMBER nResult;
-
- begin
-
- // TODO : Add all your registry entry keys here
- //
- //
- // RegDBCreateKeyEx, RegDBSetKeyValueEx....
- //
-
- nResult = CreateRegistrySet( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// Function: SetupFolders
-//
-// Purpose: This function creates all the folders and shortcuts for the
-// setup. This includes program groups and items for Windows 3.1.
-//
-///////////////////////////////////////////////////////////////////////////////
-function SetupFolders()
- NUMBER nResult;
-
- begin
-
-
- // TODO : Add all your folder (program group) along with shortcuts (program items)
- //
- //
- // CreateProgramFolder, AddFolderIcon....
- //
-
- nResult = CreateShellObjects( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CleanUpInstall //
-// //
-// Purpose: This cleans up the setup. Anything that should //
-// be released or deleted at the end of the setup should //
-// be done here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CleanUpInstall()
- begin
-
-
- if (bInstallAborted) then
- return 0;
- endif;
-
- DialogShowSdFinishReboot();
-
- if (BATCH_INSTALL) then // ensure locked files are properly written
- CommitSharedFiles(0);
- endif;
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupInstall //
-// //
-// Purpose: This will setup the installation. Any general initialization //
-// needed for the installation should be performed here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupInstall()
- begin
-
- Enable( CORECOMPONENTHANDLING );
-
- bInstallAborted = FALSE;
-
- if (bIs32BitSetup) then
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME ^ @PRODUCT_NAME;
- else
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME16 ^ @PRODUCT_NAME16; // use shorten names
- endif;
-
- TARGETDIR = svDir;
-
- SdProductName( @PRODUCT_NAME );
-
- Enable( DIALOGCACHE );
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupScreen //
-// //
-// Purpose: This function establishes the screen look. This includes //
-// colors, fonts, and text to be displayed. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupScreen()
- begin
-
- Enable( FULLWINDOWMODE );
- Enable( INDVFILESTATUS );
- SetTitle( @TITLE_MAIN, 24, WHITE );
-
- SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
-
- Enable( BACKGROUND );
-
- Delay( 1 );
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CheckRequirements //
-// //
-// Purpose: This function checks all minimum requirements for the //
-// application being installed. If any fail, then the user //
-// is informed and the setup is terminated. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CheckRequirements()
- NUMBER nvDx, nvDy, nvResult;
- STRING svResult;
-
- begin
-
- bWinNT = FALSE;
- bIsShellExplorer = FALSE;
-
- // Check screen resolution.
- GetExtents( nvDx, nvDy );
-
- if (nvDy < 480) then
- MessageBox( @ERROR_VGARESOLUTION, WARNING );
- abort;
- endif;
-
- // set 'setup' operation mode
- bIs32BitSetup = TRUE;
- GetSystemInfo( ISTYPE, nvResult, svResult );
- if (nvResult = 16) then
- bIs32BitSetup = FALSE; // running 16-bit setup
- return 0; // no additional information required
- endif;
-
- // --- 32-bit testing after this point ---
-
- // Determine the target system's operating system.
- GetSystemInfo( OS, nvResult, svResult );
-
- if (nvResult = IS_WINDOWSNT) then
- // Running Windows NT.
- bWinNT = TRUE;
-
- // Check to see if the shell being used is EXPLORER shell.
- if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
- if (nvResult >= 4) then
- bIsShellExplorer = TRUE;
- endif;
- endif;
-
- elseif (nvResult = IS_WINDOWS95 ) then
- bIsShellExplorer = TRUE;
-
- endif;
-
-end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdWelcome //
-// //
-// Purpose: This function handles the standard welcome dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdWelcome()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdWelcome( szTitle, szMsg );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdShowInfoList //
-// //
-// Purpose: This function displays the general information list dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdShowInfoList()
- NUMBER nResult;
- LIST list;
- STRING szTitle, szMsg, szFile;
- begin
-
- szFile = SUPPORTDIR ^ "infolist.txt";
-
- list = ListCreate( STRINGLIST );
- ListReadFromFile( list, szFile );
- szTitle = "";
- szMsg = " ";
- nResult = SdShowInfoList( szTitle, szMsg, list );
-
- ListDestroy( list );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdAskDestPath //
-// //
-// Purpose: This function asks the user for the destination directory. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdAskDestPath()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
-
- TARGETDIR = svDir;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdSetupType //
-// //
-// Purpose: This function displays the standard setup type dialog. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdSetupType()
- NUMBER nResult, nType;
- STRING szTitle, szMsg;
- begin
-
- switch (svSetupType)
- case "Typical":
- nType = TYPICAL;
- case "Custom":
- nType = CUSTOM;
- case "Compact":
- nType = COMPACT;
- case "":
- svSetupType = "Typical";
- nType = TYPICAL;
- endswitch;
-
- szTitle = "";
- szMsg = "";
- nResult = SetupType( szTitle, szMsg, "", nType, 0 );
-
- switch (nResult)
- case COMPACT:
- svSetupType = "Compact";
- case TYPICAL:
- svSetupType = "Typical";
- case CUSTOM:
- svSetupType = "Custom";
- endswitch;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdComponentDialog2 //
-// //
-// Purpose: This function displays the custom component dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdComponentDialog2()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- if ((svSetupType != "Custom") && (svSetupType != "")) then
- return 0;
- endif;
-
- szTitle = "";
- szMsg = "";
- nResult = SdComponentDialog2( szTitle, szMsg, svDir, "" );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdFinishReboot //
-// //
-// Purpose: This function will show the last dialog of the product. //
-// It will allow the user to reboot and/or show some readme text. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdFinishReboot()
- NUMBER nResult, nDefOptions;
- STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
- NUMBER bOpt1, bOpt2;
- begin
-
- if (!BATCH_INSTALL) then
- bOpt1 = FALSE;
- bOpt2 = FALSE;
- szMsg1 = "";
- szMsg2 = "";
- szOption1 = "";
- szOption2 = "";
- nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
- return 0;
- endif;
-
- nDefOptions = SYS_BOOTMACHINE;
- szTitle = "";
- szMsg1 = "";
- szMsg2 = "";
- nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );
-
- return nResult;
- end;
-
- // --- include script file section ---
-
-#include "sddialog.rul"
-
-
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt b/VC++Files/InstallShield/4.0.XX-pro/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt
deleted file mode 100755
index 52ccf8e11a9..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Setup Files/Compressed Files/Language Independent/OS Independent/infolist.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-This is a release of MySQL Pro @VERSION@ for Win32.
-
-NOTE: If you install MySQL in a folder other than
-C:\MYSQL or you intend to start MySQL on NT/Win2000
-as a service, you must create a file named C:\MY.CNF
-or \Windows\my.ini or \winnt\my.ini with the following
-information::
-
-[mysqld]
-basedir=E:/installation-path/
-datadir=E:/data-path/
-
-After your have installed MySQL, the installation
-directory will contain 4 files named 'my-small.cnf,
-my-medium.cnf, my-large.cnf, my-huge.cnf'.
-You can use this as a starting point for your own
-C:\my.cnf file.
-
-If you have any problems, you can mail them to
-win32@lists.mysql.com after you have consulted the
-MySQL manual and the MySQL mailing list archive
-(http://www.mysql.com/documentation/index.html)
-
-On behalf of the MySQL AB gang,
-Michael Widenius
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmp b/VC++Files/InstallShield/4.0.XX-pro/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmp
deleted file mode 100755
index 3229d50c9bf..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Setup Files/Uncompressed Files/Language Independent/OS Independent/setup.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Shell Objects/Default.shl b/VC++Files/InstallShield/4.0.XX-pro/Shell Objects/Default.shl
deleted file mode 100755
index 187cb651307..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Shell Objects/Default.shl
+++ /dev/null
@@ -1,12 +0,0 @@
-[Data]
-Folder3=<FOLDER_STARTUP>
-Group0=Main
-Group1=Startup
-Folder0=<FOLDER_DESKTOP>
-Folder1=<FOLDER_STARTMENU>
-Folder2=<FOLDER_PROGRAMS>
-
-[Info]
-Type=ShellObject
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl b/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl
deleted file mode 100755
index 525f3be0b3e..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl
+++ /dev/null
@@ -1,23 +0,0 @@
-[Data]
-TITLE_MAIN=MySQL Pro Servers and Clients @VERSION@
-COMPANY_NAME=MySQL AB
-ERROR_COMPONENT=Component:
-COMPANY_NAME16=Company
-PRODUCT_VERSION=MySQL Pro Servers and Clients @VERSION@
-ERROR_MOVEDATA=An error occurred during the move data process: %d
-ERROR_FILEGROUP=File Group:
-UNINST_KEY=MySQL Pro Servers and Clients @VERSION@
-TITLE_CAPTIONBAR=MySQL Pro Servers and Clients @VERSION@
-PRODUCT_NAME16=Product
-ERROR_VGARESOLUTION=This program requires VGA or better resolution.
-ERROR_FILE=File:
-UNINST_DISPLAY_NAME=MySQL Pro Servers and Clients @VERSION@
-PRODUCT_KEY=yourapp.Exe
-PRODUCT_NAME=MySQL Pro Servers and Clients @VERSION@
-ERROR_UNINSTSETUP=unInstaller setup failed to initialize. You may not be able to uninstall this product.
-
-[General]
-Language=0009
-Type=STRINGTABLESPECIFIC
-Version=1.00.000
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/String Tables/Default.shl b/VC++Files/InstallShield/4.0.XX-pro/String Tables/Default.shl
deleted file mode 100755
index d4dc4925ab1..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/String Tables/Default.shl
+++ /dev/null
@@ -1,74 +0,0 @@
-[TITLE_MAIN]
-Comment=
-
-[COMPANY_NAME]
-Comment=
-
-[ERROR_COMPONENT]
-Comment=
-
-[COMPANY_NAME16]
-Comment=
-
-[PRODUCT_VERSION]
-Comment=
-
-[ERROR_MOVEDATA]
-Comment=
-
-[ERROR_FILEGROUP]
-Comment=
-
-[Language]
-Lang0=0009
-CurrentLang=0
-
-[UNINST_KEY]
-Comment=
-
-[TITLE_CAPTIONBAR]
-Comment=
-
-[Data]
-Entry0=ERROR_VGARESOLUTION
-Entry1=TITLE_MAIN
-Entry2=TITLE_CAPTIONBAR
-Entry3=UNINST_KEY
-Entry4=UNINST_DISPLAY_NAME
-Entry5=COMPANY_NAME
-Entry6=PRODUCT_NAME
-Entry7=PRODUCT_VERSION
-Entry8=PRODUCT_KEY
-Entry9=ERROR_MOVEDATA
-Entry10=ERROR_UNINSTSETUP
-Entry11=COMPANY_NAME16
-Entry12=PRODUCT_NAME16
-Entry13=ERROR_COMPONENT
-Entry14=ERROR_FILEGROUP
-Entry15=ERROR_FILE
-
-[PRODUCT_NAME16]
-Comment=
-
-[ERROR_VGARESOLUTION]
-Comment=
-
-[ERROR_FILE]
-Comment=
-
-[General]
-Type=STRINGTABLE
-Version=1.00.000
-
-[UNINST_DISPLAY_NAME]
-Comment=
-
-[PRODUCT_KEY]
-Comment=
-
-[PRODUCT_NAME]
-Comment=
-
-[ERROR_UNINSTSETUP]
-Comment=
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Text Substitutions/Build.tsb b/VC++Files/InstallShield/4.0.XX-pro/Text Substitutions/Build.tsb
deleted file mode 100755
index 3949bd4c066..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Text Substitutions/Build.tsb
+++ /dev/null
@@ -1,56 +0,0 @@
-[<HKUS>]
-Value=
-KeyType=4
-
-[<HKCR>]
-Value=
-KeyType=4
-
-[<PROGRAMFILES>]
-Value=
-KeyType=4
-
-[<WINSYSDIR>]
-Value=
-KeyType=4
-
-[<COMMONFILES>]
-Value=
-KeyType=4
-
-[<WINDIR>]
-Value=
-KeyType=4
-
-[Data]
-Key0=<PROGRAMFILES>
-Key1=<COMMONFILES>
-Key2=<WINDIR>
-Key3=<WINSYSDIR>
-Key4=<HKLM>
-Key5=<HKCU>
-Key6=<HKCC>
-Key7=<HKDD>
-Key8=<HKUS>
-Key9=<HKCR>
-
-[General]
-Type=TEXTSUB
-Version=1.00.000
-
-[<HKLM>]
-Value=
-KeyType=4
-
-[<HKCU>]
-Value=
-KeyType=4
-
-[<HKCC>]
-Value=
-KeyType=4
-
-[<HKDD>]
-Value=
-KeyType=4
-
diff --git a/VC++Files/InstallShield/4.0.XX-pro/Text Substitutions/Setup.tsb b/VC++Files/InstallShield/4.0.XX-pro/Text Substitutions/Setup.tsb
deleted file mode 100755
index b0c5a509f0b..00000000000
--- a/VC++Files/InstallShield/4.0.XX-pro/Text Substitutions/Setup.tsb
+++ /dev/null
@@ -1,76 +0,0 @@
-[<SRCDIR>]
-Value=
-KeyType=4
-
-[<HKUS>]
-Value=
-KeyType=4
-
-[<HKCR>]
-Value=
-KeyType=4
-
-[<PROGRAMFILES>]
-Value=
-KeyType=4
-
-[<TARGETDIR>]
-Value=
-KeyType=4
-
-[<WINSYSDIR>]
-Value=
-KeyType=4
-
-[<COMMONFILES>]
-Value=
-KeyType=4
-
-[<WINDIR>]
-Value=
-KeyType=4
-
-[Data]
-Key0=<PROGRAMFILES>
-Key1=<COMMONFILES>
-Key2=<WINDIR>
-Key3=<WINSYSDIR>
-Key4=<TARGETDIR>
-Key5=<SUPPORTDIR>
-Key10=<HKDD>
-Key6=<SRCDIR>
-Key11=<HKUS>
-Key7=<HKLM>
-Key12=<HKCR>
-Key8=<HKCU>
-Key13=<SHELL_OBJECT_FOLDER>
-Key9=<HKCC>
-
-[<SUPPORTDIR>]
-Value=
-KeyType=4
-
-[<SHELL_OBJECT_FOLDER>]
-Value=
-KeyType=4
-
-[General]
-Type=TEXTSUB
-Version=1.00.000
-
-[<HKLM>]
-Value=
-KeyType=4
-
-[<HKCU>]
-Value=
-KeyType=4
-
-[<HKCC>]
-Value=
-KeyType=4
-
-[<HKDD>]
-Value=
-KeyType=4
-
diff --git a/VC++Files/InstallShield/Script Files/Setup.dbg b/VC++Files/InstallShield/Script Files/Setup.dbg
deleted file mode 100644
index 0c6d4e6b708..00000000000
--- a/VC++Files/InstallShield/Script Files/Setup.dbg
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/Script Files/Setup.ino b/VC++Files/InstallShield/Script Files/Setup.ino
deleted file mode 100644
index 204d8ea0f36..00000000000
--- a/VC++Files/InstallShield/Script Files/Setup.ino
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/Script Files/Setup.ins b/VC++Files/InstallShield/Script Files/Setup.ins
deleted file mode 100644
index 759009b5c84..00000000000
--- a/VC++Files/InstallShield/Script Files/Setup.ins
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/Script Files/Setup.obs b/VC++Files/InstallShield/Script Files/Setup.obs
deleted file mode 100644
index 5fcfcb62c4e..00000000000
--- a/VC++Files/InstallShield/Script Files/Setup.obs
+++ /dev/null
Binary files differ
diff --git a/VC++Files/InstallShield/Script Files/Setup.rul b/VC++Files/InstallShield/Script Files/Setup.rul
deleted file mode 100644
index df143b493c4..00000000000
--- a/VC++Files/InstallShield/Script Files/Setup.rul
+++ /dev/null
@@ -1,640 +0,0 @@
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// IIIIIII SSSSSS
-// II SS InstallShield (R)
-// II SSSSSS (c) 1996-1997, InstallShield Software Corporation
-// II SS (c) 1990-1996, InstallShield Corporation
-// IIIIIII SSSSSS All Rights Reserved.
-//
-//
-// This code is generated as a starting setup template. You should
-// modify it to provide all necessary steps for your setup.
-//
-//
-// File Name: Setup.rul
-//
-// Description: InstallShield script
-//
-// Comments: This template script performs a basic setup on a
-// Windows 95 or Windows NT 4.0 platform. With minor
-// modifications, this template can be adapted to create
-// new, customized setups.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
- // Include header file
-#include "sdlang.h"
-#include "sddialog.h"
-
-////////////////////// string defines ////////////////////////////
-
-#define UNINST_LOGFILE_NAME "Uninst.isu"
-
-//////////////////// installation declarations ///////////////////
-
- // ----- DLL prototypes -----
-
-
- // your DLL prototypes
-
-
- // ---- script prototypes -----
-
- // generated
- prototype ShowDialogs();
- prototype MoveFileData();
- prototype HandleMoveDataError( NUMBER );
- prototype ProcessBeforeDataMove();
- prototype ProcessAfterDataMove();
- prototype SetupRegistry();
- prototype SetupFolders();
- prototype CleanUpInstall();
- prototype SetupInstall();
- prototype SetupScreen();
- prototype CheckRequirements();
- prototype DialogShowSdWelcome();
- prototype DialogShowSdShowInfoList();
- prototype DialogShowSdAskDestPath();
- prototype DialogShowSdSetupType();
- prototype DialogShowSdComponentDialog2();
- prototype DialogShowSdFinishReboot();
-
- // your prototypes
-
-
- // ----- global variables ------
-
- // generated
- BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
- STRING svDir;
- STRING svName, svCompany, svSerial;
- STRING szAppPath;
- STRING svSetupType;
-
-
- // your global variables
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// MAIN PROGRAM
-//
-// The setup begins here by hiding the visible setup
-// window. This is done to allow all the titles, images, etc. to
-// be established before showing the main window. The following
-// logic then performs the setup in a series of steps.
-//
-///////////////////////////////////////////////////////////////////////////////
-program
- Disable( BACKGROUND );
-
- CheckRequirements();
-
- SetupInstall();
-
- SetupScreen();
-
- if (ShowDialogs()<0) goto end_install;
-
- if (ProcessBeforeDataMove()<0) goto end_install;
-
- if (MoveFileData()<0) goto end_install;
-
- if (ProcessAfterDataMove()<0) goto end_install;
-
- if (SetupRegistry()<0) goto end_install;
-
- if (SetupFolders()<0) goto end_install;
-
-
- end_install:
-
- CleanUpInstall();
-
- // If an unrecoverable error occurred, clean up the partial installation.
- // Otherwise, exit normally.
-
- if (bInstallAborted) then
- abort;
- endif;
-
-endprogram
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ShowDialogs //
-// //
-// Purpose: This function manages the display and navigation //
-// the standard dialogs that exist in a setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ShowDialogs()
- NUMBER nResult;
- begin
-
- Dlg_Start:
- // beginning of dialogs label
-
- Dlg_SdWelcome:
- nResult = DialogShowSdWelcome();
- if (nResult = BACK) goto Dlg_Start;
-
- Dlg_SdShowInfoList:
- nResult = DialogShowSdShowInfoList();
- if (nResult = BACK) goto Dlg_SdWelcome;
-
- Dlg_SdAskDestPath:
- nResult = DialogShowSdAskDestPath();
- if (nResult = BACK) goto Dlg_SdShowInfoList;
-
- Dlg_SdSetupType:
- nResult = DialogShowSdSetupType();
- if (nResult = BACK) goto Dlg_SdAskDestPath;
-
- Dlg_SdComponentDialog2:
- if ((nResult = BACK) && (svSetupType != "Custom") && (svSetupType != "")) then
- goto Dlg_SdSetupType;
- endif;
- nResult = DialogShowSdComponentDialog2();
- if (nResult = BACK) goto Dlg_SdSetupType;
-
- return 0;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessBeforeDataMove //
-// //
-// Purpose: This function performs any necessary operations prior to the //
-// actual data move operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessBeforeDataMove()
- STRING svLogFile;
- NUMBER nResult;
- begin
-
- InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
-
- svLogFile = UNINST_LOGFILE_NAME;
-
- nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
- if (nResult < 0) then
- MessageBox( @ERROR_UNINSTSETUP, WARNING );
- endif;
-
- szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir
-
- if ((bIs32BitSetup) && (bIsShellExplorer)) then
- RegDBSetItem( REGDB_APPPATH, szAppPath );
- RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
- RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
- endif;
-
- // TODO : update any items you want to process before moving the data
- //
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: MoveFileData //
-// //
-// Purpose: This function handles the data movement for //
-// the setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function MoveFileData()
- NUMBER nResult, nDisk;
- begin
-
- nDisk = 1;
- SetStatusWindow( 0, "" );
- Disable( DIALOGCACHE );
- Enable( STATUS );
- StatusUpdate( ON, 100 );
- nResult = ComponentMoveData( MEDIA, nDisk, 0 );
-
- HandleMoveDataError( nResult );
-
- Disable( STATUS );
-
- return nResult;
-
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: HandleMoveDataError //
-// //
-// Purpose: This function handles the error (if any) during the move data //
-// operation. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function HandleMoveDataError( nResult )
- STRING szErrMsg, svComponent , svFileGroup , svFile;
- begin
-
- svComponent = "";
- svFileGroup = "";
- svFile = "";
-
- switch (nResult)
- case 0:
- return 0;
- default:
- ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
- szErrMsg = @ERROR_MOVEDATA + "\n\n" +
- @ERROR_COMPONENT + " " + svComponent + "\n" +
- @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
- @ERROR_FILE + " " + svFile;
- SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
- bInstallAborted = TRUE;
- return nResult;
- endswitch;
-
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: ProcessAfterDataMove //
-// //
-// Purpose: This function performs any necessary operations needed after //
-// all data has been moved. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function ProcessAfterDataMove()
- begin
-
- // TODO : update self-registered files and other processes that
- // should be performed after the data has been moved.
-
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupRegistry //
-// //
-// Purpose: This function makes the registry entries for this setup. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupRegistry()
- NUMBER nResult;
-
- begin
-
- // TODO : Add all your registry entry keys here
- //
- //
- // RegDBCreateKeyEx, RegDBSetKeyValueEx....
- //
-
- nResult = CreateRegistrySet( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// Function: SetupFolders
-//
-// Purpose: This function creates all the folders and shortcuts for the
-// setup. This includes program groups and items for Windows 3.1.
-//
-///////////////////////////////////////////////////////////////////////////////
-function SetupFolders()
- NUMBER nResult;
-
- begin
-
-
- // TODO : Add all your folder (program group) along with shortcuts (program items)
- //
- //
- // CreateProgramFolder, AddFolderIcon....
- //
-
- nResult = CreateShellObjects( "" );
-
- return nResult;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CleanUpInstall //
-// //
-// Purpose: This cleans up the setup. Anything that should //
-// be released or deleted at the end of the setup should //
-// be done here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CleanUpInstall()
- begin
-
-
- if (bInstallAborted) then
- return 0;
- endif;
-
- DialogShowSdFinishReboot();
-
- if (BATCH_INSTALL) then // ensure locked files are properly written
- CommitSharedFiles(0);
- endif;
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupInstall //
-// //
-// Purpose: This will setup the installation. Any general initialization //
-// needed for the installation should be performed here. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupInstall()
- begin
-
- Enable( CORECOMPONENTHANDLING );
-
- bInstallAborted = FALSE;
-
- if (bIs32BitSetup) then
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME ^ @PRODUCT_NAME;
- else
- svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME16 ^ @PRODUCT_NAME16; // use shorten names
- endif;
-
- TARGETDIR = svDir;
-
- SdProductName( @PRODUCT_NAME );
-
- Enable( DIALOGCACHE );
-
- return 0;
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: SetupScreen //
-// //
-// Purpose: This function establishes the screen look. This includes //
-// colors, fonts, and text to be displayed. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function SetupScreen()
- begin
-
- Enable( FULLWINDOWMODE );
- Enable( INDVFILESTATUS );
- SetTitle( @TITLE_MAIN, 24, WHITE );
-
- SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
-
- Enable( BACKGROUND );
-
- Delay( 1 );
- end;
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: CheckRequirements //
-// //
-// Purpose: This function checks all minimum requirements for the //
-// application being installed. If any fail, then the user //
-// is informed and the setup is terminated. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function CheckRequirements()
- NUMBER nvDx, nvDy, nvResult;
- STRING svResult;
-
- begin
-
- bWinNT = FALSE;
- bIsShellExplorer = FALSE;
-
- // Check screen resolution.
- GetExtents( nvDx, nvDy );
-
- if (nvDy < 480) then
- MessageBox( @ERROR_VGARESOLUTION, WARNING );
- abort;
- endif;
-
- // set 'setup' operation mode
- bIs32BitSetup = TRUE;
- GetSystemInfo( ISTYPE, nvResult, svResult );
- if (nvResult = 16) then
- bIs32BitSetup = FALSE; // running 16-bit setup
- return 0; // no additional information required
- endif;
-
- // --- 32-bit testing after this point ---
-
- // Determine the target system's operating system.
- GetSystemInfo( OS, nvResult, svResult );
-
- if (nvResult = IS_WINDOWSNT) then
- // Running Windows NT.
- bWinNT = TRUE;
-
- // Check to see if the shell being used is EXPLORER shell.
- if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
- if (nvResult >= 4) then
- bIsShellExplorer = TRUE;
- endif;
- endif;
-
- elseif (nvResult = IS_WINDOWS95 ) then
- bIsShellExplorer = TRUE;
-
- endif;
-
-end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdWelcome //
-// //
-// Purpose: This function handles the standard welcome dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdWelcome()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdWelcome( szTitle, szMsg );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdShowInfoList //
-// //
-// Purpose: This function displays the general information list dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdShowInfoList()
- NUMBER nResult;
- LIST list;
- STRING szTitle, szMsg, szFile;
- begin
-
- szFile = SUPPORTDIR ^ "infolist.txt";
-
- list = ListCreate( STRINGLIST );
- ListReadFromFile( list, szFile );
- szTitle = "";
- szMsg = " ";
- nResult = SdShowInfoList( szTitle, szMsg, list );
-
- ListDestroy( list );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdAskDestPath //
-// //
-// Purpose: This function asks the user for the destination directory. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdAskDestPath()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- szTitle = "";
- szMsg = "";
- nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
-
- TARGETDIR = svDir;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdSetupType //
-// //
-// Purpose: This function displays the standard setup type dialog. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdSetupType()
- NUMBER nResult, nType;
- STRING szTitle, szMsg;
- begin
-
- switch (svSetupType)
- case "Typical":
- nType = TYPICAL;
- case "Custom":
- nType = CUSTOM;
- case "Compact":
- nType = COMPACT;
- case "":
- svSetupType = "Typical";
- nType = TYPICAL;
- endswitch;
-
- szTitle = "";
- szMsg = "";
- nResult = SetupType( szTitle, szMsg, "", nType, 0 );
-
- switch (nResult)
- case COMPACT:
- svSetupType = "Compact";
- case TYPICAL:
- svSetupType = "Typical";
- case CUSTOM:
- svSetupType = "Custom";
- endswitch;
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdComponentDialog2 //
-// //
-// Purpose: This function displays the custom component dialog. //
-// //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdComponentDialog2()
- NUMBER nResult;
- STRING szTitle, szMsg;
- begin
-
- if ((svSetupType != "Custom") && (svSetupType != "")) then
- return 0;
- endif;
-
- szTitle = "";
- szMsg = "";
- nResult = SdComponentDialog2( szTitle, szMsg, svDir, "" );
-
- return nResult;
- end;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// //
-// Function: DialogShowSdFinishReboot //
-// //
-// Purpose: This function will show the last dialog of the product. //
-// It will allow the user to reboot and/or show some readme text. //
-// //
-///////////////////////////////////////////////////////////////////////////////
-function DialogShowSdFinishReboot()
- NUMBER nResult, nDefOptions;
- STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
- NUMBER bOpt1, bOpt2;
- begin
-
- if (!BATCH_INSTALL) then
- bOpt1 = FALSE;
- bOpt2 = FALSE;
- szMsg1 = "";
- szMsg2 = "";
- szOption1 = "";
- szOption2 = "";
- nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
- return 0;
- endif;
-
- nDefOptions = SYS_BOOTMACHINE;
- szTitle = "";
- szMsg1 = "";
- szMsg2 = "";
- nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );
-
- return nResult;
- end;
-
- // --- include script file section ---
-
-#include "sddialog.rul"
-
-
diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp
index a46c3fd2369..4de32e447d3 100644
--- a/VC++Files/client/mysqlclient.dsp
+++ b/VC++Files/client/mysqlclient.dsp
@@ -19,6 +19,7 @@ CFG=mysqlclient - Win32 Debug
!MESSAGE
!MESSAGE "mysqlclient - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "mysqlclient - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "mysqlclient - Win32 authent" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
@@ -41,7 +42,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "DBUG_OFF" /D "_WINDOWS" /D "USE_TLS" /D "NDEBUG" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "DBUG_OFF" /D "_WINDOWS" /D "USE_TLS" /D "MYSQL_CLIENT" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
@@ -65,7 +66,7 @@ LIB32=xilink6.exe -lib
# PROP Intermediate_Dir "debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "USE_TLS" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "USE_TLS" /D "MYSQL_CLIENT" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
@@ -76,12 +77,38 @@ LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\mysqlclient.lib"
+!ELSEIF "$(CFG)" == "mysqlclient - Win32 authent"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "mysqlclient___Win32_authent"
+# PROP BASE Intermediate_Dir "mysqlclient___Win32_authent"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "authent"
+# PROP Intermediate_Dir "authent"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "DBUG_OFF" /D "_WINDOWS" /D "USE_TLS" /D "MYSQL_CLIENT" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "DBUG_OFF" /D "_WINDOWS" /D "USE_TLS" /D "MYSQL_CLIENT" /D "NDEBUG" /D "CHECK_LICENSE" /D LICENSE=Commercial /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=xilink6.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib_release\mysqlclient.lib"
+# ADD LIB32 /nologo /out:"..\lib_authent\mysqlclient.lib"
+
!ENDIF
# Begin Target
# Name "mysqlclient - Win32 Release"
# Name "mysqlclient - Win32 Debug"
+# Name "mysqlclient - Win32 authent"
# Begin Source File
SOURCE=..\mysys\array.c
@@ -256,6 +283,8 @@ SOURCE=..\mysys\mf_iocache2.c
# ADD CPP /Od
+!ELSEIF "$(CFG)" == "mysqlclient - Win32 authent"
+
!ENDIF
# End Source File
@@ -406,6 +435,10 @@ SOURCE=..\mysys\my_tempnam.c
# End Source File
# Begin Source File
+SOURCE=..\libmysql\my_time.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\my_thr_init.c
# End Source File
# Begin Source File
diff --git a/VC++Files/examples/udf_example/udf_example.def b/VC++Files/examples/udf_example/udf_example.def
new file mode 100644
index 00000000000..9764343e5f2
--- /dev/null
+++ b/VC++Files/examples/udf_example/udf_example.def
@@ -0,0 +1,18 @@
+LIBRARY MYUDF
+DESCRIPTION 'MySQL Sample for UDF'
+VERSION 1.0
+EXPORTS
+ metaphon_init
+ metaphon_deinit
+ metaphon
+ myfunc_double_init
+ myfunc_double
+ myfunc_int
+ sequence_init
+ sequence_deinit
+ sequence
+ avgcost_init
+ avgcost_deinit
+ avgcost_reset
+ avgcost_add
+ avgcost
diff --git a/VC++Files/examples/udf_example/udf_example.dsp b/VC++Files/examples/udf_example/udf_example.dsp
new file mode 100644
index 00000000000..bfe4d76bcc7
--- /dev/null
+++ b/VC++Files/examples/udf_example/udf_example.dsp
@@ -0,0 +1,111 @@
+# Microsoft Developer Studio Project File - Name="udf_example" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=udf_example - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "udf_example.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "udf_example.mak" CFG="udf_example - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "udf_example - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "udf_example - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "udf_example - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "UDF_EXAMPLE_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "UDF_EXAMPLE_EXPORTS" /D "HAVE_DLOPEN" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x416 /d "NDEBUG"
+# ADD RSC /l 0x416 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\..\lib\opt\strings.lib /nologo /dll /machine:I386 /out:"Release/myudf.dll"
+
+!ELSEIF "$(CFG)" == "udf_example - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "UDF_EXAMPLE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "UDF_EXAMPLE_EXPORTS" /D "HAVE_DLOPEN" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x416 /d "_DEBUG"
+# ADD RSC /l 0x416 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\..\lib\debug\strings.lib /nologo /dll /debug /machine:I386 /out:"Debug/myudf.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "udf_example - Win32 Release"
+# Name "udf_example - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\udf_example.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\udf_example.def
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/examples/udf_example/udf_example.dsw b/VC++Files/examples/udf_example/udf_example.dsw
new file mode 100644
index 00000000000..6716e107f6a
--- /dev/null
+++ b/VC++Files/examples/udf_example/udf_example.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "udf_example"=.\udf_example.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp
index c315775443b..f382f36cb85 100644
--- a/VC++Files/libmysql/libmysql.dsp
+++ b/VC++Files/libmysql/libmysql.dsp
@@ -427,6 +427,10 @@ SOURCE=.\pack.c
# End Source File
# Begin Source File
+SOURCE=.\my_time.c
+# End Source File
+# Begin Source File
+
SOURCE=.\password.c
# End Source File
# Begin Source File
diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp
index f087c8a7b06..4dd4af9b12f 100644
--- a/VC++Files/libmysqld/libmysqld.dsp
+++ b/VC++Files/libmysqld/libmysqld.dsp
@@ -368,6 +368,10 @@ SOURCE="..\sql-common\pack.c"
# End Source File
# Begin Source File
+SOURCE=..\sql-common\my_time.c
+# End Source File
+# Begin Source File
+
SOURCE=..\libmysql\password.c
# End Source File
# Begin Source File
@@ -588,6 +592,10 @@ SOURCE=..\sql\time.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\tztime.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\uniques.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp
index 4e7bc644cc4..8a56e700220 100644
--- a/VC++Files/sql/mysqld.dsp
+++ b/VC++Files/sql/mysqld.dsp
@@ -110,7 +110,7 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=xilink6.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\dbug.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /debug /machine:I386
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe"
# SUBTRACT LINK32 /pdb:none /debug
@@ -1053,6 +1053,10 @@ SOURCE=.\pack.c
# End Source File
# Begin Source File
+SOURCE=.\my_time.c
+# End Source File
+# Begin Source File
+
SOURCE=.\password.c
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -1840,6 +1844,10 @@ SOURCE=.\time.cpp
# End Source File
# Begin Source File
+SOURCE=.\tztime.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\uniques.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/winmysqladmin/main.cpp b/VC++Files/winmysqladmin/main.cpp
index 6ca29659255..dfb2004a780 100644
--- a/VC++Files/winmysqladmin/main.cpp
+++ b/VC++Files/winmysqladmin/main.cpp
@@ -1196,7 +1196,7 @@ bool __fastcall TForm1::Shutd()
if (IsConnect)
{
mysql_kill(MySQL,mysql_thread_id(MySQL));
- mysql_shutdown(MySQL);
+ mysql_shutdown(MySQL, SHUTDOWN_DEFAULT);
StatusLine->SimpleText = "";
}
diff --git a/VC++Files/winmysqladmin/mysql.h b/VC++Files/winmysqladmin/mysql.h
index e83babb8fa8..f01b55f5d3f 100644
--- a/VC++Files/winmysqladmin/mysql.h
+++ b/VC++Files/winmysqladmin/mysql.h
@@ -229,7 +229,9 @@ int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
unsigned int length);
int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
-int STDCALL mysql_shutdown(MYSQL *mysql);
+int STDCALL mysql_shutdown(MYSQL *mysql,
+ enum enum_shutdown_level
+ shutdown_level);
int STDCALL mysql_dump_debug_info(MYSQL *mysql);
int STDCALL mysql_refresh(MYSQL *mysql,
unsigned int refresh_options);
diff --git a/VC++Files/winmysqladmin/mysql_com.h b/VC++Files/winmysqladmin/mysql_com.h
index 2a1471f735d..0870f340451 100644
--- a/VC++Files/winmysqladmin/mysql_com.h
+++ b/VC++Files/winmysqladmin/mysql_com.h
@@ -155,6 +155,32 @@ enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
#define FIELD_TYPE_CHAR FIELD_TYPE_TINY /* For compability */
#define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM /* For compability */
+enum enum_shutdown_level {
+ /*
+ We want levels to be in growing order of hardness. So we leave room
+ for future intermediate levels. For now, escalating one level is += 10;
+ later if we insert new levels in between we will need a function
+ next_shutdown_level(level). Note that DEFAULT does not respect the
+ growing property.
+ */
+ SHUTDOWN_DEFAULT= 0, /* mapped to WAIT_ALL_BUFFERS for now */
+ /*
+ Here is the list in growing order (the next does the previous plus
+ something). WAIT_ALL_BUFFERS is what we have now. Others are "this MySQL
+ server does not support this shutdown level yet".
+ */
+ SHUTDOWN_WAIT_CONNECTIONS= 10, /* wait for existing connections to finish */
+ SHUTDOWN_WAIT_TRANSACTIONS= 20, /* wait for existing trans to finish */
+ SHUTDOWN_WAIT_STATEMENTS= 30, /* wait for existing updating stmts to finish */
+ SHUTDOWN_WAIT_ALL_BUFFERS= 40, /* flush InnoDB buffers */
+ SHUTDOWN_WAIT_CRITICAL_BUFFERS= 50, /* flush MyISAM buffs (no corruption) */
+ /* Now the 2 levels of the KILL command */
+#if MYSQL_VERSION_ID >= 50000
+ KILL_QUERY= 254,
+#endif
+ KILL_CONNECTION= 255
+};
+
extern unsigned long max_allowed_packet;
extern unsigned long net_buffer_length;
diff --git a/VC++Files/zlib/zlib.dsp b/VC++Files/zlib/zlib.dsp
index 6edab34d93c..7093c51d558 100644
--- a/VC++Files/zlib/zlib.dsp
+++ b/VC++Files/zlib/zlib.dsp
@@ -19,6 +19,7 @@ CFG=zlib - Win32 Debug
!MESSAGE
!MESSAGE "zlib - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "zlib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "zlib - Win32 authent" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
@@ -75,12 +76,38 @@ LIB32=xilink6.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\zlib.lib"
+!ELSEIF "$(CFG)" == "zlib - Win32 authent"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zlib___Win32_authent"
+# PROP BASE Intermediate_Dir "zlib___Win32_authent"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "zlib___Win32_authent"
+# PROP Intermediate_Dir "zlib___Win32_authent"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /G6 /MT /W3 /O2 /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=xilink6.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib_release\zlib.lib"
+# ADD LIB32 /nologo /out:"..\lib_release\zlib.lib"
+
!ENDIF
# Begin Target
# Name "zlib - Win32 Release"
# Name "zlib - Win32 Debug"
+# Name "zlib - Win32 authent"
# Begin Source File
SOURCE=.\adler32.c
diff --git a/acconfig.h b/acconfig.h
index 67e9d1759c6..f9cff3010ca 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -84,6 +84,7 @@
#undef HAVE_CHARSET_euckr
#undef HAVE_CHARSET_gb2312
#undef HAVE_CHARSET_gbk
+#undef HAVE_CHARSET_geostd8
#undef HAVE_CHARSET_greek
#undef HAVE_CHARSET_hebrew
#undef HAVE_CHARSET_hp8
@@ -115,6 +116,9 @@
/* Builds Example DB */
#undef HAVE_EXAMPLE_DB
+/* Builds Archive Storage Engine */
+#undef HAVE_ARCHIVE_DB
+
/* fp_except from ieeefp.h */
#undef HAVE_FP_EXCEPT
@@ -155,6 +159,12 @@
/* Using Ndb Cluster DB */
#undef HAVE_NDBCLUSTER_DB
+/* Including Ndb Cluster DB shared memory transporter */
+#undef NDB_SHM_TRANSPORTER
+
+/* Including Ndb Cluster DB sci transporter */
+#undef NDB_SCI_TRANSPORTER
+
/* For some non posix threads */
#undef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC
@@ -197,6 +207,15 @@
/* If we want to have query cache */
#undef HAVE_QUERY_CACHE
+/* Spatial extentions */
+#undef HAVE_SPATIAL
+
+/* RTree keys */
+#undef HAVE_RTREE_KEYS
+
+/* Access checks in embedded library */
+#undef HAVE_EMBEDDED_PRIVILEGE_CONTROL
+
/* Solaris define gethostbyaddr_r with 7 arguments. glibc2 defines
this with 8 arguments */
#undef HAVE_SOLARIS_STYLE_GETHOST
@@ -263,6 +282,12 @@
/* mysql client protocoll version */
#undef PROTOCOL_VERSION
+/* ndb version */
+#undef NDB_VERSION_MAJOR
+#undef NDB_VERSION_MINOR
+#undef NDB_VERSION_BUILD
+#undef NDB_VERSION_STATUS
+
/* Define if qsort returns void */
#undef QSORT_TYPE_IS_VOID
diff --git a/acinclude.m4 b/acinclude.m4
index 677c3cc9e99..5e642c547c3 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -777,14 +777,15 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [
---)
for d in /usr/ssl/include /usr/local/ssl/include /usr/include \
/usr/include/ssl /opt/ssl/include /opt/openssl/include \
-/usr/local/ssl/include /usr/local/include ; do
+/usr/local/ssl/include /usr/local/include /usr/freeware/include ; do
if test -f $d/openssl/ssl.h ; then
OPENSSL_INCLUDE=-I$d
fi
done
for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \
-/usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib /usr/local/lib/ ; do
+/usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib \
+/usr/freeware/lib32 /usr/local/lib/ ; do
if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl.dylib ; then
OPENSSL_LIB=$d
fi
@@ -1310,7 +1311,7 @@ AC_DEFUN([MYSQL_CHECK_EXAMPLEDB], [
AC_ARG_WITH([example-storage-engine],
[
--with-example-storage-engine
- Enable the Example Storge Engine],
+ Enable the Example Storage Engine],
[exampledb="$withval"],
[exampledb=no])
AC_MSG_CHECKING([for example storage engine])
@@ -1333,10 +1334,114 @@ dnl END OF MYSQL_CHECK_EXAMPLE SECTION
dnl ---------------------------------------------------------------------------
dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_ARCHIVEDB
+dnl Sets HAVE_ARCHIVE_DB if --with-archive-storage-engine is used
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_ARCHIVEDB], [
+ AC_ARG_WITH([archive-storage-engine],
+ [
+ --with-archive-storage-engine
+ Enable the Archive Storage Engine],
+ [archivedb="$withval"],
+ [archivedb=no])
+ AC_MSG_CHECKING([for archive storage engine])
+
+ case "$archivedb" in
+ yes )
+ AC_DEFINE(HAVE_ARCHIVE_DB)
+ AC_MSG_RESULT([yes])
+ [archivedb=yes]
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ [archivedb=no]
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_ARCHIVE SECTION
+dnl ---------------------------------------------------------------------------
+
+dnl ---------------------------------------------------------------------------
dnl Macro: MYSQL_CHECK_NDBCLUSTER
dnl Sets HAVE_NDBCLUSTER_DB if --with-ndbcluster is used
dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_NDB_OPTIONS], [
+ AC_ARG_WITH([ndb-shm],
+ [
+ --with-ndb-shm Include the NDB Cluster shared memory transporter],
+ [ndb_shm="$withval"],
+ [ndb_shm=no])
+ AC_ARG_WITH([ndb-sci],
+ [
+ --with-ndb-sci Include the NDB Cluster sci transporter],
+ [ndb_sci="$withval"],
+ [ndb_sci=no])
+ AC_ARG_WITH([ndb-test],
+ [
+ --with-ndb-test Include the NDB Cluster ndbapi test programs],
+ [ndb_test="$withval"],
+ [ndb_test=no])
+ AC_ARG_WITH([ndb-docs],
+ [
+ --with-ndb-docs Include the NDB Cluster ndbapi and mgmapi documentation],
+ [ndb_docs="$withval"],
+ [ndb_docs=no])
+
+ AC_MSG_CHECKING([for NDB Cluster options])
+ AC_MSG_RESULT([])
+
+ have_ndb_shm=no
+ case "$ndb_shm" in
+ yes )
+ AC_MSG_RESULT([-- including shared memory transporter])
+ AC_DEFINE(NDB_SHM_TRANSPORTER)
+ have_ndb_shm="yes"
+ ;;
+ * )
+ AC_MSG_RESULT([-- not including shared memory transporter])
+ ;;
+ esac
+
+ have_ndb_sci=no
+ case "$ndb_sci" in
+ yes )
+ AC_MSG_RESULT([-- including sci transporter])
+ AC_DEFINE(NDB_SCI_TRANSPORTER)
+ have_ndb_sci="yes"
+ ;;
+ * )
+ AC_MSG_RESULT([-- not including sci transporter])
+ ;;
+ esac
+
+ have_ndb_test=no
+ case "$ndb_test" in
+ yes )
+ AC_MSG_RESULT([-- including ndbapi test programs])
+ have_ndb_test="yes"
+ ;;
+ * )
+ AC_MSG_RESULT([-- not including ndbapi test programs])
+ ;;
+ esac
+
+ have_ndb_docs=no
+ case "$ndb_docs" in
+ yes )
+ AC_MSG_RESULT([-- including ndbapi and mgmapi documentation])
+ have_ndb_docs="yes"
+ ;;
+ * )
+ AC_MSG_RESULT([-- not including ndbapi and mgmapi documentation])
+ ;;
+ esac
+
+ AC_MSG_RESULT([done.])
+])
+
AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [
AC_ARG_WITH([ndbcluster],
[
@@ -1355,14 +1460,16 @@ AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [
AC_DEFINE(HAVE_NDBCLUSTER_DB)
have_ndbcluster="yes"
ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi"
- ndbcluster_libs="\$(top_builddir)/ndb/lib/libNDB_API.a"
+ ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a"
ndbcluster_system_libs=""
+ MYSQL_CHECK_NDB_OPTIONS
;;
* )
AC_MSG_RESULT([Not using NDB Cluster])
;;
esac
+ AM_CONDITIONAL([HAVE_NDBCLUSTER_DB], [ test "$have_ndbcluster" = "yes" ])
AC_SUBST(ndbcluster_includes)
AC_SUBST(ndbcluster_libs)
AC_SUBST(ndbcluster_system_libs)
diff --git a/client/mysql.cc b/client/mysql.cc
index 01d867cca07..98bc7e750e1 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -136,6 +136,7 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0,
tty_password= 0, opt_nobeep=0, opt_reconnect=1,
default_charset_used= 0, opt_secure_auth= 0,
default_pager_set= 0;
+static ulong opt_max_allowed_packet, opt_net_buffer_length;
static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
static my_string opt_mysql_unix_port=0;
static int connect_flag=CLIENT_INTERACTIVE;
@@ -368,7 +369,7 @@ int main(int argc,char *argv[])
exit(1);
}
if (status.batch && !status.line_buff &&
- !(status.line_buff=batch_readline_init(max_allowed_packet+512,stdin)))
+ !(status.line_buff=batch_readline_init(opt_max_allowed_packet+512,stdin)))
{
free_defaults(defaults_argv);
my_end(0);
@@ -644,12 +645,12 @@ static struct my_option my_long_options[] =
0, 1},
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
"Max packet length to send to, or receive from server",
- (gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0, GET_ULONG,
+ (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0, GET_ULONG,
REQUIRED_ARG, 16 *1024L*1024L, 4096, (longlong) 2*1024L*1024L*1024L,
MALLOC_OVERHEAD, 1024, 0},
{"net_buffer_length", OPT_NET_BUFFER_LENGTH,
"Buffer for TCP/IP and socket communication",
- (gptr*) &net_buffer_length, (gptr*) &net_buffer_length, 0, GET_ULONG,
+ (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0, GET_ULONG,
REQUIRED_ARG, 16384, 1024, 512*1024*1024L, MALLOC_OVERHEAD, 1024, 0},
{"select_limit", OPT_SELECT_LIMIT,
"Automatic limit for SELECT when using --safe-updates",
@@ -839,6 +840,7 @@ static int get_options(int argc, char **argv)
{
char *tmp, *pagpoint;
int ho_error;
+ MYSQL_PARAMETERS *mysql_params= mysql_get_parameters();
tmp= (char *) getenv("MYSQL_HOST");
if (tmp)
@@ -854,9 +856,15 @@ static int get_options(int argc, char **argv)
strmov(pager, pagpoint);
strmov(default_pager, pager);
+ opt_max_allowed_packet= *mysql_params->p_max_allowed_packet;
+ opt_net_buffer_length= *mysql_params->p_net_buffer_length;
+
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error);
+ *mysql_params->p_max_allowed_packet= opt_max_allowed_packet;
+ *mysql_params->p_net_buffer_length= opt_net_buffer_length;
+
if (status.batch) /* disable pager and outfile in this case */
{
strmov(default_pager, "stdout");
@@ -1864,7 +1872,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
{
*pos++= ',';
*pos++= ' ';
- pos=int2str(warnings, pos, 10);
+ pos=int10_to_str(warnings, pos, 10);
pos=strmov(pos, " warning");
if (warnings != 1)
*pos++= 's';
@@ -2529,7 +2537,7 @@ static int com_source(String *buffer, char *line)
return put_info(buff, INFO_ERROR, 0);
}
- if (!(line_buff=batch_readline_init(max_allowed_packet+512,sql_file)))
+ if (!(line_buff=batch_readline_init(opt_max_allowed_packet+512,sql_file)))
{
my_fclose(sql_file,MYF(0));
return put_info("Can't initialize batch_readline", INFO_ERROR, 0);
@@ -3082,21 +3090,21 @@ static void nice_time(double sec,char *buff,bool part_second)
{
tmp=(ulong) floor(sec/(3600.0*24));
sec-=3600.0*24*tmp;
- buff=int2str((long) tmp,buff,10);
+ buff=int10_to_str((long) tmp, buff, 10);
buff=strmov(buff,tmp > 1 ? " days " : " day ");
}
if (sec >= 3600.0)
{
tmp=(ulong) floor(sec/3600.0);
sec-=3600.0*tmp;
- buff=int2str((long) tmp,buff,10);
+ buff=int10_to_str((long) tmp, buff, 10);
buff=strmov(buff,tmp > 1 ? " hours " : " hour ");
}
if (sec >= 60.0)
{
tmp=(ulong) floor(sec/60.0);
sec-=60.0*tmp;
- buff=int2str((long) tmp,buff,10);
+ buff=int10_to_str((long) tmp, buff, 10);
buff=strmov(buff," min ");
}
if (part_second)
diff --git a/client/mysqladmin.c b/client/mysqladmin.c
index e6e90fc628c..aaed101a83e 100644
--- a/client/mysqladmin.c
+++ b/client/mysqladmin.c
@@ -509,7 +509,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
!stat(pidfile, &pidfile_status))
last_modified= pidfile_status.st_mtime;
- if (mysql_shutdown(mysql))
+ if (mysql_shutdown(mysql, SHUTDOWN_DEFAULT))
{
my_printf_error(0,"shutdown failed; error: '%s'",MYF(ME_BELL),
mysql_error(mysql));
@@ -961,24 +961,24 @@ static void nice_time(ulong sec,char *buff)
{
tmp=sec/(3600L*24);
sec-=3600L*24*tmp;
- buff=int2str(tmp,buff,10);
+ buff=int10_to_str(tmp, buff, 10);
buff=strmov(buff,tmp > 1 ? " days " : " day ");
}
if (sec >= 3600L)
{
tmp=sec/3600L;
sec-=3600L*tmp;
- buff=int2str(tmp,buff,10);
+ buff=int10_to_str(tmp, buff, 10);
buff=strmov(buff,tmp > 1 ? " hours " : " hour ");
}
if (sec >= 60)
{
tmp=sec/60;
sec-=60*tmp;
- buff=int2str(tmp,buff,10);
+ buff=int10_to_str(tmp, buff, 10);
buff=strmov(buff," min ");
}
- strmov(int2str(sec,buff,10)," sec");
+ strmov(int10_to_str(sec, buff, 10)," sec");
}
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 1d042f1a9a1..b1fdb3722d8 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -32,7 +32,6 @@
#undef MYSQL_SERVER
#include "client_priv.h"
#include <time.h>
-#include <assert.h>
#include "log_event.h"
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
#include "mysql_priv.h"
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 0366e0da87f..dfac9ea0e7c 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -43,7 +43,6 @@
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
-#include <assert.h>
#include "client_priv.h"
#include "mysql.h"
@@ -56,6 +55,7 @@
#define EX_MYSQLERR 2
#define EX_CONSCHECK 3
#define EX_EOM 4
+#define EX_EOF 5 /* ferror for output file was got */
/* index into 'show fields from table' */
@@ -82,7 +82,7 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1,
opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0,
opt_delete_master_logs=0, tty_password=0,
opt_single_transaction=0, opt_comments= 0, opt_compact= 0;
-
+static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*sock=0;
static char insert_pat[12 * 1024],*opt_password=0,*current_user=0,
*current_host=0,*path=0,*fields_terminated=0,
@@ -95,7 +95,6 @@ static ulong opt_compatible_mode= 0;
static uint opt_mysql_port= 0, err_len= 0;
static my_string opt_mysql_unix_port=0;
static int first_error=0;
-extern ulong net_buffer_length;
static DYNAMIC_STRING extended_row;
#include <sslopt-vars.h>
FILE *md_result_file;
@@ -129,6 +128,9 @@ TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
static struct my_option my_long_options[] =
{
+ {"all", 'a', "Deprecated. Use --create-options instead.",
+ (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1,
+ 0, 0, 0, 0, 0},
{"all-databases", 'A',
"Dump all the databases. This will be same as --databases with all databases selected.",
(gptr*) &opt_alldbs, (gptr*) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
@@ -241,10 +243,10 @@ static struct my_option my_long_options[] =
{"no-data", 'd', "No row information.", (gptr*) &dFlag, (gptr*) &dFlag, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"no-set-names", 'N',
- "Deprecated, use --set-charset or --skip-set-charset to enable/disable charset settings instead",
+ "Deprecated. Use --skip-set-charset instead.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"set-charset", OPT_SET_CHARSET,
- "'SET CHARACTER_SET_CLIENT=default_character_set' will be put in the output",
+ "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.",
(gptr*) &opt_set_charset, (gptr*) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0},
{"set-variable", 'O',
@@ -304,11 +306,11 @@ static struct my_option my_long_options[] =
{"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
- (gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0,
+ (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0,
GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
(longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
{"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
- (gptr*) &net_buffer_length, (gptr*) &net_buffer_length, 0,
+ (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0,
GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
MALLOC_OVERHEAD-1024, 1024, 0},
{"comments", 'i', "Write additional information.",
@@ -334,6 +336,23 @@ static const char *check_if_ignore_table(const char *table_name);
#include <help_start.h>
+/*
+ exit with message if ferror(file)
+
+ SYNOPSIS
+ check_io()
+ file - checked file
+*/
+
+void check_io(FILE *file)
+{
+ if (ferror(file))
+ {
+ fprintf(stderr, "%s: Got errno %d on write\n", my_progname, errno);
+ safe_exit(EX_EOF);
+ }
+}
+
static void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
@@ -380,6 +399,7 @@ static void write_header(FILE *sql_file, char *db_name)
{
fputs("<?xml version=\"1.0\"?>\n", sql_file);
fputs("<mysqldump>\n", sql_file);
+ check_io(sql_file);
}
else if (!opt_compact)
{
@@ -395,7 +415,11 @@ static void write_header(FILE *sql_file, char *db_name)
mysql_get_server_info(&mysql_connection));
}
if (opt_set_charset)
- fprintf(sql_file,"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=%s */;\n",default_charset);
+ fprintf(sql_file,
+"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
+"\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
+"\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
+"\n/*!40101 SET NAMES %s */;\n",default_charset);
if (!path)
{
fprintf(md_result_file,"\
@@ -407,6 +431,7 @@ static void write_header(FILE *sql_file, char *db_name)
"/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=\"%s%s%s\" */;\n",
path?"":"NO_AUTO_VALUE_ON_ZERO",compatible_mode_normal_str[0]==0?"":",",
compatible_mode_normal_str);
+ check_io(sql_file);
}
} /* write_header */
@@ -414,7 +439,10 @@ static void write_header(FILE *sql_file, char *db_name)
static void write_footer(FILE *sql_file)
{
if (opt_xml)
+ {
fputs("</mysqldump>\n", sql_file);
+ check_io(sql_file);
+ }
else if (!opt_compact)
{
fprintf(sql_file,"\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n");
@@ -426,8 +454,11 @@ static void write_footer(FILE *sql_file)
}
if (opt_set_charset)
fprintf(sql_file,
- "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n");
+"/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
+"/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
+"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
fputs("\n", sql_file);
+ check_io(sql_file);
}
} /* write_footer */
@@ -566,6 +597,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
static int get_options(int *argc, char ***argv)
{
int ho_error;
+ MYSQL_PARAMETERS *mysql_params= mysql_get_parameters();
+
+ opt_max_allowed_packet= *mysql_params->p_max_allowed_packet;
+ opt_net_buffer_length= *mysql_params->p_net_buffer_length;
md_result_file= stdout;
load_defaults("my",load_default_groups,argc,argv);
@@ -573,6 +608,9 @@ static int get_options(int *argc, char ***argv)
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
exit(ho_error);
+ *mysql_params->p_max_allowed_packet= opt_max_allowed_packet;
+ *mysql_params->p_net_buffer_length= opt_net_buffer_length;
+
if (opt_delayed)
opt_lock=0; /* Can't have lock with delayed */
if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
@@ -714,6 +752,7 @@ static void unescape(FILE *file,char *pos,uint length)
fputc('\'', file);
fputs(tmp, file);
fputc('\'', file);
+ check_io(file);
my_free(tmp, MYF(MY_WME));
DBUG_VOID_RETURN;
} /* unescape */
@@ -805,6 +844,7 @@ static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
break;
}
}
+ check_io(xml_file);
}
@@ -838,6 +878,7 @@ static void print_xml_tag1(FILE * xml_file, const char* sbeg,
print_quoted_xml(xml_file, sval, strlen(sval));
fputs("\">", xml_file);
fputs(send, xml_file);
+ check_io(xml_file);
}
@@ -866,6 +907,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name,
ulong *lengths= mysql_fetch_lengths(tableRes);
fprintf(xml_file, "\t\t<%s", row_name);
+ check_io(xml_file);
mysql_field_seek(tableRes, 0);
for (i= 0; (field= mysql_fetch_field(tableRes)); i++)
{
@@ -876,9 +918,11 @@ static void print_xml_row(FILE *xml_file, const char *row_name,
fputs("=\"", xml_file);
print_quoted_xml(xml_file, (*row)[i], lengths[i]);
fputc('"', xml_file);
+ check_io(xml_file);
}
}
fputs(" />\n", xml_file);
+ check_io(xml_file);
}
/*
@@ -945,14 +989,21 @@ static uint getTableStructure(char *table, char* db)
write_header(sql_file, db);
}
if (!opt_xml && opt_comments)
+ {
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
result_table);
+ check_io(sql_file);
+ }
if (opt_drop)
+ {
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
+ check_io(sql_file);
+ }
tableRes=mysql_store_result(sock);
row=mysql_fetch_row(tableRes);
fprintf(sql_file, "%s;\n", row[1]);
+ check_io(sql_file);
mysql_free_result(tableRes);
}
sprintf(insert_pat,"show fields from %s", result_table);
@@ -1032,6 +1083,7 @@ static uint getTableStructure(char *table, char* db)
fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
else
print_xml_tag1(sql_file, "\t", "table_structure name=", table, "\n");
+ check_io(sql_file);
}
if (cFlag)
sprintf(insert_pat, "INSERT %sINTO %s (", delayed, result_table);
@@ -1049,7 +1101,10 @@ static uint getTableStructure(char *table, char* db)
if (init)
{
if (!opt_xml && !tFlag)
+ {
fputs(",\n",sql_file);
+ check_io(sql_file);
+ }
if (cFlag)
strpos=strmov(strpos,", ");
}
@@ -1081,6 +1136,7 @@ static uint getTableStructure(char *table, char* db)
fputs(" NOT NULL", sql_file);
if (row[SHOW_EXTRA][0])
fprintf(sql_file, " %s",row[SHOW_EXTRA]);
+ check_io(sql_file);
}
}
numFields = (uint) mysql_num_rows(tableRes);
@@ -1149,12 +1205,14 @@ static uint getTableStructure(char *table, char* db)
fputs(quote_name(row[4], name_buff, 0), sql_file);
if (row[7])
fprintf(sql_file, " (%s)",row[7]); /* Sub key */
+ check_io(sql_file);
}
if (!opt_xml)
{
if (keynr)
putc(')', sql_file);
fputs("\n)",sql_file);
+ check_io(sql_file);
}
/* Get MySQL specific create options */
@@ -1193,6 +1251,7 @@ static uint getTableStructure(char *table, char* db)
print_value(sql_file,tableRes,row,"","Create_options",0);
print_value(sql_file,tableRes,row,"comment=","Comment",1);
fputs(" */",sql_file);
+ check_io(sql_file);
}
}
mysql_free_result(tableRes); /* Is always safe to free */
@@ -1201,6 +1260,7 @@ static uint getTableStructure(char *table, char* db)
fputs(";\n", sql_file);
else
fputs("\t</table_structure>\n", sql_file);
+ check_io(sql_file);
}
}
if (cFlag)
@@ -1354,19 +1414,28 @@ static void dumpTable(uint numFields, char *table)
else
{
if (!opt_xml && opt_comments)
+ {
fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n",
result_table);
+ check_io(md_result_file);
+ }
sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
result_table);
if (where)
{
if (!opt_xml && opt_comments)
+ {
fprintf(md_result_file,"-- WHERE: %s\n",where);
+ check_io(md_result_file);
+ }
query= alloc_query_str((ulong) (strlen(where) + strlen(query) + 10));
strxmov(query, query_buf, " WHERE ", where, NullS);
}
if (!opt_xml && !opt_compact)
+ {
fputs("\n", md_result_file);
+ check_io(md_result_file);
+ }
if (mysql_query(sock, query))
{
DBerror(sock, "when retrieving data from server");
@@ -1394,12 +1463,18 @@ static void dumpTable(uint numFields, char *table)
}
if (opt_disable_keys)
+ {
fprintf(md_result_file, "\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
opt_quoted_table);
+ check_io(md_result_file);
+ }
if (opt_lock)
+ {
fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
+ check_io(md_result_file);
+ }
- total_length=net_buffer_length; /* Force row break */
+ total_length= opt_net_buffer_length; /* Force row break */
row_break=0;
rownr=0;
init_length=(uint) strlen(insert_pat)+4;
@@ -1407,7 +1482,10 @@ static void dumpTable(uint numFields, char *table)
print_xml_tag1(md_result_file, "\t", "table_data name=", table, "\n");
if (opt_autocommit)
+ {
fprintf(md_result_file, "set autocommit=0;\n");
+ check_io(md_result_file);
+ }
while ((row=mysql_fetch_row(res)))
{
@@ -1415,11 +1493,17 @@ static void dumpTable(uint numFields, char *table)
ulong *lengths=mysql_fetch_lengths(res);
rownr++;
if (!extended_insert && !opt_xml)
+ {
fputs(insert_pat,md_result_file);
+ check_io(md_result_file);
+ }
mysql_field_seek(res,0);
if (opt_xml)
+ {
fputs("\t<row>\n", md_result_file);
+ check_io(md_result_file);
+ }
for (i = 0; i < mysql_num_fields(res); i++)
{
@@ -1492,7 +1576,10 @@ static void dumpTable(uint numFields, char *table)
else
{
if (i && !opt_xml)
+ {
fputc(',', md_result_file);
+ check_io(md_result_file);
+ }
if (row[i])
{
if (!IS_NUM_FIELD(field))
@@ -1533,18 +1620,24 @@ static void dumpTable(uint numFields, char *table)
fputs(ptr, md_result_file);
}
}
+ else
+ fputs("NULL", md_result_file);
+ check_io(md_result_file);
}
}
if (opt_xml)
+ {
fputs("\t</row>\n", md_result_file);
+ check_io(md_result_file);
+ }
if (extended_insert)
{
ulong row_length;
dynstr_append(&extended_row,")");
row_length = 2 + extended_row.length;
- if (total_length + row_length < net_buffer_length)
+ if (total_length + row_length < opt_net_buffer_length)
{
total_length += row_length;
fputc(',',md_result_file); /* Always row break */
@@ -1560,9 +1653,13 @@ static void dumpTable(uint numFields, char *table)
fputs(extended_row.str,md_result_file);
total_length = row_length+init_length;
}
+ check_io(md_result_file);
}
else if (!opt_xml)
+ {
fputs(");\n", md_result_file);
+ check_io(md_result_file);
+ }
}
/* XML - close table tag and supress regular output */
@@ -1571,6 +1668,7 @@ static void dumpTable(uint numFields, char *table)
else if (extended_insert && row_break)
fputs(";\n", md_result_file); /* If not empty table */
fflush(md_result_file);
+ check_io(md_result_file);
if (mysql_errno(sock))
{
sprintf(query,"%s: Error %d: %s when dumping table %s at row: %ld\n",
@@ -1584,12 +1682,21 @@ static void dumpTable(uint numFields, char *table)
goto err;
}
if (opt_lock)
+ {
fputs("UNLOCK TABLES;\n", md_result_file);
+ check_io(md_result_file);
+ }
if (opt_disable_keys)
+ {
fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n",
opt_quoted_table);
+ check_io(md_result_file);
+ }
if (opt_autocommit)
+ {
fprintf(md_result_file, "commit;\n");
+ check_io(md_result_file);
+ }
mysql_free_result(res);
if (query != query_buf)
my_free(query, MYF(MY_ALLOW_ZERO_PTR));
@@ -1680,7 +1787,10 @@ static int init_dumping(char *database)
char quoted_database_buf[64*2+3];
char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
if (opt_comments)
+ {
fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
+ check_io(md_result_file);
+ }
if (!opt_create_db)
{
char qbuf[256];
@@ -1707,6 +1817,7 @@ static int init_dumping(char *database)
}
}
fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
+ check_io(md_result_file);
}
}
if (extended_insert && init_dynamic_string(&extended_row, "", 1024, 1024))
@@ -1753,7 +1864,10 @@ static int dump_all_tables_in_db(char *database)
dumpTable(numrows,table);
}
if (opt_xml)
+ {
fputs("</database>\n", md_result_file);
+ check_io(md_result_file);
+ }
if (lock_tables)
mysql_query(sock,"UNLOCK TABLES");
return 0;
@@ -1799,7 +1913,10 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
dumpTable(numrows, *table_names);
}
if (opt_xml)
+ {
fputs("</database>\n", md_result_file);
+ check_io(md_result_file);
+ }
if (lock_tables)
mysql_query(sock,"UNLOCK TABLES");
return 0;
@@ -1868,6 +1985,7 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row,
unescape(file,row[0],(uint) strlen(row[0]));
else
fputs(row[0], file);
+ check_io(file);
return;
}
}
@@ -2007,6 +2125,7 @@ int main(int argc, char **argv)
fprintf(md_result_file,
"CHANGE MASTER TO MASTER_LOG_FILE='%s', \
MASTER_LOG_POS=%s ;\n",row[0],row[1]);
+ check_io(md_result_file);
}
mysql_free_result(master);
}
diff --git a/client/mysqltest.c b/client/mysqltest.c
index be2270850fa..5ba4ad7336c 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -59,7 +59,8 @@
#include <sys/stat.h>
#include <violite.h>
-#define MAX_QUERY 65536
+#define MAX_QUERY 131072
+#define MAX_VAR_NAME 256
#define MAX_COLUMNS 256
#define PAD_SIZE 128
#define MAX_CONS 128
@@ -187,7 +188,7 @@ typedef struct
*/
static char *subst_env_var(const char *cmd);
-static int my_popen(const char *cmd, const char *mode);
+static FILE *my_popen(const char *cmd, const char *mode);
#define popen(A,B) my_popen((A),(B))
#endif /* __NETWARE__ */
@@ -223,7 +224,7 @@ Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
Q_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER,
Q_WAIT_FOR_SLAVE_TO_STOP,
-Q_REQUIRE_VERSION,
+Q_REQUIRE_VERSION, Q_REQUIRE_OS,
Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
Q_ENABLE_INFO, Q_DISABLE_INFO,
Q_ENABLE_METADATA, Q_DISABLE_METADATA,
@@ -297,6 +298,7 @@ const char *command_names[]=
"require_manager",
"wait_for_slave_to_stop",
"require_version",
+ "require_os",
"enable_warnings",
"disable_warnings",
"enable_info",
@@ -318,6 +320,7 @@ TYPELIB command_typelib= {array_elements(command_names),"",
DYNAMIC_STRING ds_res;
static void die(const char *fmt, ...);
static void init_var_hash();
+static VAR* var_from_env(const char *, const char *);
static byte* get_var_key(const byte* rec, uint* len,
my_bool __attribute__((unused)) t);
static VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
@@ -385,6 +388,7 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
register char c;
register int escaped = 0;
VAR* v;
+ DBUG_ENTER("do_eval");
for (p= query; (c = *p); ++p)
{
@@ -416,6 +420,7 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
break;
}
}
+ DBUG_VOID_RETURN;
}
@@ -627,6 +632,7 @@ static int check_result(DYNAMIC_STRING* ds, const char* fname,
return error;
}
+
VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw,
my_bool ignore_not_existing)
{
@@ -641,26 +647,26 @@ VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw,
if (!(digit < 10 && digit >= 0))
{
const char* save_var_name = var_name, *end;
+ uint length;
end = (var_name_end) ? *var_name_end : 0;
while (my_isvar(charset_info,*var_name) && var_name != end)
- ++var_name;
+ var_name++;
if (var_name == save_var_name)
{
if (ignore_not_existing)
DBUG_RETURN(0);
die("Empty variable");
}
+ length= (uint) (var_name - save_var_name);
- if (!(v = (VAR*) hash_search(&var_hash, save_var_name,
- var_name - save_var_name)))
+ if (!(v = (VAR*) hash_search(&var_hash, save_var_name, length)) &&
+ length < MAX_VAR_NAME)
{
- if (ignore_not_existing)
- DBUG_RETURN(0);
- if (end)
- *(char*) end = 0;
- die("Variable '%s' used uninitialized", save_var_name);
+ char buff[MAX_VAR_NAME+1];
+ strmake(buff, save_var_name, length);
+ v= var_from_env(buff, "");
}
- --var_name; /* Point at last character */
+ var_name--; /* Point at last character */
}
else
v = var_reg + digit;
@@ -848,6 +854,27 @@ int do_require_version(struct st_query* q)
return 0;
}
+int do_require_os(struct st_query* q)
+{
+ char *p=q->first_argument, *os_arg;
+ DBUG_ENTER("do_require_os");
+
+ if (!*p)
+ die("Missing version argument in require_os\n");
+ os_arg= p;
+ while (*p && !my_isspace(charset_info,*p))
+ p++;
+ *p = 0;
+
+ if (strcmp(os_arg, "unix"))
+ die("For now only testing of os=unix is implemented\n");
+
+#if defined(__NETWARE__) || defined(__WIN__) || defined(__OS2__)
+ abort_not_supported_test();
+#endif
+ DBUG_RETURN(0);
+}
+
int do_source(struct st_query* q)
{
char* p=q->first_argument, *name;
@@ -1737,6 +1764,7 @@ int read_line(char* buf, int size)
enum {R_NORMAL, R_Q1, R_ESC_Q_Q1, R_ESC_Q_Q2,
R_ESC_SLASH_Q1, R_ESC_SLASH_Q2,
R_Q2, R_COMMENT, R_LINE_START} state= R_LINE_START;
+ DBUG_ENTER("read_line");
start_lineno= *lineno;
for (; p < buf_end ;)
@@ -1750,7 +1778,7 @@ int read_line(char* buf, int size)
cur_file--;
lineno--;
if (cur_file == file_stack)
- return 1;
+ DBUG_RETURN(1);
continue;
}
@@ -1760,7 +1788,7 @@ int read_line(char* buf, int size)
if (end_of_query(c))
{
*p= 0;
- return 0;
+ DBUG_RETURN(0);
}
else if (c == '\'')
state = R_Q1;
@@ -1777,7 +1805,7 @@ int read_line(char* buf, int size)
{
*p= 0;
(*lineno)++;
- return 0;
+ DBUG_RETURN(0);
}
break;
case R_LINE_START:
@@ -1795,12 +1823,12 @@ int read_line(char* buf, int size)
{
*buf++= '}';
*buf= 0;
- return 0;
+ DBUG_RETURN(0);
}
else if (end_of_query(c) || c == '{')
{
*p= 0;
- return 0;
+ DBUG_RETURN(0);
}
else if (c == '\'')
state= R_Q1;
@@ -1820,7 +1848,7 @@ int read_line(char* buf, int size)
if (end_of_query(c))
{
*p= 0;
- return 0;
+ DBUG_RETURN(0);
}
if (c != '\'')
state= R_NORMAL;
@@ -1841,7 +1869,7 @@ int read_line(char* buf, int size)
if (end_of_query(c))
{
*p= 0;
- return 0;
+ DBUG_RETURN(0);
}
if (c != '"')
state= R_NORMAL;
@@ -1857,7 +1885,7 @@ int read_line(char* buf, int size)
*p++= c;
}
*p= 0; /* Always end with \0 */
- return feof(*cur_file);
+ DBUG_RETURN(feof(*cur_file));
}
@@ -1892,8 +1920,11 @@ int read_query(struct st_query** q_ptr)
q->type = Q_UNKNOWN;
q->query_buf= q->query= 0;
if (read_line(read_query_buf, sizeof(read_query_buf)))
+ {
+ DBUG_PRINT("warning",("too long query"));
DBUG_RETURN(1);
-
+ }
+ DBUG_PRINT("info", ("query: %s", read_query_buf));
if (*p == '#')
{
q->type = Q_COMMENT;
@@ -2259,6 +2290,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
char* query;
int query_len, got_error_on_send= 0;
DBUG_ENTER("run_query");
+ DBUG_PRINT("enter",("flags: %d", flags));
if (q->type != Q_EVAL)
{
@@ -2580,7 +2612,7 @@ static void var_free(void *v)
}
-static void var_from_env(const char *name, const char *def_val)
+static VAR* var_from_env(const char *name, const char *def_val)
{
const char *tmp;
VAR *v;
@@ -2589,6 +2621,7 @@ static void var_from_env(const char *name, const char *def_val)
v = var_init(0, name, 0, tmp, 0);
my_hash_insert(&var_hash, (byte*)v);
+ return v;
}
@@ -2599,10 +2632,8 @@ static void init_var_hash(MYSQL *mysql)
if (hash_init(&var_hash, charset_info,
1024, 0, 0, get_var_key, var_free, MYF(0)))
die("Variable hash initialization failed");
- var_from_env("MASTER_MYPORT", "9306");
- var_from_env("SLAVE_MYPORT", "9307");
- var_from_env("MYSQL_TEST_DIR", "/tmp");
- var_from_env("BIG_TEST", opt_big_test ? "1" : "0");
+ if (opt_big_test)
+ my_hash_insert(&var_hash, (byte*) var_init(0,"BIG_TEST", 0, "1",0));
v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0);
my_hash_insert(&var_hash, (byte*) v);
v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);
@@ -2706,6 +2737,7 @@ int main(int argc, char **argv)
case Q_SLEEP: do_sleep(q, 0); break;
case Q_REAL_SLEEP: do_sleep(q, 1); break;
case Q_REQUIRE_VERSION: do_require_version(q); break;
+ case Q_REQUIRE_OS: do_require_os(q); break;
case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(q); break;
case Q_REQUIRE_MANAGER: do_require_manager(q); break;
#ifndef EMBEDDED_LIBRARY
@@ -2727,7 +2759,10 @@ int main(int argc, char **argv)
case Q_EVAL_RESULT: eval_result = 1; break;
case Q_EVAL:
if (q->query == q->query_buf)
+ {
q->query= q->first_argument;
+ q->first_word_len= 0;
+ }
/* fall through */
case Q_QUERY_VERTICAL:
case Q_QUERY_HORIZONTAL:
@@ -2737,13 +2772,16 @@ int main(int argc, char **argv)
{
/* This happens when we use 'query_..' on it's own line */
q_send_flag=1;
+ DBUG_PRINT("info",
+ ("query: '%s' first_word_len: %d send_flag=1",
+ q->query, q->first_word_len));
break;
}
/* fix up query pointer if this is * first iteration for this line */
if (q->query == q->query_buf)
q->query += q->first_word_len + 1;
display_result_vertically= (q->type==Q_QUERY_VERTICAL);
- error |= run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND);
+ error|= run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND);
display_result_vertically= old_display_result_vertically;
break;
}
@@ -3710,6 +3748,7 @@ static void get_replace_column(struct st_query *q)
static char *subst_env_var(const char *str)
{
char *result;
+ char *pos;
result= pos= my_malloc(MAX_QUERY, MYF(MY_FAE));
while (*str)
@@ -3729,7 +3768,7 @@ static char *subst_env_var(const char *str)
*str && !isspace(*str) && *str != '\\' && *str != '/' &&
*str != '$';
str++)
- *env_pos++ *str;
+ *env_pos++= *str;
*env_pos= 0;
if (!(subst= getenv(env_var)))
@@ -3772,11 +3811,11 @@ static char *subst_env_var(const char *str)
#undef popen /* Remove wrapper */
-int my_popen(const char *cmd, const char *mode __attribute__((unused)) t)
+FILE *my_popen(const char *cmd, const char *mode __attribute__((unused)))
{
char *subst_cmd;
- int res_file;
-
+ FILE *res_file;
+
subst_cmd= subst_env_var(cmd);
res_file= popen(subst_cmd, "r0");
my_free(subst_cmd, MYF(0));
diff --git a/configure.in b/configure.in
index baa20a42b33..8abd0a0908c 100644
--- a/configure.in
+++ b/configure.in
@@ -12,6 +12,12 @@ DOT_FRM_VERSION=6
# See the libtool docs for information on how to do shared lib versions.
SHARED_LIB_VERSION=14:0:0
+# ndb version
+NDB_VERSION_MAJOR=3
+NDB_VERSION_MINOR=5
+NDB_VERSION_BUILD=0
+NDB_VERSION_STATUS=beta
+
# Set all version vars based on $VERSION. How do we do this more elegant ?
# Remember that regexps needs to quote [ and ] since this is run through m4
MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[[a-z]]*-.*$||"`
@@ -26,7 +32,7 @@ MYSQL_UNIX_ADDR_DEFAULT="/tmp/mysql.sock"
AVAILABLE_LANGUAGES="\
czech danish dutch english estonian french german greek hungarian \
italian japanese korean norwegian norwegian-ny polish portuguese \
-romanian russian slovak spanish swedish ukrainian"
+romanian russian serbian slovak spanish swedish ukrainian"
# Generate make rules for all error messages
AVAILABLE_LANGUAGES_ERRORS=
@@ -64,6 +70,16 @@ AC_SUBST(AVAILABLE_LANGUAGES)
AC_SUBST(AVAILABLE_LANGUAGES_ERRORS)
AC_SUBST_FILE(AVAILABLE_LANGUAGES_ERRORS_RULES)
+AC_SUBST([NDB_VERSION_MAJOR])
+AC_SUBST([NDB_VERSION_MINOR])
+AC_SUBST([NDB_VERSION_BUILD])
+AC_SUBST([NDB_VERSION_STATUS])
+AC_DEFINE_UNQUOTED([NDB_VERSION_MAJOR], [$NDB_VERSION_MAJOR])
+AC_DEFINE_UNQUOTED([NDB_VERSION_MINOR], [$NDB_VERSION_MINOR])
+AC_DEFINE_UNQUOTED([NDB_VERSION_BUILD], [$NDB_VERSION_BUILD])
+AC_DEFINE_UNQUOTED([NDB_VERSION_STATUS], ["$NDB_VERSION_STATUS"])
+
+
# Canonicalize the configuration name.
SYSTEM_TYPE="$host_vendor-$host_os"
MACHINE_TYPE="$host_cpu"
@@ -95,7 +111,6 @@ AC_SUBST(CXXLDFLAGS)
AC_PREREQ(2.12)dnl Minimum Autoconf version required.
-AM_MAINTAINER_MODE
#AC_ARG_PROGRAM # Automaticly invoked by AM_INIT_AUTOMAKE
AM_SANITY_CHECK
# This is needed is SUBDIRS is set
@@ -355,12 +370,15 @@ AC_SUBST(INSTALL_SCRIPT)
export CC CXX CFLAGS LD LDFLAGS AR
+ndb_cxxflags_fix=
if test "$GXX" = "yes"
then
# mysqld requires -fno-implicit-templates.
# 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"
+ # ndb cannot be compiled with -fno-implicit-templaces
+ ndb_cxxflags_fix="$ndb_cxxflags_fix -fimplicit-templates"
# If you are using 'gcc' 3.0 (not g++) to compile C++ programs on Linux,
# we will gets some problems when linking static programs.
@@ -433,6 +451,15 @@ AC_SUBST(HOSTNAME)
AC_SUBST(PERL)
AC_SUBST(PERL5)
+# for build ndb docs
+
+AC_PATH_PROG(DOXYGEN, doxygen, no)
+AC_PATH_PROG(PDFLATEX, pdflatex, no)
+AC_PATH_PROG(MAKEINDEX, makeindex, no)
+AC_SUBST(DOXYGEN)
+AC_SUBST(PDFLATEX)
+AC_SUBST(MAKEINDEX)
+
# Lock for PS
AC_PATH_PROG(PS, ps, ps)
AC_MSG_CHECKING("how to check if pid exists")
@@ -768,7 +795,14 @@ AC_CHECK_FUNC(crypt, AC_DEFINE(HAVE_CRYPT))
AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4, sem_init))
# For compress in zlib
-MYSQL_CHECK_ZLIB_WITH_COMPRESS($with_named_zlib)
+case $SYSTEM_TYPE in
+ *netware* | *modesto*)
+ AC_DEFINE(HAVE_COMPRESS)
+ ;;
+ *)
+ MYSQL_CHECK_ZLIB_WITH_COMPRESS($with_named_zlib)
+ ;;
+esac
#--------------------------------------------------------------------
# Check for TCP wrapper support
@@ -998,6 +1032,7 @@ case $SYSTEM_TYPE in
CXXFLAGS="$CXXFLAGS +O2"
MAX_C_OPTIMIZE=""
MAX_CXX_OPTIMIZE=""
+ ndb_cxxflags_fix="$ndb_cxxflags_fix -Aa"
fi
;;
*rhapsody*)
@@ -1120,7 +1155,7 @@ dnl Is this the right match for DEC OSF on alpha?
sql/Makefile.in)
# Use gen_lex_hash.linux instead of gen_lex_hash
# Add library dependencies to mysqld_DEPENDENCIES
- lib_DEPENDENCIES="\$(bdb_libs_with_path) \$(innodb_libs) \$(pstack_libs) \$(innodb_system_libs) \$(openssl_libs)"
+ lib_DEPENDENCIES="\$(bdb_libs_with_path) \$(innodb_libs) \$(ndbcluster_libs) \$(pstack_libs) \$(innodb_system_libs) \$(openssl_libs)"
cat > $filesed << EOF
s,\(^.*\$(MAKE) gen_lex_hash\)\$(EXEEXT),#\1,
s,\(\./gen_lex_hash\)\$(EXEEXT),\1.linux,
@@ -2135,6 +2170,31 @@ then
AC_DEFINE(HAVE_QUERY_CACHE)
fi
+AC_ARG_WITH(geometry,
+ [ --without-geometry Do not build geometry-related parts.],
+ [with_geometry=$withval],
+ [with_geometry=yes]
+)
+
+if test "$with_geometry" = "yes"
+then
+ AC_DEFINE(HAVE_SPATIAL)
+ AC_DEFINE(HAVE_RTREE_KEYS)
+fi
+
+AC_ARG_WITH(embedded_privilege_control,
+ [ --with-embedded-privilege-control
+ Build parts to check user's privileges.
+ Only affects embedded library.],
+ [with_embedded_privilege_control=$withval],
+ [with_embedded_privilege_control=no]
+)
+
+if test "$with_embedded_privilege_control" = "yes"
+then
+ AC_DEFINE(HAVE_EMBEDDED_PRIVILEGE_CONTROL)
+fi
+
AC_ARG_WITH(extra-tools,
[ --without-extra-tools Skip building utilites in the tools directory.],
[with_tools=$withval],
@@ -2278,14 +2338,15 @@ dnl you must also create strings/ctype-$charset_name.c
AC_DIVERT_PUSH(0)
+define(CHARSETS_AVAILABLE0,binary)
define(CHARSETS_AVAILABLE1,ascii armscii8 ascii big5 cp1250 cp1251 cp1256 cp1257)
-define(CHARSETS_AVAILABLE2,cp850 cp852 cp866 dec8 euckr gb2312 gbk)
+define(CHARSETS_AVAILABLE2,cp850 cp852 cp866 dec8 euckr gb2312 gbk geostd8)
define(CHARSETS_AVAILABLE3,greek hebrew hp8 keybcs2 koi8r koi8u)
define(CHARSETS_AVAILABLE4,latin1 latin2 latin5 latin7 macce macroman)
define(CHARSETS_AVAILABLE5,sjis swe7 tis620 ucs2 ujis utf8)
DEFAULT_CHARSET=latin1
-CHARSETS_AVAILABLE="CHARSETS_AVAILABLE1 CHARSETS_AVAILABLE2 CHARSETS_AVAILABLE3 CHARSETS_AVAILABLE4 CHARSETS_AVAILABLE5"
+CHARSETS_AVAILABLE="CHARSETS_AVAILABLE0 CHARSETS_AVAILABLE1 CHARSETS_AVAILABLE2 CHARSETS_AVAILABLE3 CHARSETS_AVAILABLE4 CHARSETS_AVAILABLE5"
CHARSETS_COMPLEX="big5 cp1250 euckr gb2312 gbk latin1 latin2 sjis tis620 ucs2 ujis utf8"
AC_DIVERT_POP
@@ -2293,6 +2354,7 @@ AC_DIVERT_POP
AC_ARG_WITH(charset,
[ --with-charset=CHARSET
Default character set, use one of:
+ CHARSETS_AVAILABLE0
CHARSETS_AVAILABLE1
CHARSETS_AVAILABLE2
CHARSETS_AVAILABLE3
@@ -2347,6 +2409,8 @@ do
AC_DEFINE(USE_MB)
AC_DEFINE(USE_MB_IDENT)
;;
+ binary)
+ ;;
cp1250)
AC_DEFINE(HAVE_CHARSET_cp1250)
;;
@@ -2386,6 +2450,9 @@ do
AC_DEFINE(USE_MB)
AC_DEFINE(USE_MB_IDENT)
;;
+ geostd8)
+ AC_DEFINE(HAVE_CHARSET_geostd8)
+ ;;
greek)
AC_DEFINE(HAVE_CHARSET_greek)
;;
@@ -2470,6 +2537,10 @@ case $default_charset in
default_charset_default_collation="big5_chinese_ci"
default_charset_collations="big5_chinese_ci big5_bin"
;;
+ binary)
+ default_charset_default_collation="binary"
+ default_charset_collations="binary"
+ ;;
cp1250)
default_charset_default_collation="cp1250_general_ci"
default_charset_collations="cp1250_general_ci cp1250_czech_ci cp1250_bin"
@@ -2514,6 +2585,10 @@ case $default_charset in
default_charset_default_collation="gbk_chinese_ci"
default_charset_collations="gbk_chinese_ci gbk_bin"
;;
+ geostd8)
+ default_charset_default_collation="geostd8_general_ci"
+ default_charset_collations="geostd8_general_ci geostd8_bin"
+ ;;
greek)
default_charset_default_collation="greek_general_ci"
default_charset_collations="greek_general_ci greek_bin"
@@ -2576,7 +2651,17 @@ case $default_charset in
;;
ucs2)
default_charset_default_collation="ucs2_general_ci"
- default_charset_collations="ucs2_general_ci ucs2_bin"
+ define(UCSC1, ucs2_general_ci ucs2_bin)
+ define(UCSC2, ucs2_czech_ci ucs2_danish_ci)
+ define(UCSC3, ucs2_estonian_ci ucs2_icelandic_ci)
+ define(UCSC4, ucs2_latvian_ci ucs2_lithuanian_ci)
+ define(UCSC5, ucs2_polish_ci ucs2_romanian_ci)
+ define(UCSC6, ucs2_slovak_ci ucs2_slovenian_ci)
+ define(UCSC7, ucs2_spanish2_ci ucs2_spanish_ci)
+ define(UCSC8, ucs2_swedish_ci ucs2_turkish_ci)
+ define(UCSC9, ucs2_unicode_ci)
+ UCSC="UCSC1 UCSC2 UCSC3 UCSC4 UCSC5 UCSC6 UCSC7 UCSC8 UCSC9"
+ default_charset_collations="$UCSC"
;;
ujis)
default_charset_default_collation="ujis_japanese_ci"
@@ -2584,7 +2669,17 @@ case $default_charset in
;;
utf8)
default_charset_default_collation="utf8_general_ci"
- default_charset_collations="utf8_general_ci utf8_bin"
+ define(UTFC1, utf8_general_ci utf8_bin)
+ define(UTFC2, utf8_czech_ci utf8_danish_ci)
+ define(UTFC3, utf8_estonian_ci utf8_icelandic_ci)
+ define(UTFC4, utf8_latvian_ci utf8_lithuanian_ci)
+ define(UTFC5, utf8_polish_ci utf8_romanian_ci)
+ define(UTFC6, utf8_slovak_ci utf8_slovenian_ci)
+ define(UTFC7, utf8_spanish2_ci utf8_spanish_ci)
+ define(UTFC8, utf8_swedish_ci utf8_turkish_ci)
+ define(UTFC9, utf8_unicode_ci)
+ UTFC="UTFC1 UTFC2 UTFC3 UTFC4 UTFC5 UTFC6 UTFC7 UTFC8 UTFC9"
+ default_charset_collations="$UTFC"
;;
*)
AC_MSG_ERROR([Charset $cs not available. (Available are: $CHARSETS_AVAILABLE).
@@ -2623,6 +2718,7 @@ MYSQL_CHECK_ISAM
MYSQL_CHECK_BDB
MYSQL_CHECK_INNODB
MYSQL_CHECK_EXAMPLEDB
+MYSQL_CHECK_ARCHIVEDB
MYSQL_CHECK_NDBCLUSTER
# If we have threads generate some library functions and test programs
@@ -2657,6 +2753,11 @@ if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then
fi
AC_SUBST(netware_dir)
AC_SUBST(linked_netware_sources)
+AM_CONDITIONAL(HAVE_NETWARE, test "$netware_dir" = "netware")
+
+# Ensure that table handlers gets all modifications to CFLAGS/CXXFLAGS
+export CC CXX CFLAGS CXXFLAGS LD LDFLAGS AR
+ac_configure_args="$ac_configure_args CFLAGS='$CFLAGS' CXXFLAGS='$CXXFLAGS'"
if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no"
then
@@ -2677,12 +2778,14 @@ then
if test X"$have_isam" != Xno
then
sql_server_dirs="$sql_server_dirs isam merge"
+ AC_CONFIG_FILES(isam/Makefile merge/Makefile)
fi
if test X"$have_berkeley_db" != Xno; then
if test X"$have_berkeley_db" != Xyes; then
# we must build berkeley db from source
sql_server_dirs="$sql_server_dirs $have_berkeley_db"
+ AC_CONFIG_FILES(bdb/Makefile)
echo "CONFIGURING FOR BERKELEY DB"
bdb_conf_flags=
@@ -2756,16 +2859,15 @@ EOF
if test X"$have_ndbcluster" = Xyes
then
+ if test X"$mysql_cv_compress" != Xyes
+ then
+ echo
+ echo "MySQL Cluster table handler ndbcluster requires compress/uncompress."
+ echo "Commonly available in libzlib.a. Please install and rerun configure."
+ echo
+ exit 1
+ fi
sql_server_dirs="$sql_server_dirs ndb"
- echo "CONFIGURING FOR NDB CLUSTER"
- case $with_debug in
- no) flag="-R" ;;
- *) flag="-D" ;;
- esac
- flag="$flag --VERSION=$VERSION --PACKAGE=$PACKAGE"
- (cd ndb && ./configure $flag) \
- || AC_MSG_ERROR([could not configure NDB Cluster])
- echo "END OF NDB CLUSTER CONFIGURATION"
fi
#
# END of configuration for optional table handlers
@@ -2828,16 +2930,103 @@ case $SYSTEM_TYPE in
MAKE_BINARY_DISTRIBUTION_OPTIONS=
;;
esac
+
if test X"$have_ndbcluster" = Xyes
then
MAKE_BINARY_DISTRIBUTION_OPTIONS="$MAKE_BINARY_DISTRIBUTION_OPTIONS --with-ndbcluster"
+
+ CXXFLAGS="$CXXFLAGS \$(NDB_CXXFLAGS)"
+ if test "$with_debug" = "yes"
+ then
+ # Medium debug.
+ NDB_DEFS="-DVM_TRACE -DERROR_INSERT -DARRAY_GUARD"
+ elif test "$with_debug" = "full"
+ then
+ NDB_DEFS="-DVM_TRACE -DERROR_INSERT -DARRAY_GUARD"
+ else
+ NDB_DEFS="-DNDEBUG"
+ fi
+
+AC_SUBST([NDB_DEFS])
+AC_SUBST([ndb_cxxflags_fix])
+
+ndb_transporter_opt_objs=""
+if test X"$have_ndb_shm" = Xyes
+then
+ ndb_transporter_opt_objs="$(ndb_transporter_opt_objs) SHM_Transporter.lo SHM_Transporter.unix.lo"
+fi
+if test X"$have_ndb_sci" = Xyes
+then
+ ndb_transporter_opt_objs="$(ndb_transporter_opt_objs) SCI_Transporter.lo"
+fi
+AC_SUBST([ndb_transporter_opt_objs])
+
+ndb_opt_subdirs=
+ndb_bin_am_ldflags="-static"
+if test X"$have_ndb_test" = Xyes
+then
+ ndb_opt_subdirs="test"
+ ndb_bin_am_ldflags=""
+fi
+if test X"$have_ndb_docs" = Xyes
+then
+ ndb_opt_subdirs="$ndb_opt_subdirs docs"
+ ndb_bin_am_ldflags=""
+fi
+AC_SUBST([ndb_bin_am_ldflags])
+AC_SUBST([ndb_opt_subdirs])
+AC_CONFIG_FILES(ndb/Makefile ndb/include/Makefile dnl
+ ndb/src/Makefile ndb/src/common/Makefile dnl
+ ndb/docs/Makefile dnl
+ ndb/tools/Makefile dnl
+ ndb/src/common/debugger/Makefile ndb/src/common/debugger/signaldata/Makefile dnl
+ ndb/src/common/portlib/Makefile dnl
+ ndb/src/common/util/Makefile dnl
+ ndb/src/common/logger/Makefile dnl
+ ndb/src/common/transporter/Makefile dnl
+ ndb/src/common/mgmcommon/Makefile dnl
+ ndb/src/common/editline/Makefile dnl
+ ndb/src/kernel/Makefile dnl
+ ndb/src/kernel/error/Makefile dnl
+ ndb/src/kernel/blocks/Makefile dnl
+ ndb/src/kernel/blocks/cmvmi/Makefile dnl
+ ndb/src/kernel/blocks/dbacc/Makefile dnl
+ ndb/src/kernel/blocks/dbdict/Makefile dnl
+ ndb/src/kernel/blocks/dbdih/Makefile dnl
+ ndb/src/kernel/blocks/dblqh/Makefile dnl
+ ndb/src/kernel/blocks/dbtc/Makefile dnl
+ ndb/src/kernel/blocks/dbtup/Makefile dnl
+ ndb/src/kernel/blocks/ndbfs/Makefile dnl
+ ndb/src/kernel/blocks/ndbcntr/Makefile dnl
+ ndb/src/kernel/blocks/qmgr/Makefile dnl
+ ndb/src/kernel/blocks/trix/Makefile dnl
+ ndb/src/kernel/blocks/backup/Makefile dnl
+ ndb/src/kernel/blocks/backup/restore/Makefile dnl
+ ndb/src/kernel/blocks/dbutil/Makefile dnl
+ ndb/src/kernel/blocks/suma/Makefile dnl
+ ndb/src/kernel/blocks/grep/Makefile dnl
+ ndb/src/kernel/blocks/dbtux/Makefile dnl
+ ndb/src/kernel/vm/Makefile dnl
+ ndb/src/mgmapi/Makefile dnl
+ ndb/src/ndbapi/Makefile dnl
+ ndb/src/mgmsrv/Makefile dnl
+ ndb/src/mgmclient/Makefile dnl
+ ndb/src/cw/Makefile dnl
+ ndb/src/cw/cpcd/Makefile dnl
+ ndb/test/Makefile dnl
+ ndb/test/src/Makefile dnl
+ ndb/test/ndbapi/Makefile dnl
+ ndb/test/ndbapi/bank/Makefile dnl
+ ndb/test/tools/Makefile dnl
+ ndb/test/run-test/Makefile mysql-test/ndb/Makefile dnl
+ )
fi
+
AC_SUBST(MAKE_BINARY_DISTRIBUTION_OPTIONS)
# Output results
-AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile dnl
+AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
strings/Makefile regex/Makefile heap/Makefile dnl
- bdb/Makefile dnl
myisam/Makefile myisammrg/Makefile dnl
os2/Makefile os2/include/Makefile os2/include/sys/Makefile dnl
man/Makefile BUILD/Makefile vio/Makefile dnl
@@ -2845,7 +3034,7 @@ AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile dnl
libmysql/Makefile client/Makefile dnl
pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile dnl
sql-common/Makefile SSL/Makefile dnl
- merge/Makefile dbug/Makefile scripts/Makefile dnl
+ dbug/Makefile scripts/Makefile dnl
include/Makefile sql-bench/Makefile tools/Makefile dnl
tests/Makefile Docs/Makefile support-files/Makefile dnl
support-files/MacOSX/Makefile mysql-test/Makefile dnl
@@ -2853,10 +3042,9 @@ AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile dnl
include/mysql_version.h dnl
cmd-line-utils/Makefile dnl
cmd-line-utils/libedit/Makefile dnl
- cmd-line-utils/readline/Makefile dnl
- , , [
- test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
- ])
+ cmd-line-utils/readline/Makefile)
+ AC_CONFIG_COMMANDS([default], , test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h)
+ AC_OUTPUT
rm -f $AVAILABLE_LANGUAGES_ERRORS_RULES
echo
diff --git a/dbug/dbug.c b/dbug/dbug.c
index 4e4dd87d0a3..1796d883c5e 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -985,8 +985,8 @@ uint length)
fputc('\n',_db_fp_);
pos=3;
}
- fputc(_dig_vec[((tmp >> 4) & 15)], _db_fp_);
- fputc(_dig_vec[tmp & 15], _db_fp_);
+ fputc(_dig_vec_upper[((tmp >> 4) & 15)], _db_fp_);
+ fputc(_dig_vec_upper[tmp & 15], _db_fp_);
fputc(' ',_db_fp_);
}
(void) fputc('\n',_db_fp_);
diff --git a/extra/Makefile.am b/extra/Makefile.am
index df29a3a6ab7..aec7ad7dda5 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -14,7 +14,8 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include @ndbcluster_includes@
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include \
+ @ndbcluster_includes@ -I$(top_srcdir)/sql
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
diff --git a/extra/perror.c b/extra/perror.c
index a31889cc26d..f1b1a4c2005 100644
--- a/extra/perror.c
+++ b/extra/perror.c
@@ -197,7 +197,7 @@ int main(int argc,char *argv[])
for (code=1 ; code < sys_nerr ; code++)
{
if (sys_errlist[code][0])
- { /* Skipp if no error-text */
+ { /* Skip if no error-text */
printf("%3d = %s\n",code,sys_errlist[code]);
}
}
@@ -256,7 +256,7 @@ int main(int argc,char *argv[])
else
{
if (verbose)
- printf("MySql error: %3d = %s\n",code,msg);
+ printf("MySQL error: %3d = %s\n",code,msg);
else
puts(msg);
}
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index 38ed581fe58..2014b2b0adc 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -18,7 +18,6 @@
#include "heapdef.h"
#include <m_ctype.h>
-#include <assert.h>
@@ -236,7 +235,7 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
key+=seg->length;
if (seg->null_bit)
{
- key++; /* Skipp null byte */
+ key++; /* Skip null byte */
if (*pos) /* Found null */
{
nr^= (nr << 1) | 1;
diff --git a/include/Makefile.am b/include/Makefile.am
index 01b8f295be4..0c845900a4f 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -22,15 +22,15 @@ pkginclude_HEADERS = my_dbug.h m_string.h my_sys.h my_list.h my_xml.h \
errmsg.h my_global.h my_net.h my_alloc.h \
my_getopt.h sslopt-longopts.h my_dir.h typelib.h \
sslopt-vars.h sslopt-case.h sql_common.h keycache.h \
- sql_state.h $(BUILT_SOURCES)
+ sql_state.h mysql_time.h $(BUILT_SOURCES)
noinst_HEADERS = config-win.h config-os2.h config-netware.h \
nisam.h heap.h merge.h my_bitmap.h\
myisam.h myisampack.h myisammrg.h ft_global.h\
- mysys_err.h my_base.h \
+ mysys_err.h my_base.h help_start.h help_end.h \
my_nosys.h my_alarm.h queues.h rijndael.h sha1.h \
my_aes.h my_tree.h hash.h thr_alarm.h \
thr_lock.h t_ctype.h violite.h md5.h \
- mysql_version.h.in my_handler.h
+ mysql_version.h.in my_handler.h my_time.h
# mysql_version.h are generated
SUPERCLEANFILES = mysql_version.h my_config.h
diff --git a/include/config-netware.h b/include/config-netware.h
index c4e63056353..3e145f566a1 100644
--- a/include/config-netware.h
+++ b/include/config-netware.h
@@ -57,6 +57,10 @@ extern "C" {
#undef HAVE_CRYPT
#endif /* HAVE_OPENSSL */
+/* Configure can't detect this because it uses AC_TRY_RUN */
+#undef HAVE_COMPRESS
+#define HAVE_COMPRESS
+
/* include the old function apis */
#define USE_OLD_FUNCTIONS 1
diff --git a/include/errmsg.h b/include/errmsg.h
index 140ff531248..6115b24a3d8 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -14,8 +14,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Error messages for mysql clients */
-/* error messages for the demon is in share/language/errmsg.sys */
+/* Error messages for MySQL clients */
+/* (Error messages for the daemon are in share/language/errmsg.sys) */
#ifdef __cplusplus
extern "C" {
@@ -83,10 +83,10 @@ extern const char *client_errors[]; /* Error messages */
#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2042
#define CR_SHARED_MEMORY_MAP_ERROR 2043
#define CR_SHARED_MEMORY_EVENT_ERROR 2044
-#define CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR 2045
+#define CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR 2045
#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046
#define CR_CONN_UNKNOW_PROTOCOL 2047
#define CR_INVALID_CONN_HANDLE 2048
#define CR_SECURE_AUTH 2049
-#define CR_FETCH_CANCELLED 2050
+#define CR_FETCH_CANCELED 2050
#define CR_NO_DATA 2051
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 9502805b017..785fa431385 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -53,7 +53,6 @@ typedef struct unicase_info_st
#define MY_SEQ_SPACES 2
/* My charsets_list flags */
-#define MY_NO_SETS 0
#define MY_CS_COMPILED 1 /* compiled-in sets */
#define MY_CS_CONFIG 2 /* sets that have a *.conf file */
#define MY_CS_INDEX 4 /* sets listed in the Index file */
@@ -62,7 +61,7 @@ typedef struct unicase_info_st
#define MY_CS_PRIMARY 32 /* if primary collation */
#define MY_CS_STRNXFRM 64 /* if strnxfrm is used for sort */
#define MY_CS_UNICODE 128 /* is a charset is full unicode */
-#define MY_CS_NONTEXT 256 /* if a charset is not sprintf() compatible */
+#define MY_CS_READY 256 /* if a charset is initialized */
#define MY_CS_AVAILABLE 512 /* If either compiled-in or loaded*/
#define MY_CHARSET_UNDEFINED 0
@@ -102,9 +101,10 @@ struct charset_info_st;
typedef struct my_collation_handler_st
{
+ my_bool (*init)(struct charset_info_st *, void *(*alloc)(uint));
/* Collation routines */
int (*strnncoll)(struct charset_info_st *,
- const uchar *, uint, const uchar *, uint);
+ const uchar *, uint, const uchar *, uint, my_bool);
int (*strnncollsp)(struct charset_info_st *,
const uchar *, uint, const uchar *, uint);
int (*strnxfrm)(struct charset_info_st *,
@@ -140,6 +140,7 @@ extern MY_COLLATION_HANDLER my_collation_ucs2_uca_handler;
typedef struct my_charset_handler_st
{
+ my_bool (*init)(struct charset_info_st *, void *(*alloc)(uint));
/* Multibyte routines */
int (*ismbchar)(struct charset_info_st *, const char *, const char *);
int (*mbcharlen)(struct charset_info_st *, uint);
@@ -200,15 +201,17 @@ typedef struct charset_info_st
const char *csname;
const char *name;
const char *comment;
+ const char *tailoring;
uchar *ctype;
uchar *to_lower;
uchar *to_upper;
uchar *sort_order;
+ uint16 *contractions;
uint16 **sort_order_big;
uint16 *tab_to_uni;
MY_UNI_IDX *tab_from_uni;
- uchar state_map[256];
- uchar ident_map[256];
+ uchar *state_map;
+ uchar *ident_map;
uint strxfrm_multiply;
uint mbminlen;
uint mbmaxlen;
@@ -251,7 +254,7 @@ extern CHARSET_INFO my_charset_cp1250_czech_ci;
extern int my_strnxfrm_simple(CHARSET_INFO *, uchar *, uint, const uchar *,
uint);
extern int my_strnncoll_simple(CHARSET_INFO *, const uchar *, uint,
- const uchar *, uint);
+ const uchar *, uint, my_bool);
extern int my_strnncollsp_simple(CHARSET_INFO *, const uchar *, uint,
const uchar *, uint);
@@ -385,7 +388,7 @@ extern my_bool my_parse_charset_xml(const char *bug, uint len,
#define my_binary_compare(s) ((s)->state & MY_CS_BINSORT)
#define use_strnxfrm(s) ((s)->state & MY_CS_STRNXFRM)
#define my_strnxfrm(s, a, b, c, d) ((s)->coll->strnxfrm((s), (a), (b), (c), (d)))
-#define my_strnncoll(s, a, b, c, d) ((s)->coll->strnncoll((s), (a), (b), (c), (d)))
+#define my_strnncoll(s, a, b, c, d) ((s)->coll->strnncoll((s), (a), (b), (c), (d), 0))
#define my_like_range(s, a, b, c, d, e, f, g, h, i, j) \
((s)->coll->like_range((s), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j)))
#define my_wildcmp(cs,s,se,w,we,e,o,m) ((cs)->coll->wildcmp((cs),(s),(se),(w),(we),(e),(o),(m)))
diff --git a/include/m_string.h b/include/m_string.h
index 371e20d130f..0709dbaffb4 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -95,7 +95,9 @@ extern char *stpcpy(char *, const char *); /* For AIX with gcc 2.95.3 */
#endif
#endif
-extern char NEAR _dig_vec[]; /* Declared in int2str() */
+/* Declared in int2str() */
+extern char NEAR _dig_vec_upper[];
+extern char NEAR _dig_vec_lower[];
#ifdef BAD_STRING_COMPILER
#define strmov(A,B) (memccpy(A,B,0,INT_MAX)-1)
@@ -113,8 +115,6 @@ extern char NEAR _dig_vec[]; /* Declared in int2str() */
#ifdef MSDOS
#undef bmove_align
#define bmove512(A,B,C) bmove_align(A,B,C)
-#define my_itoa(A,B,C) itoa(A,B,C)
-#define my_ltoa(A,B,C) ltoa(A,B,C)
extern void bmove_align(gptr dst,const gptr src,uint len);
#endif
@@ -123,7 +123,6 @@ extern void bmove_align(gptr dst,const gptr src,uint len);
#endif
#ifdef HAVE_purify
-#include <assert.h>
#define memcpy_overlap(A,B,C) \
DBUG_ASSERT((A) <= (B) || ((B)+(C)) <= (A)); \
bmove((byte*) (A),(byte*) (B),(size_t) (C));
@@ -219,24 +218,19 @@ extern int is_prefix(const char *, const char *);
double my_strtod(const char *str, char **end);
double my_atof(const char *nptr);
-#ifdef USE_MY_ITOA
-extern char *my_itoa(int val,char *dst,int radix);
-extern char *my_ltoa(long val,char *dst,int radix);
-#endif
-
extern char *llstr(longlong value,char *buff);
#ifndef HAVE_STRTOUL
extern long strtol(const char *str, char **ptr, int base);
extern ulong strtoul(const char *str, char **ptr, int base);
#endif
-extern char *int2str(long val,char *dst,int radix);
+extern char *int2str(long val, char *dst, int radix, int upcase);
extern char *int10_to_str(long val,char *dst,int radix);
extern char *str2int(const char *src,int radix,long lower,long upper,
long *val);
longlong my_strtoll10(const char *nptr, char **endptr, int *error);
#if SIZEOF_LONG == SIZEOF_LONG_LONG
-#define longlong2str(A,B,C) int2str((A),(B),(C))
+#define longlong2str(A,B,C) int2str((A),(B),(C),1)
#define longlong10_to_str(A,B,C) int10_to_str((A),(B),(C))
#undef strtoll
#define strtoll(A,B,C) strtol((A),(B),(C))
diff --git a/include/my_base.h b/include/my_base.h
index dd8918da858..583cd473936 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -383,7 +383,4 @@ typedef ulong ha_rows;
#define MAX_FILE_SIZE LONGLONG_MAX
#endif
-/* Currently used for saying which interfaces a Storage Engine implements */
-#define HA_ERR_NOT_IMPLEMENTED -1
-
#endif /* _my_base_h */
diff --git a/include/my_dbug.h b/include/my_dbug.h
index 5c88e2e42db..9174a8b1ef9 100644
--- a/include/my_dbug.h
+++ b/include/my_dbug.h
@@ -16,6 +16,7 @@
#ifndef _dbug_h
#define _dbug_h
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/include/my_global.h b/include/my_global.h
index af58139fb29..6490a775e7c 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -178,7 +178,11 @@ C_MODE_END
#ifdef HAVE_BROKEN_SNPRINTF /* HPUX 10.20 don't have this defined */
#undef HAVE_SNPRINTF
#endif
-#ifdef HAVE_BROKEN_PREAD /* These doesn't work on HPUX 11.x */
+#ifdef HAVE_BROKEN_PREAD
+/*
+ pread()/pwrite() are not 64 bit safe on HP-UX 11.0 without
+ installing the kernel patch PHKL_20349 or greater
+*/
#undef HAVE_PREAD
#undef HAVE_PWRITE
#endif
@@ -309,6 +313,13 @@ C_MODE_END
#include <crypt.h>
#endif
+/*
+ A lot of our programs uses asserts, so better to always include it
+ This also fixes a problem when people uses DBUG_ASSERT without including
+ assert.h
+*/
+#include <assert.h>
+
/* Go around some bugs in different OS and compilers */
#if defined(_HPUX_SOURCE) && defined(HAVE_SYS_STREAM_H)
#include <sys/stream.h> /* HPUX 10.20 defines ulong here. UGLY !!! */
@@ -587,12 +598,6 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define USE_MY_STAT_STRUCT /* For my_lib */
#endif
-/* Some things that this system does have */
-
-#ifndef HAVE_ITOA
-#define USE_MY_ITOA /* There is no itoa */
-#endif
-
/* Some defines of functions for portability */
#undef remove /* Crashes MySQL on SCO 5.0.0 */
@@ -1033,22 +1038,22 @@ do { doubleget_union _tmp; \
32))
#define int2store(T,A) do { uint def_temp= (uint) (A) ;\
*((uchar*) (T))= (uchar)(def_temp); \
- *((uchar*) (T+1))=(uchar)((def_temp >> 8)); \
+ *((uchar*) (T)+1)=(uchar)((def_temp >> 8)); \
} while(0)
#define int3store(T,A) do { /*lint -save -e734 */\
*((uchar*)(T))=(uchar) ((A));\
*((uchar*) (T)+1)=(uchar) (((A) >> 8));\
*((uchar*)(T)+2)=(uchar) (((A) >> 16)); \
/*lint -restore */} while(0)
-#define int4store(T,A) do { *(T)=(char) ((A));\
- *((T)+1)=(char) (((A) >> 8));\
- *((T)+2)=(char) (((A) >> 16));\
- *((T)+3)=(char) (((A) >> 24)); } while(0)
-#define int5store(T,A) do { *(T)=((A));\
- *((T)+1)=(((A) >> 8));\
- *((T)+2)=(((A) >> 16));\
- *((T)+3)=(((A) >> 24)); \
- *((T)+4)=(((A) >> 32)); } while(0)
+#define int4store(T,A) do { *((char *)(T))=(char) ((A));\
+ *(((char *)(T))+1)=(char) (((A) >> 8));\
+ *(((char *)(T))+2)=(char) (((A) >> 16));\
+ *(((char *)(T))+3)=(char) (((A) >> 24)); } while(0)
+#define int5store(T,A) do { *((char *)(T))=((A));\
+ *(((char *)(T))+1)=(((A) >> 8));\
+ *(((char *)(T))+2)=(((A) >> 16));\
+ *(((char *)(T))+3)=(((A) >> 24)); \
+ *(((char *)(T))+4)=(((A) >> 32)); } while(0)
#define int8store(T,A) do { uint def_temp= (uint) (A), def_temp2= (uint) ((A) >> 32); \
int4store((T),def_temp); \
int4store((T+4),def_temp2); } while(0)
@@ -1089,13 +1094,14 @@ do { doubleget_union _tmp; \
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
#define doublestore(T,V) do { *(T)= ((byte *) &V)[4];\
- *((T)+1)=(char) ((byte *) &V)[5];\
- *((T)+2)=(char) ((byte *) &V)[6];\
- *((T)+3)=(char) ((byte *) &V)[7];\
- *((T)+4)=(char) ((byte *) &V)[0];\
- *((T)+5)=(char) ((byte *) &V)[1];\
- *((T)+6)=(char) ((byte *) &V)[2];\
- *((T)+7)=(char) ((byte *) &V)[3]; } while(0)
+ *(((char*)T)+1)=(char) ((byte *) &V)[5];\
+ *(((char*)T)+2)=(char) ((byte *) &V)[6];\
+ *(((char*)T)+3)=(char) ((byte *) &V)[7];\
+ *(((char*)T)+4)=(char) ((byte *) &V)[0];\
+ *(((char*)T)+5)=(char) ((byte *) &V)[1];\
+ *(((char*)T)+6)=(char) ((byte *) &V)[2];\
+ *(((char*)T)+7)=(char) ((byte *) &V)[3]; }\
+ while(0)
#define doubleget(V,M) do { double def_temp;\
((byte*) &def_temp)[0]=(M)[4];\
((byte*) &def_temp)[1]=(M)[5];\
@@ -1115,6 +1121,14 @@ do { doubleget_union _tmp; \
#endif /* sint2korr */
/*
+ Macro for reading 32-bit integer from network byte order (big-endian)
+ from unaligned memory location.
+*/
+#define int4net(A) (int32) (((uint32) ((uchar) (A)[3])) |\
+ (((uint32) ((uchar) (A)[2])) << 8) |\
+ (((uint32) ((uchar) (A)[1])) << 16) |\
+ (((uint32) ((uchar) (A)[0])) << 24))
+/*
Define-funktions for reading and storing in machine format from/to
short/long to/from some place in memory V should be a (not
register) variable, M is a pointer to byte
@@ -1139,12 +1153,12 @@ do { doubleget_union _tmp; \
((byte*) &def_temp)[3]=(M)[3];\
(V)=def_temp; } while(0)
#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\
- *(T+1)=(char)(def_temp); \
- *(T+0)=(char)(def_temp >> 8); } while(0)
-#define longstore(T,A) do { *((T)+3)=((A));\
- *((T)+2)=(((A) >> 8));\
- *((T)+1)=(((A) >> 16));\
- *((T)+0)=(((A) >> 24)); } while(0)
+ *(((char*)T)+1)=(char)(def_temp); \
+ *(((char*)T)+0)=(char)(def_temp >> 8); } while(0)
+#define longstore(T,A) do { *(((char*)T)+3)=((A));\
+ *(((char*)T)+2)=(((A) >> 8));\
+ *(((char*)T)+1)=(((A) >> 16));\
+ *(((char*)T)+0)=(((A) >> 24)); } while(0)
#define floatstore(T,V) memcpy_fixed((byte*)(T), (byte*)(&V), sizeof(float))
#define doubleget(V,M) memcpy_fixed((byte*) &V,(byte*) (M),sizeof(double))
@@ -1191,22 +1205,14 @@ do { doubleget_union _tmp; \
#define statistic_add(V,C,L) (V)+=(C)
#endif
-#ifdef HAVE_OPENSSL
-#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x0090700f
-#define DES_cblock des_cblock
-#define DES_key_schedule des_key_schedule
-#define DES_set_key_unchecked(k,ks) des_set_key_unchecked((k),*(ks))
-#define DES_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e) des_ede3_cbc_encrypt((i),(o),(l),*(k1),*(k2),*(k3),(iv),(e))
-#endif
-#endif
-
#ifdef HAVE_CHARSET_utf8
#define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8"
#else
#define MYSQL_UNIVERSAL_CLIENT_CHARSET MYSQL_DEFAULT_CHARSET_NAME
#endif
-#define HAVE_SPATIAL
-#define HAVE_RTREE_KEYS
+#if defined(EMBEDDED_LIBRARY) && !defined(HAVE_EMBEDDED_PRIVILEGE_CONTROL)
+#define NO_EMBEDDED_ACCESS_CHECKS
+#endif
+
#endif /* my_global_h */
diff --git a/include/my_time.h b/include/my_time.h
new file mode 100644
index 00000000000..e42f7e9e402
--- /dev/null
+++ b/include/my_time.h
@@ -0,0 +1,46 @@
+/* Copyright (C) 2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ This is a private header of sql-common library, containing
+ declarations for my_time.c
+*/
+
+#ifndef _my_time_h_
+#define _my_time_h_
+#include "my_global.h"
+#include "mysql_time.h"
+
+C_MODE_START
+
+extern ulonglong log_10_int[20];
+
+#define YY_PART_YEAR 70
+
+/* Flags to str_to_datetime */
+#define TIME_FUZZY_DATE 1
+#define TIME_DATETIME_ONLY 2
+
+enum enum_mysql_timestamp_type
+str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
+ uint flags, int *was_cut);
+
+bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time,
+ int *was_cut);
+
+C_MODE_END
+
+#endif /* _my_time_h_ */
diff --git a/include/myisam.h b/include/myisam.h
index c99e9a30b08..02c56115dfd 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -47,7 +47,7 @@ extern "C" {
#define MI_NAME_IEXT ".MYI"
#define MI_NAME_DEXT ".MYD"
/* Max extra space to use when sorting keys */
-#define MI_MAX_TEMP_LENGTH 256*1024L*1024L
+#define MI_MAX_TEMP_LENGTH 2*1024L*1024L*1024L
/* Possible values for myisam_block_size (must be power of 2) */
#define MI_KEY_BLOCK_LENGTH 1024 /* default key block length */
diff --git a/include/myisampack.h b/include/myisampack.h
index 95793e2aaeb..06c94fea75f 100644
--- a/include/myisampack.h
+++ b/include/myisampack.h
@@ -21,6 +21,10 @@
better compression
*/
+/* these two are for uniformity */
+#define mi_sint1korr(A) (int8)(*A)
+#define mi_uint1korr(A) (uint8)(*A)
+
#define mi_sint2korr(A) (int16) (((int16) ((uchar) (A)[1])) +\
((int16) ((int16) (A)[0]) << 8))
#define mi_sint3korr(A) ((int32) ((((uchar) (A)[0]) & 128) ? \
@@ -75,6 +79,9 @@
(((uint32) ((uchar) (A)[0])) << 24))) <<\
32))
+/* This one is for uniformity */
+#define mi_int1store(T,A) *((uchar*)(T))= (uchar) (A)
+
#define mi_int2store(T,A) { uint def_temp= (uint) (A) ;\
*((uchar*) ((T)+1))= (uchar)(def_temp); \
*((uchar*) ((T)+0))= (uchar)(def_temp >> 8); }
diff --git a/include/mysql.h b/include/mysql.h
index 51540a7d89f..0f3fdc90548 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -55,6 +55,7 @@ typedef int my_socket;
#endif /* _global_h */
#include "mysql_com.h"
+#include "mysql_time.h"
#include "mysql_version.h"
#include "typelib.h"
@@ -77,7 +78,6 @@ extern char *mysql_unix_port;
#define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG)
#define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR)
-#define HAVE_DEPRECATED_411_API 1
typedef struct st_mysql_field {
char *name; /* Name of column */
@@ -302,7 +302,6 @@ typedef struct st_mysql_res {
#endif
-
typedef struct st_mysql_manager
{
NET net;
@@ -317,6 +316,17 @@ typedef struct st_mysql_manager
char last_error[MAX_MYSQL_MANAGER_ERR];
} MYSQL_MANAGER;
+typedef struct st_mysql_parameters
+{
+ unsigned long *p_max_allowed_packet;
+ unsigned long *p_net_buffer_length;
+} MYSQL_PARAMETERS;
+
+#if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
+#define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet)
+#define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length)
+#endif
+
/*
Set up and bring down the server; to ensure that applications will
work when linked against either the standard client library or the
@@ -325,6 +335,8 @@ typedef struct st_mysql_manager
int STDCALL mysql_server_init(int argc, char **argv, char **groups);
void STDCALL mysql_server_end(void);
+MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void);
+
/*
Set up and bring down a thread; these function should be called
for each thread in an application which opens at least one MySQL
@@ -441,7 +453,9 @@ int STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
const char* user,
const char* passwd);
-int STDCALL mysql_shutdown(MYSQL *mysql);
+int STDCALL mysql_shutdown(MYSQL *mysql,
+ enum enum_shutdown_level
+ shutdown_level);
int STDCALL mysql_dump_debug_info(MYSQL *mysql);
int STDCALL mysql_refresh(MYSQL *mysql,
unsigned int refresh_options);
@@ -519,34 +533,17 @@ enum enum_mysql_stmt_state
MYSQL_STMT_FETCH_DONE
};
-/*
- client TIME structure to handle TIME, DATE and TIMESTAMP directly in
- binary protocol
-*/
-enum mysql_st_timestamp_type { MYSQL_TIMESTAMP_NONE, MYSQL_TIMESTAMP_DATE,
- MYSQL_TIMESTAMP_FULL, MYSQL_TIMESTAMP_TIME };
-
-typedef struct mysql_st_time
-{
- unsigned int year,month,day,hour,minute,second;
- unsigned long second_part;
- my_bool neg;
-
- enum mysql_st_timestamp_type time_type;
-
-} MYSQL_TIME;
-
/* bind structure */
typedef struct st_mysql_bind
{
unsigned long *length; /* output length pointer */
my_bool *is_null; /* Pointer to null indicators */
- char *buffer; /* buffer to get/put data */
+ void *buffer; /* buffer to get/put data */
enum enum_field_types buffer_type; /* buffer type */
unsigned long buffer_length; /* buffer length, must be set for str/binary */
- /* Following are for internal use. Set by mysql_bind_param */
+ /* Following are for internal use. Set by mysql_stmt_bind_param */
unsigned char *inter_buffer; /* for the current data position */
unsigned long offset; /* offset position for char/binary fetch */
unsigned long internal_length; /* Used if length is 0 */
@@ -698,6 +695,7 @@ void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset);
my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt);
my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt);
+unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt);
my_bool STDCALL mysql_commit(MYSQL * mysql);
my_bool STDCALL mysql_rollback(MYSQL * mysql);
diff --git a/include/mysql_com.h b/include/mysql_com.h
index b4947a64236..ea375128455 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -36,12 +36,6 @@
#define MYSQL_SERVICENAME "MySQL"
#endif /* __WIN__ */
-#if defined(__WIN__) && !defined(MYSQL_SERVER) && !defined(MYSQL_CLIENT) && !defined(EMBEDDED_LIBRARY)
-#define dll_import_spec __declspec( dllimport )
-#else
-#define dll_import_spec
-#endif
-
enum enum_server_command
{
COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST,
@@ -232,6 +226,32 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
+enum enum_shutdown_level {
+ /*
+ We want levels to be in growing order of hardness. So we leave room
+ for future intermediate levels. For now, escalating one level is += 10;
+ later if we insert new levels in between we will need a function
+ next_shutdown_level(level). Note that DEFAULT does not respect the
+ growing property.
+ */
+ SHUTDOWN_DEFAULT= 0, /* mapped to WAIT_ALL_BUFFERS for now */
+ /*
+ Here is the list in growing order (the next does the previous plus
+ something). WAIT_ALL_BUFFERS is what we have now. Others are "this MySQL
+ server does not support this shutdown level yet".
+ */
+ SHUTDOWN_WAIT_CONNECTIONS= 10, /* wait for existing connections to finish */
+ SHUTDOWN_WAIT_TRANSACTIONS= 20, /* wait for existing trans to finish */
+ SHUTDOWN_WAIT_STATEMENTS= 30, /* wait for existing updating stmts to finish */
+ SHUTDOWN_WAIT_ALL_BUFFERS= 40, /* flush InnoDB buffers */
+ SHUTDOWN_WAIT_CRITICAL_BUFFERS= 50, /* flush MyISAM buffs (no corruption) */
+ /* Now the 2 levels of the KILL command */
+#if MYSQL_VERSION_ID >= 50000
+ KILL_QUERY= 254,
+#endif
+ KILL_CONNECTION= 255
+};
+
/* options for mysql_set_option */
enum enum_mysql_set_option
{
@@ -317,9 +337,6 @@ typedef struct st_udf_init
extern "C" {
#endif
-dll_import_spec extern unsigned long max_allowed_packet;
-dll_import_spec extern unsigned long net_buffer_length;
-
/*
These functions are used for authentication by client and server and
implemented in sql/password.c
diff --git a/include/mysql_time.h b/include/mysql_time.h
new file mode 100644
index 00000000000..943d018fc14
--- /dev/null
+++ b/include/mysql_time.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef _mysql_time_h_
+#define _mysql_time_h_
+
+/* Time declarations shared between server and client library */
+
+enum enum_mysql_timestamp_type
+{
+ MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1,
+ MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2
+};
+
+
+typedef struct st_mysql_time
+{
+ unsigned int year, month, day, hour, minute, second;
+ unsigned long second_part;
+ my_bool neg;
+ enum enum_mysql_timestamp_type time_type;
+} MYSQL_TIME;
+
+#endif /* _mysql_time_h_ */
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index b5ea5b911c1..840b9c7f42a 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -312,46 +312,50 @@
#define ER_TOO_MUCH_AUTO_TIMESTAMP_COLS 1293
#define ER_INVALID_ON_UPDATE 1294
#define ER_UNSUPPORTED_PS 1295
-#define ER_SP_NO_RECURSIVE_CREATE 1296
-#define ER_SP_ALREADY_EXISTS 1297
-#define ER_SP_DOES_NOT_EXIST 1298
-#define ER_SP_DROP_FAILED 1299
-#define ER_SP_STORE_FAILED 1300
-#define ER_SP_LILABEL_MISMATCH 1301
-#define ER_SP_LABEL_REDEFINE 1302
-#define ER_SP_LABEL_MISMATCH 1303
-#define ER_SP_UNINIT_VAR 1304
-#define ER_SP_BADSELECT 1305
-#define ER_SP_BADRETURN 1306
-#define ER_SP_BADSTATEMENT 1307
-#define ER_UPDATE_LOG_DEPRECATED_IGNORED 1308
-#define ER_UPDATE_LOG_DEPRECATED_TRANSLATED 1309
-#define ER_QUERY_INTERRUPTED 1310
-#define ER_SP_WRONG_NO_OF_ARGS 1311
-#define ER_SP_COND_MISMATCH 1312
-#define ER_SP_NORETURN 1313
-#define ER_SP_NORETURNEND 1314
-#define ER_SP_BAD_CURSOR_QUERY 1315
-#define ER_SP_BAD_CURSOR_SELECT 1316
-#define ER_SP_CURSOR_MISMATCH 1317
-#define ER_SP_CURSOR_ALREADY_OPEN 1318
-#define ER_SP_CURSOR_NOT_OPEN 1319
-#define ER_SP_UNDECLARED_VAR 1320
-#define ER_SP_WRONG_NO_OF_FETCH_ARGS 1321
-#define ER_SP_FETCH_NO_DATA 1322
-#define ER_SP_DUP_PARAM 1323
-#define ER_SP_DUP_VAR 1324
-#define ER_SP_DUP_COND 1325
-#define ER_SP_DUP_CURS 1326
-#define ER_SP_CANT_ALTER 1327
-#define ER_SP_SUBSELECT_NYI 1328
-#define ER_SP_NO_USE 1329
-#define ER_SP_VARCOND_AFTER_CURSHNDLR 1330
-#define ER_SP_CURSOR_AFTER_HANDLER 1331
-#define ER_SP_CASE_NOT_FOUND 1332
-#define ER_FPARSER_TOO_BIG_FILE 1333
-#define ER_FPARSER_BAD_HEADER 1334
-#define ER_FPARSER_EOF_IN_COMMENT 1335
-#define ER_FPARSER_ERROR_IN_PARAMETER 1336
-#define ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER 1337
-#define ER_ERROR_MESSAGES 338
+#define ER_GET_ERRMSG 1296
+#define ER_GET_TEMPORARY_ERRMSG 1297
+#define ER_UNKNOWN_TIME_ZONE 1298
+#define ER_WARN_INVALID_TIMESTAMP 1299
+#define ER_SP_NO_RECURSIVE_CREATE 1300
+#define ER_SP_ALREADY_EXISTS 1301
+#define ER_SP_DOES_NOT_EXIST 1302
+#define ER_SP_DROP_FAILED 1303
+#define ER_SP_STORE_FAILED 1304
+#define ER_SP_LILABEL_MISMATCH 1305
+#define ER_SP_LABEL_REDEFINE 1306
+#define ER_SP_LABEL_MISMATCH 1307
+#define ER_SP_UNINIT_VAR 1308
+#define ER_SP_BADSELECT 1309
+#define ER_SP_BADRETURN 1310
+#define ER_SP_BADSTATEMENT 1311
+#define ER_UPDATE_LOG_DEPRECATED_IGNORED 1312
+#define ER_UPDATE_LOG_DEPRECATED_TRANSLATED 1313
+#define ER_QUERY_INTERRUPTED 1314
+#define ER_SP_WRONG_NO_OF_ARGS 1315
+#define ER_SP_COND_MISMATCH 1316
+#define ER_SP_NORETURN 1317
+#define ER_SP_NORETURNEND 1318
+#define ER_SP_BAD_CURSOR_QUERY 1319
+#define ER_SP_BAD_CURSOR_SELECT 1320
+#define ER_SP_CURSOR_MISMATCH 1321
+#define ER_SP_CURSOR_ALREADY_OPEN 1322
+#define ER_SP_CURSOR_NOT_OPEN 1323
+#define ER_SP_UNDECLARED_VAR 1324
+#define ER_SP_WRONG_NO_OF_FETCH_ARGS 1325
+#define ER_SP_FETCH_NO_DATA 1326
+#define ER_SP_DUP_PARAM 1327
+#define ER_SP_DUP_VAR 1328
+#define ER_SP_DUP_COND 1329
+#define ER_SP_DUP_CURS 1330
+#define ER_SP_CANT_ALTER 1331
+#define ER_SP_SUBSELECT_NYI 1332
+#define ER_SP_NO_USE 1333
+#define ER_SP_VARCOND_AFTER_CURSHNDLR 1334
+#define ER_SP_CURSOR_AFTER_HANDLER 1335
+#define ER_SP_CASE_NOT_FOUND 1336
+#define ER_FPARSER_TOO_BIG_FILE 1337
+#define ER_FPARSER_BAD_HEADER 1338
+#define ER_FPARSER_EOF_IN_COMMENT 1339
+#define ER_FPARSER_ERROR_IN_PARAMETER 1340
+#define ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER 1341
+#define ER_ERROR_MESSAGES 342
diff --git a/include/sql_state.h b/include/sql_state.h
index 9eff300d494..7bf05203463 100644
--- a/include/sql_state.h
+++ b/include/sql_state.h
@@ -23,10 +23,10 @@
the second column is the ODBC state (which the 4.1 server sends out by
default) and the last is the state used by the JDBC driver.
If the last column is "" then it means that the JDBC driver is using the
- ODBC state
+ ODBC state.
- The errors in this file is sorted in the same order as in mysqld_error.h
- to allow on to do binary searches for the sqlstate.
+ The errors in this file are sorted in the same order as in mysqld_error.h
+ to allow one to do binary searches for the sqlstate.
*/
ER_DUP_KEY, "23000", "",
diff --git a/include/violite.h b/include/violite.h
index b4b9f724d89..ba7de3ee175 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -83,6 +83,14 @@ my_bool vio_poll_read(Vio *vio,uint timeout);
void vio_timeout(Vio *vio,uint timeout);
#ifdef HAVE_OPENSSL
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER < 0x0090700f
+#define DES_cblock des_cblock
+#define DES_key_schedule des_key_schedule
+#define DES_set_key_unchecked(k,ks) des_set_key_unchecked((k),*(ks))
+#define DES_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e) des_ede3_cbc_encrypt((i),(o),(l),*(k1),*(k2),*(k3),(iv),(e))
+#endif
+
#define HEADER_DES_LOCL_H dummy_something
#include <openssl/ssl.h>
#include <openssl/err.h>
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index 09f5c66f687..27d798f925a 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -2165,7 +2165,6 @@ btr_discard_page(
ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
}
-#ifdef UNIV_DEBUG
/*****************************************************************
Prints size info of a B-tree. */
@@ -2287,7 +2286,6 @@ btr_print_tree(
btr_validate_tree(tree);
}
-#endif /* UNIV_DEBUG */
/****************************************************************
Checks that the node pointer to a page is appropriate. */
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 5829cc2c406..2e9194ff30f 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -2937,7 +2937,7 @@ btr_cur_mark_dtuple_inherited_extern(
if (!is_updated) {
dfield = dtuple_get_nth_field(entry, ext_vec[i]);
- data = dfield_get_data(dfield);
+ data = (byte*) dfield_get_data(dfield);
len = dfield_get_len(dfield);
len -= BTR_EXTERN_FIELD_REF_SIZE;
@@ -2997,7 +2997,7 @@ btr_cur_unmark_dtuple_extern_fields(
for (i = 0; i < n_ext_vec; i++) {
dfield = dtuple_get_nth_field(entry, ext_vec[i]);
- data = dfield_get_data(dfield);
+ data = (byte*) dfield_get_data(dfield);
len = dfield_get_len(dfield);
len -= BTR_EXTERN_FIELD_REF_SIZE;
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 4d83fb4c9f2..5ec8998473d 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -223,14 +223,12 @@ in the free list to the frames.
buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */
-#ifdef UNIV_DEBUG
-static ulint buf_dbg_counter = 0; /* This is used to insert validation
+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
@@ -719,7 +717,9 @@ buf_awe_map_page_to_frame(
{
buf_block_t* bck;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(block);
if (block->frame) {
@@ -1727,12 +1727,10 @@ 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;
@@ -1883,11 +1881,9 @@ 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);
@@ -1900,21 +1896,17 @@ 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 */
}
/*************************************************************************
@@ -1943,7 +1935,6 @@ buf_pool_invalidate(void)
mutex_exit(&(buf_pool->mutex));
}
-#ifdef UNIV_DEBUG
/*************************************************************************
Validates the buffer buf_pool data structure. */
@@ -2143,7 +2134,6 @@ buf_print(void)
ut_a(buf_validate());
}
-#endif /* UNIV_DEBUG */
/*************************************************************************
Returns the number of pending buf pool ios. */
diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
index 885bcf06456..6cefdb60956 100644
--- a/innobase/buf/buf0flu.c
+++ b/innobase/buf/buf0flu.c
@@ -32,7 +32,6 @@ flushed along with the original page. */
#define BUF_FLUSH_AREA ut_min(BUF_READ_AHEAD_AREA,\
buf_pool->curr_size / 16)
-#ifdef UNIV_DEBUG
/**********************************************************************
Validates the flush list. */
static
@@ -40,7 +39,6 @@ ibool
buf_flush_validate_low(void);
/*========================*/
/* out: TRUE if ok */
-#endif /* UNIV_DEBUG */
/************************************************************************
Inserts a modified block into the flush list. */
@@ -513,13 +511,11 @@ 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);
@@ -603,14 +599,12 @@ 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);
@@ -837,7 +831,6 @@ 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);
@@ -846,7 +839,6 @@ buf_flush_batch(
: "Flushed %lu pages in flush list flush\n",
(ulong) page_count);
}
-#endif /* UNIV_DEBUG */
return(page_count);
}
@@ -938,7 +930,6 @@ buf_flush_free_margin(void)
}
}
-#ifdef UNIV_DEBUG
/**********************************************************************
Validates the flush list. */
static
@@ -988,4 +979,3 @@ buf_flush_validate(void)
return(ret);
}
-#endif /* UNIV_DEBUG */
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index 053161986e4..796311f0157 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -209,14 +209,12 @@ 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);
@@ -888,7 +886,6 @@ buf_LRU_block_free_hashed_page(
buf_LRU_block_free_non_file_page(block);
}
-#ifdef UNIV_DEBUG
/**************************************************************************
Validates the LRU list. */
@@ -1019,4 +1016,3 @@ 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 e0f8291977e..71e885ff439 100644
--- a/innobase/buf/buf0rea.c
+++ b/innobase/buf/buf0rea.c
@@ -284,14 +284,12 @@ 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 */
return(count);
}
@@ -571,13 +569,11 @@ 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 */
return(count);
}
@@ -636,13 +632,11 @@ 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, (ulong) n_stored);
+ (ulong) space_ids[0], (ulong) n_stored);
}
-#endif /* UNIV_DEBUG */
}
/************************************************************************
@@ -706,10 +700,8 @@ 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/data/data0type.c b/innobase/data/data0type.c
index 698b5361dfa..97d93b1b0ec 100644
--- a/innobase/data/data0type.c
+++ b/innobase/data/data0type.c
@@ -104,7 +104,6 @@ dtype_form_prtype(
return(old_prtype + (charset_coll << 16));
}
-#ifdef UNIV_DEBUG
/*************************************************************************
Validates a data type structure. */
@@ -123,7 +122,6 @@ dtype_validate(
return(TRUE);
}
-#endif /* UNIV_DEBUG */
/*************************************************************************
Prints a data type structure. */
diff --git a/innobase/dict/dict0boot.c b/innobase/dict/dict0boot.c
index 8e1629819f3..f156cf67a18 100644
--- a/innobase/dict/dict0boot.c
+++ b/innobase/dict/dict0boot.c
@@ -254,29 +254,26 @@ dict_boot(void)
/* Insert into the dictionary cache the descriptions of the basic
system tables */
/*-------------------------*/
- table = dict_mem_table_create((char *) "SYS_TABLES", DICT_HDR_SPACE,8);
-
- dict_mem_table_add_col(table, (char *) "NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, (char *) "ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, (char *) "N_COLS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "TYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "MIX_ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, (char *) "MIX_LEN", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "CLUSTER_NAME", DATA_BINARY,
- 0, 0, 0);
- dict_mem_table_add_col(table, (char *) "SPACE", DATA_INT, 0, 4, 0);
+ table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE,8);
+
+ dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, "N_COLS", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "TYPE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "MIX_ID", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, "MIX_LEN", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "CLUSTER_NAME", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, "SPACE", DATA_INT, 0, 4, 0);
table->id = DICT_TABLES_ID;
dict_table_add_to_cache(table);
dict_sys->sys_tables = table;
- index = dict_mem_index_create((char *) "SYS_TABLES", (char *)
- "CLUST_IND",
- DICT_HDR_SPACE,
- DICT_UNIQUE | DICT_CLUSTERED, 1);
+ index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
+ DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 1);
- dict_mem_index_add_field(index, (char *) "NAME", 0, 0);
+ dict_mem_index_add_field(index, "NAME", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_TABLES,
MLOG_4BYTES, &mtr);
@@ -284,52 +281,50 @@ dict_boot(void)
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- index = dict_mem_index_create((char *) "SYS_TABLES",
- (char *) "ID_IND", DICT_HDR_SPACE,
- DICT_UNIQUE, 1);
- dict_mem_index_add_field(index, (char *) "ID", 0, 0);
+ index = dict_mem_index_create("SYS_TABLES", "ID_IND",
+ DICT_HDR_SPACE, DICT_UNIQUE, 1);
+ dict_mem_index_add_field(index, "ID", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_TABLE_IDS,
MLOG_4BYTES, &mtr);
index->id = DICT_TABLE_IDS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- table = dict_mem_table_create((char *) "SYS_COLUMNS",DICT_HDR_SPACE,7);
-
- dict_mem_table_add_col(table, (char *) "TABLE_ID", DATA_BINARY,0,0,0);
- dict_mem_table_add_col(table, (char *) "POS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, (char *) "MTYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "PRTYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "LEN", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "PREC", DATA_INT, 0, 4, 0);
+ table = dict_mem_table_create("SYS_COLUMNS",DICT_HDR_SPACE,7);
+
+ dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY,0,0,0);
+ dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, "MTYPE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "PRTYPE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "LEN", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "PREC", DATA_INT, 0, 4, 0);
table->id = DICT_COLUMNS_ID;
dict_table_add_to_cache(table);
dict_sys->sys_columns = table;
- index = dict_mem_index_create((char *) "SYS_COLUMNS",
- (char *) "CLUST_IND", DICT_HDR_SPACE,
- DICT_UNIQUE | DICT_CLUSTERED, 2);
+ index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
+ DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2);
- dict_mem_index_add_field(index, (char *) "TABLE_ID", 0, 0);
- dict_mem_index_add_field(index, (char *) "POS", 0, 0);
+ dict_mem_index_add_field(index, "TABLE_ID", 0, 0);
+ dict_mem_index_add_field(index, "POS", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_COLUMNS,
MLOG_4BYTES, &mtr);
index->id = DICT_COLUMNS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- table = dict_mem_table_create((char *) "SYS_INDEXES",DICT_HDR_SPACE,7);
+ table = dict_mem_table_create("SYS_INDEXES",DICT_HDR_SPACE,7);
- dict_mem_table_add_col(table, (char *) "TABLE_ID", DATA_BINARY, 0,0,0);
- dict_mem_table_add_col(table, (char *) "ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, (char *) "NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, (char *) "N_FIELDS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "TYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "SPACE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "PAGE_NO", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY, 0,0,0);
+ dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, "N_FIELDS", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "TYPE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "SPACE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "PAGE_NO", DATA_INT, 0, 4, 0);
/* The '+ 2' below comes from the 2 system fields */
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
@@ -343,34 +338,32 @@ dict_boot(void)
dict_table_add_to_cache(table);
dict_sys->sys_indexes = table;
- index = dict_mem_index_create((char *) "SYS_INDEXES",
- (char *) "CLUST_IND", DICT_HDR_SPACE,
- DICT_UNIQUE | DICT_CLUSTERED, 2);
+ index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
+ DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2);
- dict_mem_index_add_field(index, (char *) "TABLE_ID", 0, 0);
- dict_mem_index_add_field(index, (char *) "ID", 0, 0);
+ dict_mem_index_add_field(index, "TABLE_ID", 0, 0);
+ dict_mem_index_add_field(index, "ID", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_INDEXES,
MLOG_4BYTES, &mtr);
index->id = DICT_INDEXES_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- table = dict_mem_table_create((char *) "SYS_FIELDS", DICT_HDR_SPACE,3);
+ table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE,3);
- dict_mem_table_add_col(table, (char *) "INDEX_ID", DATA_BINARY, 0,0,0);
- dict_mem_table_add_col(table, (char *) "POS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, (char *) "COL_NAME", DATA_BINARY, 0,0,0);
+ dict_mem_table_add_col(table, "INDEX_ID", DATA_BINARY, 0,0,0);
+ dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, "COL_NAME", DATA_BINARY, 0,0,0);
table->id = DICT_FIELDS_ID;
dict_table_add_to_cache(table);
dict_sys->sys_fields = table;
- index = dict_mem_index_create((char *) "SYS_FIELDS",
- (char *) "CLUST_IND", DICT_HDR_SPACE,
- DICT_UNIQUE | DICT_CLUSTERED, 2);
+ index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
+ DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2);
- dict_mem_index_add_field(index, (char *) "INDEX_ID", 0, 0);
- dict_mem_index_add_field(index, (char *) "POS", 0, 0);
+ dict_mem_index_add_field(index, "INDEX_ID", 0, 0);
+ dict_mem_index_add_field(index, "POS", 0, 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_FIELDS,
MLOG_4BYTES, &mtr);
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index f0b5906ec50..fd8e02585ae 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -1004,12 +1004,12 @@ dict_create_or_check_foreign_constraint_tables(void)
que_t* graph;
ulint error;
trx_t* trx;
- char* str;
+ const char* str;
mutex_enter(&(dict_sys->mutex));
- table1 = dict_table_get_low((char *) "SYS_FOREIGN");
- table2 = dict_table_get_low((char *) "SYS_FOREIGN_COLS");
+ table1 = dict_table_get_low("SYS_FOREIGN");
+ table2 = dict_table_get_low("SYS_FOREIGN_COLS");
if (table1 && table2
&& UT_LIST_GET_LEN(table1->indexes) == 3
@@ -1027,20 +1027,20 @@ dict_create_or_check_foreign_constraint_tables(void)
trx = trx_allocate_for_mysql();
- trx->op_info = (char *) "creating foreign key sys tables";
+ trx->op_info = "creating foreign key sys tables";
row_mysql_lock_data_dictionary(trx);
if (table1) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN table\n");
- row_drop_table_for_mysql((char*)"SYS_FOREIGN", trx, TRUE);
+ row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
}
if (table2) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n");
- row_drop_table_for_mysql((char*)"SYS_FOREIGN_COLS", trx, TRUE);
+ row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
}
fprintf(stderr,
@@ -1050,7 +1050,7 @@ dict_create_or_check_foreign_constraint_tables(void)
there are 2 secondary indexes on SYS_FOREIGN, and they
are defined just like below */
- str = (char *)
+ str =
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
"BEGIN\n"
"CREATE TABLE\n"
@@ -1090,15 +1090,15 @@ dict_create_or_check_foreign_constraint_tables(void)
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN tables\n");
- row_drop_table_for_mysql((char*)"SYS_FOREIGN", trx, TRUE);
- row_drop_table_for_mysql((char*)"SYS_FOREIGN_COLS", trx, TRUE);
+ row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
+ row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
error = DB_MUST_GET_MORE_FILE_SPACE;
}
que_graph_free(graph);
- trx->op_info = (char *) "";
+ trx->op_info = "";
row_mysql_unlock_data_dictionary(trx);
@@ -1161,7 +1161,7 @@ dict_create_add_foreigns_to_dictionary(
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
- if (NULL == dict_table_get_low((char *) "SYS_FOREIGN")) {
+ if (NULL == dict_table_get_low("SYS_FOREIGN")) {
fprintf(stderr,
"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 6a6ac2492f8..71cf908db4e 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -198,13 +198,14 @@ dict_tables_have_same_db(
/************************************************************************
Return the end of table name where we have removed dbname and '/'. */
static
-char*
+const char*
dict_remove_db_name(
/*================*/
- /* out: table name */
- char* name) /* in: table name in the form dbname '/' tablename */
+ /* out: table name */
+ const char* name) /* in: table name in the form
+ dbname '/' tablename */
{
- char* s;
+ const char* s;
s = strchr(name, '/');
ut_a(s);
if (s) s++;
@@ -680,7 +681,7 @@ dict_init(void)
rw_lock_create(&dict_operation_lock);
rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
- dict_foreign_err_file = tmpfile();
+ dict_foreign_err_file = os_file_create_tmpfile();
mutex_create(&dict_foreign_err_mutex);
mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
}
@@ -783,23 +784,33 @@ dict_table_add_to_cache(
The clustered index will not always physically contain all
system columns. */
- dict_mem_table_add_col(table, (char *) "DB_ROW_ID", DATA_SYS,
+ dict_mem_table_add_col(table, "DB_ROW_ID", DATA_SYS,
DATA_ROW_ID, 0, 0);
- ut_ad(DATA_ROW_ID == 0);
- dict_mem_table_add_col(table, (char *) "DB_TRX_ID", DATA_SYS,
+#if DATA_ROW_ID != 0
+#error "DATA_ROW_ID != 0"
+#endif
+ dict_mem_table_add_col(table, "DB_TRX_ID", DATA_SYS,
DATA_TRX_ID, 0, 0);
- ut_ad(DATA_TRX_ID == 1);
- dict_mem_table_add_col(table, (char *) "DB_ROLL_PTR", DATA_SYS,
- DATA_ROLL_PTR,
- 0, 0);
- ut_ad(DATA_ROLL_PTR == 2);
+#if DATA_TRX_ID != 1
+#error "DATA_TRX_ID != 1"
+#endif
+ dict_mem_table_add_col(table, "DB_ROLL_PTR", DATA_SYS,
+ DATA_ROLL_PTR, 0, 0);
+#if DATA_ROLL_PTR != 2
+#error "DATA_ROLL_PTR != 2"
+#endif
- dict_mem_table_add_col(table, (char *) "DB_MIX_ID", DATA_SYS,
+ dict_mem_table_add_col(table, "DB_MIX_ID", DATA_SYS,
DATA_MIX_ID, 0, 0);
- ut_ad(DATA_MIX_ID == 3);
- ut_ad(DATA_N_SYS_COLS == 4); /* This assert reminds that if a new
- system column is added to the program,
- it should be dealt with here */
+#if DATA_MIX_ID != 3
+#error "DATA_MIX_ID != 3"
+#endif
+
+ /* This check reminds that if a new system column is added to
+ the program, it should be dealt with here */
+#if DATA_N_SYS_COLS != 4
+#error "DATA_N_SYS_COLS != 4"
+#endif
/* Look for a table with the same name: error if such exists */
{
@@ -1107,7 +1118,9 @@ dict_table_change_id_in_cache(
dulint new_id) /* in: new id to set */
{
ut_ad(table);
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* Remove the table from the hash table of id's */
@@ -1973,7 +1986,7 @@ dict_foreign_find(
/*==============*/
/* out: foreign constraint */
dict_table_t* table, /* in: table object */
- char* id) /* in: foreign constraint id */
+ const char* id) /* in: foreign constraint id */
{
dict_foreign_t* foreign;
@@ -2367,7 +2380,7 @@ dict_scan_id(
*id = mem_heap_strdupl(heap, s, len);
} else {
/* no heap given: id will point to source string */
- *id = (char*) s;
+ *id = s;
}
return(ptr);
@@ -2750,7 +2763,7 @@ dict_create_foreign_constraints_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
- table = dict_table_get_low((char*) name);
+ table = dict_table_get_low(name);
if (table == NULL) {
mutex_enter(&dict_foreign_err_mutex);
@@ -3475,9 +3488,9 @@ dict_tree_create(
tree->id = index->id;
UT_LIST_INIT(tree->tree_indexes);
-#ifdef UNIV_DEBUG
+
tree->magic_n = DICT_TREE_MAGIC_N;
-#endif /* UNIV_DEBUG */
+
rw_lock_create(&(tree->lock));
rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE);
@@ -3916,7 +3929,6 @@ dict_foreign_print_low(
fputs(" )\n", stderr);
}
-#ifdef UNIV_DEBUG
/**************************************************************************
Prints a table data. */
@@ -3936,7 +3948,7 @@ Prints a table data when we know the table name. */
void
dict_table_print_by_name(
/*=====================*/
- char* name)
+ const char* name)
{
dict_table_t* table;
@@ -3949,7 +3961,6 @@ dict_table_print_by_name(
dict_table_print_low(table);
mutex_exit(&(dict_sys->mutex));
}
-#endif /* UNIV_DEBUG */
/**************************************************************************
Prints a table data. */
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index 071a3b4c684..ee4ae9dd1a1 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -51,7 +51,7 @@ dict_get_first_table_name_in_db(
mtr_start(&mtr);
- sys_tables = dict_table_get_low((char *) "SYS_TABLES");
+ sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
tuple = dtuple_create(heap, 1);
@@ -127,7 +127,7 @@ dict_print(void)
mtr_start(&mtr);
- sys_tables = dict_table_get_low((char *) "SYS_TABLES");
+ sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
@@ -207,13 +207,12 @@ dict_check_tablespaces_or_store_max_id(
ulint space_id;
ulint max_space_id = 0;
mtr_t mtr;
- char name[OS_FILE_MAX_PATH];
mutex_enter(&(dict_sys->mutex));
mtr_start(&mtr);
- sys_tables = dict_table_get_low((char *) "SYS_TABLES");
+ sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
@@ -247,9 +246,7 @@ loop:
/* We found one */
- ut_a(len < OS_FILE_MAX_PATH - 10);
- ut_memcpy(name, field, len);
- name[len] = '\0';
+ char* name = mem_strdupl(field, len);
field = rec_get_nth_field(rec, 9, &len);
ut_a(len == 4);
@@ -267,7 +264,9 @@ loop:
fil_space_for_table_exists_in_mem(space_id, name,
TRUE, TRUE);
}
-
+
+ mem_free(name);
+
if (space_id > max_space_id) {
max_space_id = space_id;
}
@@ -312,7 +311,7 @@ dict_load_columns(
mtr_start(&mtr);
- sys_columns = dict_table_get_low((char*) "SYS_COLUMNS");
+ sys_columns = dict_table_get_low("SYS_COLUMNS");
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
tuple = dtuple_create(heap, 1);
@@ -342,7 +341,7 @@ dict_load_columns(
ut_ad(len == 4);
ut_a(i == mach_read_from_4(field));
- ut_a(0 == ut_strcmp((char*) "NAME",
+ ut_a(0 == ut_strcmp("NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_columns), 4))->name));
@@ -368,7 +367,7 @@ dict_load_columns(
field = rec_get_nth_field(rec, 7, &len);
col_len = mach_read_from_4(field);
- ut_a(0 == ut_strcmp((char*) "PREC",
+ ut_a(0 == ut_strcmp("PREC",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_columns), 8))->name));
@@ -438,7 +437,7 @@ dict_load_fields(
mtr_start(&mtr);
- sys_fields = dict_table_get_low((char*) "SYS_FIELDS");
+ sys_fields = dict_table_get_low("SYS_FIELDS");
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
tuple = dtuple_create(heap, 1);
@@ -489,7 +488,7 @@ dict_load_fields(
prefix_len = 0;
}
- ut_a(0 == ut_strcmp((char*) "COL_NAME",
+ ut_a(0 == ut_strcmp("COL_NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_fields), 4))->name));
@@ -551,7 +550,7 @@ dict_load_indexes(
mtr_start(&mtr);
- sys_indexes = dict_table_get_low((char*) "SYS_INDEXES");
+ sys_indexes = dict_table_get_low("SYS_INDEXES");
sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
tuple = dtuple_create(heap, 1);
@@ -594,7 +593,7 @@ dict_load_indexes(
ut_ad(len == 8);
id = mach_read_from_8(field);
- ut_a(0 == ut_strcmp((char*) "NAME",
+ ut_a(0 == ut_strcmp("NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_indexes), 4))->name));
@@ -611,7 +610,7 @@ dict_load_indexes(
field = rec_get_nth_field(rec, 7, &len);
space = mach_read_from_4(field);
- ut_a(0 == ut_strcmp((char*) "PAGE_NO",
+ ut_a(0 == ut_strcmp("PAGE_NO",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_indexes), 8))->name));
@@ -654,7 +653,7 @@ dict_load_indexes(
&& ((type & DICT_CLUSTERED)
|| ((table == dict_sys->sys_tables)
&& (name_len == (sizeof "ID_IND") - 1)
- && (0 == ut_memcmp(name_buf, (char*) "ID_IND",
+ && (0 == ut_memcmp(name_buf, "ID_IND",
name_len))))) {
/* The index was created in memory already at booting
@@ -721,7 +720,7 @@ dict_load_table(
mtr_start(&mtr);
- sys_tables = dict_table_get_low((char *) "SYS_TABLES");
+ sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
tuple = dtuple_create(heap, 1);
@@ -757,7 +756,7 @@ dict_load_table(
return(NULL);
}
- ut_a(0 == ut_strcmp((char *) "SPACE",
+ ut_a(0 == ut_strcmp("SPACE",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_tables), 9))->name));
@@ -782,7 +781,7 @@ dict_load_table(
}
}
- ut_a(0 == ut_strcmp((char *) "N_COLS",
+ ut_a(0 == ut_strcmp("N_COLS",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_tables), 4))->name));
@@ -794,7 +793,7 @@ dict_load_table(
table->ibd_file_missing = ibd_file_missing;
- ut_a(0 == ut_strcmp((char *) "ID",
+ ut_a(0 == ut_strcmp("ID",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_tables), 3))->name));
@@ -983,7 +982,7 @@ static
void
dict_load_foreign_cols(
/*===================*/
- char* id, /* in: foreign constraint id as a null-
+ const char* id, /* in: foreign constraint id as a null-
terminated string */
dict_foreign_t* foreign)/* in: foreign constraint object */
{
@@ -1009,7 +1008,7 @@ dict_load_foreign_cols(
foreign->n_fields * sizeof(void*));
mtr_start(&mtr);
- sys_foreign_cols = dict_table_get_low((char *) "SYS_FOREIGN_COLS");
+ sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
tuple = dtuple_create(foreign->heap, 1);
@@ -1056,9 +1055,9 @@ static
ulint
dict_load_foreign(
/*==============*/
- /* out: DB_SUCCESS or error code */
- char* id) /* in: foreign constraint id as a null-terminated
- string */
+ /* out: DB_SUCCESS or error code */
+ const char* id) /* in: foreign constraint id as a
+ null-terminated string */
{
dict_foreign_t* foreign;
dict_table_t* sys_foreign;
@@ -1081,7 +1080,7 @@ dict_load_foreign(
mtr_start(&mtr);
- sys_foreign = dict_table_get_low((char *) "SYS_FOREIGN");
+ sys_foreign = dict_table_get_low("SYS_FOREIGN");
sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
tuple = dtuple_create(heap2, 1);
@@ -1207,7 +1206,7 @@ dict_load_foreigns(
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
- sys_foreign = dict_table_get_low((char *) "SYS_FOREIGN");
+ sys_foreign = dict_table_get_low("SYS_FOREIGN");
if (sys_foreign == NULL) {
/* No foreign keys defined yet in this database */
diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c
index 936b06b1905..8f05475df47 100644
--- a/innobase/dict/dict0mem.c
+++ b/innobase/dict/dict0mem.c
@@ -87,9 +87,9 @@ dict_mem_table_create(
mutex_set_level(&(table->autoinc_mutex), SYNC_DICT_AUTOINC_MUTEX);
table->autoinc_inited = FALSE;
-#ifdef UNIV_DEBUG
+
table->magic_n = DICT_TABLE_MAGIC_N;
-#endif /* UNIV_DEBUG */
+
return(table);
}
@@ -205,9 +205,7 @@ dict_mem_index_create(
index->stat_n_diff_key_vals = NULL;
index->cached = FALSE;
-#ifdef UNIV_DEBUG
index->magic_n = DICT_INDEX_MAGIC_N;
-#endif /* UNIV_DEBUG */
return(index);
}
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index 28eea0ba188..59fbd6f785d 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -274,7 +274,7 @@ fil_get_space_id_for_table(
/*=======================*/
/* out: space id, ULINT_UNDEFINED if not
found */
- char* name); /* in: table name in the standard
+ const char* name); /* in: table name in the standard
'databasename/tablename' format */
@@ -463,8 +463,9 @@ fil_node_open_file(
ulint size_high;
ibool ret;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(system->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
ut_a(node->n_pending == 0);
ut_a(node->open == FALSE);
@@ -575,8 +576,9 @@ fil_try_to_close_file_in_LRU(
fil_system_t* system = fil_system;
fil_node_t* node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(system->mutex)));
-
+#endif /* UNIV_SYNC_DEBUG */
node = UT_LIST_GET_LAST(system->LRU);
if (print_info) {
@@ -630,7 +632,9 @@ fil_mutex_enter_and_prepare_for_io(
ulint count = 0;
ulint count2 = 0;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&(system->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
retry:
mutex_enter(&(system->mutex));
@@ -1311,13 +1315,12 @@ fil_write_lsn_and_arch_no_to_file(
ulint sum_of_sizes, /* in: combined size of previous files in
space, in database pages */
dulint lsn, /* in: lsn to write */
- ulint arch_log_no) /* in: archived log number to write */
+ ulint arch_log_no /* in: archived log number to write */
+ __attribute__((unused)))
{
byte* buf1;
byte* buf;
- UT_NOT_USED(arch_log_no);
-
buf1 = mem_alloc(2 * UNIV_PAGE_SIZE);
buf = ut_align(buf1, UNIV_PAGE_SIZE);
@@ -1396,17 +1399,17 @@ fil_read_flushed_lsn_and_arch_log_no(
os_file_t data_file, /* in: open data file */
ibool one_read_already, /* in: TRUE if min and max parameters
below already contain sensible data */
- dulint* min_flushed_lsn, /* in/out: */
+#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /* in/out: */
- dulint* max_flushed_lsn, /* in/out: */
- ulint* max_arch_log_no) /* in/out: */
+ ulint* max_arch_log_no, /* in/out: */
+#endif /* UNIV_LOG_ARCHIVE */
+ dulint* min_flushed_lsn, /* in/out: */
+ dulint* max_flushed_lsn) /* in/out: */
{
byte* buf;
byte* buf2;
dulint flushed_lsn;
- ulint arch_log_no = 0; /* since InnoDB does not archive
- its own logs under MySQL, this
- parameter is not relevant */
+
buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
/* Align the memory for a possible read from a raw device */
buf = ut_align(buf2, UNIV_PAGE_SIZE);
@@ -1420,9 +1423,10 @@ fil_read_flushed_lsn_and_arch_log_no(
if (!one_read_already) {
*min_flushed_lsn = flushed_lsn;
*max_flushed_lsn = flushed_lsn;
+#ifdef UNIV_LOG_ARCHIVE
*min_arch_log_no = arch_log_no;
*max_arch_log_no = arch_log_no;
-
+#endif /* UNIV_LOG_ARCHIVE */
return;
}
@@ -1432,12 +1436,14 @@ fil_read_flushed_lsn_and_arch_log_no(
if (ut_dulint_cmp(*max_flushed_lsn, flushed_lsn) < 0) {
*max_flushed_lsn = flushed_lsn;
}
+#ifdef UNIV_LOG_ARCHIVE
if (*min_arch_log_no > arch_log_no) {
*min_arch_log_no = arch_log_no;
}
if (*max_arch_log_no < arch_log_no) {
*max_arch_log_no = arch_log_no;
}
+#endif /* UNIV_LOG_ARCHIVE */
}
/*================ SINGLE-TABLE TABLESPACES ==========================*/
@@ -1507,33 +1513,31 @@ fil_decr_pending_ibuf_merges(
mutex_exit(&(system->mutex));
}
-/************************************************************
-Creates the database directory for a table if it does not exist yet. */
static
void
fil_create_directory_for_tablename(
/*===============================*/
- char* name) /* in: name in the standard 'databasename/tablename'
- format */
+ const char* name) /* in: name in the standard
+ 'databasename/tablename' format */
{
- char* ptr;
- char path[OS_FILE_MAX_PATH];
+ const char* namend;
+ char* path;
+ ulint len;
- sprintf(path, "%s/%s", fil_path_to_mysql_datadir, name);
+ len = strlen(fil_path_to_mysql_datadir);
+ namend = strchr(name, '/');
+ ut_a(namend);
+ path = mem_alloc(len + (namend - name) + 2);
- ptr = path + ut_strlen(path);
-
- while (*ptr != '/') {
- ptr--;
-
- ut_a(ptr >= path);
- }
-
- *ptr = '\0';
+ memcpy(path, fil_path_to_mysql_datadir, len);
+ path[len] = '/';
+ memcpy(path + len + 1, name, namend - name);
+ path[len + (namend - name) + 1] = 0;
srv_normalize_path_for_win(path);
ut_a(os_file_create_directory(path, FALSE));
+ mem_free(path);
}
#ifndef UNIV_HOTBACKUP
@@ -1615,10 +1619,10 @@ fil_op_log_parse_or_replay(
the tablespace in question; otherwise
ignored */
{
- ulint name_len;
- ulint new_name_len;
- char* name;
- char* new_name = NULL;
+ ulint name_len;
+ ulint new_name_len;
+ const char* name;
+ const char* new_name = NULL;
if (end_ptr < ptr + 2) {
@@ -1634,7 +1638,7 @@ fil_op_log_parse_or_replay(
return(NULL);
}
- name = (char*) ptr;
+ name = (const char*) ptr;
ptr += name_len;
@@ -1653,7 +1657,7 @@ fil_op_log_parse_or_replay(
return(NULL);
}
- new_name = (char*) ptr;
+ new_name = (const char*) ptr;
ptr += new_name_len;
}
@@ -1746,7 +1750,7 @@ fil_delete_tablespace(
fil_space_t* space;
fil_node_t* node;
ulint count = 0;
- char path[OS_FILE_MAX_PATH];
+ char* path;
ut_a(id != 0);
stop_ibuf_merges:
@@ -1803,11 +1807,8 @@ try_again:
}
ut_a(space);
- ut_a(strlen(space->name) < OS_FILE_MAX_PATH);
ut_a(space->n_pending_ibuf_merges == 0);
- strcpy(path, space->name);
-
space->is_being_deleted = TRUE;
ut_a(UT_LIST_GET_LEN(space->chain) == 1);
@@ -1831,6 +1832,8 @@ try_again:
goto try_again;
}
+ path = mem_strdup(space->name);
+
mutex_exit(&(system->mutex));
#ifndef UNIV_HOTBACKUP
/* Invalidate in the buffer pool all pages belonging to the
@@ -1848,29 +1851,30 @@ try_again:
if (success) {
success = os_file_delete(path);
+ }
- if (success) {
- /* Write a log record about the deletion of the .ibd
- file, so that ibbackup can replay it in the
- --apply-log phase. We use a dummy mtr and the familiar
- log write mechanism. */
+ if (success) {
#ifndef UNIV_HOTBACKUP
- {
- mtr_t mtr;
+ /* Write a log record about the deletion of the .ibd
+ file, so that ibbackup can replay it in the
+ --apply-log phase. We use a dummy mtr and the familiar
+ log write mechanism. */
+ mtr_t mtr;
- /* When replaying the operation in ibbackup, do not try
- to write any log record */
- mtr_start(&mtr);
+ /* When replaying the operation in ibbackup, do not try
+ to write any log record */
+ mtr_start(&mtr);
- fil_op_write_log(MLOG_FILE_DELETE, id, path,
- NULL, &mtr);
- mtr_commit(&mtr);
- }
+ fil_op_write_log(MLOG_FILE_DELETE, id, path, NULL, &mtr);
+ mtr_commit(&mtr);
#endif
- return(TRUE);
- }
+ mem_free(path);
+
+ return(TRUE);
}
+ mem_free(path);
+
return(FALSE);
}
@@ -1916,11 +1920,11 @@ fil_rename_tablespace_in_mem(
/* out: TRUE if success */
fil_space_t* space, /* in: tablespace memory object */
fil_node_t* node, /* in: file node of that tablespace */
- char* path) /* in: new name */
+ const char* path) /* in: new name */
{
fil_system_t* system = fil_system;
fil_space_t* space2;
- char* old_name = space->name;
+ const char* old_name = space->name;
HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(old_name),
space2, 0 == strcmp(old_name, space2->name));
@@ -1945,11 +1949,8 @@ fil_rename_tablespace_in_mem(
mem_free(space->name);
mem_free(node->name);
- space->name = mem_alloc(strlen(path) + 1);
- node->name = mem_alloc(strlen(path) + 1);
-
- strcpy(space->name, path);
- strcpy(node->name, path);
+ space->name = mem_strdup(path);
+ node->name = mem_strdup(path);
HASH_INSERT(fil_space_t, name_hash, system->name_hash,
ut_fold_string(path), space);
@@ -1957,6 +1958,29 @@ fil_rename_tablespace_in_mem(
}
/***********************************************************************
+Allocates a file name for a single-table tablespace.
+The string must be freed by caller with mem_free(). */
+static
+char*
+fil_make_ibd_name(
+/*==============*/
+ /* out, own: file name */
+ const char* name) /* in: table name */
+{
+ ulint namelen = strlen(name);
+ ulint dirlen = strlen(fil_path_to_mysql_datadir);
+ char* filename = mem_alloc(namelen + dirlen + sizeof "/.ibd");
+
+ memcpy(filename, fil_path_to_mysql_datadir, dirlen);
+ filename[dirlen] = '/';
+ memcpy(filename + dirlen + 1, name, namelen);
+ memcpy(filename + dirlen + namelen + 1, ".ibd", sizeof ".ibd");
+
+ srv_normalize_path_for_win(filename);
+ return(filename);
+}
+
+/***********************************************************************
Renames a single-table tablespace. The tablespace must be cached in the
tablespace memory cache. */
@@ -1978,14 +2002,14 @@ fil_rename_tablespace(
fil_space_t* space;
fil_node_t* node;
ulint count = 0;
- char* path = NULL;
+ char* path;
ibool old_name_was_specified = TRUE;
- char old_path[OS_FILE_MAX_PATH];
+ char* old_path;
ut_a(id != 0);
if (old_name == NULL) {
- old_name = (char*)"(name not specified)";
+ old_name = "(name not specified)";
old_name_was_specified = FALSE;
}
retry:
@@ -2059,48 +2083,33 @@ retry:
/* Check that the old name in the space is right */
if (old_name_was_specified) {
- ut_a(strlen(old_name) + strlen(fil_path_to_mysql_datadir)
- < OS_FILE_MAX_PATH - 10);
- sprintf(old_path, "%s/%s.ibd", fil_path_to_mysql_datadir,
- old_name);
- srv_normalize_path_for_win(old_path);
+ old_path = fil_make_ibd_name(old_name);
ut_a(strcmp(space->name, old_path) == 0);
ut_a(strcmp(node->name, old_path) == 0);
} else {
- sprintf(old_path, "%s", space->name);
+ old_path = mem_strdup(space->name);
}
/* Rename the tablespace and the node in the memory cache */
-
- ut_a(strlen(new_name) + strlen(fil_path_to_mysql_datadir)
- < OS_FILE_MAX_PATH - 10);
- path = mem_alloc(OS_FILE_MAX_PATH);
-
- sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, new_name);
-
- srv_normalize_path_for_win(path);
-
+ path = fil_make_ibd_name(new_name);
success = fil_rename_tablespace_in_mem(space, node, path);
- if (!success) {
-
- goto func_exit;
- }
-
- success = os_file_rename(old_path, path);
+ if (success) {
+ success = os_file_rename(old_path, path);
- if (!success) {
- /* We have to revert the changes we made to the tablespace
- memory cache */
+ if (!success) {
+ /* We have to revert the changes we made
+ to the tablespace memory cache */
- ut_a(fil_rename_tablespace_in_mem(space, node, old_path));
+ ut_a(fil_rename_tablespace_in_mem(space, node,
+ old_path));
+ }
}
-func_exit:
- if (path) {
- mem_free(path);
- }
+ mem_free(path);
+ mem_free(old_path);
+
space->stop_ios = FALSE;
mutex_exit(&(system->mutex));
@@ -2142,17 +2151,14 @@ fil_create_new_single_table_tablespace(
os_file_t file;
ibool ret;
ulint err;
+ byte* buf2;
byte* page;
ibool success;
- char path[OS_FILE_MAX_PATH];
+ char* path;
ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
- ut_a(strlen(tablename) + strlen(fil_path_to_mysql_datadir)
- < OS_FILE_MAX_PATH - 10);
- sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, tablename);
-
- srv_normalize_path_for_win(path);
+ path = fil_make_ibd_name(tablename);
file = os_file_create(path, OS_FILE_CREATE, OS_FILE_NORMAL,
OS_DATA_FILE, &ret);
@@ -2175,26 +2181,32 @@ fil_create_new_single_table_tablespace(
"InnoDB: resolve the problem by removing the file %s\n"
"InnoDB: under the 'datadir' of MySQL.\n", path);
+ mem_free(path);
return(DB_TABLESPACE_ALREADY_EXISTS);
}
if (err == OS_FILE_DISK_FULL) {
+ mem_free(path);
return(DB_OUT_OF_FILE_SPACE);
}
+ mem_free(path);
return(DB_ERROR);
}
- page = ut_malloc(UNIV_PAGE_SIZE);
+ buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
+ /* Align the memory for file i/o if we might have O_DIRECT set */
+ page = ut_align(buf2, UNIV_PAGE_SIZE);
ret = os_file_set_size(path, file, size * UNIV_PAGE_SIZE, 0);
if (!ret) {
- ut_free(page);
+ ut_free(buf2);
os_file_close(file);
os_file_delete(path);
+ mem_free(path);
return(DB_OUT_OF_FILE_SPACE);
}
@@ -2205,10 +2217,13 @@ fil_create_new_single_table_tablespace(
/* printf("Creating tablespace %s id %lu\n", path, *space_id); */
if (*space_id == ULINT_UNDEFINED) {
- ut_free(page);
+ ut_free(buf2);
+ error_exit:
os_file_close(file);
+ error_exit2:
os_file_delete(path);
+ mem_free(path);
return(DB_ERROR);
}
@@ -2229,16 +2244,12 @@ fil_create_new_single_table_tablespace(
ret = os_file_write(path, file, page, 0, 0, UNIV_PAGE_SIZE);
- ut_free(page);
+ ut_free(buf2);
if (!ret) {
fprintf(stderr,
"InnoDB: Error: could not write the first page to tablespace %s\n", path);
-
- os_file_close(file);
- os_file_delete(path);
-
- return(DB_ERROR);
+ goto error_exit;
}
ret = os_file_flush(file);
@@ -2246,27 +2257,19 @@ fil_create_new_single_table_tablespace(
if (!ret) {
fprintf(stderr,
"InnoDB: Error: file flush of tablespace %s failed\n", path);
-
- os_file_close(file);
- os_file_delete(path);
-
- return(DB_ERROR);
+ goto error_exit;
}
os_file_close(file);
if (*space_id == ULINT_UNDEFINED) {
- os_file_delete(path);
-
- return(DB_ERROR);
+ goto error_exit2;
}
success = fil_space_create(path, *space_id, FIL_TABLESPACE);
if (!success) {
- os_file_delete(path);
-
- return(DB_ERROR);
+ goto error_exit2;
}
fil_node_create(path, size, *space_id, FALSE);
@@ -2282,6 +2285,7 @@ fil_create_new_single_table_tablespace(
mtr_commit(&mtr);
}
#endif
+ mem_free(path);
return(DB_SUCCESS);
}
@@ -2308,6 +2312,7 @@ fil_reset_too_high_lsns(
os_file_t file;
char* filepath;
byte* page;
+ byte* buf2;
dulint flush_lsn;
ulint space_id;
ib_longlong file_size;
@@ -2315,25 +2320,21 @@ fil_reset_too_high_lsns(
ulint page_no;
ibool success;
- filepath = ut_malloc(OS_FILE_MAX_PATH);
-
- ut_a(strlen(name) < OS_FILE_MAX_PATH - 10);
-
- sprintf(filepath, "%s/%s.ibd", fil_path_to_mysql_datadir, name);
-
- srv_normalize_path_for_win(filepath);
+ filepath = fil_make_ibd_name(name);
file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN,
OS_FILE_READ_WRITE, &success);
if (!success) {
- ut_free(filepath);
+ mem_free(filepath);
return(FALSE);
}
/* Read the first page of the tablespace */
- page = ut_malloc(UNIV_PAGE_SIZE);
+ buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
+ /* Align the memory for file i/o if we might have O_DIRECT set */
+ page = ut_align(buf2, UNIV_PAGE_SIZE);
success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
if (!success) {
@@ -2420,8 +2421,8 @@ fil_reset_too_high_lsns(
success = os_file_flush(file);
func_exit:
os_file_close(file);
- ut_free(page);
- ut_free(filepath);
+ ut_free(buf2);
+ mem_free(filepath);
return(success);
}
@@ -2446,17 +2447,12 @@ fil_open_single_table_tablespace(
os_file_t file;
char* filepath;
ibool success;
+ byte* buf2;
byte* page;
ulint space_id;
ibool ret = TRUE;
- filepath = ut_malloc(OS_FILE_MAX_PATH);
-
- ut_a(strlen(name) < OS_FILE_MAX_PATH - 10);
-
- sprintf(filepath, "%s/%s.ibd", fil_path_to_mysql_datadir, name);
-
- srv_normalize_path_for_win(filepath);
+ filepath = fil_make_ibd_name(name);
file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN,
OS_FILE_READ_ONLY, &success);
@@ -2475,14 +2471,16 @@ fil_open_single_table_tablespace(
"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n"
"InnoDB: how to resolve the issue.\n");
- ut_free(filepath);
+ mem_free(filepath);
return(FALSE);
}
/* Read the first page of the tablespace */
- page = ut_malloc(UNIV_PAGE_SIZE);
+ buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
+ /* Align the memory for file i/o if we might have O_DIRECT set */
+ page = ut_align(buf2, UNIV_PAGE_SIZE);
success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
@@ -2519,12 +2517,34 @@ fil_open_single_table_tablespace(
fil_node_create(filepath, 0, space_id, FALSE);
func_exit:
os_file_close(file);
- ut_free(page);
- ut_free(filepath);
+ ut_free(buf2);
+ mem_free(filepath);
return(ret);
}
+#ifdef UNIV_HOTBACKUP
+/***********************************************************************
+Allocates a file name for an old version of a single-table tablespace.
+The string must be freed by caller with mem_free()! */
+static
+char*
+fil_make_ibbackup_old_name(
+/*=======================*/
+ /* out, own: file name */
+ const char* name) /* in: original file name */
+{
+ static const char suffix[] = "_ibbackup_old_vers_";
+ ulint len = strlen(name);
+ char* path = mem_alloc(len + (15 + sizeof suffix));
+
+ memcpy(path, name, len);
+ memcpy(path + len, suffix, (sizeof suffix) - 1);
+ ut_sprintf_timestamp_without_extra_chars(path + len + sizeof suffix);
+ return(path);
+}
+#endif /* UNIV_HOTBACKUP */
+
/************************************************************************
Opens an .ibd file and adds the associated single-table tablespace to the
InnoDB fil0fil.c data structures. */
@@ -2532,13 +2552,14 @@ static
void
fil_load_single_table_tablespace(
/*=============================*/
- char* dbname, /* in: database name */
- char* filename) /* in: file name (not a path), including the
- .ibd extension */
+ const char* dbname, /* in: database name */
+ const char* filename) /* in: file name (not a path),
+ including the .ibd extension */
{
os_file_t file;
char* filepath;
ibool success;
+ byte* buf2;
byte* page;
ulint space_id;
ulint size_low;
@@ -2547,10 +2568,8 @@ fil_load_single_table_tablespace(
#ifdef UNIV_HOTBACKUP
fil_space_t* space;
#endif
- filepath = ut_malloc(OS_FILE_MAX_PATH);
-
- ut_a(strlen(dbname) + strlen(filename)
- + strlen(fil_path_to_mysql_datadir) < OS_FILE_MAX_PATH - 100);
+ filepath = mem_alloc(strlen(dbname) + strlen(filename)
+ + strlen(fil_path_to_mysql_datadir) + 3);
sprintf(filepath, "%s/%s/%s", fil_path_to_mysql_datadir, dbname,
filename);
@@ -2564,11 +2583,30 @@ fil_load_single_table_tablespace(
fprintf(stderr,
"InnoDB: Error: could not open single-table tablespace file\n"
-"InnoDB: %s!", filepath);
-
- ut_free(filepath);
+"InnoDB: %s!\n"
+"InnoDB: We do not continue crash recovery, because the table will become\n"
+"InnoDB: corrupt if we cannot apply the log records in the InnoDB log to it.\n"
+"InnoDB: To fix the problem and start mysqld:\n"
+"InnoDB: 1) If there is a permission problem in the file and mysqld cannot\n"
+"InnoDB: open the file, you should modify the permissions.\n"
+"InnoDB: 2) If the table is not needed, or you can restore it from a backup,\n"
+"InnoDB: then you can remove the .ibd file, and InnoDB will do a normal\n"
+"InnoDB: crash recovery and ignore that table.\n"
+"InnoDB: 3) If the file system or the disk is broken, and you cannot remove\n"
+"InnoDB: the .ibd file, you can set innodb_force_recovery > 0 in my.cnf\n"
+"InnoDB: and force InnoDB to continue crash recovery here.\n", filepath);
+
+ mem_free(filepath);
+
+ if (srv_force_recovery > 0) {
+ fprintf(stderr,
+"InnoDB: innodb_force_recovery was set to %lu. Continuing crash recovery\n"
+"InnoDB: even though we cannot access the .ibd file of this table.\n",
+ srv_force_recovery);
+ return;
+ }
- return;
+ exit(1);
}
success = os_file_get_size(file, &size_low, &size_high);
@@ -2579,14 +2617,36 @@ fil_load_single_table_tablespace(
fprintf(stderr,
"InnoDB: Error: could not measure the size of single-table tablespace file\n"
-"InnoDB: %s!", filepath);
+"InnoDB: %s!\n"
+"InnoDB: We do not continue crash recovery, because the table will become\n"
+"InnoDB: corrupt if we cannot apply the log records in the InnoDB log to it.\n"
+"InnoDB: To fix the problem and start mysqld:\n"
+"InnoDB: 1) If there is a permission problem in the file and mysqld cannot\n"
+"InnoDB: access the file, you should modify the permissions.\n"
+"InnoDB: 2) If the table is not needed, or you can restore it from a backup,\n"
+"InnoDB: then you can remove the .ibd file, and InnoDB will do a normal\n"
+"InnoDB: crash recovery and ignore that table.\n"
+"InnoDB: 3) If the file system or the disk is broken, and you cannot remove\n"
+"InnoDB: the .ibd file, you can set innodb_force_recovery > 0 in my.cnf\n"
+"InnoDB: and force InnoDB to continue crash recovery here.\n", filepath);
os_file_close(file);
- ut_free(filepath);
+ mem_free(filepath);
- return;
+ if (srv_force_recovery > 0) {
+ fprintf(stderr,
+"InnoDB: innodb_force_recovery was set to %lu. Continuing crash recovery\n"
+"InnoDB: even though we cannot access the .ibd file of this table.\n",
+ srv_force_recovery);
+ return;
+ }
+
+ exit(1);
}
+ /* TODO: What to do in other cases where we cannot access an .ibd
+ file during a crash recovery? */
+
/* Every .ibd file is created >= 4 pages in size. Smaller files
cannot be ok. */
@@ -2599,14 +2659,16 @@ fil_load_single_table_tablespace(
(ulong) size_high,
(ulong) size_low, (ulong) (4 * UNIV_PAGE_SIZE));
os_file_close(file);
- ut_free(filepath);
+ mem_free(filepath);
return;
}
#endif
/* Read the first page of the tablespace if the size big enough */
- page = ut_malloc(UNIV_PAGE_SIZE);
+ buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
+ /* Align the memory for file i/o if we might have O_DIRECT set */
+ page = ut_align(buf2, UNIV_PAGE_SIZE);
if (size >= FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
@@ -2639,16 +2701,12 @@ fil_load_single_table_tablespace(
filepath, space_id, filepath, size);
os_file_close(file);
- new_path = ut_malloc(OS_FILE_MAX_PATH);
-
- sprintf(new_path, "%s_ibbackup_old_vers_", filepath);
- ut_sprintf_timestamp_without_extra_chars(
- new_path + ut_strlen(new_path));
+ new_path = fil_make_ibbackup_old_name(filepath);
ut_a(os_file_rename(filepath, new_path));
- ut_free(page);
- ut_free(filepath);
- ut_free(new_path);
+ ut_free(buf2);
+ mem_free(filepath);
+ mem_free(new_path);
return;
}
@@ -2676,18 +2734,15 @@ fil_load_single_table_tablespace(
space->name);
os_file_close(file);
- new_path = ut_malloc(OS_FILE_MAX_PATH);
+ new_path = fil_make_ibbackup_old_name(filepath);
- sprintf(new_path, "%s_ibbackup_old_vers_", filepath);
- ut_sprintf_timestamp_without_extra_chars(
- new_path + ut_strlen(new_path));
mutex_exit(&(fil_system->mutex));
ut_a(os_file_rename(filepath, new_path));
- ut_free(page);
- ut_free(filepath);
- ut_free(new_path);
+ ut_free(buf2);
+ mem_free(filepath);
+ mem_free(new_path);
return;
}
@@ -2706,8 +2761,8 @@ fil_load_single_table_tablespace(
fil_node_create(filepath, 0, space_id, FALSE);
func_exit:
os_file_close(file);
- ut_free(page);
- ut_free(filepath);
+ ut_free(buf2);
+ mem_free(filepath);
}
/************************************************************************
@@ -2724,7 +2779,8 @@ fil_load_single_table_tablespaces(void)
/* out: DB_SUCCESS or error number */
{
int ret;
- char* dbpath;
+ char* dbpath = NULL;
+ ulint dbpath_len = 100;
os_file_dir_t dir;
os_file_dir_t dbdir;
os_file_stat_t dbinfo;
@@ -2732,21 +2788,22 @@ fil_load_single_table_tablespaces(void)
/* The datadir of MySQL is always the default directory of mysqld */
- dir = os_file_opendir((char*) fil_path_to_mysql_datadir, TRUE);
+ dir = os_file_opendir(fil_path_to_mysql_datadir, TRUE);
if (dir == NULL) {
return(DB_ERROR);
}
- dbpath = ut_malloc(OS_FILE_MAX_PATH);
+ dbpath = mem_alloc(dbpath_len);
/* Scan all directories under the datadir. They are the database
directories of MySQL. */
- ret = os_file_readdir_next_file((char*) fil_path_to_mysql_datadir, dir,
+ ret = os_file_readdir_next_file(fil_path_to_mysql_datadir, dir,
&dbinfo);
while (ret == 0) {
+ ulint len;
/* printf("Looking at %s in datadir\n", dbinfo.name); */
if (dbinfo.type == OS_FILE_TYPE_FILE
@@ -2757,9 +2814,18 @@ fil_load_single_table_tablespaces(void)
/* We found a symlink or a directory; try opening it to see
if a symlink is a directory */
-
- ut_a(strlen(dbinfo.name) < OS_FILE_MAX_PATH - 10);
+ len = strlen(fil_path_to_mysql_datadir)
+ + strlen (dbinfo.name) + 2;
+ if (len > dbpath_len) {
+ dbpath_len = len;
+
+ if (dbpath) {
+ mem_free(dbpath);
+ }
+
+ dbpath = mem_alloc(dbpath_len);
+ }
sprintf(dbpath, "%s/%s", fil_path_to_mysql_datadir,
dbinfo.name);
srv_normalize_path_for_win(dbpath);
@@ -2805,11 +2871,11 @@ next_file_item:
}
next_datadir_item:
- ret = os_file_readdir_next_file((char*) fil_path_to_mysql_datadir,
+ ret = os_file_readdir_next_file(fil_path_to_mysql_datadir,
dir, &dbinfo);
}
- ut_free(dbpath);
+ mem_free(dbpath);
/* At the end of directory we should get 1 as the return value, -1
if there was an error */
@@ -2962,14 +3028,13 @@ fil_space_for_table_exists_in_mem(
fil_system_t* system = fil_system;
fil_space_t* namespace;
fil_space_t* space;
- char path[OS_FILE_MAX_PATH];
+ char* path;
ut_ad(system);
mutex_enter(&(system->mutex));
- sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, name);
- srv_normalize_path_for_win(path);
+ path = fil_make_ibd_name(name);
/* Look if there is a space with the same id */
@@ -2988,6 +3053,7 @@ fil_space_for_table_exists_in_mem(
space->mark = TRUE;
}
+ mem_free(path);
mutex_exit(&(system->mutex));
return(TRUE);
@@ -2995,6 +3061,7 @@ fil_space_for_table_exists_in_mem(
if (!print_error_if_does_not_exist) {
+ mem_free(path);
mutex_exit(&(system->mutex));
return(FALSE);
@@ -3024,6 +3091,7 @@ fil_space_for_table_exists_in_mem(
"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n"
"InnoDB: how to resolve the issue.\n");
+ mem_free(path);
mutex_exit(&(system->mutex));
return(FALSE);
@@ -3047,11 +3115,13 @@ fil_space_for_table_exists_in_mem(
"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n"
"InnoDB: how to resolve the issue.\n");
+ mem_free(path);
mutex_exit(&(system->mutex));
return(FALSE);
}
+ mem_free(path);
mutex_exit(&(system->mutex));
return(FALSE);
@@ -3066,20 +3136,19 @@ fil_get_space_id_for_table(
/*=======================*/
/* out: space id, ULINT_UNDEFINED if not
found */
- char* name) /* in: table name in the standard
+ const char* name) /* in: table name in the standard
'databasename/tablename' format */
{
fil_system_t* system = fil_system;
fil_space_t* namespace;
ulint id = ULINT_UNDEFINED;
- char path[OS_FILE_MAX_PATH];
+ char* path;
ut_ad(system);
mutex_enter(&(system->mutex));
- sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, name);
- srv_normalize_path_for_win(path);
+ path = fil_make_ibd_name(name);
/* Look if there is a space with the same name; the name is the
directory path to the file */
@@ -3091,6 +3160,8 @@ fil_get_space_id_for_table(
id = namespace->id;
}
+ mem_free(path);
+
mutex_exit(&(system->mutex));
return(id);
@@ -3219,7 +3290,7 @@ fil_extend_space_to_desired_size(
/************************************************************************
Extends all tablespaces to the size stored in the space header. During the
ibbackup --apply-log phase we extended the spaces on-demand so that log records
-could be appllied, but that may have left spaces still too small compared to
+could be applied, but that may have left spaces still too small compared to
the size stored in the space header. */
void
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index e7b97e88f32..34b6de76ff4 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -3476,8 +3476,7 @@ fseg_validate_low(
return(TRUE);
}
-
-#ifdef UNIV_DEBUG
+
/***********************************************************************
Validates a segment. */
@@ -3502,7 +3501,6 @@ fseg_validate(
return(ret);
}
-#endif /* UNIV_DEBUG */
/***********************************************************************
Writes info of a segment. */
@@ -3554,7 +3552,6 @@ fseg_print_low(
(ulong) n_used);
}
-#ifdef UNIV_DEBUG
/***********************************************************************
Writes info of a segment. */
@@ -3575,7 +3572,6 @@ fseg_print(
fseg_print_low(inode, mtr);
}
-#endif /* UNIV_DEBUG */
/***********************************************************************
Validates the file space system and its segments. */
diff --git a/innobase/fut/fut0lst.c b/innobase/fut/fut0lst.c
index 3d92aaba1ef..8deaa8adb3f 100644
--- a/innobase/fut/fut0lst.c
+++ b/innobase/fut/fut0lst.c
@@ -490,7 +490,6 @@ flst_validate(
return(TRUE);
}
-#ifdef UNIV_DEBUG
/************************************************************************
Prints info of a file-based list. */
@@ -517,4 +516,3 @@ flst_print(
(ulong) buf_frame_get_page_no(frame),
(ulong) (base - frame), (ulong) len);
}
-#endif /* UNIV_DEBUG */
diff --git a/innobase/ha/ha0ha.c b/innobase/ha/ha0ha.c
index e8082f016b9..ad1391ff83e 100644
--- a/innobase/ha/ha0ha.c
+++ b/innobase/ha/ha0ha.c
@@ -211,7 +211,9 @@ ha_search_and_update_if_found(
{
ha_node_t* node;
+#ifdef UNIV_SYNC_DEBUG
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
+#endif /* UNIV_SYNC_DEBUG */
node = ha_search_with_data(table, fold, data);
diff --git a/innobase/ha/hash0hash.c b/innobase/ha/hash0hash.c
index 372104e54b3..facdea66198 100644
--- a/innobase/ha/hash0hash.c
+++ b/innobase/ha/hash0hash.c
@@ -22,7 +22,6 @@ hash_mutex_enter(
hash_table_t* table, /* in: hash table */
ulint fold) /* in: fold */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
mutex_enter(hash_get_mutex(table, fold));
}
@@ -35,10 +34,41 @@ hash_mutex_exit(
hash_table_t* table, /* in: hash table */
ulint fold) /* in: fold */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
mutex_exit(hash_get_mutex(table, fold));
}
+/****************************************************************
+Reserves all the mutexes of a hash table, in an ascending order. */
+
+void
+hash_mutex_enter_all(
+/*=================*/
+ hash_table_t* table) /* in: hash table */
+{
+ ulint i;
+
+ for (i = 0; i < table->n_mutexes; i++) {
+
+ mutex_enter(table->mutexes + i);
+ }
+}
+
+/****************************************************************
+Releases all the mutexes of a hash table. */
+
+void
+hash_mutex_exit_all(
+/*================*/
+ hash_table_t* table) /* in: hash table */
+{
+ ulint i;
+
+ for (i = 0; i < table->n_mutexes; i++) {
+
+ mutex_exit(table->mutexes + i);
+ }
+}
+
/*****************************************************************
Creates a hash table with >= n array cells. The actual number of cells is
chosen to be a prime number slightly bigger than n. */
@@ -68,9 +98,7 @@ hash_create(
table->mutexes = NULL;
table->heaps = NULL;
table->heap = NULL;
-#ifdef UNIV_DEBUG
table->magic_n = HASH_TABLE_MAGIC_N;
-#endif /* UNIV_DEBUG */
/* Initialize the cell array */
@@ -91,7 +119,6 @@ hash_table_free(
/*============*/
hash_table_t* table) /* in, own: hash table */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_a(table->mutexes == NULL);
ut_free(table->array);
@@ -113,7 +140,6 @@ hash_create_mutexes(
ulint i;
ut_a(n_mutexes == ut_2_power_up(n_mutexes));
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t));
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index 9246bb03138..f05e69863a3 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -201,15 +201,13 @@ because ibuf merge is done to a page when it is read in, and it is
still physically like the index page even if the index would have been
dropped! So, there seems to be no problem. */
-#ifdef UNIV_DEBUG
/**********************************************************************
Validates the ibuf data structures when the caller owns ibuf_mutex. */
-static
+
ibool
ibuf_validate_low(void);
/*===================*/
/* out: TRUE if ok */
-#endif /* UNIV_DEBUG */
/**********************************************************************
Sets the flag in the current OS thread local storage denoting that it is
@@ -530,18 +528,18 @@ ibuf_data_init_for_space(
table = dict_mem_table_create(buf, space, 2);
- dict_mem_table_add_col(table,(char *) "PAGE_NO", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table,(char *) "TYPES", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, "PAGE_NO", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, "TYPES", DATA_BINARY, 0, 0, 0);
table->id = ut_dulint_add(DICT_IBUF_ID_MIN, space);
dict_table_add_to_cache(table);
- index = dict_mem_index_create(buf, (char *) "CLUST_IND", space,
+ index = dict_mem_index_create(buf, "CLUST_IND", space,
DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,2);
- dict_mem_index_add_field(index, (char *) "PAGE_NO", 0, 0);
- dict_mem_index_add_field(index, (char *) "TYPES", 0, 0);
+ dict_mem_index_add_field(index, "PAGE_NO", 0, 0);
+ dict_mem_index_add_field(index, "TYPES", 0, 0);
index->page_no = FSP_IBUF_TREE_ROOT_PAGE_NO;
@@ -3278,10 +3276,10 @@ leave_loop:
mem_heap_free(heap);
}
-#ifdef UNIV_DEBUG
+
/**********************************************************************
Validates the ibuf data structures when the caller owns ibuf_mutex. */
-static
+
ibool
ibuf_validate_low(void)
/*===================*/
@@ -3308,7 +3306,6 @@ ibuf_validate_low(void)
return(TRUE);
}
-#endif /* UNIV_DEBUG */
/**********************************************************************
Looks if the insert buffer is empty. */
diff --git a/innobase/include/Makefile.am b/innobase/include/Makefile.am
index 5ec70da97a2..102d25566da 100644
--- a/innobase/include/Makefile.am
+++ b/innobase/include/Makefile.am
@@ -43,7 +43,7 @@ noinst_HEADERS = btr0btr.h btr0btr.ic btr0cur.h btr0cur.ic \
row0purge.ic row0row.h row0row.ic row0sel.h row0sel.ic \
row0types.h row0uins.h row0uins.ic row0umod.h row0umod.ic \
row0undo.h row0undo.ic row0upd.h row0upd.ic row0vers.h \
- row0vers.ic srv0srv.h srv0srv.ic srv0start.h \
+ row0vers.ic srv0que.h srv0srv.h srv0srv.ic srv0start.h \
sync0arr.h sync0arr.ic sync0rw.h \
sync0rw.ic sync0sync.h sync0sync.ic sync0types.h \
thr0loc.h thr0loc.ic trx0purge.h trx0purge.ic trx0rec.h \
diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h
index e904db3272f..8606fcd2a5c 100644
--- a/innobase/include/btr0btr.h
+++ b/innobase/include/btr0btr.h
@@ -392,7 +392,6 @@ 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_DEBUG
/*****************************************************************
Prints size info of a B-tree. */
@@ -409,7 +408,6 @@ btr_print_tree(
dict_tree_t* tree, /* in: tree */
ulint width); /* in: print this many entries from start
and end */
-#endif /* UNIV_DEBUG */
/****************************************************************
Checks the size and number of fields in a record based on the definition of
the index. */
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index 9590fea1276..53599d03c73 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -54,11 +54,9 @@ Created 11/5/1995 Heikki Tuuri
#define BUF_KEEP_OLD 52
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 */
/************************************************************************
Creates the buffer pool. */
@@ -478,14 +476,12 @@ 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);
/*==============*/
-#endif /* UNIV_DEBUG */
/************************************************************************
Prints a page to stderr. */
@@ -897,7 +893,7 @@ struct buf_pool_struct{
ulint n_pend_reads; /* number of pending read operations */
- time_t last_printout_time; /* when buf_print_io was last time
+ time_t last_printout_time; /* when buf_print was last time
called */
ulint n_pages_read; /* number read operations */
ulint n_pages_written;/* number write operations */
@@ -912,10 +908,10 @@ struct buf_pool_struct{
ulint n_pages_awe_remapped; /* if AWE is enabled, the
number of remaps of blocks to
buffer frames */
- ulint n_page_gets_old;/* n_page_gets when buf_print_io was
+ ulint n_page_gets_old;/* n_page_gets when buf_print was
last time called: used to calculate
hit rate */
- ulint n_pages_read_old;/* n_pages_read when buf_print_io was
+ ulint n_pages_read_old;/* n_pages_read when buf_print was
last time called */
ulint n_pages_written_old;/* number write operations */
ulint n_pages_created_old;/* number of pages created in
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index 4d1173a0d7f..681a0ef000a 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -11,6 +11,10 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0rea.h"
#include "mtr0mtr.h"
+extern ulint buf_dbg_counter; /* This is used to insert validation
+ operations in execution in the
+ debug version */
+
/************************************************************************
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
@@ -508,7 +512,7 @@ void
buf_block_buf_fix_inc_debug(
/*========================*/
buf_block_t* block, /* in: block to bufferfix */
- char* file __attribute__ ((unused)), /* in: file name */
+ const char* file __attribute__ ((unused)), /* in: file name */
ulint line __attribute__ ((unused))) /* in: line */
{
#ifdef UNIV_SYNC_DEBUG
diff --git a/innobase/include/buf0flu.h b/innobase/include/buf0flu.h
index 6f39eef7210..1b40acaa269 100644
--- a/innobase/include/buf0flu.h
+++ b/innobase/include/buf0flu.h
@@ -97,7 +97,6 @@ buf_flush_ready_for_replace(
/* out: TRUE if can replace immediately */
buf_block_t* block); /* in: buffer control block, must be in state
BUF_BLOCK_FILE_PAGE and in the LRU list */
-#ifdef UNIV_DEBUG
/**********************************************************************
Validates the flush list. */
@@ -105,7 +104,6 @@ ibool
buf_flush_validate(void);
/*====================*/
/* out: TRUE if ok */
-#endif /* UNIV_DEBUG */
/* When buf_flush_free_margin is called, it tries to make this many blocks
available to replacement in the free list and at the end of the LRU list (to
diff --git a/innobase/include/buf0lru.h b/innobase/include/buf0lru.h
index 98aa0252e12..69a376f8cab 100644
--- a/innobase/include/buf0lru.h
+++ b/innobase/include/buf0lru.h
@@ -112,7 +112,6 @@ void
buf_LRU_make_block_old(
/*===================*/
buf_block_t* block); /* in: control block */
-#ifdef UNIV_DEBUG
/**************************************************************************
Validates the LRU list. */
@@ -125,7 +124,6 @@ Prints the LRU list. */
void
buf_LRU_print(void);
/*===============*/
-#endif /* UNIV_DEBUG */
#ifndef UNIV_NONINL
#include "buf0lru.ic"
diff --git a/innobase/include/data0data.h b/innobase/include/data0data.h
index e2de13d0520..2136de0f9b3 100644
--- a/innobase/include/data0data.h
+++ b/innobase/include/data0data.h
@@ -395,11 +395,9 @@ struct dtuple_struct {
UT_LIST_NODE_T(dtuple_t) tuple_list;
/* data tuples can be linked into a
list using this field */
-#ifdef UNIV_DEBUG
- ulint magic_n;
-#define DATA_TUPLE_MAGIC_N 65478679
-#endif /* UNIV_DEBUG */
+ ulint magic_n;
};
+#define DATA_TUPLE_MAGIC_N 65478679
/* A slot for a field in a big rec vector */
diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h
index 2138df97392..fe38a224a66 100644
--- a/innobase/include/data0type.h
+++ b/innobase/include/data0type.h
@@ -305,7 +305,7 @@ dtype_new_read_for_order_and_null_size(
/*===================================*/
dtype_t* type, /* in: type struct */
byte* buf); /* in: buffer for stored type order info */
-#ifdef UNIV_DEBUG
+
/*************************************************************************
Validates a data type structure. */
@@ -314,7 +314,6 @@ dtype_validate(
/*===========*/
/* out: TRUE if ok */
dtype_t* type); /* in: type struct to validate */
-#endif /* UNIV_DEBUG */
/*************************************************************************
Prints a data type structure. */
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index fe04359d6f1..ebb34f7dda0 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -325,19 +325,18 @@ dict_table_get_index_noninline(
dict_table_t* table, /* in: table */
const char* name); /* in: index name */
/**************************************************************************
-Prints a table data. */
+Prints a table definition. */
void
-dict_table_print_low(
-/*=================*/
+dict_table_print(
+/*=============*/
dict_table_t* table); /* in: table */
-#ifdef UNIV_DEBUG
/**************************************************************************
-Prints a table definition. */
+Prints a table data. */
void
-dict_table_print(
-/*=============*/
+dict_table_print_low(
+/*=================*/
dict_table_t* table); /* in: table */
/**************************************************************************
Prints a table data when we know the table name. */
@@ -346,7 +345,6 @@ void
dict_table_print_by_name(
/*=====================*/
const char* name);
-#endif /* UNIV_DEBUG */
/**************************************************************************
Outputs info on foreign keys of a table. */
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index f141ea9da09..3fc3e850987 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -188,12 +188,11 @@ struct dict_tree_struct{
the list; if the tree is of the mixed
type, the first index in the list is the
index of the cluster which owns the tree */
-#ifdef UNIV_DEBUG
ulint magic_n;/* magic number */
-#define DICT_TREE_MAGIC_N 7545676
-#endif /* UNIV_DEBUG */
};
+#define DICT_TREE_MAGIC_N 7545676
+
/* Data structure for an index */
struct dict_index_struct{
dulint id; /* id of the index */
@@ -238,10 +237,7 @@ struct dict_index_struct{
ulint stat_n_leaf_pages;
/* approximate number of leaf pages in the
index tree */
-#ifdef UNIV_DEBUG
ulint magic_n;/* magic number */
-#define DICT_INDEX_MAGIC_N 76789786
-#endif /* UNIV_DEBUG */
};
/* Data structure for a foreign key constraint; an example:
@@ -292,6 +288,9 @@ a foreign key constraint is enforced, therefore RESTRICT just means no flag */
#define DICT_FOREIGN_ON_DELETE_NO_ACTION 16
#define DICT_FOREIGN_ON_UPDATE_NO_ACTION 32
+
+#define DICT_INDEX_MAGIC_N 76789786
+
/* Data structure for a database table */
struct dict_table_struct{
dulint id; /* id of the table or cluster */
@@ -410,12 +409,10 @@ struct dict_table_struct{
inited; MySQL gets the init value by executing
SELECT MAX(auto inc column) */
ib_longlong autoinc;/* autoinc counter value to give to the
- next inserted row */
-#ifdef UNIV_DEBUG
+ next inserted row */
ulint magic_n;/* magic number */
-#define DICT_TABLE_MAGIC_N 76333786
-#endif /* UNIV_DEBUG */
};
+#define DICT_TABLE_MAGIC_N 76333786
#ifndef UNIV_NONINL
#include "dict0mem.ic"
diff --git a/innobase/include/fil0fil.h b/innobase/include/fil0fil.h
index b750e9b38f2..45549aee63c 100644
--- a/innobase/include/fil0fil.h
+++ b/innobase/include/fil0fil.h
@@ -248,10 +248,12 @@ fil_read_flushed_lsn_and_arch_log_no(
os_file_t data_file, /* in: open data file */
ibool one_read_already, /* in: TRUE if min and max parameters
below already contain sensible data */
- dulint* min_flushed_lsn, /* in/out: */
+#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /* in/out: */
- dulint* max_flushed_lsn, /* in/out: */
- ulint* max_arch_log_no); /* in/out: */
+ ulint* max_arch_log_no, /* in/out: */
+#endif /* UNIV_LOG_ARCHIVE */
+ dulint* min_flushed_lsn, /* in/out: */
+ dulint* max_flushed_lsn); /* in/out: */
/***********************************************************************
Increments the count of pending insert buffer page merges, if space is not
being deleted. */
diff --git a/innobase/include/fsp0fsp.h b/innobase/include/fsp0fsp.h
index 20f4f4c2abd..2fcde882df7 100644
--- a/innobase/include/fsp0fsp.h
+++ b/innobase/include/fsp0fsp.h
@@ -332,7 +332,6 @@ void
fsp_print(
/*======*/
ulint space); /* in: space id */
-#ifdef UNIV_DEBUG
/***********************************************************************
Validates a segment. */
@@ -350,7 +349,6 @@ fseg_print(
/*=======*/
fseg_header_t* header, /* in: segment header */
mtr_t* mtr); /* in: mtr */
-#endif /* UNIV_DEBUG */
/* Flags for fsp_reserve_free_extents */
#define FSP_NORMAL 1000000
diff --git a/innobase/include/fut0lst.h b/innobase/include/fut0lst.h
index 3f679d61ab5..5427e2248da 100644
--- a/innobase/include/fut0lst.h
+++ b/innobase/include/fut0lst.h
@@ -181,7 +181,6 @@ flst_validate(
/* out: TRUE if ok */
flst_base_node_t* base, /* in: pointer to base node of list */
mtr_t* mtr1); /* in: mtr */
-#ifdef UNIV_DEBUG
/************************************************************************
Prints info of a file-based list. */
@@ -190,7 +189,7 @@ flst_print(
/*=======*/
flst_base_node_t* base, /* in: pointer to base node of list */
mtr_t* mtr); /* in: mtr */
-#endif /* UNIV_DEBUG */
+
#ifndef UNIV_NONINL
#include "fut0lst.ic"
diff --git a/innobase/include/hash0hash.h b/innobase/include/hash0hash.h
index 79efe016324..51315e40875 100644
--- a/innobase/include/hash0hash.h
+++ b/innobase/include/hash0hash.h
@@ -283,6 +283,21 @@ hash_mutex_exit(
/*============*/
hash_table_t* table, /* in: hash table */
ulint fold); /* in: fold */
+/****************************************************************
+Reserves all the mutexes of a hash table, in an ascending order. */
+
+void
+hash_mutex_enter_all(
+/*=================*/
+ hash_table_t* table); /* in: hash table */
+/****************************************************************
+Releases all the mutexes of a hash table. */
+
+void
+hash_mutex_exit_all(
+/*================*/
+ hash_table_t* table); /* in: hash table */
+
struct hash_cell_struct{
void* node; /* hash chain node, NULL if none */
@@ -303,12 +318,11 @@ struct hash_table_struct {
memory heaps; there are then n_mutexes many of
these heaps */
mem_heap_t* heap;
-#ifdef UNIV_DEBUG
ulint magic_n;
-#define HASH_TABLE_MAGIC_N 76561114
-#endif /* UNIV_DEBUG */
};
+#define HASH_TABLE_MAGIC_N 76561114
+
#ifndef UNIV_NONINL
#include "hash0hash.ic"
#endif
diff --git a/innobase/include/hash0hash.ic b/innobase/include/hash0hash.ic
index 1b9acfa2f34..0d713140c13 100644
--- a/innobase/include/hash0hash.ic
+++ b/innobase/include/hash0hash.ic
@@ -18,7 +18,6 @@ hash_get_nth_cell(
hash_table_t* table, /* in: hash table */
ulint n) /* in: cell index */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(n < table->n_cells);
return(table->array + n);
@@ -33,7 +32,6 @@ hash_get_n_cells(
/* out: number of cells */
hash_table_t* table) /* in: table */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
return(table->n_cells);
}
@@ -47,7 +45,6 @@ hash_calc_hash(
ulint fold, /* in: folded value */
hash_table_t* table) /* in: hash table */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
return(ut_hash_ulint(fold, table->n_cells));
}
@@ -61,7 +58,6 @@ hash_get_mutex_no(
hash_table_t* table, /* in: hash table */
ulint fold) /* in: fold */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
return(ut_2pow_remainder(fold, table->n_mutexes));
}
@@ -75,7 +71,6 @@ hash_get_nth_heap(
hash_table_t* table, /* in: hash table */
ulint i) /* in: index of the heap */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(i < table->n_mutexes);
return(table->heaps[i]);
@@ -93,8 +88,6 @@ hash_get_heap(
{
ulint i;
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
-
if (table->heap) {
return(table->heap);
}
@@ -114,7 +107,6 @@ hash_get_nth_mutex(
hash_table_t* table, /* in: hash table */
ulint i) /* in: index of the mutex */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(i < table->n_mutexes);
return(table->mutexes + i);
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index b1f9a10ee05..9c5f35c6674 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -19,9 +19,7 @@ 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;
@@ -475,7 +473,6 @@ lock_check_trx_id_sanity(
dict_index_t* index, /* in: clustered index */
ibool has_kernel_mutex);/* in: TRUE if the caller owns the
kernel mutex */
-#ifdef UNIV_DEBUG
/*************************************************************************
Validates the lock queue on a single record. */
@@ -485,7 +482,6 @@ lock_rec_queue_validate(
/* out: TRUE if ok */
rec_t* rec, /* in: record to look at */
dict_index_t* index); /* in: index, or NULL if not known */
-#endif /* UNIV_DEBUG */
/*************************************************************************
Prints info of a table lock. */
@@ -509,7 +505,6 @@ void
lock_print_info(
/*============*/
FILE* file); /* in: file where to print */
-#ifdef UNIV_DEBUG
/*************************************************************************
Validates the lock queue on a table. */
@@ -534,7 +529,6 @@ ibool
lock_validate(void);
/*===============*/
/* out: TRUE if ok */
-#endif /* UNIV_DEBUG */
/* The lock system */
extern lock_sys_t* lock_sys;
diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h
index 4badd2cd7b3..d14a116072d 100644
--- a/innobase/include/log0log.h
+++ b/innobase/include/log0log.h
@@ -18,9 +18,7 @@ typedef struct log_struct log_t;
typedef struct log_group_struct log_group_t;
extern ibool log_do_write;
-#ifdef UNIV_LOG_DEBUG
extern ibool log_debug_writes;
-#endif /* UNIV_LOG_DEBUG */
/* Wait modes for log_write_up_to */
#define LOG_NO_WAIT 91
@@ -114,20 +112,6 @@ dulint
log_get_lsn(void);
/*=============*/
/* out: current lsn */
-/****************************************************************************
-Gets the online backup lsn. */
-UNIV_INLINE
-dulint
-log_get_online_backup_lsn_low(void);
-/*===============================*/
-/****************************************************************************
-Gets the online backup state. */
-UNIV_INLINE
-ibool
-log_get_online_backup_state_low(void);
-/*=================================*/
- /* out: online backup state, the caller must
- own the log_sys mutex */
/**********************************************************
Initializes the log. */
@@ -326,20 +310,6 @@ log_archived_file_name_gen(
char* buf, /* in: buffer where to write */
ulint id, /* in: group id */
ulint file_no);/* in: file number */
-/**********************************************************
-Switches the database to the online backup state. */
-
-ulint
-log_switch_backup_state_on(void);
-/*============================*/
- /* out: DB_SUCCESS or DB_ERROR */
-/**********************************************************
-Switches the online backup state off. */
-
-ulint
-log_switch_backup_state_off(void);
-/*=============================*/
- /* out: DB_SUCCESS or DB_ERROR */
/************************************************************************
Checks that there is enough free space in the log to start a new query step.
Flushes the log buffer or makes a new checkpoint if necessary. NOTE: this
@@ -719,13 +689,11 @@ struct log_struct{
ulint max_buf_free; /* recommended maximum value of
buf_free, after which the buffer is
flushed */
-#ifdef UNIV_LOG_DEBUG
ulint old_buf_free; /* value of buf free when log was
last time opened; only in the debug
version */
dulint old_lsn; /* value of lsn when log was last time
opened; only in the debug version */
-#endif /* UNIV_LOG_DEBUG */
ibool check_flush_or_checkpoint;
/* this is set to TRUE when there may
be need to flush the log buffer, or
@@ -878,13 +846,6 @@ struct log_struct{
os_event_t archiving_on; /* if archiving has been stopped,
a thread can wait for this event to
become signaled */
- /* Fields involved in online backups */
- ibool online_backup_state;
- /* TRUE if the database is in the
- online backup state */
- dulint online_backup_lsn;
- /* lsn when the state was changed to
- the online backup state */
};
#define LOG_ARCH_ON 71
diff --git a/innobase/include/log0log.ic b/innobase/include/log0log.ic
index e273b6a292b..ca7531783a2 100644
--- a/innobase/include/log0log.ic
+++ b/innobase/include/log0log.ic
@@ -10,7 +10,6 @@ Created 12/9/1995 Heikki Tuuri
#include "mach0data.h"
#include "mtr0mtr.h"
-#ifdef UNIV_LOG_DEBUG
/**********************************************************
Checks by parsing that the catenated log segment for a single mtr is
consistent. */
@@ -22,7 +21,6 @@ log_check_log_recs(
in the log_sys->buf log buffer */
ulint len, /* in: segment length in bytes */
dulint buf_start_lsn); /* in: buffer start lsn */
-#endif /* UNIV_LOG_DEBUG */
/****************************************************************
Gets a log block flush bit. */
@@ -318,8 +316,7 @@ log_reserve_and_write_fast(
data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE;
- if (log->online_backup_state
- || (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE)) {
+ if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
/* The string does not fit within the current log block
or the log block would become full */
@@ -403,36 +400,3 @@ log_free_check(void)
log_check_margins();
}
}
-
-/****************************************************************************
-Gets the online backup lsn. */
-UNIV_INLINE
-dulint
-log_get_online_backup_lsn_low(void)
-/*===============================*/
- /* out: online_backup_lsn, the caller must
- own the log_sys mutex */
-{
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(log_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
- ut_ad(log_sys->online_backup_state);
-
- return(log_sys->online_backup_lsn);
-}
-
-/****************************************************************************
-Gets the online backup state. */
-UNIV_INLINE
-ibool
-log_get_online_backup_state_low(void)
-/*=================================*/
- /* out: online backup state, the caller must
- own the log_sys mutex */
-{
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(log_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- return(log_sys->online_backup_state);
-}
diff --git a/innobase/include/log0recv.h b/innobase/include/log0recv.h
index c972c3ce977..658df4d5586 100644
--- a/innobase/include/log0recv.h
+++ b/innobase/include/log0recv.h
@@ -15,7 +15,9 @@ Created 9/20/1997 Heikki Tuuri
#include "hash0hash.h"
#include "log0log.h"
+#ifdef UNIV_HOTBACKUP
extern ibool recv_replay_file_ops;
+#endif /* UNIV_HOTBACKUP */
/***********************************************************************
Reads the checkpoint info needed in hot backup. */
@@ -134,20 +136,25 @@ recv_reset_logs(
dulint lsn, /* in: reset to this lsn rounded up to
be divisible by OS_FILE_LOG_BLOCK_SIZE,
after which we add LOG_BLOCK_HDR_SIZE */
+#ifdef UNIV_LOG_ARCHIVE
ulint arch_log_no, /* in: next archived log file number */
+#endif /* UNIV_LOG_ARCHIVE */
ibool new_logs_created);/* in: TRUE if resetting logs is done
at the log creation; FALSE if it is done
after archive recovery */
+#ifdef UNIV_HOTBACKUP
/**********************************************************
Creates new log files after a backup has been restored. */
void
recv_reset_log_files_for_backup(
/*============================*/
- char* log_dir, /* in: log file directory path */
- ulint n_log_files, /* in: number of log files */
- ulint log_file_size, /* in: log file size */
- dulint lsn); /* in: new start lsn */
+ const char* log_dir, /* in: log file directory path */
+ ulint n_log_files, /* in: number of log files */
+ ulint log_file_size, /* in: log file size */
+ dulint lsn); /* in: new start lsn, must be
+ divisible by OS_FILE_LOG_BLOCK_SIZE */
+#endif /* UNIV_HOTBACKUP */
/************************************************************
Creates the recovery system. */
@@ -185,6 +192,7 @@ void
recv_apply_log_recs_for_backup(void);
/*================================*/
#endif
+#ifdef UNIV_LOG_ARCHIVE
/************************************************************
Recovers from archived log files, and also from log files, if they exist. */
@@ -205,6 +213,7 @@ Completes recovery from archive. */
void
recv_recovery_from_archive_finish(void);
/*===================================*/
+#endif /* UNIV_LOG_ARCHIVE */
/***********************************************************************
Checks that a replica of a space is identical to the original space. */
@@ -333,7 +342,9 @@ extern ibool recv_no_ibuf_operations;
extern ibool recv_needed_recovery;
extern ibool recv_lsn_checks_on;
+#ifdef UNIV_HOTBACKUP
extern ibool recv_is_making_a_backup;
+#endif /* UNIV_HOTBACKUP */
extern ulint recv_max_parsed_page_no;
/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
diff --git a/innobase/include/mach0data.h b/innobase/include/mach0data.h
index f28c9422670..7ad760cd60f 100644
--- a/innobase/include/mach0data.h
+++ b/innobase/include/mach0data.h
@@ -89,7 +89,7 @@ mach_read_from_4(
/* out: ulint integer */
byte* b); /* in: pointer to four bytes */
/*************************************************************
-Writes a ulint in a compressed form. */
+Writes a ulint in a compressed form (1..5 bytes). */
UNIV_INLINE
ulint
mach_write_compressed(
@@ -168,7 +168,7 @@ mach_read_from_8(
/* out: dulint integer */
byte* b); /* in: pointer to 8 bytes */
/*************************************************************
-Writes a dulint in a compressed form. */
+Writes a dulint in a compressed form (5..9 bytes). */
UNIV_INLINE
ulint
mach_dulint_write_compressed(
@@ -193,7 +193,7 @@ mach_dulint_read_compressed(
/* out: read dulint */
byte* b); /* in: pointer to memory from where to read */
/*************************************************************
-Writes a dulint in a compressed form. */
+Writes a dulint in a compressed form (1..11 bytes). */
UNIV_INLINE
ulint
mach_dulint_write_much_compressed(
diff --git a/innobase/include/mach0data.ic b/innobase/include/mach0data.ic
index 3ccdcf1dc0a..3ffb9baa344 100644
--- a/innobase/include/mach0data.ic
+++ b/innobase/include/mach0data.ic
@@ -366,7 +366,7 @@ mach_read_from_6(
}
/*************************************************************
-Writes a dulint in a compressed form. */
+Writes a dulint in a compressed form (5..9 bytes). */
UNIV_INLINE
ulint
mach_dulint_write_compressed(
@@ -422,7 +422,7 @@ mach_dulint_read_compressed(
}
/*************************************************************
-Writes a dulint in a compressed form. */
+Writes a dulint in a compressed form (1..11 bytes). */
UNIV_INLINE
ulint
mach_dulint_write_much_compressed(
diff --git a/innobase/include/mem0dbg.h b/innobase/include/mem0dbg.h
index 61c66cc218c..96f30842df6 100644
--- a/innobase/include/mem0dbg.h
+++ b/innobase/include/mem0dbg.h
@@ -31,7 +31,6 @@ check fields at the both ends of the field. */
#define MEM_SPACE_NEEDED(N) ut_calc_align((N), UNIV_MEM_ALIGNMENT)
#endif
-#ifdef UNIV_DEBUG
/*******************************************************************
Checks a memory heap for consistency and prints the contents if requested.
Outputs the sum of sizes of buffers given to the user (only in
@@ -61,7 +60,6 @@ mem_heap_validate_or_print(
ulint* n_blocks); /* out: number of blocks in the heap,
if a NULL pointer is passed as this
argument, it is ignored */
-#endif /* UNIV_DEBUG */
#ifdef UNIV_MEM_DEBUG
/******************************************************************
Prints the contents of a memory heap. */
@@ -71,7 +69,6 @@ mem_heap_print(
/*===========*/
mem_heap_t* heap); /* in: memory heap */
#endif /* UNIV_MEM_DEBUG */
-#ifdef UNIV_DEBUG
/******************************************************************
Checks that an object is a memory heap (or a block of it) */
@@ -88,7 +85,6 @@ mem_heap_validate(
/*==============*/
/* out: TRUE if ok */
mem_heap_t* heap); /* in: memory heap */
-#endif /* UNIV_DEBUG */
#ifdef UNIV_MEM_DEBUG
/*********************************************************************
TRUE if no memory is currently allocated. */
@@ -120,4 +116,17 @@ void
mem_analyze_corruption(
/*===================*/
byte* ptr); /* in: pointer to place of possible corruption */
+/*********************************************************************
+Prints information of dynamic memory usage and currently allocated memory
+heaps or buffers. Can only be used in the debug version. */
+void
+mem_print_info(void);
+/*================*/
+/*********************************************************************
+Prints information of dynamic memory usage and currently allocated memory
+heaps or buffers since the last ..._print_info or..._print_new_info. */
+
+void
+mem_print_new_info(void);
+/*====================*/
diff --git a/innobase/include/mem0dbg.ic b/innobase/include/mem0dbg.ic
index 2e79c814529..7ce5f6f1ba5 100644
--- a/innobase/include/mem0dbg.ic
+++ b/innobase/include/mem0dbg.ic
@@ -54,9 +54,8 @@ void
mem_hash_insert(
/*============*/
mem_heap_t* heap, /* in: the created heap */
- char* file_name, /* in: file name of creation */
+ const char* file_name, /* in: file name of creation */
ulint line); /* in: line where created */
-#ifdef UNIV_MEM_DEBUG
/*******************************************************************
Removes a memory heap (which is going to be freed by the caller)
from the list of live memory heaps. Returns the size of the heap
@@ -70,9 +69,9 @@ void
mem_hash_remove(
/*============*/
mem_heap_t* heap, /* in: the heap to be freed */
- char* file_name, /* in: file name of freeing */
+ const char* file_name, /* in: file name of freeing */
ulint line); /* in: line where freed */
-#endif /* UNIV_MEM_DEBUG */
+
void
mem_field_header_set_len(byte* field, ulint len);
diff --git a/innobase/include/mem0mem.h b/innobase/include/mem0mem.h
index 18bffe5732e..cd01ac77bf3 100644
--- a/innobase/include/mem0mem.h
+++ b/innobase/include/mem0mem.h
@@ -261,18 +261,6 @@ mem_free_func(
const char* file_name, /* in: file name where created */
ulint line /* in: line where created */
);
-/*******************************************************************
-Implements realloc. */
-UNIV_INLINE
-void*
-mem_realloc(
-/*========*/
- /* out, own: free storage,
- NULL if did not succeed */
- void* buf, /* in: pointer to an old buffer */
- ulint n, /* in: desired number of bytes */
- const char* file_name, /* in: file name where called */
- ulint line); /* in: line where called */
/**************************************************************************
Duplicates a NUL-terminated string. */
diff --git a/innobase/include/mem0mem.ic b/innobase/include/mem0mem.ic
index df3dbf9b576..d97b7d6c4dd 100644
--- a/innobase/include/mem0mem.ic
+++ b/innobase/include/mem0mem.ic
@@ -562,24 +562,6 @@ mem_heap_get_size(
return(size);
}
-/*******************************************************************
-Implements realloc. */
-UNIV_INLINE
-void*
-mem_realloc(
-/*========*/
- /* out, own: free storage,
- NULL if did not succeed */
- void* buf, /* in: pointer to an old buffer */
- ulint n, /* in: desired number of bytes */
- const char* file_name, /* in: file name where called */
- ulint line) /* in: line where called */
-{
- mem_free(buf);
-
- return(mem_alloc_func(n, file_name, line));
-}
-
/**************************************************************************
Duplicates a NUL-terminated string. */
UNIV_INLINE
diff --git a/innobase/include/mem0pool.h b/innobase/include/mem0pool.h
index 95cf19676fb..43707bd5f61 100644
--- a/innobase/include/mem0pool.h
+++ b/innobase/include/mem0pool.h
@@ -83,7 +83,6 @@ Releases the mem pool mutex. */
void
mem_pool_mutex_exit(void);
/*=====================*/
-#ifdef UNIV_DEBUG
/************************************************************************
Validates a memory pool. */
@@ -100,7 +99,7 @@ mem_pool_print_info(
/*================*/
FILE* outfile,/* in: output file to write to */
mem_pool_t* pool); /* in: memory pool */
-#endif /* UNIV_DEBUG */
+
#ifndef UNIV_NONINL
#include "mem0pool.ic"
diff --git a/innobase/include/mtr0log.h b/innobase/include/mtr0log.h
index f50c1dfcb6a..41be168a371 100644
--- a/innobase/include/mtr0log.h
+++ b/innobase/include/mtr0log.h
@@ -121,7 +121,9 @@ mlog_close(
mtr_t* mtr, /* in: mtr */
byte* ptr); /* in: buffer space from ptr up was not used */
/************************************************************
-Writes the initial part of a log record. */
+Writes the initial part of a log record (3..11 bytes).
+If the implementation of this function is changed, all
+size parameters to mlog_open() should be adjusted accordingly! */
UNIV_INLINE
byte*
mlog_write_initial_log_record_fast(
diff --git a/innobase/include/mtr0log.ic b/innobase/include/mtr0log.ic
index c02e0a96a81..aa3f945c202 100644
--- a/innobase/include/mtr0log.ic
+++ b/innobase/include/mtr0log.ic
@@ -137,7 +137,9 @@ mlog_catenate_dulint_compressed(
}
/************************************************************
-Writes the initial part of a log record. */
+Writes the initial part of a log record (3..11 bytes).
+If the implementation of this function is changed, all
+size parameters to mlog_open() should be adjusted accordingly! */
UNIV_INLINE
byte*
mlog_write_initial_log_record_fast(
diff --git a/innobase/include/mtr0mtr.h b/innobase/include/mtr0mtr.h
index f6dfe23bc41..e8c68a91dad 100644
--- a/innobase/include/mtr0mtr.h
+++ b/innobase/include/mtr0mtr.h
@@ -82,7 +82,7 @@ flag value must give the length also! */
predefined minimum record */
#define MLOG_IBUF_BITMAP_INIT ((byte)27) /* initialize an ibuf bitmap
page */
-#define MLOG_FULL_PAGE ((byte)28) /* full contents of a page */
+/*#define MLOG_FULL_PAGE ((byte)28) full contents of a page */
#define MLOG_INIT_FILE_PAGE ((byte)29) /* this means that a file page
is taken into use and the prior
contents of the page should be
@@ -236,16 +236,6 @@ mtr_memo_release(
mtr_t* mtr, /* in: mtr */
void* object, /* in: object */
ulint type); /* in: object type: MTR_MEMO_S_LOCK, ... */
-/****************************************************************
-Parses a log record which contains the full contents of a page. */
-
-byte*
-mtr_log_parse_full_page(
-/*====================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
/**************************************************************
Checks if memo contains the given item. */
UNIV_INLINE
@@ -256,7 +246,6 @@ mtr_memo_contains(
mtr_t* mtr, /* in: mtr */
void* object, /* in: object to search */
ulint type); /* in: type of object */
-#ifdef UNIV_DEBUG
/*************************************************************
Prints info of an mtr handle. */
@@ -264,7 +253,6 @@ void
mtr_print(
/*======*/
mtr_t* mtr); /* in: mtr */
-#endif /* UNIV_DEBUG */
/*######################################################################*/
#define MTR_BUF_MEMO_SIZE 200 /* number of slots in memo */
@@ -297,12 +285,7 @@ struct mtr_memo_slot_struct{
/* Mini-transaction handle and buffer */
struct mtr_struct{
-#ifdef UNIV_DEBUG
ulint state; /* MTR_ACTIVE, MTR_COMMITTING, MTR_COMMITTED */
-#define MTR_ACTIVE 12231
-#define MTR_COMMITTING 56456
-#define MTR_COMMITTED 34676
-#endif /* UNIV_DEBUG */
dyn_array_t memo; /* memo stack for locks etc. */
dyn_array_t log; /* mini-transaction log */
ibool modifications;
@@ -317,12 +300,15 @@ struct mtr_struct{
this mtr */
dulint end_lsn;/* end lsn of the possible log entry for
this mtr */
-#ifdef UNIV_DEBUG
ulint magic_n;
-#define MTR_MAGIC_N 54551
-#endif /* UNIV_DEBUG */
};
+#define MTR_MAGIC_N 54551
+
+#define MTR_ACTIVE 12231
+#define MTR_COMMITTING 56456
+#define MTR_COMMITTED 34676
+
#ifndef UNIV_NONINL
#include "mtr0mtr.ic"
#endif
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index 930390241d3..6549a3748df 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -169,6 +169,13 @@ void
os_io_init_simple(void);
/*===================*/
/***************************************************************************
+Creates a temporary file. In case of error, causes abnormal termination. */
+
+FILE*
+os_file_create_tmpfile(void);
+/*========================*/
+ /* out: temporary file handle (never NULL) */
+/***************************************************************************
The os_file_opendir() function opens a directory stream corresponding to the
directory named by the dirname argument. The directory stream is positioned
at the first entry. In both Unix and Windows we automatically skip the '.'
diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h
index 6603229e524..c00d28baf60 100644
--- a/innobase/include/os0thread.h
+++ b/innobase/include/os0thread.h
@@ -78,6 +78,10 @@ os_thread_create(
function */
os_thread_id_t* thread_id); /* out: id of the created
thread */
+int
+os_thread_join(
+/*=============*/
+ os_thread_id_t thread_id); /* in: id of the thread to join */
/*********************************************************************
Exits the current thread. */
diff --git a/innobase/include/pars0opt.h b/innobase/include/pars0opt.h
index ac0e885d05a..d091c3ee2d0 100644
--- a/innobase/include/pars0opt.h
+++ b/innobase/include/pars0opt.h
@@ -43,7 +43,6 @@ opt_find_all_cols(
to add new found columns */
plan_t* plan, /* in: plan or NULL */
que_node_t* exp); /* in: expression or condition */
-#ifdef UNIV_SQL_DEBUG
/************************************************************************
Prints info of a query plan. */
@@ -51,7 +50,6 @@ void
opt_print_query_plan(
/*=================*/
sel_node_t* sel_node); /* in: select node */
-#endif /* UNIV_SQL_DEBUG */
#ifndef UNIV_NONINL
#include "pars0opt.ic"
diff --git a/innobase/include/que0que.h b/innobase/include/que0que.h
index a438116781f..e1874edcaf2 100644
--- a/innobase/include/que0que.h
+++ b/innobase/include/que0que.h
@@ -152,6 +152,17 @@ que_run_threads(
/*============*/
que_thr_t* thr); /* in: query thread which is run initially */
/**************************************************************************
+After signal handling is finished, returns control to a query graph error
+handling routine. (Currently, just returns the control to the root of the
+graph so that the graph can communicate an error message to the client.) */
+
+void
+que_fork_error_handle(
+/*==================*/
+ trx_t* trx, /* in: trx */
+ que_t* fork); /* in: query graph which was run before signal
+ handling started, NULL not allowed */
+/**************************************************************************
Handles an SQL error noticed during query thread execution. At the moment,
does nothing! */
@@ -170,15 +181,18 @@ a single worker thread to execute it. This function should be used to end
the wait state of a query thread waiting for a lock or a stored procedure
completion. */
-que_thr_t*
+void
que_thr_end_wait(
/*=============*/
- /* out: next query thread to run;
- NULL if none */
- que_thr_t* thr); /* in: query thread in the
+ que_thr_t* thr, /* in: query thread in the
QUE_THR_LOCK_WAIT,
or QUE_THR_PROCEDURE_WAIT, or
QUE_THR_SIG_REPLY_WAIT state */
+ que_thr_t** next_thr); /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread */
/**************************************************************************
Same as que_thr_end_wait, but no parameter next_thr available. */
@@ -293,6 +307,22 @@ que_thr_peek_stop(
mutex reserved is necessary before deciding
the actual stopping */
que_thr_t* thr); /* in: query thread */
+/***************************************************************************
+Returns TRUE if the query graph is for a SELECT statement. */
+UNIV_INLINE
+ibool
+que_graph_is_select(
+/*================*/
+ /* out: TRUE if a select */
+ que_t* graph); /* in: graph */
+/**************************************************************************
+Prints info of an SQL query graph node. */
+
+void
+que_node_print_info(
+/*================*/
+ que_node_t* node); /* in: query graph node */
+
/* Query graph query thread node: the fields are protected by the kernel
mutex with the exceptions named below */
diff --git a/innobase/include/que0que.ic b/innobase/include/que0que.ic
index a63922f8c80..ae4ed10560f 100644
--- a/innobase/include/que0que.ic
+++ b/innobase/include/que0que.ic
@@ -238,3 +238,21 @@ que_thr_peek_stop(
return(FALSE);
}
+
+/***************************************************************************
+Returns TRUE if the query graph is for a SELECT statement. */
+UNIV_INLINE
+ibool
+que_graph_is_select(
+/*================*/
+ /* out: TRUE if a select */
+ que_t* graph) /* in: graph */
+{
+ if (graph->fork_type == QUE_FORK_SELECT_SCROLL
+ || graph->fork_type == QUE_FORK_SELECT_NON_SCROLL) {
+
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
diff --git a/innobase/include/row0ins.h b/innobase/include/row0ins.h
index f3f0b7e8eca..a5b4b74e7fc 100644
--- a/innobase/include/row0ins.h
+++ b/innobase/include/row0ins.h
@@ -145,12 +145,11 @@ struct ins_node_struct{
entry_list and sys fields are stored here;
if this is NULL, entry list should be created
and buffers for sys fields in row allocated */
-#ifdef UNIV_DEBUG
ulint magic_n;
-#define INS_NODE_MAGIC_N 15849075
-#endif /* UNIV_DEBUG */
};
+#define INS_NODE_MAGIC_N 15849075
+
/* Insert node types */
#define INS_SEARCHED 0 /* INSERT INTO ... SELECT ... */
#define INS_VALUES 1 /* INSERT INTO ... VALUES ... */
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 364ac006ba7..768279fefd4 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -558,6 +558,9 @@ struct row_prebuilt_struct {
dtuple_t* clust_ref; /* prebuilt dtuple used in
sel/upd/del */
ulint select_lock_type;/* LOCK_NONE, LOCK_S, or LOCK_X */
+ ulint stored_select_lock_type;/* inside LOCK TABLES, either
+ LOCK_S or LOCK_X depending on the lock
+ type */
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/row0upd.h b/innobase/include/row0upd.h
index 687e90deee5..f5e0a88231f 100644
--- a/innobase/include/row0upd.h
+++ b/innobase/include/row0upd.h
@@ -384,12 +384,11 @@ struct upd_node_struct{
sym_node_t* table_sym;/* table node in symbol table */
que_node_t* col_assign_list;
/* column assignment list */
-#ifdef UNIV_DEBUG
ulint magic_n;
-#define UPD_NODE_MAGIC_N 1579975
-#endif /* UNIV_DEBUG */
};
+#define UPD_NODE_MAGIC_N 1579975
+
/* Node execution states */
#define UPD_NODE_SET_IX_LOCK 1 /* execution came to the node from
a node above and if the field
diff --git a/innobase/include/srv0que.h b/innobase/include/srv0que.h
new file mode 100644
index 00000000000..05c339cdd32
--- /dev/null
+++ b/innobase/include/srv0que.h
@@ -0,0 +1,53 @@
+/******************************************************
+Server query execution
+
+(c) 1996 Innobase Oy
+
+Created 6/5/1996 Heikki Tuuri
+*******************************************************/
+
+
+#ifndef srv0que_h
+#define srv0que_h
+
+#include "univ.i"
+#include "que0types.h"
+
+/**************************************************************************
+Checks if there is work to do in the server task queue. If there is, the
+thread starts processing a task. Before leaving, it again checks the task
+queue and picks a new task if any exists. This is called by a SRV_WORKER
+thread. */
+
+void
+srv_que_task_queue_check(void);
+/*==========================*/
+/**************************************************************************
+Performs round-robin on the server tasks. This is called by a SRV_WORKER
+thread every second or so. */
+
+que_thr_t*
+srv_que_round_robin(
+/*================*/
+ /* out: the new (may be == thr) query thread
+ to run */
+ que_thr_t* thr); /* in: query thread */
+/**************************************************************************
+Enqueues a task to server task queue and releases a worker thread, if
+there exists one suspended. */
+
+void
+srv_que_task_enqueue(
+/*=================*/
+ que_thr_t* thr); /* in: query thread */
+/**************************************************************************
+Enqueues a task to server task queue and releases a worker thread, if
+there exists one suspended. */
+
+void
+srv_que_task_enqueue_low(
+/*=====================*/
+ que_thr_t* thr); /* in: query thread */
+
+#endif
+
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 7f067c75466..c527d40bc79 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -16,10 +16,7 @@ Created 10/10/1995 Heikki Tuuri
#include "que0types.h"
#include "trx0types.h"
-extern char* srv_main_thread_op_info;
-
-/* Buffer which can be used in printing fatal error messages */
-extern char srv_fatal_errbuf[];
+extern const char* srv_main_thread_op_info;
/* When this event is set the lock timeout and InnoDB monitor
thread starts running */
@@ -40,7 +37,9 @@ extern FILE* srv_monitor_file;
/* Server parameters which are read from the initfile */
extern char* srv_data_home;
+#ifdef UNIV_LOG_ARCHIVE
extern char* srv_arch_dir;
+#endif /* UNIV_LOG_ARCHIVE */
extern ibool srv_file_per_table;
@@ -62,7 +61,6 @@ extern char** srv_log_group_home_dirs;
extern ulint srv_n_log_groups;
extern ulint srv_n_log_files;
extern ulint srv_log_file_size;
-extern ibool srv_log_archive_on;
extern ulint srv_log_buffer_size;
extern ulint srv_flush_log_at_trx_commit;
@@ -75,8 +73,11 @@ extern ulint srv_lock_table_size;
extern ulint srv_n_file_io_threads;
+#ifdef UNIV_LOG_ARCHIVE
+extern ibool srv_log_archive_on;
extern ibool srv_archive_recovery;
extern dulint srv_archive_recovery_limit_lsn;
+#endif /* UNIV_LOG_ARCHIVE */
extern ulint srv_lock_wait_timeout;
diff --git a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h
index 63b01ffac80..9a988a03e92 100644
--- a/innobase/include/sync0rw.h
+++ b/innobase/include/sync0rw.h
@@ -85,7 +85,6 @@ void
rw_lock_free(
/*=========*/
rw_lock_t* lock); /* in: rw-lock */
-#ifdef UNIV_DEBUG
/**********************************************************************
Checks that the rw-lock has been initialized and that there are no
simultaneous shared and exclusive locks. */
@@ -94,7 +93,6 @@ ibool
rw_lock_validate(
/*=============*/
rw_lock_t* lock);
-#endif /* UNIV_DEBUG */
/******************************************************************
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
index 655bd7f6517..3a92100ba01 100644
--- a/innobase/include/sync0rw.ic
+++ b/innobase/include/sync0rw.ic
@@ -30,7 +30,7 @@ rw_lock_add_debug_info(
rw_lock_t* lock, /* in: rw-lock */
ulint pass, /* in: pass value */
ulint lock_type, /* in: lock type */
- char* file_name, /* in: file where requested */
+ const char* file_name, /* in: file where requested */
ulint line); /* in: line where requested */
/**********************************************************************
Removes a debug information struct for an rw-lock. */
diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h
index 4307ca5ba0c..8e0ec715b12 100644
--- a/innobase/include/sync0sync.h
+++ b/innobase/include/sync0sync.h
@@ -143,7 +143,6 @@ void
sync_print(
/*=======*/
FILE* file); /* in: file where to print */
-#ifdef UNIV_DEBUG
/**********************************************************************
Checks that the mutex has been initialized. */
@@ -151,7 +150,6 @@ ibool
mutex_validate(
/*===========*/
mutex_t* mutex);
-#endif /* UNIV_DEBUG */
/**********************************************************************
Sets the mutex latching level field. */
diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic
index ecb498918e2..aaf5e1fd9e9 100644
--- a/innobase/include/sync0sync.ic
+++ b/innobase/include/sync0sync.ic
@@ -33,7 +33,7 @@ void
mutex_set_debug_info(
/*=================*/
mutex_t* mutex, /* in: mutex */
- char* file_name, /* in: file where requested */
+ const char* file_name, /* in: file where requested */
ulint line); /* in: line where requested */
#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
diff --git a/innobase/include/trx0roll.h b/innobase/include/trx0roll.h
index aa88fc249fc..6004551f456 100644
--- a/innobase/include/trx0roll.h
+++ b/innobase/include/trx0roll.h
@@ -91,12 +91,16 @@ trx_undo_rec_release(
/*************************************************************************
Starts a rollback operation. */
-que_thr_t*
+void
trx_rollback(
/*=========*/
- /* out: next query thread to run */
trx_t* trx, /* in: transaction */
- trx_sig_t* sig); /* in: signal starting the rollback */
+ trx_sig_t* sig, /* in: signal starting the rollback */
+ que_thr_t** next_thr);/* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread */
/***********************************************************************
Rollback or clean up transactions which have no user session. If the
transaction already was committed, then we clean up a possible insert
@@ -108,12 +112,17 @@ trx_rollback_or_clean_all_without_sess(void);
/********************************************************************
Finishes a transaction rollback. */
-que_thr_t*
+void
trx_finish_rollback_off_kernel(
/*===========================*/
- /* out: next query thread to run */
que_t* graph, /* in: undo graph which can now be freed */
- trx_t* trx); /* in: transaction */
+ trx_t* trx, /* in: transaction */
+ que_thr_t** next_thr);/* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if this parameter is
+ NULL, it is ignored */
/********************************************************************
Builds an undo 'query' graph for a transaction. The actual rollback is
performed by executing this query graph like a query subprocedure call.
diff --git a/innobase/include/trx0sys.h b/innobase/include/trx0sys.h
index 7d20455ffdf..8f402881224 100644
--- a/innobase/include/trx0sys.h
+++ b/innobase/include/trx0sys.h
@@ -32,6 +32,14 @@ or there was no master log position info inside InnoDB. */
extern char trx_sys_mysql_master_log_name[];
extern ib_longlong trx_sys_mysql_master_log_pos;
+/* If this MySQL server uses binary logging, after InnoDB has been inited
+and if it has done a crash recovery, we store the binlog file name and position
+here. If .._pos is -1, it means there was no binlog position info inside
+InnoDB. */
+
+extern char trx_sys_mysql_bin_log_name[];
+extern ib_longlong trx_sys_mysql_bin_log_pos;
+
/* The transaction system */
extern trx_sys_t* trx_sys;
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 9b7ac22e617..a8c1df534da 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -194,10 +194,9 @@ trx_end_lock_wait(
/********************************************************************
Sends a signal to a trx object. */
-que_thr_t*
+ibool
trx_sig_send(
/*=========*/
- /* out: next query thread to run */
/* out: TRUE if the signal was
successfully delivered */
trx_t* trx, /* in: trx handle */
@@ -207,17 +206,27 @@ trx_sig_send(
que_thr_t* receiver_thr, /* in: query thread which wants the
reply, or NULL; if type is
TRX_SIG_END_WAIT, this must be NULL */
- trx_savept_t* savept); /* in: possible rollback savepoint, or
+ trx_savept_t* savept, /* in: possible rollback savepoint, or
NULL */
+ que_thr_t** next_thr); /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if the parameter
+ is NULL, it is ignored */
/********************************************************************
Send the reply message when a signal in the queue of the trx has
been handled. */
-que_thr_t*
+void
trx_sig_reply(
/*==========*/
- /* out: next query thread to run */
- trx_sig_t* sig); /* in: signal */
+ trx_sig_t* sig, /* in: signal */
+ que_thr_t** next_thr); /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread */
/********************************************************************
Removes the signal object from a trx signal queue. */
@@ -229,11 +238,15 @@ trx_sig_remove(
/********************************************************************
Starts handling of a trx signal. */
-que_thr_t*
+void
trx_sig_start_handle(
/*=================*/
- /* out: next query thread to run, or NULL */
- trx_t* trx); /* in: trx handle */
+ trx_t* trx, /* in: trx handle */
+ que_thr_t** next_thr); /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread */
/********************************************************************
Ends signal handling. If the session is in the error state, and
trx->graph_before_signal_handling != NULL, returns control to the error
diff --git a/innobase/include/usr0sess.h b/innobase/include/usr0sess.h
index aeff7191e68..c7bcfb20fed 100644
--- a/innobase/include/usr0sess.h
+++ b/innobase/include/usr0sess.h
@@ -38,6 +38,7 @@ sess_try_close(
/* The session handle. All fields are protected by the kernel mutex */
struct sess_struct{
+ ulint state; /* state of the session */
trx_t* trx; /* transaction object permanently
assigned for the session: the
transaction instance designated by the
@@ -48,6 +49,11 @@ struct sess_struct{
session */
};
+/* Session states */
+#define SESS_ACTIVE 1
+#define SESS_ERROR 2 /* session contains an error message
+ which has not yet been communicated
+ to the client */
#ifndef UNIV_NONINL
#include "usr0sess.ic"
#endif
diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h
index 85b99efff68..2e02b3f0b6b 100644
--- a/innobase/include/ut0mem.h
+++ b/innobase/include/ut0mem.h
@@ -67,6 +67,37 @@ ut_free(
/*====*/
void* ptr); /* in, own: memory block */
/**************************************************************************
+Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not
+use this function because the allocation functions in mem0mem.h are the
+recommended ones in InnoDB.
+
+man realloc in Linux, 2004:
+
+ realloc() changes the size of the memory block pointed to
+ by ptr to size bytes. The contents will be unchanged to
+ the minimum of the old and new sizes; newly allocated mem­
+ ory will be uninitialized. If ptr is NULL, the call is
+ equivalent to malloc(size); if size is equal to zero, the
+ call is equivalent to free(ptr). Unless ptr is NULL, it
+ must have been returned by an earlier call to malloc(),
+ calloc() or realloc().
+
+RETURN VALUE
+ realloc() returns a pointer to the newly allocated memory,
+ which is suitably aligned for any kind of variable and may
+ be different from ptr, or NULL if the request fails. If
+ size was equal to 0, either NULL or a pointer suitable to
+ be passed to free() is returned. If realloc() fails the
+ original block is left untouched - it is not freed or
+ moved. */
+
+void*
+ut_realloc(
+/*=======*/
+ /* out, own: pointer to new mem block or NULL */
+ void* ptr, /* in: pointer to old block or NULL */
+ ulint size); /* in: desired size */
+/**************************************************************************
Frees in shutdown all allocated memory not freed yet. */
void
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 223d9af78d1..be0806590a9 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -292,9 +292,7 @@ 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. */
-#ifdef UNIV_DEBUG
ibool lock_print_waits = FALSE;
-#endif /* UNIV_DEBUG */
/* The lock system */
lock_sys_t* lock_sys = NULL;
@@ -510,7 +508,7 @@ lock_sys_create(
/* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */
- lock_latest_err_file = tmpfile();
+ lock_latest_err_file = os_file_create_tmpfile();
}
/*************************************************************************
@@ -1354,8 +1352,7 @@ lock_rec_has_expl(
return(NULL);
}
-
-#ifdef UNIV_DEBUG
+
/*************************************************************************
Checks if some other transaction has a lock request in the queue. */
static
@@ -1398,7 +1395,6 @@ lock_rec_other_has_expl_req(
return(NULL);
}
-#endif /* UNIV_DEBUG */
/*************************************************************************
Checks if some other transaction has a conflicting explicit lock request
@@ -1688,13 +1684,11 @@ 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, index->name);
}
-#endif /* UNIV_DEBUG */
return(DB_LOCK_WAIT);
}
@@ -2034,12 +2028,10 @@ lock_grant(
lock->trx->n_tables_locked++;
}
-#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
@@ -3110,11 +3102,9 @@ lock_deadlock_recursive(
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) {
@@ -4177,7 +4167,6 @@ loop:
goto loop;
}
-#ifdef UNIV_DEBUG
/*************************************************************************
Validates the lock queue on a table. */
@@ -4488,7 +4477,6 @@ lock_validate(void)
return(TRUE);
}
-#endif /* UNIV_DEBUG */
/*============ RECORD LOCK CHECKS FOR ROW OPERATIONS ====================*/
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index 292fed4b4ec..923ab448e07 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -32,18 +32,20 @@ ulint log_fsp_current_free_limit = 0;
log_t* log_sys = NULL;
ibool log_do_write = TRUE;
-#ifdef UNIV_LOG_DEBUG
+
ibool log_debug_writes = FALSE;
-#endif /* UNIV_LOG_DEBUG */
+
/* These control how often we print warnings if the last checkpoint is too
old */
ibool log_has_printed_chkp_warning = FALSE;
time_t log_last_warning_time;
+#ifdef UNIV_LOG_ARCHIVE
/* Pointer to this variable is used as the i/o-message when we do i/o to an
archive */
byte log_archive_io;
+#endif /* UNIV_LOG_ARCHIVE */
/* A margin for free space in the log buffer before a log entry is catenated */
#define LOG_BUF_WRITE_MARGIN (4 * OS_FILE_LOG_BLOCK_SIZE)
@@ -90,12 +92,14 @@ static
void
log_io_complete_checkpoint(void);
/*============================*/
+#ifdef UNIV_LOG_ARCHIVE
/**********************************************************
Completes an archiving i/o. */
static
void
log_io_complete_archive(void);
/*=========================*/
+#endif /* UNIV_LOG_ARCHIVE */
/********************************************************************
Sets the global variable log_fsp_current_free_limit. Also makes a checkpoint,
@@ -160,9 +164,13 @@ log_reserve_and_open(
{
log_t* log = log_sys;
ulint len_upper_limit;
+#ifdef UNIV_LOG_ARCHIVE
ulint archived_lsn_age;
- ulint count = 0;
ulint dummy;
+#endif /* UNIV_LOG_ARCHIVE */
+#ifdef UNIV_DEBUG
+ ulint count = 0;
+#endif /* UNIV_DEBUG */
ut_a(len < log->buf_size / 2);
loop:
@@ -182,13 +190,12 @@ loop:
log_buffer_flush_to_disk();
- count++;
-
- ut_ad(count < 50);
+ ut_ad(++count < 50);
goto loop;
}
+#ifdef UNIV_LOG_ARCHIVE
if (log->archiving_state != LOG_ARCH_OFF) {
archived_lsn_age = ut_dulint_minus(log->lsn,
@@ -204,13 +211,12 @@ loop:
log_archive_do(TRUE, &dummy);
- count++;
-
- ut_ad(count < 50);
+ ut_ad(++count < 50);
goto loop;
}
}
+#endif /* UNIV_LOG_ARCHIVE */
#ifdef UNIV_LOG_DEBUG
log->old_buf_free = log->buf_free;
@@ -378,6 +384,7 @@ function_exit:
return(lsn);
}
+#ifdef UNIV_LOG_ARCHIVE
/**********************************************************
Pads the current log block full with dummy log records. Used in producing
consistent archived log files. */
@@ -410,6 +417,7 @@ log_pad_current_log_block(void)
ut_a((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
== LOG_BLOCK_HDR_SIZE);
}
+#endif /* UNIV_LOG_ARCHIVE */
/**********************************************************
Calculates the data capacity of a log group, when the log file headers are not
@@ -663,11 +671,13 @@ log_calc_max_ages(void)
/ LOG_POOL_CHECKPOINT_RATIO_ASYNC;
log_sys->max_checkpoint_age = margin;
+#ifdef UNIV_LOG_ARCHIVE
log_sys->max_archived_lsn_age = smallest_archive_margin;
log_sys->max_archived_lsn_age_async = smallest_archive_margin
- smallest_archive_margin /
LOG_ARCHIVE_RATIO_ASYNC;
+#endif /* UNIV_LOG_ARCHIVE */
failure:
mutex_exit(&(log_sys->mutex));
@@ -767,6 +777,7 @@ log_init(void)
memset(log_sys->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE);
/*----------------------------*/
+#ifdef UNIV_LOG_ARCHIVE
/* Under MySQL, log archiving is always off */
log_sys->archiving_state = LOG_ARCH_OFF;
log_sys->archived_lsn = log_sys->lsn;
@@ -788,13 +799,10 @@ log_init(void)
/* memset(log_sys->archive_buf, '\0', LOG_ARCHIVE_BUF_SIZE); */
log_sys->archiving_on = os_event_create(NULL);
+#endif /* UNIV_LOG_ARCHIVE */
/*----------------------------*/
-
- log_sys->online_backup_state = FALSE;
- /*----------------------------*/
-
log_block_init(log_sys->buf, log_sys->lsn);
log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE);
@@ -827,7 +835,8 @@ log_group_init(
ulint space_id, /* in: space id of the file space
which contains the log files of this
group */
- ulint archive_space_id) /* in: space id of the file space
+ ulint archive_space_id __attribute__((unused)))
+ /* in: space id of the file space
which contains some archived log
files for this group; currently, only
for the first log group this is
@@ -849,7 +858,9 @@ log_group_init(
group->n_pending_writes = 0;
group->file_header_bufs = mem_alloc(sizeof(byte*) * n_files);
+#ifdef UNIV_LOG_ARCHIVE
group->archive_file_header_bufs = mem_alloc(sizeof(byte*) * n_files);
+#endif /* UNIV_LOG_ARCHIVE */
for (i = 0; i < n_files; i++) {
*(group->file_header_bufs + i) = ut_align(
@@ -859,17 +870,21 @@ log_group_init(
memset(*(group->file_header_bufs + i), '\0',
LOG_FILE_HDR_SIZE);
+#ifdef UNIV_LOG_ARCHIVE
*(group->archive_file_header_bufs + i) = ut_align(
mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE),
OS_FILE_LOG_BLOCK_SIZE);
memset(*(group->archive_file_header_bufs + i), '\0',
LOG_FILE_HDR_SIZE);
+#endif /* UNIV_LOG_ARCHIVE */
}
+#ifdef UNIV_LOG_ARCHIVE
group->archive_space_id = archive_space_id;
group->archived_file_no = 0;
group->archived_offset = 0;
+#endif /* UNIV_LOG_ARCHIVE */
group->checkpoint_buf = ut_align(
mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE),
@@ -930,12 +945,10 @@ log_group_check_flush_completion(
#endif /* UNIV_SYNC_DEBUG */
if (!log_sys->one_flushed && group->n_pending_writes == 0) {
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Log flushed first to group %lu\n", (ulong) group->id);
}
-#endif /* UNIV_LOG_DEBUG */
log_sys->written_to_some_lsn = log_sys->write_lsn;
log_sys->one_flushed = TRUE;
@@ -943,12 +956,10 @@ log_group_check_flush_completion(
return(LOG_UNLOCK_NONE_FLUSHED_LOCK);
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes && (group->n_pending_writes == 0)) {
fprintf(stderr, "Log flushed to group %lu\n", (ulong) group->id);
}
-#endif /* UNIV_LOG_DEBUG */
return(0);
}
@@ -1006,6 +1017,7 @@ log_io_complete(
{
ulint unlock;
+#ifdef UNIV_LOG_ARCHIVE
if ((byte*)group == &log_archive_io) {
/* It was an archive write */
@@ -1013,6 +1025,7 @@ log_io_complete(
return;
}
+#endif /* UNIV_LOG_ARCHIVE */
if ((ulint)group & 0x1UL) {
/* It was a checkpoint write */
@@ -1024,13 +1037,11 @@ log_io_complete(
fil_flush(group->space_id);
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Checkpoint info written to group %lu\n",
group->id);
}
-#endif /* UNIV_LOG_DEBUG */
log_io_complete_checkpoint();
@@ -1093,13 +1104,11 @@ log_group_file_header_flush(
dest_offset = nth_file * group->file_size;
-#ifdef UNIV_LOG_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_LOG_DEBUG */
if (log_do_write) {
log_sys->n_log_ios++;
@@ -1183,7 +1192,6 @@ loop:
write_len = len;
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
@@ -1193,7 +1201,7 @@ loop:
(ulong) group->id, (ulong) next_offset,
(ulong) write_len,
(ulong) ut_dulint_get_high(start_lsn),
- (ulong) ut_dulint_get_low(start_lsn).
+ (ulong) ut_dulint_get_low(start_lsn),
(ulong) log_block_get_hdr_no(buf),
(ulong) log_block_get_hdr_no(
buf + write_len - OS_FILE_LOG_BLOCK_SIZE));
@@ -1207,7 +1215,6 @@ loop:
+ i * OS_FILE_LOG_BLOCK_SIZE));
}
}
-#endif /* UNIV_LOG_DEBUG */
/* Calculate the checksums for each log block and write them to
the trailer fields of the log blocks */
@@ -1335,7 +1342,6 @@ loop:
return;
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Writing log from %lu %lu up to lsn %lu %lu\n",
@@ -1344,7 +1350,6 @@ loop:
(ulong) ut_dulint_get_high(log_sys->lsn),
(ulong) ut_dulint_get_low(log_sys->lsn));
}
-#endif /* UNIV_LOG_DEBUG */
log_sys->n_pending_writes++;
@@ -1633,8 +1638,10 @@ log_group_checkpoint(
log_group_t* group) /* in: log group */
{
log_group_t* group2;
+#ifdef UNIV_LOG_ARCHIVE
dulint archived_lsn;
dulint next_archived_lsn;
+#endif /* UNIV_LOG_ARCHIVE */
ulint write_offset;
ulint fold;
byte* buf;
@@ -1657,6 +1664,7 @@ log_group_checkpoint(
mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, log_sys->buf_size);
+#ifdef UNIV_LOG_ARCHIVE
if (log_sys->archiving_state == LOG_ARCH_OFF) {
archived_lsn = ut_dulint_max;
} else {
@@ -1668,8 +1676,11 @@ log_group_checkpoint(
/* For debugging only */
}
}
-
+
mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, archived_lsn);
+#else /* UNIV_LOG_ARCHIVE */
+ mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, ut_dulint_max);
+#endif /* UNIV_LOG_ARCHIVE */
for (i = 0; i < LOG_MAX_N_GROUPS; i++) {
log_checkpoint_set_nth_group_info(buf, i, 0, 0);
@@ -1679,8 +1690,13 @@ log_group_checkpoint(
while (group2) {
log_checkpoint_set_nth_group_info(buf, group2->id,
+#ifdef UNIV_LOG_ARCHIVE
group2->archived_file_no,
- group2->archived_offset);
+ group2->archived_offset
+#else /* UNIV_LOG_ARCHIVE */
+ 0, 0
+#endif /* UNIV_LOG_ARCHIVE */
+ );
group2 = UT_LIST_GET_NEXT(log_groups, group2);
}
@@ -1903,14 +1919,12 @@ log_checkpoint(
log_sys->next_checkpoint_lsn = oldest_lsn;
-#ifdef UNIV_LOG_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_LOG_DEBUG */
log_groups_write_checkpoint_info();
@@ -2106,16 +2120,18 @@ loop:
len = group->file_size - (source_offset % group->file_size);
}
+#ifdef UNIV_LOG_ARCHIVE
if (type == LOG_ARCHIVE) {
log_sys->n_pending_archive_ios++;
}
+#endif /* UNIV_LOG_ARCHIVE */
log_sys->n_log_ios++;
fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id,
source_offset / UNIV_PAGE_SIZE, source_offset % UNIV_PAGE_SIZE,
- len, buf, &log_archive_io);
+ len, buf, NULL);
start_lsn = ut_dulint_add(start_lsn, len);
buf += len;
@@ -2126,6 +2142,7 @@ loop:
}
}
+#ifdef UNIV_LOG_ARCHIVE
/**********************************************************
Generates an archived log file name. */
@@ -2138,8 +2155,6 @@ log_archived_file_name_gen(
currently we only archive the first group */
ulint file_no)/* in: file number */
{
- ut_a(0);
-
sprintf(buf, "%sib_arch_log_%010lu", srv_arch_dir, (ulong) file_no);
}
@@ -2160,8 +2175,6 @@ log_group_archive_file_header_write(
ulint dest_offset;
#ifdef UNIV_SYNC_DEBUG
- ut_a(0);
-
ut_ad(mutex_own(&(log_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
@@ -2201,8 +2214,6 @@ log_group_archive_completed_header_write(
ulint dest_offset;
#ifdef UNIV_SYNC_DEBUG
- ut_a(0);
-
ut_ad(mutex_own(&(log_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
ut_a(nth_file < group->n_files);
@@ -2244,8 +2255,6 @@ log_group_archive(
ulint open_mode;
#ifdef UNIV_SYNC_DEBUG
- ut_a(0);
-
ut_ad(mutex_own(&(log_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
@@ -2296,11 +2305,9 @@ loop:
exit(1);
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr, "Created archive file %s\n", name);
}
-#endif /* UNIV_LOG_DEBUG */
ret = os_file_close(file_handle);
@@ -2327,7 +2334,6 @@ loop:
len = group->file_size - (next_offset % group->file_size);
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Archiving starting at lsn %lu %lu, len %lu to group %lu\n",
@@ -2335,7 +2341,6 @@ loop:
(ulong) ut_dulint_get_low(start_lsn),
(ulong) len, (ulong) group->id);
}
-#endif /* UNIV_LOG_DEBUG */
log_sys->n_pending_archive_ios++;
@@ -2376,8 +2381,6 @@ log_archive_groups(void)
log_group_t* group;
#ifdef UNIV_SYNC_DEBUG
- ut_a(0);
-
ut_ad(mutex_own(&(log_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
@@ -2403,8 +2406,6 @@ log_archive_write_complete_groups(void)
ulint i;
#ifdef UNIV_SYNC_DEBUG
- ut_a(0);
-
ut_ad(mutex_own(&(log_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
@@ -2430,13 +2431,11 @@ log_archive_write_complete_groups(void)
trunc_files = n_files - 1;
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes && trunc_files) {
fprintf(stderr,
"Complete file(s) archived to group %lu\n",
(ulong) group->id);
}
-#endif /* UNIV_LOG_DEBUG */
/* Calculate the archive file space start lsn */
start_lsn = ut_dulint_subtract(log_sys->next_archived_lsn,
@@ -2459,11 +2458,9 @@ log_archive_write_complete_groups(void)
fil_space_truncate_start(group->archive_space_id,
trunc_files * group->file_size);
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fputs("Archiving writes completed\n", stderr);
}
-#endif /* UNIV_LOG_DEBUG */
}
/**********************************************************
@@ -2474,19 +2471,15 @@ log_archive_check_completion_low(void)
/*==================================*/
{
#ifdef UNIV_SYNC_DEBUG
- ut_a(0);
-
ut_ad(mutex_own(&(log_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
if (log_sys->n_pending_archive_ios == 0
&& log_sys->archiving_phase == LOG_ARCHIVE_READ) {
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fputs("Archiving read completed\n", stderr);
}
-#endif /* UNIV_LOG_DEBUG */
/* Archive buffer has now been read in: start archive writes */
@@ -2515,8 +2508,6 @@ log_io_complete_archive(void)
{
log_group_t* group;
- ut_a(0);
-
mutex_enter(&(log_sys->mutex));
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -2552,8 +2543,6 @@ log_archive_do(
dulint start_lsn;
dulint limit_lsn;
- ut_a(0);
-
calc_new_limit = TRUE;
loop:
mutex_enter(&(log_sys->mutex));
@@ -2634,7 +2623,6 @@ loop:
log_sys->next_archived_lsn = limit_lsn;
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Archiving from lsn %lu %lu to lsn %lu %lu\n",
@@ -2643,7 +2631,6 @@ loop:
(ulong) ut_dulint_get_high(limit_lsn),
(ulong) ut_dulint_get_low(limit_lsn));
}
-#endif /* UNIV_LOG_DEBUG */
/* Read the log segment to the archive buffer */
@@ -2682,8 +2669,6 @@ log_archive_all(void)
return;
}
- ut_a(0);
-
present_lsn = log_sys->lsn;
mutex_exit(&(log_sys->mutex));
@@ -2728,8 +2713,6 @@ log_archive_close_groups(
return;
}
- ut_a(0);
-
group = UT_LIST_GET_FIRST(log_sys->log_groups);
trunc_len = UNIV_PAGE_SIZE
@@ -2750,14 +2733,12 @@ log_archive_close_groups(
group->archived_file_no += 2;
}
-#ifdef UNIV_LOG_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_LOG_DEBUG */
}
}
@@ -2774,8 +2755,6 @@ log_archive_stop(void)
{
ibool success;
- ut_a(0);
-
mutex_enter(&(log_sys->mutex));
if (log_sys->archiving_state != LOG_ARCH_ON) {
@@ -2838,8 +2817,6 @@ log_archive_start(void)
/*===================*/
/* out: DB_SUCCESS or DB_ERROR */
{
- ut_a(0);
-
mutex_enter(&(log_sys->mutex));
if (log_sys->archiving_state != LOG_ARCH_STOPPED) {
@@ -2866,7 +2843,6 @@ log_archive_noarchivelog(void)
/*==========================*/
/* out: DB_SUCCESS or DB_ERROR */
{
- ut_a(0);
loop:
mutex_enter(&(log_sys->mutex));
@@ -2899,7 +2875,6 @@ log_archive_archivelog(void)
/*========================*/
/* out: DB_SUCCESS or DB_ERROR */
{
- ut_a(0);
mutex_enter(&(log_sys->mutex));
if (log_sys->archiving_state == LOG_ARCH_OFF) {
@@ -2918,7 +2893,6 @@ log_archive_archivelog(void)
return(DB_ERROR);
}
-#ifdef notdefined
/********************************************************************
Tries to establish a big enough margin of free space in the log groups, such
that a new log entry can be catenated without an immediate need for
@@ -2972,7 +2946,7 @@ loop:
goto loop;
}
}
-#endif
+#endif /* UNIV_LOG_ARCHIVE */
/************************************************************************
Checks that there is enough free space in the log to start a new query step.
@@ -2989,7 +2963,9 @@ loop:
log_checkpoint_margin();
- /* log_archive_margin(); */
+#ifdef UNIV_LOG_ARCHIVE
+ log_archive_margin();
+#endif /* UNIV_LOG_ARCHIVE */
mutex_enter(&(log_sys->mutex));
@@ -3003,66 +2979,6 @@ loop:
mutex_exit(&(log_sys->mutex));
}
-/**********************************************************
-Switches the database to the online backup state. */
-
-ulint
-log_switch_backup_state_on(void)
-/*============================*/
- /* out: DB_SUCCESS or DB_ERROR */
-{
- dulint backup_lsn;
-
- mutex_enter(&(log_sys->mutex));
-
- if (log_sys->online_backup_state) {
-
- /* The database is already in that state */
-
- mutex_exit(&(log_sys->mutex));
-
- return(DB_ERROR);
- }
-
- log_sys->online_backup_state = TRUE;
-
- backup_lsn = log_sys->lsn;
-
- log_sys->online_backup_lsn = backup_lsn;
-
- mutex_exit(&(log_sys->mutex));
-
- /* log_checkpoint_and_mark_file_spaces(); */
-
- return(DB_SUCCESS);
-}
-
-/**********************************************************
-Switches the online backup state off. */
-
-ulint
-log_switch_backup_state_off(void)
-/*=============================*/
- /* out: DB_SUCCESS or DB_ERROR */
-{
- mutex_enter(&(log_sys->mutex));
-
- if (!log_sys->online_backup_state) {
-
- /* The database is already in that state */
-
- mutex_exit(&(log_sys->mutex));
-
- return(DB_ERROR);
- }
-
- log_sys->online_backup_state = FALSE;
-
- mutex_exit(&(log_sys->mutex));
-
- return(DB_SUCCESS);
-}
-
/********************************************************************
Makes a checkpoint at the latest lsn and writes it to first page of each
data file in the database, so that we know that the file spaces contain
@@ -3111,9 +3027,12 @@ loop:
mutex_enter(&(log_sys->mutex));
- if (log_sys->n_pending_archive_ios
- + log_sys->n_pending_checkpoint_writes
- + log_sys->n_pending_writes > 0) {
+ if (
+#ifdef UNIV_LOG_ARCHIVE
+ log_sys->n_pending_archive_ios ||
+#endif /* UNIV_LOG_ARCHIVE */
+ log_sys->n_pending_checkpoint_writes ||
+ log_sys->n_pending_writes) {
mutex_exit(&(log_sys->mutex));
@@ -3127,7 +3046,9 @@ loop:
goto loop;
}
- /* log_archive_all(); */
+#ifdef UNIV_LOG_ARCHIVE
+ log_archive_all();
+#endif /* UNIV_LOG_ARCHIVE */
log_make_checkpoint_at(ut_dulint_max, TRUE);
mutex_enter(&(log_sys->mutex));
@@ -3135,10 +3056,13 @@ loop:
lsn = log_sys->lsn;
if (ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0
+#ifdef UNIV_LOG_ARCHIVE
|| (srv_log_archive_on
&& ut_dulint_cmp(lsn,
ut_dulint_add(log_sys->archived_lsn, LOG_BLOCK_HDR_SIZE))
- != 0)) {
+ != 0)
+#endif /* UNIV_LOG_ARCHIVE */
+ ) {
mutex_exit(&(log_sys->mutex));
@@ -3146,15 +3070,17 @@ loop:
}
arch_log_no = 0;
-/*
- UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no;
-
+
+#ifdef UNIV_LOG_ARCHIVE
+ UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no;
+
if (0 == UT_LIST_GET_FIRST(log_sys->log_groups)->archived_offset) {
-
+
arch_log_no--;
}
-*/
- /* log_archive_close_groups(TRUE); */
+
+ log_archive_close_groups(TRUE);
+#endif /* UNIV_LOG_ARCHIVE */
mutex_exit(&(log_sys->mutex));
@@ -3227,7 +3153,6 @@ loop:
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
}
-#ifdef UNIV_LOG_DEBUG
/**********************************************************
Checks by parsing that the catenated log segment for a single mtr is
consistent. */
@@ -3280,7 +3205,6 @@ log_check_log_recs(
return(TRUE);
}
-#endif /* UNIV_LOG_DEBUG */
/**********************************************************
Peeks the current lsn. */
@@ -3292,8 +3216,7 @@ log_peek_lsn(
log system mutex */
dulint* lsn) /* out: if returns TRUE, current lsn is here */
{
- if (0 == mutex_enter_nowait(&(log_sys->mutex), (char*)__FILE__,
- __LINE__)) {
+ if (0 == mutex_enter_nowait(&(log_sys->mutex), __FILE__, __LINE__)) {
*lsn = log_sys->lsn;
mutex_exit(&(log_sys->mutex));
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index 65fb3466ad5..7e57efcf9e1 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -34,10 +34,12 @@ Created 9/20/1997 Heikki Tuuri
#include "dict0boot.h"
#include "fil0fil.h"
+#ifdef UNIV_HOTBACKUP
/* This is set to FALSE if the backup was originally taken with the
ibbackup --include regexp option: then we do not want to create tables in
directories which were not included */
ibool recv_replay_file_ops = TRUE;
+#endif /* UNIV_HOTBACKUP */
/* Log records are stored in the hash table in chunks at most of this size;
this must be less than UNIV_PAGE_SIZE as it is stored in the buffer pool */
@@ -71,7 +73,11 @@ log scan */
ulint recv_scan_print_counter = 0;
ibool recv_is_from_backup = FALSE;
+#ifdef UNIV_HOTBACKUP
ibool recv_is_making_a_backup = FALSE;
+#else
+# define recv_is_making_a_backup FALSE
+#endif /* UNIV_HOTBACKUP */
ulint recv_previous_parsed_rec_type = 999999;
ulint recv_previous_parsed_rec_offset = 0;
@@ -183,7 +189,6 @@ recv_sys_empty_hash(void)
recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 256);
}
-#ifndef UNIV_LOG_DEBUG
/************************************************************
Frees the recovery system. */
static
@@ -203,7 +208,6 @@ recv_sys_free(void)
mutex_exit(&(recv_sys->mutex));
}
-#endif /* !UNIV_LOG_DEBUG */
/************************************************************
Truncates possible corrupted or extra records from a log group. */
@@ -485,7 +489,6 @@ recv_find_max_checkpoint(
log_group_read_checkpoint_info(group, field);
if (!recv_check_cp_is_consistent(buf)) {
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n",
@@ -495,7 +498,6 @@ recv_find_max_checkpoint(
+ LOG_CHECKPOINT_CHECKSUM_1));
}
-#endif /* UNIV_LOG_DEBUG */
goto not_consistent;
}
@@ -509,14 +511,12 @@ recv_find_max_checkpoint(
checkpoint_no =
mach_read_from_8(buf + LOG_CHECKPOINT_NO);
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Checkpoint number %lu found in group %lu\n",
(ulong) ut_dulint_get_low(checkpoint_no),
(ulong) group->id);
}
-#endif /* UNIV_LOG_DEBUG */
if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) {
*max_group = group;
@@ -808,9 +808,6 @@ recv_parse_or_apply_log_rec_body(
} else if (type == MLOG_IBUF_BITMAP_INIT) {
new_ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr);
- } else if (type == MLOG_FULL_PAGE) {
- new_ptr = mtr_log_parse_full_page(ptr, end_ptr, page);
-
} else if (type == MLOG_INIT_FILE_PAGE) {
new_ptr = fsp_parse_init_file_page(ptr, end_ptr, page);
@@ -1127,15 +1124,7 @@ recv_recover_page(
buf = ((byte*)(recv->data)) + sizeof(recv_data_t);
}
- if (recv->type == MLOG_INIT_FILE_PAGE
- || recv->type == MLOG_FULL_PAGE) {
- /* A new file page may have been taken into use,
- or we have stored the full contents of the page:
- in this case it may be that the original log record
- type was MLOG_INIT_FILE_PAGE, and we replaced it
- with MLOG_FULL_PAGE, thus we have to apply
- any record of type MLOG_FULL_PAGE */
-
+ if (recv->type == MLOG_INIT_FILE_PAGE) {
page_lsn = page_newest_lsn;
mach_write_to_8(page + UNIV_PAGE_SIZE
@@ -1151,7 +1140,6 @@ recv_recover_page(
start_lsn = recv->start_lsn;
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Applying log rec type %lu len %lu to space %lu page no %lu\n",
@@ -1159,7 +1147,6 @@ recv_recover_page(
(ulong) recv_addr->space,
(ulong) recv_addr->page_no);
}
-#endif /* UNIV_LOG_DEBUG */
recv_parse_or_apply_log_rec_body(recv->type, buf,
buf + recv->len, page, &mtr);
@@ -1402,7 +1389,6 @@ loop:
mutex_exit(&(recv_sys->mutex));
}
-#ifdef UNIV_HOTBACKUP
/* This page is allocated from the buffer pool and used in the function
below */
page_t* recv_backup_application_page = NULL;
@@ -1527,7 +1513,6 @@ skip_this_recv_addr:
recv_sys_empty_hash();
}
-#endif
#ifdef notdefined
/***********************************************************************
@@ -1729,7 +1714,7 @@ recv_compare_spaces_low(
recv_compare_spaces(space1, space2, n_pages);
}
-#endif
+#endif /* UNIV_LOG_REPLICATE */
/***********************************************************************
Tries to parse a single log record and returns its length. */
@@ -1825,11 +1810,10 @@ recv_calc_lsn_on_data_add(
return(ut_dulint_add(lsn, lsn_len));
}
-#ifdef UNIV_LOG_DEBUG
/***********************************************************
Checks that the parser recognizes incomplete initial segments of a log
record as incomplete. */
-static
+
void
recv_check_incomplete_log_recs(
/*===========================*/
@@ -1847,7 +1831,6 @@ recv_check_incomplete_log_recs(
&page_no, &body));
}
}
-#endif /* UNIV_LOG_DEBUG */
/***********************************************************
Prints diagnostic info of corrupt log. */
@@ -1984,14 +1967,12 @@ loop:
recv_sys->recovered_offset += len;
recv_sys->recovered_lsn = new_recovered_lsn;
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Parsed a single log rec type %lu len %lu space %lu page no %lu\n",
(ulong) type, (ulong) len, (ulong) space,
(ulong) page_no);
}
-#endif /* UNIV_LOG_DEBUG */
if (type == MLOG_DUMMY_RECORD) {
/* Do nothing */
@@ -2029,11 +2010,13 @@ loop:
becomes identical with the original page */
#ifdef UNIV_LOG_DEBUG
recv_check_incomplete_log_recs(ptr, len);
-#endif
-/* recv_update_replicate(type, space, page_no, body,
+#endif/* UNIV_LOG_DEBUG */
+#ifdef UNIV_LOG_REPLICATE
+ recv_update_replicate(type, space, page_no, body,
ptr + len);
recv_compare_replicate(space, page_no);
-*/
+#endif /* UNIV_LOG_REPLICATE */
+
}
} else {
/* Check that all the records associated with the single mtr
@@ -2066,21 +2049,19 @@ loop:
according to the log record */
#ifdef UNIV_LOG_DEBUG
recv_check_incomplete_log_recs(ptr, len);
-#endif
-/*
+#endif /* UNIV_LOG_DEBUG */
+#ifdef UNIV_LOG_REPLICATE
recv_update_replicate(type, space, page_no,
body, ptr + len);
-*/
+#endif /* UNIV_LOG_REPLICATE */
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Parsed a multi log rec type %lu len %lu space %lu page no %lu\n",
(ulong) type, (ulong) len, (ulong) space,
(ulong) page_no);
}
-#endif /* UNIV_LOG_DEBUG */
total_len += len;
n_recs++;
@@ -2138,12 +2119,13 @@ loop:
recv_add_to_hash_table(type, space, page_no,
body, ptr + len, old_lsn,
new_recovered_lsn);
+#ifdef UNIV_LOG_REPLICATE
} else {
/* In debug checking, check that the replicate
page has become identical with the original
page */
-
-/* recv_compare_replicate(space, page_no); */
+ recv_compare_replicate(space, page_no);
+#endif /* UNIV_LOG_REPLICATE */
}
ptr += len;
@@ -2486,7 +2468,6 @@ recv_group_scan_log_recs(
start_lsn = end_lsn;
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Scanned group %lu up to log sequence number %lu %lu\n",
@@ -2494,7 +2475,6 @@ recv_group_scan_log_recs(
(ulong) ut_dulint_get_high(*group_scanned_lsn),
(ulong) ut_dulint_get_low(*group_scanned_lsn));
}
-#endif /* UNIV_LOG_DEBUG */
}
/************************************************************
@@ -2587,15 +2567,16 @@ recv_recovery_from_checkpoint_start(
/* Wipe over the label now */
- ut_memcpy(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
- (char*)" ", 4);
+ memset(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
+ ' ', 4);
/* Write to the log file to wipe over the label */
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE,
max_cp_group->space_id,
0, 0, OS_FILE_LOG_BLOCK_SIZE,
log_hdr_buf, max_cp_group);
}
-
+
+#ifdef UNIV_LOG_ARCHIVE
group = UT_LIST_GET_FIRST(log_sys->log_groups);
while (group) {
@@ -2605,6 +2586,7 @@ recv_recovery_from_checkpoint_start(
group = UT_LIST_GET_NEXT(log_groups, group);
}
+#endif /* UNIV_LOG_ARCHIVE */
if (type == LOG_CHECKPOINT) {
/* Start reading the log groups from the checkpoint lsn up. The
@@ -2800,7 +2782,9 @@ recv_recovery_from_checkpoint_start(
log_sys->next_checkpoint_lsn = checkpoint_lsn;
log_sys->next_checkpoint_no = ut_dulint_add(checkpoint_no, 1);
+#ifdef UNIV_LOG_ARCHIVE
log_sys->archived_lsn = archived_lsn;
+#endif /* UNIV_LOG_ARCHIVE */
recv_synchronize_groups(up_to_date_group);
@@ -2833,10 +2817,12 @@ recv_recovery_from_checkpoint_start(
log_sys->next_checkpoint_no = ut_dulint_add(checkpoint_no, 1);
+#ifdef UNIV_LOG_ARCHIVE
if (ut_dulint_cmp(archived_lsn, ut_dulint_max) == 0) {
log_sys->archiving_state = LOG_ARCH_OFF;
}
+#endif /* UNIV_LOG_ARCHIVE */
mutex_enter(&(recv_sys->mutex));
@@ -2875,12 +2861,10 @@ recv_recovery_from_checkpoint_finish(void)
recv_apply_hashed_log_recs(TRUE);
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Log records applied to the database\n");
}
-#endif /* UNIV_LOG_DEBUG */
if (recv_needed_recovery) {
trx_sys_print_mysql_master_log_pos();
@@ -2915,7 +2899,9 @@ recv_reset_logs(
dulint lsn, /* in: reset to this lsn rounded up to
be divisible by OS_FILE_LOG_BLOCK_SIZE,
after which we add LOG_BLOCK_HDR_SIZE */
+#ifdef UNIV_LOG_ARCHIVE
ulint arch_log_no, /* in: next archived log file number */
+#endif /* UNIV_LOG_ARCHIVE */
ibool new_logs_created)/* in: TRUE if resetting logs is done
at the log creation; FALSE if it is done
after archive recovery */
@@ -2932,9 +2918,10 @@ recv_reset_logs(
while (group) {
group->lsn = log_sys->lsn;
group->lsn_offset = LOG_FILE_HDR_SIZE;
-
+#ifdef UNIV_LOG_ARCHIVE
group->archived_file_no = arch_log_no;
group->archived_offset = 0;
+#endif /* UNIV_LOG_ARCHIVE */
if (!new_logs_created) {
recv_truncate_group(group, group->lsn, group->lsn,
@@ -2951,7 +2938,9 @@ recv_reset_logs(
log_sys->next_checkpoint_no = ut_dulint_zero;
log_sys->last_checkpoint_lsn = ut_dulint_zero;
+#ifdef UNIV_LOG_ARCHIVE
log_sys->archived_lsn = log_sys->lsn;
+#endif /* UNIV_LOG_ARCHIVE */
log_block_init(log_sys->buf, log_sys->lsn);
log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE);
@@ -2969,17 +2958,18 @@ recv_reset_logs(
mutex_enter(&(log_sys->mutex));
}
+#ifdef UNIV_HOTBACKUP
/**********************************************************
Creates new log files after a backup has been restored. */
void
recv_reset_log_files_for_backup(
/*============================*/
- char* log_dir, /* in: log file directory path */
- ulint n_log_files, /* in: number of log files */
- ulint log_file_size, /* in: log file size */
- dulint lsn) /* in: new start lsn, must be divisible by
- OS_FILE_LOG_BLOCK_SIZE */
+ const char* log_dir, /* in: log file directory path */
+ ulint n_log_files, /* in: number of log files */
+ ulint log_file_size, /* in: log file size */
+ dulint lsn) /* in: new start lsn, must be
+ divisible by OS_FILE_LOG_BLOCK_SIZE */
{
os_file_t log_file;
ibool success;
@@ -2987,8 +2977,8 @@ recv_reset_log_files_for_backup(
ulint i;
ulint log_dir_len;
char* name;
- static
- char logfilename[] = "ib_logfile";
+ static const
+ char logfilename[] = "ib_logfile";
log_dir_len = strlen(log_dir);
/* reserve space for log_dir, "ib_logfile" and a number */
@@ -3058,7 +3048,9 @@ recv_reset_log_files_for_backup(
mem_free(name);
ut_free(buf);
}
+#endif /* UNIV_HOTBACKUP */
+#ifdef UNIV_LOG_ARCHIVE
/**********************************************************
Reads from the archive of a log group and performs recovery. */
static
@@ -3202,7 +3194,6 @@ ask_again:
break;
}
-#ifdef UNIV_LOG_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Archive read starting at lsn %lu %lu, len %lu from file %s\n",
@@ -3210,7 +3201,6 @@ ask_again:
(ulong) ut_dulint_get_low(start_lsn),
(ulong) len, name);
}
-#endif /* UNIV_LOG_DEBUG */
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE,
group->archive_space_id, read_offset / UNIV_PAGE_SIZE,
@@ -3364,9 +3354,8 @@ void
recv_recovery_from_archive_finish(void)
/*===================================*/
{
- ut_a(0);
-
recv_recovery_from_checkpoint_finish();
recv_recovery_from_backup_on = FALSE;
}
+#endif /* UNIV_LOG_ARCHIVE */
diff --git a/innobase/mem/mem0dbg.c b/innobase/mem/mem0dbg.c
index 5ace0441180..ea8c296f8cf 100644
--- a/innobase/mem/mem0dbg.c
+++ b/innobase/mem/mem0dbg.c
@@ -22,6 +22,7 @@ static ulint mem_n_allocations = 0;
static ulint mem_total_allocated_memory = 0;
ulint mem_current_allocated_memory = 0;
static ulint mem_max_allocated_memory = 0;
+static ulint mem_last_print_info = 0;
/* Size of the hash table for memory management tracking */
#define MEM_HASH_SIZE 997
@@ -33,7 +34,7 @@ struct mem_hash_node_struct {
UT_LIST_NODE_T(mem_hash_node_t)
list; /* hash list node */
mem_heap_t* heap; /* memory heap */
- char* file_name;/* file where heap was created*/
+ const char* file_name;/* file where heap was created*/
ulint line; /* file line of creation */
ulint nth_heap;/* this is the nth heap created */
UT_LIST_NODE_T(mem_hash_node_t)
@@ -266,7 +267,7 @@ void
mem_hash_insert(
/*============*/
mem_heap_t* heap, /* in: the created heap */
- char* file_name, /* in: file name of creation */
+ const char* file_name, /* in: file name of creation */
ulint line) /* in: line where created */
{
mem_hash_node_t* new_node;
@@ -309,7 +310,7 @@ void
mem_hash_remove(
/*============*/
mem_heap_t* heap, /* in: the heap to be freed */
- char* file_name, /* in: file name of freeing */
+ const char* file_name, /* in: file name of freeing */
ulint line) /* in: line where freed */
{
mem_hash_node_t* node;
@@ -373,7 +374,6 @@ mem_hash_remove(
}
#endif /* UNIV_MEM_DEBUG */
-#ifdef UNIV_DEBUG
/*******************************************************************
Checks a memory heap for consistency and prints the contents if requested.
Outputs the sum of sizes of buffers given to the user (only in
@@ -603,7 +603,6 @@ mem_heap_validate(
return(TRUE);
}
-#endif /* UNIV_DEBUG */
#ifdef UNIV_MEM_DEBUG
/*********************************************************************
@@ -816,3 +815,128 @@ mem_analyze_corruption(
dist++;
}
}
+
+/*********************************************************************
+Prints information of dynamic memory usage and currently allocated
+memory heaps or buffers. Can only be used in the debug version. */
+static
+void
+mem_print_info_low(
+/*===============*/
+ ibool print_all) /* in: if TRUE, all heaps are printed,
+ else only the heaps allocated after the
+ previous call of this function */
+{
+#ifdef UNIV_MEM_DEBUG
+ mem_hash_node_t* node;
+ ulint n_heaps = 0;
+ ulint allocated_mem;
+ ulint ph_size;
+ ulint total_allocated_mem = 0;
+ ibool error;
+ ulint n_blocks;
+#endif
+ FILE* outfile;
+
+ /* outfile = fopen("ibdebug", "a"); */
+
+ outfile = stdout;
+
+ fprintf(outfile, "\n");
+ fprintf(outfile,
+ "________________________________________________________\n");
+ fprintf(outfile, "MEMORY ALLOCATION INFORMATION\n\n");
+
+#ifndef UNIV_MEM_DEBUG
+
+ UT_NOT_USED(print_all);
+
+ mem_pool_print_info(outfile, mem_comm_pool);
+
+ fprintf(outfile,
+ "Sorry, non-debug version cannot give more memory info\n");
+
+ /* fclose(outfile); */
+
+ return;
+#else
+ mutex_enter(&mem_hash_mutex);
+
+ fprintf(outfile, "LIST OF CREATED HEAPS AND ALLOCATED BUFFERS: \n\n");
+
+ if (!print_all) {
+ fprintf(outfile, "AFTER THE LAST PRINT INFO\n");
+ }
+
+ node = UT_LIST_GET_FIRST(mem_all_list_base);
+
+ while (node != NULL) {
+ n_heaps++;
+
+ if (!print_all && node->nth_heap < mem_last_print_info) {
+
+ goto next_heap;
+ }
+
+ mem_heap_validate_or_print(node->heap, NULL,
+ FALSE, &error, &allocated_mem,
+ &ph_size, &n_blocks);
+ total_allocated_mem += allocated_mem;
+
+ fprintf(outfile,
+ "%lu: file %s line %lu of size %lu phys.size %lu with %lu blocks, type %lu\n",
+ node->nth_heap, node->file_name, node->line,
+ allocated_mem, ph_size, n_blocks,
+ (node->heap)->type);
+ next_heap:
+ node = UT_LIST_GET_NEXT(all_list, node);
+ }
+
+ fprintf(outfile, "\n");
+
+ fprintf(outfile, "Current allocated memory : %lu\n",
+ mem_current_allocated_memory);
+ fprintf(outfile, "Current allocated heaps and buffers : %lu\n",
+ n_heaps);
+ fprintf(outfile, "Cumulative allocated memory : %lu\n",
+ mem_total_allocated_memory);
+ fprintf(outfile, "Maximum allocated memory : %lu\n",
+ mem_max_allocated_memory);
+ fprintf(outfile, "Cumulative created heaps and buffers : %lu\n",
+ mem_n_created_heaps);
+ fprintf(outfile, "Cumulative number of allocations : %lu\n",
+ mem_n_allocations);
+
+ mem_last_print_info = mem_n_created_heaps;
+
+ mutex_exit(&mem_hash_mutex);
+
+ mem_pool_print_info(outfile, mem_comm_pool);
+
+/* mem_validate(); */
+
+/* fclose(outfile); */
+#endif
+}
+
+/*********************************************************************
+Prints information of dynamic memory usage and currently allocated memory
+heaps or buffers. Can only be used in the debug version. */
+
+void
+mem_print_info(void)
+/*================*/
+{
+ mem_print_info_low(TRUE);
+}
+
+/*********************************************************************
+Prints information of dynamic memory usage and currently allocated memory
+heaps or buffers since the last ..._print_info or..._print_new_info. */
+
+void
+mem_print_new_info(void)
+/*====================*/
+{
+ mem_print_info_low(FALSE);
+}
diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c
index 0227c2d0969..023369e8ec5 100644
--- a/innobase/mem/mem0pool.c
+++ b/innobase/mem/mem0pool.c
@@ -559,7 +559,6 @@ mem_area_free(
ut_ad(mem_pool_validate(pool));
}
-#ifdef UNIV_DEBUG
/************************************************************************
Validates a memory pool. */
@@ -637,7 +636,6 @@ mem_pool_print_info(
(ulong) pool->reserved);
mutex_exit(&(pool->mutex));
}
-#endif /* UNIV_DEBUG */
/************************************************************************
Returns the amount of reserved memory. */
diff --git a/innobase/mtr/mtr0mtr.c b/innobase/mtr/mtr0mtr.c
index fa1481dcb5f..6e918806eb1 100644
--- a/innobase/mtr/mtr0mtr.c
+++ b/innobase/mtr/mtr0mtr.c
@@ -106,179 +106,6 @@ mtr_memo_pop_all(
}
/****************************************************************
-Writes to the log the contents of a full page. This is called when the
-database is in the online backup state. */
-static
-void
-mtr_log_write_full_page(
-/*====================*/
- page_t* page, /* in: page to write */
- ulint i, /* in: i'th page for mtr */
- ulint n_pages,/* in: total number of pages for mtr */
- mtr_t* mtr) /* in: mtr */
-{
- byte* buf;
- byte* ptr;
- ulint len;
-
- buf = mem_alloc(UNIV_PAGE_SIZE + 50);
-
- ptr = mlog_write_initial_log_record_fast(page, MLOG_FULL_PAGE, buf,
- mtr);
- ut_memcpy(ptr, page, UNIV_PAGE_SIZE);
-
- len = (ptr - buf) + UNIV_PAGE_SIZE;
-
- if (i == n_pages - 1) {
- if (n_pages > 1) {
- *(buf + len) = MLOG_MULTI_REC_END;
- len++;
- } else {
- *buf = (byte)((ulint)*buf | MLOG_SINGLE_REC_FLAG);
- }
- }
-
- ut_ad(len < UNIV_PAGE_SIZE + 50);
-
- log_write_low(buf, len);
-
- mem_free(buf);
-}
-
-/****************************************************************
-Parses a log record which contains the full contents of a page. */
-
-byte*
-mtr_log_parse_full_page(
-/*====================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page) /* in: page or NULL */
-{
- if (end_ptr < ptr + UNIV_PAGE_SIZE) {
-
- return(NULL);
- }
-
- if (page) {
- ut_memcpy(page, ptr, UNIV_PAGE_SIZE);
- }
-
- return(ptr + UNIV_PAGE_SIZE);
-}
-
-/****************************************************************
-Writes to the database log the full contents of the pages that this mtr has
-modified. */
-static
-void
-mtr_log_write_backup_full_pages(
-/*============================*/
- mtr_t* mtr, /* in: mini-transaction */
- ulint n_pages)/* in: number of pages modified by mtr */
-{
- mtr_memo_slot_t* slot;
- dyn_array_t* memo;
- buf_block_t* block;
- ulint offset;
- ulint type;
- ulint i;
-
- ut_ad(mtr);
- ut_ad(mtr->magic_n == MTR_MAGIC_N);
- ut_ad(mtr->state == MTR_COMMITTING);
-
- /* Open the database log for log_write_low */
- mtr->start_lsn = log_reserve_and_open(n_pages * (UNIV_PAGE_SIZE + 50));
-
- memo = &(mtr->memo);
-
- offset = dyn_array_get_data_size(memo);
-
- i = 0;
-
- while (offset > 0) {
- offset -= sizeof(mtr_memo_slot_t);
- slot = dyn_array_get_element(memo, offset);
-
- block = slot->object;
- type = slot->type;
-
- if ((block != NULL) && (type == MTR_MEMO_PAGE_X_FIX)) {
-
- mtr_log_write_full_page(block->frame, i, n_pages, mtr);
-
- i++;
- }
- }
-
- ut_ad(i == n_pages);
-}
-
-/****************************************************************
-Checks if mtr is the first to modify any page after online_backup_lsn. */
-static
-ibool
-mtr_first_to_modify_page_after_backup(
-/*==================================*/
- /* out: TRUE if first for a page */
- mtr_t* mtr, /* in: mini-transaction */
- ulint* n_pages) /* out: number of modified pages (all modified
- pages, backup_lsn does not matter here) */
-{
- mtr_memo_slot_t* slot;
- dyn_array_t* memo;
- ulint offset;
- buf_block_t* block;
- ulint type;
- dulint backup_lsn;
- ibool ret = FALSE;
-
- ut_ad(mtr);
- ut_ad(mtr->magic_n == MTR_MAGIC_N);
- ut_ad(mtr->state == MTR_COMMITTING);
-
- backup_lsn = log_get_online_backup_lsn_low();
-
- memo = &(mtr->memo);
-
- offset = dyn_array_get_data_size(memo);
-
- *n_pages = 0;
-
- while (offset > 0) {
- offset -= sizeof(mtr_memo_slot_t);
- slot = dyn_array_get_element(memo, offset);
-
- block = slot->object;
- type = slot->type;
-
- if ((block != NULL) && (type == MTR_MEMO_PAGE_X_FIX)) {
-
- *n_pages = *n_pages + 1;
-
- if (ut_dulint_cmp(buf_frame_get_newest_modification(
- block->frame),
- backup_lsn) <= 0) {
-
- fprintf(stderr,
- "Page %lu newest %lu backup %lu\n",
- (ulong) block->offset,
- (ulong) ut_dulint_get_low(
- buf_frame_get_newest_modification(
- block->frame)),
- (ulong) ut_dulint_get_low(backup_lsn));
-
- ret = TRUE;
- }
- }
- }
-
- return(ret);
-}
-
-/****************************************************************
Writes the contents of a mini-transaction log, if any, to the database log. */
static
void
@@ -291,7 +118,6 @@ mtr_log_reserve_and_write(
ulint data_size;
ibool success;
byte* first_data;
- ulint n_modified_pages;
ut_ad(mtr);
@@ -322,27 +148,12 @@ mtr_log_reserve_and_write(
if (mtr->log_mode == MTR_LOG_ALL) {
- if (log_get_online_backup_state_low()
- && mtr_first_to_modify_page_after_backup(mtr,
- &n_modified_pages)) {
-
- /* The database is in the online backup state: write
- to the log the full contents of all the pages if this
- mtr is the first to modify any page in the buffer pool
- after online_backup_lsn */
-
- log_close();
- log_release();
-
- mtr_log_write_backup_full_pages(mtr, n_modified_pages);
- } else {
- block = mlog;
+ block = mlog;
- while (block != NULL) {
- log_write_low(dyn_block_get_data(block),
- dyn_block_get_used(block));
- block = dyn_array_get_next_block(mlog, block);
- }
+ while (block != NULL) {
+ log_write_low(dyn_block_get_data(block),
+ dyn_block_get_used(block));
+ block = dyn_array_get_next_block(mlog, block);
}
} else {
ut_ad(mtr->log_mode == MTR_LOG_NONE);
@@ -508,7 +319,6 @@ mtr_read_dulint(
return(mach_read_from_8(ptr));
}
-#ifdef UNIV_DEBUG
/*************************************************************
Prints info of an mtr handle. */
@@ -522,4 +332,3 @@ mtr_print(
(ulong) dyn_array_get_data_size(&(mtr->memo)),
(ulong) dyn_array_get_data_size(&(mtr->log)));
}
-#endif /* UNIV_DEBUG */
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 5f5060c7464..d5ca8f927c6 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -311,14 +311,11 @@ os_file_handle_error(
/*=================*/
/* out: TRUE if we should retry the
operation */
- os_file_t file, /* in: file pointer */
const char* name, /* in: name of a file or NULL */
const char* operation)/* in: operation */
{
ulint err;
- UT_NOT_USED(file);
-
err = os_file_get_last_error(FALSE);
if (err == OS_FILE_DISK_FULL) {
@@ -371,7 +368,7 @@ os_file_handle_error(
#undef USE_FILE_LOCK
#define USE_FILE_LOCK
-#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__FreeBSD__)
+#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__FreeBSD__) || defined(__NETWARE__)
/* InnoDB Hot Backup does not lock the data files.
* On Windows, mandatory locking is used.
* On FreeBSD with LinuxThreads, advisory locking does not work properly.
@@ -387,22 +384,19 @@ os_file_lock(
/*=========*/
/* out: 0 on success */
int fd, /* in: file descriptor */
- const char* name, /* in: file name */
- uint lock_type) /* in: lock_type */
+ const char* name) /* in: file name */
{
struct flock lk;
- lk.l_type = lock_type;
+ lk.l_type = F_WRLCK;
lk.l_whence = SEEK_SET;
lk.l_start = lk.l_len = 0;
if (fcntl(fd, F_SETLK, &lk) == -1) {
fprintf(stderr,
- "InnoDB: Unable to lock %s with lock %d, error: %d",
- name, lock_type, errno);
- perror (": fcntl");
+ "InnoDB: Unable to lock %s, error: %d", name, errno);
close(fd);
return(-1);
}
- return 0;
+ return(0);
}
#endif /* USE_FILE_LOCK */
@@ -485,6 +479,25 @@ os_io_init_simple(void)
}
/***************************************************************************
+Creates a temporary file. In case of error, causes abnormal termination. */
+
+FILE*
+os_file_create_tmpfile(void)
+/*========================*/
+ /* out: temporary file handle (never NULL) */
+{
+ FILE* file = tmpfile();
+ if (file == NULL) {
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Error: unable to create temporary file\n",
+ stderr);
+ os_file_handle_error(NULL, "tmpfile");
+ ut_error;
+ }
+ return(file);
+}
+
+/***************************************************************************
The os_file_opendir() function opens a directory stream corresponding to the
directory named by the dirname argument. The directory stream is positioned
at the first entry. In both Unix and Windows we automatically skip the '.'
@@ -526,7 +539,7 @@ os_file_opendir(
if (dir == INVALID_HANDLE_VALUE) {
if (error_is_fatal) {
- os_file_handle_error(NULL, dirname, "opendir");
+ os_file_handle_error(dirname, "opendir");
}
return(NULL);
@@ -537,7 +550,7 @@ os_file_opendir(
dir = opendir(dirname);
if (dir == NULL && error_is_fatal) {
- os_file_handle_error(0, dirname, "opendir");
+ os_file_handle_error(dirname, "opendir");
}
return(dir);
@@ -720,7 +733,7 @@ os_file_create_directory(
if (!(rcode != 0 ||
(GetLastError() == ERROR_FILE_EXISTS && !fail_if_exists))) {
/* failure */
- os_file_handle_error(NULL, pathname, "CreateDirectory");
+ os_file_handle_error(pathname, "CreateDirectory");
return(FALSE);
}
@@ -733,7 +746,7 @@ os_file_create_directory(
if (!(rcode == 0 || (errno == EEXIST && !fail_if_exists))) {
/* failure */
- os_file_handle_error(0, pathname, "mkdir");
+ os_file_handle_error(pathname, "mkdir");
return(FALSE);
}
@@ -812,7 +825,7 @@ try_again:
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
- retry = os_file_handle_error(file, name,
+ retry = os_file_handle_error(name,
create_mode == OS_FILE_OPEN ?
"open" : "create");
if (retry) {
@@ -862,14 +875,15 @@ try_again:
if (file == -1) {
*success = FALSE;
- retry = os_file_handle_error(file, name,
+ retry = os_file_handle_error(name,
create_mode == OS_FILE_OPEN ?
"open" : "create");
if (retry) {
goto try_again;
}
#ifdef USE_FILE_LOCK
- } else if (os_file_lock(file, name, F_WRLCK)) {
+ } else if (access_type == OS_FILE_READ_WRITE
+ && os_file_lock(file, name)) {
*success = FALSE;
file = -1;
#endif
@@ -980,7 +994,8 @@ os_file_create_simple_no_error_handling(
if (file == -1) {
*success = FALSE;
#ifdef USE_FILE_LOCK
- } else if (os_file_lock(file, name, F_WRLCK)) {
+ } else if (access_type == OS_FILE_READ_WRITE
+ && os_file_lock(file, name)) {
*success = FALSE;
file = -1;
#endif
@@ -1102,7 +1117,7 @@ try_again:
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
- retry = os_file_handle_error(file, name,
+ retry = os_file_handle_error(name,
create_mode == OS_FILE_CREATE ?
"create" : "open");
if (retry) {
@@ -1187,14 +1202,15 @@ try_again:
if (file == -1) {
*success = FALSE;
- retry = os_file_handle_error(file, name,
+ retry = os_file_handle_error(name,
create_mode == OS_FILE_CREATE ?
"create" : "open");
if (retry) {
goto try_again;
}
#ifdef USE_FILE_LOCK
- } else if (os_file_lock(file, name, F_WRLCK)) {
+ } else if (create_mode != OS_FILE_OPEN_RAW
+ && os_file_lock(file, name)) {
*success = FALSE;
file = -1;
#endif
@@ -1258,7 +1274,7 @@ loop:
ret = unlink((const char*)name);
if (ret != 0 && errno != ENOENT) {
- os_file_handle_error(0, name, "delete");
+ os_file_handle_error(name, "delete");
return(FALSE);
}
@@ -1320,7 +1336,7 @@ loop:
ret = unlink((const char*)name);
if (ret != 0) {
- os_file_handle_error(0, name, "delete");
+ os_file_handle_error(name, "delete");
return(FALSE);
}
@@ -1350,7 +1366,7 @@ os_file_rename(
return(TRUE);
}
- os_file_handle_error(NULL, oldpath, "rename");
+ os_file_handle_error(oldpath, "rename");
return(FALSE);
#else
@@ -1359,7 +1375,7 @@ os_file_rename(
ret = rename((const char*)oldpath, (const char*)newpath);
if (ret != 0) {
- os_file_handle_error(0, oldpath, "rename");
+ os_file_handle_error(oldpath, "rename");
return(FALSE);
}
@@ -1389,19 +1405,16 @@ os_file_close(
return(TRUE);
}
- os_file_handle_error(file, NULL, "close");
+ os_file_handle_error(NULL, "close");
return(FALSE);
#else
int ret;
-#ifdef USE_FILE_LOCK
- (void) os_file_lock(file, "unknown", F_UNLCK);
-#endif
ret = close(file);
if (ret == -1) {
- os_file_handle_error(file, NULL, "close");
+ os_file_handle_error(NULL, "close");
return(FALSE);
}
@@ -1434,9 +1447,6 @@ os_file_close_no_error_handling(
#else
int ret;
-#ifdef USE_FILE_LOCK
- (void) os_file_lock(file, "unknown", F_UNLCK);
-#endif
ret = close(file);
if (ret == -1) {
@@ -1657,7 +1667,7 @@ os_file_flush(
return(TRUE);
}
- os_file_handle_error(file, NULL, "flush");
+ os_file_handle_error(NULL, "flush");
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
@@ -1692,7 +1702,7 @@ os_file_flush(
fprintf(stderr,
" InnoDB: Error: the OS said file flush did not succeed\n");
- os_file_handle_error(file, NULL, "flush");
+ os_file_handle_error(NULL, "flush");
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
@@ -1740,7 +1750,7 @@ os_file_pread(
os_n_file_reads++;
-#ifdef HAVE_PREAD
+#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
os_mutex_enter(os_file_count_mutex);
os_file_n_pending_preads++;
os_mutex_exit(os_file_count_mutex);
@@ -1815,7 +1825,7 @@ os_file_pwrite(
os_n_file_writes++;
-#ifdef HAVE_PWRITE
+#if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD)
os_mutex_enter(os_file_count_mutex);
os_file_n_pending_pwrites++;
os_mutex_exit(os_file_count_mutex);
@@ -1952,7 +1962,7 @@ try_again:
#ifdef __WIN__
error_handling:
#endif
- retry = os_file_handle_error(file, NULL, "read");
+ retry = os_file_handle_error(NULL, "read");
if (retry) {
goto try_again;
@@ -2331,31 +2341,25 @@ os_file_dirname(
pathname */
const char* path) /* in: pathname */
{
- char* dir;
- int i, length, last_slash;
-
- /* find the offset of the last slash */
- length = ut_strlen(path);
- for (i = length - 1; i >= 0 && path[i] != OS_FILE_PATH_SEPARATOR; i++);
- last_slash = i;
+ /* Find the offset of the last slash */
+ const char* last_slash = strrchr(path, OS_FILE_PATH_SEPARATOR);
+ if (!last_slash) {
+ /* No slash in the path, return "." */
- if (last_slash < 0) {
- /* no slash in the path, return "." */
return(mem_strdup("."));
}
- /* ok, there is a slash */
+ /* Ok, there is a slash */
- if (last_slash == 0) {
+ if (last_slash == path) {
/* last slash is the first char of the path */
+
return(mem_strdup("/"));
}
- /* non-trivial directory component */
- dir = mem_strdup(path);
- dir[last_slash] = 0;
+ /* Non-trivial directory component */
- return(dir);
+ return(mem_strdupl(path, last_slash - path));
}
/********************************************************************
@@ -2369,30 +2373,33 @@ os_file_create_subdirs_if_needed(
const char* path) /* in: path name */
{
char* subdir;
- static char rootdir[2] = { OS_FILE_PATH_SEPARATOR, 0 };
ibool success, subdir_exists;
os_file_type_t type;
subdir = os_file_dirname(path);
- if (0 == strcmp(subdir, rootdir) || 0 == strcmp(subdir, ".")) {
+ if (strlen(subdir) == 1
+ && (*subdir == OS_FILE_PATH_SEPARATOR || *subdir == '.')) {
/* subdir is root or cwd, nothing to do */
- ut_free(subdir);
+ mem_free(subdir);
+
return(TRUE);
}
- /* test if subdir exists */
+ /* Test if subdir exists */
success = os_file_status(subdir, &subdir_exists, &type);
if (success && !subdir_exists) {
/* subdir does not exist, create it */
success = os_file_create_subdirs_if_needed(subdir);
if (!success) {
- ut_free(subdir);
+ mem_free(subdir);
+
return(FALSE);
}
success = os_file_create_directory(subdir, FALSE);
}
- ut_free(subdir);
+ mem_free(subdir);
+
return(success);
}
@@ -3172,7 +3179,7 @@ try_again:
os_aio_array_free_slot(array, slot);
- retry = os_file_handle_error(file, name,
+ retry = os_file_handle_error(name,
type == OS_FILE_READ ? "aio read" : "aio write");
if (retry) {
@@ -3272,7 +3279,7 @@ os_aio_windows_handle(
ut_a(TRUE == os_file_flush(slot->file));
}
} else {
- os_file_handle_error(slot->file, slot->name, "Windows aio");
+ os_file_handle_error(slot->name, "Windows aio");
ret_val = FALSE;
}
diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c
index 59d0fdbd8c9..12a8abf3069 100644
--- a/innobase/os/os0thread.c
+++ b/innobase/os/os0thread.c
@@ -201,6 +201,15 @@ os_thread_exit(
#endif
}
+#ifdef HAVE_PTHREAD_JOIN
+int
+os_thread_join(
+/*=============*/
+ os_thread_id_t thread_id) /* in: id of the thread to join */
+{
+ return pthread_join(thread_id, NULL);
+}
+#endif
/*********************************************************************
Returns handle to the current thread. */
diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c
index aecc2dc4fd2..b5f411c43fc 100644
--- a/innobase/page/page0page.c
+++ b/innobase/page/page0page.c
@@ -325,7 +325,7 @@ page_create(
tuple = dtuple_create(heap, 1);
field = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(field,(char *) "infimum", strlen("infimum") + 1);
+ dfield_set_data(field, "infimum", sizeof "infimum");
dtype_set(dfield_get_type(field), DATA_VARCHAR, DATA_ENGLISH, 20, 0);
/* Set the corresponding physical record to its place in the page
@@ -347,7 +347,7 @@ page_create(
tuple = dtuple_create(heap, 1);
field = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(field, (char *) "supremum", strlen("supremum") + 1);
+ dfield_set_data(field, "supremum", sizeof "supremum");
dtype_set(dfield_get_type(field), DATA_VARCHAR, DATA_ENGLISH, 20, 0);
supremum_rec = rec_convert_dtuple_to_rec(heap_top, tuple);
diff --git a/innobase/pars/lexyy.c b/innobase/pars/lexyy.c
index 1b8c69ccc7a..0112f618533 100644
--- a/innobase/pars/lexyy.c
+++ b/innobase/pars/lexyy.c
@@ -25,7 +25,6 @@
#ifdef __cplusplus
#include <stdlib.h>
-#include <unistd.h>
/* Use prototypes in function declarations. */
#define YY_USE_PROTOS
@@ -636,9 +635,9 @@ Linux.
#include "mem0mem.h"
#include "os0proc.h"
-#define malloc(A) mem_alloc(A)
-#define free(A) mem_free(A)
-#define realloc(P, A) mem_realloc(P, A, __FILE__, __LINE__)
+#define malloc(A) ut_malloc(A)
+#define free(A) ut_free(A)
+#define realloc(P, A) ut_realloc(P, A)
#define exit(A) ut_error
#define YY_INPUT(buf, result, max_size) pars_get_lex_chars(buf, &result, max_size)
@@ -655,16 +654,16 @@ string_append(
const char* str, /* in: string to be appended */
ulint len) /* in: length of the string */
{
+ if (stringbuf == NULL) {
+ stringbuf = malloc(1);
+ stringbuf_len_alloc = 1;
+ }
+
if (stringbuf_len + len > stringbuf_len_alloc) {
- if (stringbuf_len_alloc == 0) {
- stringbuf_len_alloc++;
- }
while (stringbuf_len + len > stringbuf_len_alloc) {
stringbuf_len_alloc <<= 1;
}
- stringbuf = stringbuf
- ? realloc(stringbuf, stringbuf_len_alloc)
- : malloc(stringbuf_len_alloc);
+ stringbuf = realloc(stringbuf, stringbuf_len_alloc);
}
memcpy(stringbuf + stringbuf_len, str, len);
@@ -934,31 +933,54 @@ case 3:
YY_RULE_SETUP
#line 116 "pars0lex.l"
{
+/* Quoted character string literals are handled in an explicit
+start state 'quoted'. This state is entered and the buffer for
+the scanned string is emptied upon encountering a starting quote.
+
+In the state 'quoted', only two actions are possible (defined below). */
BEGIN(quoted);
stringbuf_len = 0;
}
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 120 "pars0lex.l"
-string_append(yytext, yyleng);
+#line 125 "pars0lex.l"
+{
+ /* Got a sequence of characters other than "'":
+ append to string buffer */
+ string_append(yytext, yyleng);
+}
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 121 "pars0lex.l"
-{ string_append(yytext, yyleng / 2);
+#line 130 "pars0lex.l"
+{
+ /* Got a sequence of "'" characters:
+ append half of them to string buffer,
+ as "''" represents a single "'".
+ We apply truncating division,
+ so that "'''" will result in "'". */
+
+ string_append(yytext, yyleng / 2);
+
+ /* If we got an odd number of quotes, then the
+ last quote we got is the terminating quote.
+ At the end of the string, we return to the
+ initial start state and report the scanned
+ string literal. */
+
if (yyleng % 2) {
BEGIN(INITIAL);
yylval = sym_tab_add_str_lit(
pars_sym_tab_global,
- stringbuf, stringbuf_len);
+ (byte*) stringbuf, stringbuf_len);
return(PARS_STR_LIT);
}
}
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 131 "pars0lex.l"
+#line 154 "pars0lex.l"
{
yylval = sym_tab_add_null_lit(pars_sym_tab_global);
@@ -967,521 +989,521 @@ YY_RULE_SETUP
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 137 "pars0lex.l"
+#line 160 "pars0lex.l"
{
/* Implicit cursor name */
yylval = sym_tab_add_str_lit(pars_sym_tab_global,
- yytext, yyleng);
+ (byte*) yytext, yyleng);
return(PARS_SQL_TOKEN);
}
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 144 "pars0lex.l"
+#line 167 "pars0lex.l"
{
return(PARS_AND_TOKEN);
}
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 148 "pars0lex.l"
+#line 171 "pars0lex.l"
{
return(PARS_OR_TOKEN);
}
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 152 "pars0lex.l"
+#line 175 "pars0lex.l"
{
return(PARS_NOT_TOKEN);
}
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 156 "pars0lex.l"
+#line 179 "pars0lex.l"
{
return(PARS_PROCEDURE_TOKEN);
}
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 160 "pars0lex.l"
+#line 183 "pars0lex.l"
{
return(PARS_IN_TOKEN);
}
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 164 "pars0lex.l"
+#line 187 "pars0lex.l"
{
return(PARS_OUT_TOKEN);
}
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 168 "pars0lex.l"
+#line 191 "pars0lex.l"
{
return(PARS_INT_TOKEN);
}
YY_BREAK
case 15:
YY_RULE_SETUP
-#line 172 "pars0lex.l"
+#line 195 "pars0lex.l"
{
return(PARS_INT_TOKEN);
}
YY_BREAK
case 16:
YY_RULE_SETUP
-#line 176 "pars0lex.l"
+#line 199 "pars0lex.l"
{
return(PARS_FLOAT_TOKEN);
}
YY_BREAK
case 17:
YY_RULE_SETUP
-#line 180 "pars0lex.l"
+#line 203 "pars0lex.l"
{
return(PARS_CHAR_TOKEN);
}
YY_BREAK
case 18:
YY_RULE_SETUP
-#line 184 "pars0lex.l"
+#line 207 "pars0lex.l"
{
return(PARS_IS_TOKEN);
}
YY_BREAK
case 19:
YY_RULE_SETUP
-#line 188 "pars0lex.l"
+#line 211 "pars0lex.l"
{
return(PARS_BEGIN_TOKEN);
}
YY_BREAK
case 20:
YY_RULE_SETUP
-#line 192 "pars0lex.l"
+#line 215 "pars0lex.l"
{
return(PARS_END_TOKEN);
}
YY_BREAK
case 21:
YY_RULE_SETUP
-#line 196 "pars0lex.l"
+#line 219 "pars0lex.l"
{
return(PARS_IF_TOKEN);
}
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 200 "pars0lex.l"
+#line 223 "pars0lex.l"
{
return(PARS_THEN_TOKEN);
}
YY_BREAK
case 23:
YY_RULE_SETUP
-#line 204 "pars0lex.l"
+#line 227 "pars0lex.l"
{
return(PARS_ELSE_TOKEN);
}
YY_BREAK
case 24:
YY_RULE_SETUP
-#line 208 "pars0lex.l"
+#line 231 "pars0lex.l"
{
return(PARS_ELSIF_TOKEN);
}
YY_BREAK
case 25:
YY_RULE_SETUP
-#line 212 "pars0lex.l"
+#line 235 "pars0lex.l"
{
return(PARS_LOOP_TOKEN);
}
YY_BREAK
case 26:
YY_RULE_SETUP
-#line 216 "pars0lex.l"
+#line 239 "pars0lex.l"
{
return(PARS_WHILE_TOKEN);
}
YY_BREAK
case 27:
YY_RULE_SETUP
-#line 220 "pars0lex.l"
+#line 243 "pars0lex.l"
{
return(PARS_RETURN_TOKEN);
}
YY_BREAK
case 28:
YY_RULE_SETUP
-#line 224 "pars0lex.l"
+#line 247 "pars0lex.l"
{
return(PARS_SELECT_TOKEN);
}
YY_BREAK
case 29:
YY_RULE_SETUP
-#line 228 "pars0lex.l"
+#line 251 "pars0lex.l"
{
return(PARS_SUM_TOKEN);
}
YY_BREAK
case 30:
YY_RULE_SETUP
-#line 232 "pars0lex.l"
+#line 255 "pars0lex.l"
{
return(PARS_COUNT_TOKEN);
}
YY_BREAK
case 31:
YY_RULE_SETUP
-#line 236 "pars0lex.l"
+#line 259 "pars0lex.l"
{
return(PARS_DISTINCT_TOKEN);
}
YY_BREAK
case 32:
YY_RULE_SETUP
-#line 240 "pars0lex.l"
+#line 263 "pars0lex.l"
{
return(PARS_FROM_TOKEN);
}
YY_BREAK
case 33:
YY_RULE_SETUP
-#line 244 "pars0lex.l"
+#line 267 "pars0lex.l"
{
return(PARS_WHERE_TOKEN);
}
YY_BREAK
case 34:
YY_RULE_SETUP
-#line 248 "pars0lex.l"
+#line 271 "pars0lex.l"
{
return(PARS_FOR_TOKEN);
}
YY_BREAK
case 35:
YY_RULE_SETUP
-#line 252 "pars0lex.l"
+#line 275 "pars0lex.l"
{
return(PARS_CONSISTENT_TOKEN);
}
YY_BREAK
case 36:
YY_RULE_SETUP
-#line 256 "pars0lex.l"
+#line 279 "pars0lex.l"
{
return(PARS_READ_TOKEN);
}
YY_BREAK
case 37:
YY_RULE_SETUP
-#line 260 "pars0lex.l"
+#line 283 "pars0lex.l"
{
return(PARS_ORDER_TOKEN);
}
YY_BREAK
case 38:
YY_RULE_SETUP
-#line 264 "pars0lex.l"
+#line 287 "pars0lex.l"
{
return(PARS_BY_TOKEN);
}
YY_BREAK
case 39:
YY_RULE_SETUP
-#line 268 "pars0lex.l"
+#line 291 "pars0lex.l"
{
return(PARS_ASC_TOKEN);
}
YY_BREAK
case 40:
YY_RULE_SETUP
-#line 272 "pars0lex.l"
+#line 295 "pars0lex.l"
{
return(PARS_DESC_TOKEN);
}
YY_BREAK
case 41:
YY_RULE_SETUP
-#line 276 "pars0lex.l"
+#line 299 "pars0lex.l"
{
return(PARS_INSERT_TOKEN);
}
YY_BREAK
case 42:
YY_RULE_SETUP
-#line 280 "pars0lex.l"
+#line 303 "pars0lex.l"
{
return(PARS_INTO_TOKEN);
}
YY_BREAK
case 43:
YY_RULE_SETUP
-#line 284 "pars0lex.l"
+#line 307 "pars0lex.l"
{
return(PARS_VALUES_TOKEN);
}
YY_BREAK
case 44:
YY_RULE_SETUP
-#line 288 "pars0lex.l"
+#line 311 "pars0lex.l"
{
return(PARS_UPDATE_TOKEN);
}
YY_BREAK
case 45:
YY_RULE_SETUP
-#line 292 "pars0lex.l"
+#line 315 "pars0lex.l"
{
return(PARS_SET_TOKEN);
}
YY_BREAK
case 46:
YY_RULE_SETUP
-#line 296 "pars0lex.l"
+#line 319 "pars0lex.l"
{
return(PARS_DELETE_TOKEN);
}
YY_BREAK
case 47:
YY_RULE_SETUP
-#line 300 "pars0lex.l"
+#line 323 "pars0lex.l"
{
return(PARS_CURRENT_TOKEN);
}
YY_BREAK
case 48:
YY_RULE_SETUP
-#line 304 "pars0lex.l"
+#line 327 "pars0lex.l"
{
return(PARS_OF_TOKEN);
}
YY_BREAK
case 49:
YY_RULE_SETUP
-#line 308 "pars0lex.l"
+#line 331 "pars0lex.l"
{
return(PARS_CREATE_TOKEN);
}
YY_BREAK
case 50:
YY_RULE_SETUP
-#line 312 "pars0lex.l"
+#line 335 "pars0lex.l"
{
return(PARS_TABLE_TOKEN);
}
YY_BREAK
case 51:
YY_RULE_SETUP
-#line 316 "pars0lex.l"
+#line 339 "pars0lex.l"
{
return(PARS_INDEX_TOKEN);
}
YY_BREAK
case 52:
YY_RULE_SETUP
-#line 320 "pars0lex.l"
+#line 343 "pars0lex.l"
{
return(PARS_UNIQUE_TOKEN);
}
YY_BREAK
case 53:
YY_RULE_SETUP
-#line 324 "pars0lex.l"
+#line 347 "pars0lex.l"
{
return(PARS_CLUSTERED_TOKEN);
}
YY_BREAK
case 54:
YY_RULE_SETUP
-#line 328 "pars0lex.l"
+#line 351 "pars0lex.l"
{
return(PARS_DOES_NOT_FIT_IN_MEM_TOKEN);
}
YY_BREAK
case 55:
YY_RULE_SETUP
-#line 332 "pars0lex.l"
+#line 355 "pars0lex.l"
{
return(PARS_ON_TOKEN);
}
YY_BREAK
case 56:
YY_RULE_SETUP
-#line 336 "pars0lex.l"
+#line 359 "pars0lex.l"
{
return(PARS_DECLARE_TOKEN);
}
YY_BREAK
case 57:
YY_RULE_SETUP
-#line 340 "pars0lex.l"
+#line 363 "pars0lex.l"
{
return(PARS_CURSOR_TOKEN);
}
YY_BREAK
case 58:
YY_RULE_SETUP
-#line 344 "pars0lex.l"
+#line 367 "pars0lex.l"
{
return(PARS_OPEN_TOKEN);
}
YY_BREAK
case 59:
YY_RULE_SETUP
-#line 348 "pars0lex.l"
+#line 371 "pars0lex.l"
{
return(PARS_FETCH_TOKEN);
}
YY_BREAK
case 60:
YY_RULE_SETUP
-#line 352 "pars0lex.l"
+#line 375 "pars0lex.l"
{
return(PARS_CLOSE_TOKEN);
}
YY_BREAK
case 61:
YY_RULE_SETUP
-#line 356 "pars0lex.l"
+#line 379 "pars0lex.l"
{
return(PARS_NOTFOUND_TOKEN);
}
YY_BREAK
case 62:
YY_RULE_SETUP
-#line 360 "pars0lex.l"
+#line 383 "pars0lex.l"
{
return(PARS_TO_CHAR_TOKEN);
}
YY_BREAK
case 63:
YY_RULE_SETUP
-#line 364 "pars0lex.l"
+#line 387 "pars0lex.l"
{
return(PARS_TO_NUMBER_TOKEN);
}
YY_BREAK
case 64:
YY_RULE_SETUP
-#line 368 "pars0lex.l"
+#line 391 "pars0lex.l"
{
return(PARS_TO_BINARY_TOKEN);
}
YY_BREAK
case 65:
YY_RULE_SETUP
-#line 372 "pars0lex.l"
+#line 395 "pars0lex.l"
{
return(PARS_BINARY_TO_NUMBER_TOKEN);
}
YY_BREAK
case 66:
YY_RULE_SETUP
-#line 376 "pars0lex.l"
+#line 399 "pars0lex.l"
{
return(PARS_SUBSTR_TOKEN);
}
YY_BREAK
case 67:
YY_RULE_SETUP
-#line 380 "pars0lex.l"
+#line 403 "pars0lex.l"
{
return(PARS_REPLSTR_TOKEN);
}
YY_BREAK
case 68:
YY_RULE_SETUP
-#line 384 "pars0lex.l"
+#line 407 "pars0lex.l"
{
return(PARS_CONCAT_TOKEN);
}
YY_BREAK
case 69:
YY_RULE_SETUP
-#line 388 "pars0lex.l"
+#line 411 "pars0lex.l"
{
return(PARS_INSTR_TOKEN);
}
YY_BREAK
case 70:
YY_RULE_SETUP
-#line 392 "pars0lex.l"
+#line 415 "pars0lex.l"
{
return(PARS_LENGTH_TOKEN);
}
YY_BREAK
case 71:
YY_RULE_SETUP
-#line 396 "pars0lex.l"
+#line 419 "pars0lex.l"
{
return(PARS_SYSDATE_TOKEN);
}
YY_BREAK
case 72:
YY_RULE_SETUP
-#line 400 "pars0lex.l"
+#line 423 "pars0lex.l"
{
return(PARS_PRINTF_TOKEN);
}
YY_BREAK
case 73:
YY_RULE_SETUP
-#line 404 "pars0lex.l"
+#line 427 "pars0lex.l"
{
return(PARS_ASSERT_TOKEN);
}
YY_BREAK
case 74:
YY_RULE_SETUP
-#line 408 "pars0lex.l"
+#line 431 "pars0lex.l"
{
return(PARS_RND_TOKEN);
}
YY_BREAK
case 75:
YY_RULE_SETUP
-#line 412 "pars0lex.l"
+#line 435 "pars0lex.l"
{
return(PARS_RND_STR_TOKEN);
}
YY_BREAK
case 76:
YY_RULE_SETUP
-#line 416 "pars0lex.l"
+#line 439 "pars0lex.l"
{
return(PARS_ROW_PRINTF_TOKEN);
}
YY_BREAK
case 77:
YY_RULE_SETUP
-#line 420 "pars0lex.l"
+#line 443 "pars0lex.l"
{
return(PARS_COMMIT_TOKEN);
}
YY_BREAK
case 78:
YY_RULE_SETUP
-#line 424 "pars0lex.l"
+#line 447 "pars0lex.l"
{
return(PARS_ROLLBACK_TOKEN);
}
YY_BREAK
case 79:
YY_RULE_SETUP
-#line 428 "pars0lex.l"
+#line 451 "pars0lex.l"
{
return(PARS_WORK_TOKEN);
}
YY_BREAK
case 80:
YY_RULE_SETUP
-#line 432 "pars0lex.l"
+#line 455 "pars0lex.l"
{
yylval = sym_tab_add_id(pars_sym_tab_global,
(byte*)yytext,
@@ -1491,42 +1513,42 @@ YY_RULE_SETUP
YY_BREAK
case 81:
YY_RULE_SETUP
-#line 439 "pars0lex.l"
+#line 462 "pars0lex.l"
{
return(PARS_DDOT_TOKEN);
}
YY_BREAK
case 82:
YY_RULE_SETUP
-#line 443 "pars0lex.l"
+#line 466 "pars0lex.l"
{
return(PARS_ASSIGN_TOKEN);
}
YY_BREAK
case 83:
YY_RULE_SETUP
-#line 447 "pars0lex.l"
+#line 470 "pars0lex.l"
{
return(PARS_LE_TOKEN);
}
YY_BREAK
case 84:
YY_RULE_SETUP
-#line 451 "pars0lex.l"
+#line 474 "pars0lex.l"
{
return(PARS_GE_TOKEN);
}
YY_BREAK
case 85:
YY_RULE_SETUP
-#line 455 "pars0lex.l"
+#line 478 "pars0lex.l"
{
return(PARS_NE_TOKEN);
}
YY_BREAK
case 86:
YY_RULE_SETUP
-#line 459 "pars0lex.l"
+#line 482 "pars0lex.l"
{
return((int)(*yytext));
@@ -1534,7 +1556,7 @@ YY_RULE_SETUP
YY_BREAK
case 87:
YY_RULE_SETUP
-#line 464 "pars0lex.l"
+#line 487 "pars0lex.l"
{
return((int)(*yytext));
@@ -1542,7 +1564,7 @@ YY_RULE_SETUP
YY_BREAK
case 88:
YY_RULE_SETUP
-#line 469 "pars0lex.l"
+#line 492 "pars0lex.l"
{
return((int)(*yytext));
@@ -1550,7 +1572,7 @@ YY_RULE_SETUP
YY_BREAK
case 89:
YY_RULE_SETUP
-#line 474 "pars0lex.l"
+#line 497 "pars0lex.l"
{
return((int)(*yytext));
@@ -1558,7 +1580,7 @@ YY_RULE_SETUP
YY_BREAK
case 90:
YY_RULE_SETUP
-#line 479 "pars0lex.l"
+#line 502 "pars0lex.l"
{
return((int)(*yytext));
@@ -1566,7 +1588,7 @@ YY_RULE_SETUP
YY_BREAK
case 91:
YY_RULE_SETUP
-#line 484 "pars0lex.l"
+#line 507 "pars0lex.l"
{
return((int)(*yytext));
@@ -1574,7 +1596,7 @@ YY_RULE_SETUP
YY_BREAK
case 92:
YY_RULE_SETUP
-#line 489 "pars0lex.l"
+#line 512 "pars0lex.l"
{
return((int)(*yytext));
@@ -1582,7 +1604,7 @@ YY_RULE_SETUP
YY_BREAK
case 93:
YY_RULE_SETUP
-#line 494 "pars0lex.l"
+#line 517 "pars0lex.l"
{
return((int)(*yytext));
@@ -1590,7 +1612,7 @@ YY_RULE_SETUP
YY_BREAK
case 94:
YY_RULE_SETUP
-#line 499 "pars0lex.l"
+#line 522 "pars0lex.l"
{
return((int)(*yytext));
@@ -1598,7 +1620,7 @@ YY_RULE_SETUP
YY_BREAK
case 95:
YY_RULE_SETUP
-#line 504 "pars0lex.l"
+#line 527 "pars0lex.l"
{
return((int)(*yytext));
@@ -1606,7 +1628,7 @@ YY_RULE_SETUP
YY_BREAK
case 96:
YY_RULE_SETUP
-#line 509 "pars0lex.l"
+#line 532 "pars0lex.l"
{
return((int)(*yytext));
@@ -1614,7 +1636,7 @@ YY_RULE_SETUP
YY_BREAK
case 97:
YY_RULE_SETUP
-#line 514 "pars0lex.l"
+#line 537 "pars0lex.l"
{
return((int)(*yytext));
@@ -1622,7 +1644,7 @@ YY_RULE_SETUP
YY_BREAK
case 98:
YY_RULE_SETUP
-#line 519 "pars0lex.l"
+#line 542 "pars0lex.l"
{
return((int)(*yytext));
@@ -1630,7 +1652,7 @@ YY_RULE_SETUP
YY_BREAK
case 99:
YY_RULE_SETUP
-#line 524 "pars0lex.l"
+#line 547 "pars0lex.l"
{
return((int)(*yytext));
@@ -1638,7 +1660,7 @@ YY_RULE_SETUP
YY_BREAK
case 100:
YY_RULE_SETUP
-#line 529 "pars0lex.l"
+#line 552 "pars0lex.l"
{
return((int)(*yytext));
@@ -1646,32 +1668,32 @@ YY_RULE_SETUP
YY_BREAK
case 101:
YY_RULE_SETUP
-#line 534 "pars0lex.l"
+#line 557 "pars0lex.l"
BEGIN(comment); /* eat up comment */
YY_BREAK
case 102:
YY_RULE_SETUP
-#line 536 "pars0lex.l"
+#line 559 "pars0lex.l"
YY_BREAK
case 103:
YY_RULE_SETUP
-#line 537 "pars0lex.l"
+#line 560 "pars0lex.l"
YY_BREAK
case 104:
YY_RULE_SETUP
-#line 538 "pars0lex.l"
+#line 561 "pars0lex.l"
BEGIN(INITIAL);
YY_BREAK
case 105:
YY_RULE_SETUP
-#line 540 "pars0lex.l"
+#line 563 "pars0lex.l"
/* eat up whitespace */
YY_BREAK
case 106:
YY_RULE_SETUP
-#line 543 "pars0lex.l"
+#line 566 "pars0lex.l"
{
fprintf(stderr,"Unrecognized character: %02x\n",
*yytext);
@@ -1683,10 +1705,10 @@ YY_RULE_SETUP
YY_BREAK
case 107:
YY_RULE_SETUP
-#line 552 "pars0lex.l"
+#line 575 "pars0lex.l"
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
-#line 1687 "lex.yy.c"
+#line 1710 "lex.yy.c"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(comment):
case YY_STATE_EOF(quoted):
@@ -2574,5 +2596,5 @@ int main()
return 0;
}
#endif
-#line 552 "pars0lex.l"
+#line 575 "pars0lex.l"
diff --git a/innobase/pars/pars0lex.l b/innobase/pars/pars0lex.l
index 0b1af554bed..811057d48a1 100644
--- a/innobase/pars/pars0lex.l
+++ b/innobase/pars/pars0lex.l
@@ -58,9 +58,9 @@ Linux.
#include "mem0mem.h"
#include "os0proc.h"
-#define malloc(A) mem_alloc(A)
-#define free(A) mem_free(A)
-#define realloc(P, A) mem_realloc(P, A, __FILE__, __LINE__)
+#define malloc(A) ut_malloc(A)
+#define free(A) ut_free(A)
+#define realloc(P, A) ut_realloc(P, A)
#define exit(A) ut_error
#define YY_INPUT(buf, result, max_size) pars_get_lex_chars(buf, &result, max_size)
@@ -77,16 +77,16 @@ string_append(
const char* str, /* in: string to be appended */
ulint len) /* in: length of the string */
{
+ if (stringbuf == NULL) {
+ stringbuf = malloc(1);
+ stringbuf_len_alloc = 1;
+ }
+
if (stringbuf_len + len > stringbuf_len_alloc) {
- if (stringbuf_len_alloc == 0) {
- stringbuf_len_alloc++;
- }
while (stringbuf_len + len > stringbuf_len_alloc) {
stringbuf_len_alloc <<= 1;
}
- stringbuf = stringbuf
- ? realloc(stringbuf, stringbuf_len_alloc)
- : malloc(stringbuf_len_alloc);
+ stringbuf = realloc(stringbuf, stringbuf_len_alloc);
}
memcpy(stringbuf + stringbuf_len, str, len);
@@ -114,11 +114,34 @@ ID [a-z_A-Z][a-z_A-Z0-9]*
}
"'" {
+/* Quoted character string literals are handled in an explicit
+start state 'quoted'. This state is entered and the buffer for
+the scanned string is emptied upon encountering a starting quote.
+
+In the state 'quoted', only two actions are possible (defined below). */
BEGIN(quoted);
stringbuf_len = 0;
}
-<quoted>[^\']+ string_append(yytext, yyleng);
-<quoted>"'"+ { string_append(yytext, yyleng / 2);
+<quoted>[^\']+ {
+ /* Got a sequence of characters other than "'":
+ append to string buffer */
+ string_append(yytext, yyleng);
+}
+<quoted>"'"+ {
+ /* Got a sequence of "'" characters:
+ append half of them to string buffer,
+ as "''" represents a single "'".
+ We apply truncating division,
+ so that "'''" will result in "'". */
+
+ string_append(yytext, yyleng / 2);
+
+ /* If we got an odd number of quotes, then the
+ last quote we got is the terminating quote.
+ At the end of the string, we return to the
+ initial start state and report the scanned
+ string literal. */
+
if (yyleng % 2) {
BEGIN(INITIAL);
yylval = sym_tab_add_str_lit(
diff --git a/innobase/pars/pars0opt.c b/innobase/pars/pars0opt.c
index 4fb0c937f1e..7ba4af15243 100644
--- a/innobase/pars/pars0opt.c
+++ b/innobase/pars/pars0opt.c
@@ -1190,7 +1190,6 @@ opt_search_plan(
#endif
}
-#ifdef UNIV_SQL_DEBUG
/************************************************************************
Prints info of a query plan. */
@@ -1237,4 +1236,3 @@ opt_print_query_plan(
(unsigned long) UT_LIST_GET_LEN(plan->end_conds));
}
}
-#endif /* UNIV_SQL_DEBUG */
diff --git a/innobase/pars/pars0pars.c b/innobase/pars/pars0pars.c
index 12451b4d94d..e4b388cba82 100644
--- a/innobase/pars/pars0pars.c
+++ b/innobase/pars/pars0pars.c
@@ -530,7 +530,7 @@ pars_retrieve_table_def(
/*====================*/
sym_node_t* sym_node) /* in: table node */
{
- char* table_name;
+ const char* table_name;
ut_a(sym_node);
ut_a(que_node_get_type(sym_node) == QUE_NODE_SYMBOL);
@@ -538,7 +538,7 @@ pars_retrieve_table_def(
sym_node->resolved = TRUE;
sym_node->token_type = SYM_TABLE;
- table_name = (char*) sym_node->name;
+ table_name = (const char*) sym_node->name;
sym_node->table = dict_table_get_low(table_name);
diff --git a/innobase/que/que0que.c b/innobase/que/que0que.c
index 08bf7ce3e59..22878dec27f 100644
--- a/innobase/que/que0que.c
+++ b/innobase/que/que0que.c
@@ -12,6 +12,7 @@ Created 5/27/1996 Heikki Tuuri
#include "que0que.ic"
#endif
+#include "srv0que.h"
#include "usr0sess.h"
#include "trx0trx.h"
#include "trx0roll.h"
@@ -174,15 +175,19 @@ a single worker thread to execute it. This function should be used to end
the wait state of a query thread waiting for a lock or a stored procedure
completion. */
-que_thr_t*
+void
que_thr_end_wait(
/*=============*/
- /* out: next query thread to run;
- NULL if none */
- que_thr_t* thr) /* in: query thread in the
+ que_thr_t* thr, /* in: query thread in the
QUE_THR_LOCK_WAIT,
or QUE_THR_PROCEDURE_WAIT, or
QUE_THR_SIG_REPLY_WAIT state */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if NULL is passed
+ as the parameter, it is ignored */
{
ibool was_active;
@@ -190,8 +195,6 @@ que_thr_end_wait(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(thr);
- ut_ad(next_thr);
- ut_ad(*next_thr == NULL);
ut_ad((thr->state == QUE_THR_LOCK_WAIT)
|| (thr->state == QUE_THR_PROCEDURE_WAIT)
|| (thr->state == QUE_THR_SIG_REPLY_WAIT));
@@ -203,8 +206,18 @@ que_thr_end_wait(
que_thr_move_to_run_state(thr);
- return(was_active ? NULL : thr);
-}
+ if (was_active) {
+
+ return;
+ }
+
+ if (next_thr && *next_thr == NULL) {
+ *next_thr = thr;
+ } else {
+ ut_a(0);
+ srv_que_task_enqueue_low(thr);
+ }
+}
/**************************************************************************
Same as que_thr_end_wait, but no parameter next_thr available. */
@@ -241,6 +254,8 @@ que_thr_end_wait_no_next_thr(
for the lock to be released: */
srv_release_mysql_thread_if_suspended(thr);
+
+ /* srv_que_task_enqueue_low(thr); */
}
/**************************************************************************
@@ -341,6 +356,49 @@ que_fork_start_command(
return(NULL);
}
+/**************************************************************************
+After signal handling is finished, returns control to a query graph error
+handling routine. (Currently, just returns the control to the root of the
+graph so that the graph can communicate an error message to the client.) */
+
+void
+que_fork_error_handle(
+/*==================*/
+ trx_t* trx __attribute__((unused)), /* in: trx */
+ que_t* fork) /* in: query graph which was run before signal
+ handling started, NULL not allowed */
+{
+ que_thr_t* thr;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(trx->sess->state == SESS_ERROR);
+ ut_ad(UT_LIST_GET_LEN(trx->reply_signals) == 0);
+ ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
+
+ thr = UT_LIST_GET_FIRST(fork->thrs);
+
+ while (thr != NULL) {
+ ut_ad(!thr->is_active);
+ ut_ad(thr->state != QUE_THR_SIG_REPLY_WAIT);
+ ut_ad(thr->state != QUE_THR_LOCK_WAIT);
+
+ thr->run_node = thr;
+ thr->prev_node = thr->child;
+ thr->state = QUE_THR_COMPLETED;
+
+ thr = UT_LIST_GET_NEXT(thrs, thr);
+ }
+
+ thr = UT_LIST_GET_FIRST(fork->thrs);
+
+ que_thr_move_to_run_state(thr);
+
+ ut_a(0);
+ srv_que_task_enqueue_low(thr);
+}
+
/********************************************************************
Tests if all the query threads in the same fork have a given state. */
UNIV_INLINE
@@ -709,18 +767,22 @@ this function may only be called from inside que_run_threads or
que_thr_check_if_switch! These restrictions exist to make the rollback code
easier to maintain. */
static
-que_thr_t*
+void
que_thr_dec_refer_count(
/*====================*/
- /* out: next query thread to run */
- que_thr_t* thr) /* in: query thread */
+ que_thr_t* thr, /* in: query thread */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread */
{
que_fork_t* fork;
trx_t* trx;
sess_t* sess;
ulint fork_type;
- que_thr_t* next_thr = NULL;
-
+ ibool stopped;
+
fork = thr->common.parent;
trx = thr->graph->trx;
sess = trx->sess;
@@ -731,7 +793,9 @@ que_thr_dec_refer_count(
if (thr->state == QUE_THR_RUNNING) {
- if (!que_thr_stop(thr)) {
+ stopped = que_thr_stop(thr);
+
+ if (!stopped) {
/* The reason for the thr suspension or wait was
already canceled before we came here: continue
running the thread */
@@ -739,9 +803,16 @@ que_thr_dec_refer_count(
/* fputs("!!!!!!!! Wait already ended: continue thr\n",
stderr); */
+ if (next_thr && *next_thr == NULL) {
+ *next_thr = thr;
+ } else {
+ ut_a(0);
+ srv_que_task_enqueue_low(thr);
+ }
+
mutex_exit(&kernel_mutex);
- return(thr);
+ return;
}
}
@@ -757,7 +828,7 @@ que_thr_dec_refer_count(
mutex_exit(&kernel_mutex);
- return(next_thr);
+ return;
}
fork_type = fork->fork_type;
@@ -773,7 +844,7 @@ que_thr_dec_refer_count(
ut_ad(UT_LIST_GET_LEN(trx->signals) > 0);
ut_ad(trx->handling_signals == TRUE);
- next_thr = trx_finish_rollback_off_kernel(fork, trx);
+ trx_finish_rollback_off_kernel(fork, trx, next_thr);
} else if (fork_type == QUE_FORK_PURGE) {
@@ -795,7 +866,7 @@ que_thr_dec_refer_count(
zero, then we start processing a signal; from it we may get
a new query thread to run */
- next_thr = trx_sig_start_handle(trx);
+ trx_sig_start_handle(trx, next_thr);
}
if (trx->handling_signals && UT_LIST_GET_LEN(trx->signals) == 0) {
@@ -804,8 +875,6 @@ que_thr_dec_refer_count(
}
mutex_exit(&kernel_mutex);
-
- return(next_thr);
}
/**************************************************************************
@@ -970,10 +1039,9 @@ que_thr_stop_for_mysql_no_error(
trx->n_active_thrs--;
}
-#ifdef UNIV_DEBUG
/**************************************************************************
Prints info of an SQL query graph node. */
-static
+
void
que_node_print_info(
/*================*/
@@ -1030,7 +1098,6 @@ que_node_print_info(
fprintf(stderr, "Node type %lu: %s, address %p\n", (ulong) type, str, node);
}
-#endif /* UNIV_DEBUG */
/**************************************************************************
Performs an execution step on a query thread. */
@@ -1179,7 +1246,6 @@ loop:
/*-------------------------*/
next_thr = que_thr_step(thr);
/*-------------------------*/
- ut_a(next_thr == thr || next_thr == NULL);
/* Test the effect on performance of adding extra mutex
reservations */
@@ -1192,7 +1258,8 @@ loop:
loop_count++;
if (next_thr != thr) {
- next_thr = que_thr_dec_refer_count(thr);
+ ut_a(next_thr == NULL);
+ que_thr_dec_refer_count(thr, &next_thr);
if (next_thr == NULL) {
diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c
index 254ebeec8c9..6e8f3d82ef3 100644
--- a/innobase/rem/rem0cmp.c
+++ b/innobase/rem/rem0cmp.c
@@ -33,12 +33,13 @@ At the present, the comparison functions return 0 in the case,
where two records disagree only in the way that one
has more fields than the other. */
+#ifdef UNIV_DEBUG
/*****************************************************************
Used in debug checking of cmp_dtuple_... .
This function is used to compare a data tuple to a physical record. If
dtuple has n fields then rec must have either m >= n fields, or it must
differ from dtuple in some of the m fields rec has. */
-
+static
int
cmp_debug_dtuple_rec_with_match(
/*============================*/
@@ -54,6 +55,7 @@ cmp_debug_dtuple_rec_with_match(
completely matched fields; when function
returns, contains the value for current
comparison */
+#endif /* UNIV_DEBUG */
/*****************************************************************
This function is used to compare two data fields for which the data type
is such that we must use MySQL code to compare them. The prototype here
@@ -962,13 +964,14 @@ order_resolved:
return(ret);
}
+#ifdef UNIV_DEBUG
/*****************************************************************
Used in debug checking of cmp_dtuple_... .
This function is used to compare a data tuple to a physical record. If
dtuple has n fields then rec must have either m >= n fields, or it must
differ from dtuple in some of the m fields rec has. If encounters an
externally stored field, returns 0. */
-
+static
int
cmp_debug_dtuple_rec_with_match(
/*============================*/
@@ -1064,3 +1067,4 @@ order_resolved:
return(ret);
}
+#endif /* UNIV_DEBUG */
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 062f21369a7..7f1852c70f2 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -80,9 +80,9 @@ ins_node_create(
node->trx_id = ut_dulint_zero;
node->entry_sys_heap = mem_heap_create(128);
-#ifdef UNIV_DEBUG
- node->magic_n = INS_NODE_MAGIC_N;
-#endif /* UNIV_DEBUG */
+
+ node->magic_n = INS_NODE_MAGIC_N;
+
return(node);
}
@@ -194,7 +194,6 @@ ins_node_set_new_row(
ins_node_t* node, /* in: insert node */
dtuple_t* row) /* in: new row (or first row) for the node */
{
- ut_ad(node->magic_n == INS_NODE_MAGIC_N);
node->state = INS_NODE_SET_IX_LOCK;
node->index = NULL;
node->entry = NULL;
@@ -518,7 +517,7 @@ static
void
row_ins_foreign_report_err(
/*=======================*/
- char* errstr, /* in: error string from the viewpoint
+ const char* errstr, /* in: error string from the viewpoint
of the parent table */
que_thr_t* thr, /* in: query thread whose run_node
is an update node */
@@ -652,32 +651,33 @@ row_ins_foreign_check_on_constraint(
ulint err;
ulint i;
char* ptr;
- char table_name_buf[1000];
+ char* table_name_buf;
ut_a(thr && foreign && pcur && mtr);
/* Since we are going to delete or update a row, we have to invalidate
the MySQL query cache for table */
- ut_a(ut_strlen(table->name) < 998);
- strcpy(table_name_buf, table->name);
+ table_name_buf = mem_strdup(table->name);
ptr = strchr(table_name_buf, '/');
ut_a(ptr);
*ptr = '\0';
- /* We call a function in ha_innodb.cc */
#ifndef UNIV_HOTBACKUP
+ /* We call a function in ha_innodb.cc */
innobase_invalidate_query_cache(thr_get_trx(thr), table_name_buf,
- ut_strlen(table->name) + 1);
+ strlen(table->name) + 1);
#endif
+ mem_free(table_name_buf);
+
node = thr->run_node;
if (node->is_delete && 0 == (foreign->type &
(DICT_FOREIGN_ON_DELETE_CASCADE
| DICT_FOREIGN_ON_DELETE_SET_NULL))) {
- row_ins_foreign_report_err((char*)"Trying to delete",
+ row_ins_foreign_report_err("Trying to delete",
thr, foreign,
btr_pcur_get_rec(pcur), entry);
@@ -690,7 +690,7 @@ row_ins_foreign_check_on_constraint(
/* This is an UPDATE */
- row_ins_foreign_report_err((char*)"Trying to update",
+ row_ins_foreign_report_err("Trying to update",
thr, foreign,
btr_pcur_get_rec(pcur), entry);
@@ -751,7 +751,7 @@ row_ins_foreign_check_on_constraint(
err = DB_ROW_IS_REFERENCED;
row_ins_foreign_report_err(
-(char*)"Trying an update, possibly causing a cyclic cascaded update\n"
+"Trying an update, possibly causing a cyclic cascaded update\n"
"in the child table,", thr, foreign, btr_pcur_get_rec(pcur), entry);
goto nonstandard_exit_func;
@@ -876,7 +876,7 @@ row_ins_foreign_check_on_constraint(
err = DB_ROW_IS_REFERENCED;
row_ins_foreign_report_err(
-(char*)"Trying a cascaded update where the updated value in the child\n"
+"Trying a cascaded update where the updated value in the child\n"
"table would not fit in the length of the column, or the value would\n"
"be NULL and the column is declared as not NULL in the child table,",
thr, foreign, btr_pcur_get_rec(pcur), entry);
@@ -1194,7 +1194,7 @@ run_again:
}
} else {
row_ins_foreign_report_err(
- (char*)"Trying to delete or update",
+ "Trying to delete or update",
thr, foreign, rec, entry);
err = DB_ROW_IS_REFERENCED;
@@ -2013,7 +2013,6 @@ row_ins(
ulint err;
ut_ad(node && thr);
- ut_ad(node->magic_n == INS_NODE_MAGIC_N);
if (node->state == INS_NODE_ALLOC_ROW_ID) {
@@ -2078,7 +2077,7 @@ row_ins_step(
trx_start_if_not_started(trx);
node = thr->run_node;
- ut_ad(node->magic_n == INS_NODE_MAGIC_N);
+
ut_ad(que_node_get_type(node) == QUE_NODE_INSERT);
parent = que_node_get_parent(node);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 61be3a7248e..c4408de2a85 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -397,6 +397,7 @@ row_create_prebuilt(
prebuilt->clust_pcur = btr_pcur_create_for_mysql();
prebuilt->select_lock_type = LOCK_NONE;
+ prebuilt->stored_select_lock_type = 99999999;
prebuilt->sel_graph = NULL;
@@ -691,7 +692,7 @@ row_lock_table_autoinc_for_mysql(
return(DB_SUCCESS);
}
- trx->op_info = (char *) "setting auto-inc lock";
+ trx->op_info = "setting auto-inc lock";
if (node == NULL) {
row_get_prebuilt_insert_row(prebuilt);
@@ -727,14 +728,14 @@ run_again:
goto run_again;
}
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(err);
}
que_thr_stop_for_mysql_no_error(thr, trx);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -774,7 +775,7 @@ row_lock_table_for_mysql(
ut_ad(trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
- trx->op_info = (char *) "setting table lock";
+ trx->op_info = "setting table lock";
if (prebuilt->sel_graph == NULL) {
/* Build a dummy select query graph */
@@ -811,14 +812,14 @@ run_again:
goto run_again;
}
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(err);
}
que_thr_stop_for_mysql_no_error(thr, trx);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -869,7 +870,7 @@ row_insert_for_mysql(
return(DB_ERROR);
}
- trx->op_info = (char *) "inserting";
+ trx->op_info = "inserting";
trx_start_if_not_started(trx);
@@ -910,7 +911,7 @@ run_again:
goto run_again;
}
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(err);
}
@@ -927,7 +928,7 @@ run_again:
}
row_update_statistics_if_needed(prebuilt->table);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -1084,7 +1085,7 @@ row_update_for_mysql(
return(DB_ERROR);
}
- trx->op_info = (char *) "updating or deleting";
+ trx->op_info = "updating or deleting";
trx_start_if_not_started(trx);
@@ -1131,7 +1132,7 @@ run_again:
if (err == DB_RECORD_NOT_FOUND) {
trx->error_state = DB_SUCCESS;
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -1142,7 +1143,7 @@ run_again:
goto run_again;
}
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(err);
}
@@ -1161,7 +1162,7 @@ run_again:
row_update_statistics_if_needed(prebuilt->table);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -1413,7 +1414,8 @@ row_create_table_for_mysql(
tab_node_t* node;
mem_heap_t* heap;
que_thr_t* thr;
- ulint namelen;
+ const char* table_name;
+ ulint table_name_len;
ulint err;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -1437,7 +1439,7 @@ row_create_table_for_mysql(
return(DB_ERROR);
}
- trx->op_info = (char *) "creating table";
+ trx->op_info = "creating table";
if (row_mysql_is_system_table(table->name)) {
@@ -1465,10 +1467,17 @@ row_create_table_for_mysql(
return(row_mysql_recover_tmp_table(table, trx));
}
- namelen = strlen(table->name) + 1;
+ /* The table name is prefixed with the database name and a '/'.
+ Certain table names starting with 'innodb_' have their special
+ meaning regardless of the database name. Thus, we need to
+ ignore the database name prefix in the comparisons. */
+ table_name = strchr(table->name, '/');
+ ut_a(table_name);
+ table_name++;
+ table_name_len = strlen(table_name) + 1;
- if (namelen == sizeof S_innodb_monitor
- && !memcmp(table->name, S_innodb_monitor,
+ if (table_name_len == sizeof S_innodb_monitor
+ && !memcmp(table_name, S_innodb_monitor,
sizeof S_innodb_monitor)) {
/* Table equals "innodb_monitor":
@@ -1480,27 +1489,27 @@ row_create_table_for_mysql(
of InnoDB monitor prints */
os_event_set(srv_lock_timeout_thread_event);
- } else if (namelen == sizeof S_innodb_lock_monitor
- && !memcmp(table->name, S_innodb_lock_monitor,
+ } else if (table_name_len == sizeof S_innodb_lock_monitor
+ && !memcmp(table_name, S_innodb_lock_monitor,
sizeof S_innodb_lock_monitor)) {
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- } else if (namelen == sizeof S_innodb_tablespace_monitor
- && !memcmp(table->name, S_innodb_tablespace_monitor,
+ } else if (table_name_len == sizeof S_innodb_tablespace_monitor
+ && !memcmp(table_name, S_innodb_tablespace_monitor,
sizeof S_innodb_tablespace_monitor)) {
srv_print_innodb_tablespace_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- } else if (namelen == sizeof S_innodb_table_monitor
- && !memcmp(table->name, S_innodb_table_monitor,
+ } else if (table_name_len == sizeof S_innodb_table_monitor
+ && !memcmp(table_name, S_innodb_table_monitor,
sizeof S_innodb_table_monitor)) {
srv_print_innodb_table_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- } else if (namelen == sizeof S_innodb_mem_validate
- && !memcmp(table->name, S_innodb_mem_validate,
+ } else if (table_name_len == sizeof S_innodb_mem_validate
+ && !memcmp(table_name, S_innodb_mem_validate,
sizeof S_innodb_mem_validate)) {
/* We define here a debugging feature intended for
developers */
@@ -1572,7 +1581,7 @@ row_create_table_for_mysql(
que_graph_free((que_t*) que_node_get_parent(thr));
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -1601,7 +1610,7 @@ row_create_index_for_mysql(
#endif /* UNIV_SYNC_DEBUG */
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
- trx->op_info = (char *) "creating index";
+ trx->op_info = "creating index";
/* Check that the same column does not appear twice in the index.
Starting from 4.0.14, InnoDB should be able to cope with that, but
@@ -1669,7 +1678,7 @@ error_handling:
trx->error_state = DB_SUCCESS;
}
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -1705,7 +1714,7 @@ row_table_add_foreign_constraints(
#endif /* UNIV_SYNC_DEBUG */
ut_a(sql_string);
- trx->op_info = (char *) "adding foreign keys";
+ trx->op_info = "adding foreign keys";
trx_start_if_not_started(trx);
@@ -1749,8 +1758,8 @@ static
int
row_drop_table_for_mysql_in_background(
/*===================================*/
- /* out: error code or DB_SUCCESS */
- char* name) /* in: table name */
+ /* out: error code or DB_SUCCESS */
+ const char* name) /* in: table name */
{
ulint error;
trx_t* trx;
@@ -1951,11 +1960,41 @@ row_discard_tablespace_for_mysql(
que_t* graph = NULL;
ibool success;
ulint err;
- char buf[2 * OS_FILE_MAX_PATH];
+ char* buf;
+
+ static const char discard_tablespace_proc1[] =
+ "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
+ "old_id CHAR;\n"
+ "new_id CHAR;\n"
+ "new_id_low INT;\n"
+ "new_id_high INT;\n"
+ "table_name CHAR;\n"
+ "BEGIN\n"
+ "table_name := ";
+ static const char discard_tablespace_proc2[] =
+ ";\n"
+ "new_id_high := %lu;\n"
+ "new_id_low := %lu;\n"
+ "new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n"
+ "SELECT ID INTO old_id\n"
+ "FROM SYS_TABLES\n"
+ "WHERE NAME = table_name;\n"
+ "IF (SQL %% NOTFOUND) THEN\n"
+ " COMMIT WORK;\n"
+ " RETURN;\n"
+ "END IF;\n"
+ "UPDATE SYS_TABLES SET ID = new_id\n"
+ "WHERE ID = old_id;\n"
+ "UPDATE SYS_COLUMNS SET TABLE_ID = new_id\n"
+ "WHERE TABLE_ID = old_id;\n"
+ "UPDATE SYS_INDEXES SET TABLE_ID = new_id\n"
+ "WHERE TABLE_ID = old_id;\n"
+ "COMMIT WORK;\n"
+ "END;\n";
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
- trx->op_info = (char *) "discarding tablespace";
+ trx->op_info = "discarding tablespace";
trx_start_if_not_started(trx);
/* Serialize data dictionary operations with dictionary mutex:
@@ -1973,9 +2012,10 @@ row_discard_tablespace_for_mysql(
if (table->space == 0) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: table %s\n"
-"InnoDB: is in the system tablespace 0 which cannot be discarded\n", name);
+ fputs(" InnoDB: Error: table ", stderr);
+ ut_print_name(stderr, name);
+ fputs("\n"
+"InnoDB: is in the system tablespace 0 which cannot be discarded\n", stderr);
err = DB_ERROR;
goto funct_exit;
@@ -1983,36 +2023,16 @@ row_discard_tablespace_for_mysql(
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
- sprintf(buf,
- "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
- "old_id CHAR;\n"
- "new_id CHAR;\n"
- "new_id_low INT;\n"
- "new_id_high INT;\n"
- "table_name CHAR;\n"
- "BEGIN\n"
- "table_name :='%s';\n"
- "new_id_high := %lu;\n"
- "new_id_low := %lu;\n"
- "new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n"
- "SELECT ID INTO old_id\n"
- "FROM SYS_TABLES\n"
- "WHERE NAME = table_name;\n"
- "IF (SQL %% NOTFOUND) THEN\n"
- " COMMIT WORK;\n"
- " RETURN;\n"
- "END IF;\n"
- "UPDATE SYS_TABLES SET ID = new_id\n"
- "WHERE ID = old_id;\n"
- "UPDATE SYS_COLUMNS SET TABLE_ID = new_id\n"
- "WHERE TABLE_ID = old_id;\n"
- "UPDATE SYS_INDEXES SET TABLE_ID = new_id\n"
- "WHERE TABLE_ID = old_id;\n"
- "COMMIT WORK;\n"
- "END;\n", name, (ulong) ut_dulint_get_high(new_id),
- (ulong) ut_dulint_get_low(new_id));
+ buf = mem_alloc((sizeof discard_tablespace_proc1) +
+ (sizeof discard_tablespace_proc2) +
+ 20 + ut_strlenq(name, '\''));
- ut_a(strlen(buf) < 2 * OS_FILE_MAX_PATH);
+ memcpy(buf, discard_tablespace_proc1, sizeof discard_tablespace_proc1);
+ sprintf(ut_strcpyq(buf + (sizeof discard_tablespace_proc1 - 1),
+ '\'', name),
+ discard_tablespace_proc2,
+ (ulong) ut_dulint_get_high(new_id),
+ (ulong) ut_dulint_get_low(new_id));
graph = pars_sql(buf);
@@ -2060,7 +2080,7 @@ funct_exit:
trx_commit_for_mysql(trx);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -2085,7 +2105,7 @@ row_import_tablespace_for_mysql(
trx_start_if_not_started(trx);
- trx->op_info = (char*) "importing tablespace";
+ trx->op_info = "importing tablespace";
current_lsn = log_get_lsn();
@@ -2126,9 +2146,10 @@ row_import_tablespace_for_mysql(
if (table->space == 0) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: table %s\n"
-"InnoDB: is in the system tablespace 0 which cannot be imported\n", name);
+ fputs(" InnoDB: Error: table ", stderr);
+ ut_print_name(stderr, name);
+ fputs("\n"
+"InnoDB: is in the system tablespace 0 which cannot be imported\n", stderr);
err = DB_ERROR;
goto funct_exit;
@@ -2136,10 +2157,12 @@ row_import_tablespace_for_mysql(
if (!table->tablespace_discarded) {
ut_print_timestamp(stderr);
- fprintf(stderr,
+ fputs(
" InnoDB: Error: you are trying to IMPORT a tablespace\n"
-"InnoDB: %s, though you have not called DISCARD on it yet\n"
-"InnoDB: during the lifetime of the mysqld process!\n", name);
+"InnoDB: ", stderr);
+ ut_print_name(stderr, name);
+ fputs(", though you have not called DISCARD on it yet\n"
+"InnoDB: during the lifetime of the mysqld process!\n", stderr);
err = DB_ERROR;
@@ -2165,7 +2188,7 @@ funct_exit:
trx_commit_for_mysql(trx);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -2189,6 +2212,7 @@ row_drop_table_for_mysql(
que_thr_t* thr;
que_t* graph;
ulint err;
+ const char* table_name;
ulint namelen;
ibool success;
ibool locked_dictionary = FALSE;
@@ -2274,14 +2298,21 @@ row_drop_table_for_mysql(
return(DB_ERROR);
}
- trx->op_info = (char *) "dropping table";
+ trx->op_info = "dropping table";
trx_start_if_not_started(trx);
- namelen = strlen(name) + 1;
+ /* The table name is prefixed with the database name and a '/'.
+ Certain table names starting with 'innodb_' have their special
+ meaning regardless of the database name. Thus, we need to
+ ignore the database name prefix in the comparisons. */
+ table_name = strchr(name, '/');
+ ut_a(table_name);
+ table_name++;
+ namelen = strlen(table_name) + 1;
if (namelen == sizeof S_innodb_monitor
- && !memcmp(name, S_innodb_monitor,
+ && !memcmp(table_name, S_innodb_monitor,
sizeof S_innodb_monitor)) {
/* Table name equals "innodb_monitor":
@@ -2290,17 +2321,17 @@ row_drop_table_for_mysql(
srv_print_innodb_monitor = FALSE;
srv_print_innodb_lock_monitor = FALSE;
} else if (namelen == sizeof S_innodb_lock_monitor
- && !memcmp(name, S_innodb_lock_monitor,
+ && !memcmp(table_name, S_innodb_lock_monitor,
sizeof S_innodb_lock_monitor)) {
srv_print_innodb_monitor = FALSE;
srv_print_innodb_lock_monitor = FALSE;
} else if (namelen == sizeof S_innodb_tablespace_monitor
- && !memcmp(name, S_innodb_tablespace_monitor,
+ && !memcmp(table_name, S_innodb_tablespace_monitor,
sizeof S_innodb_tablespace_monitor)) {
srv_print_innodb_tablespace_monitor = FALSE;
} else if (namelen == sizeof S_innodb_table_monitor
- && !memcmp(name, S_innodb_table_monitor,
+ && !memcmp(table_name, S_innodb_table_monitor,
sizeof S_innodb_table_monitor)) {
srv_print_innodb_table_monitor = FALSE;
@@ -2469,7 +2500,7 @@ row_drop_table_for_mysql(
if (dict_load_table(name) != NULL) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: not able to remove table ",
- stderr);
+ stderr);
ut_print_name(stderr, name);
fputs(" from the dictionary cache!\n", stderr);
err = DB_ERROR;
@@ -2491,8 +2522,10 @@ row_drop_table_for_mysql(
if (!success) {
ut_print_timestamp(stderr);
fprintf(stderr,
-" InnoDB: Error: not able to delete tablespace %lu of table %s!\n",
- (ulong) space_id, name);
+" InnoDB: Error: not able to delete tablespace %lu of table ",
+ (ulong) space_id);
+ ut_print_name(stderr, name);
+ fputs("!\n", stderr);
err = DB_ERROR;
}
}
@@ -2507,7 +2540,7 @@ funct_exit:
trx_commit_for_mysql(trx);
- trx->op_info = (char *) "";
+ trx->op_info = "";
srv_wake_master_thread();
@@ -2533,7 +2566,7 @@ row_drop_database_for_mysql(
ut_a(name != NULL);
ut_a(name[namelen - 1] == '/');
- trx->op_info = (char *) "dropping database";
+ trx->op_info = "dropping database";
trx_start_if_not_started(trx);
loop:
@@ -2587,7 +2620,7 @@ loop:
trx_commit_for_mysql(trx);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(err);
}
@@ -2738,7 +2771,7 @@ row_rename_table_for_mysql(
return(DB_ERROR);
}
- trx->op_info = (char *) "renaming table";
+ trx->op_info = "renaming table";
trx_start_if_not_started(trx);
if (row_mysql_is_recovered_tmp_table(new_name)) {
@@ -2757,15 +2790,14 @@ row_rename_table_for_mysql(
err = DB_TABLE_NOT_FOUND;
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: table %s\n"
- "InnoDB: does not exist in the InnoDB internal\n"
+ fputs(" InnoDB: Error: table ", stderr);
+ ut_print_name(stderr, old_name);
+ fputs(" does not exist in the InnoDB internal\n"
"InnoDB: data dictionary though MySQL is trying to rename the table.\n"
"InnoDB: Have you copied the .frm file of the table to the\n"
"InnoDB: MySQL database directory from another database?\n"
"InnoDB: You can look for further help from section 15.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.html\n",
- old_name);
+ "InnoDB: http://www.innodb.com/ibman.php\n", stderr);
goto funct_exit;
}
@@ -2773,12 +2805,12 @@ row_rename_table_for_mysql(
err = DB_TABLE_NOT_FOUND;
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: table %s\n"
- "InnoDB: does not have an .ibd file in the database directory.\n"
+ fputs(" InnoDB: Error: table ", stderr);
+ ut_print_name(stderr, old_name);
+ fputs(
+ " does not have an .ibd file in the database directory.\n"
"InnoDB: You can look for further help from section 15.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.html\n",
- old_name);
+ "InnoDB: http://www.innodb.com/ibman.php\n", stderr);
goto funct_exit;
}
@@ -2905,23 +2937,25 @@ row_rename_table_for_mysql(
if (err != DB_SUCCESS) {
if (err == DB_DUPLICATE_KEY) {
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: table %s exists in the InnoDB internal data\n"
- "InnoDB: dictionary though MySQL is trying rename table %s to it.\n"
+ fputs(" InnoDB: Error: table ", stderr);
+ ut_print_name(stderr, new_name);
+ fputs(" exists in the InnoDB internal data\n"
+ "InnoDB: dictionary though MySQL is trying rename table ", stderr);
+ ut_print_name(stderr, old_name);
+ fputs(" to it.\n"
"InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n"
"InnoDB: You can look for further help from section 15.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.html\n",
- new_name, old_name);
- fprintf(stderr,
- "InnoDB: If table %s is a temporary table #sql..., then it can be that\n"
+ "InnoDB: http://www.innodb.com/ibman.php\n"
+ "InnoDB: If table ", stderr);
+ ut_print_name(stderr, new_name);
+ fputs(" is a temporary table #sql..., then it can be that\n"
"InnoDB: there are still queries running on the table, and it will be\n"
- "InnoDB: dropped automatically when the queries end.\n", new_name);
- fprintf(stderr,
+ "InnoDB: dropped automatically when the queries end.\n"
"InnoDB: You can drop the orphaned table inside InnoDB by\n"
"InnoDB: creating an InnoDB table with the same name in another\n"
"InnoDB: database and moving the .frm file to the current database.\n"
"InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n"
- "InnoDB: succeed.\n");
+ "InnoDB: succeed.\n", stderr);
}
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, FALSE, NULL);
@@ -2937,9 +2971,12 @@ row_rename_table_for_mysql(
trx_general_rollback_for_mysql(trx, FALSE, NULL);
trx->error_state = DB_SUCCESS;
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error in table rename, cannot rename %s to %s\n", old_name,
- new_name);
+ fputs(" InnoDB: Error in table rename, cannot rename ",
+ stderr);
+ ut_print_name(stderr, old_name);
+ fputs(" to ", stderr);
+ ut_print_name(stderr, new_name);
+ putc('\n', stderr);
err = DB_ERROR;
goto funct_exit;
@@ -2958,11 +2995,14 @@ row_rename_table_for_mysql(
if (err != DB_SUCCESS) {
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: in ALTER TABLE table %s\n"
- "InnoDB: has or is referenced in foreign key constraints\n"
- "InnoDB: which are not compatible with the new table definition.\n",
- new_name);
+ fputs(" InnoDB: Error: in ALTER TABLE ",
+ stderr);
+ ut_print_name(stderr, new_name);
+ fputs("\n"
+ "InnoDB: has or is referenced in foreign key constraints\n"
+ "InnoDB: which are not compatible with the new table definition.\n",
+ stderr);
+
ut_a(dict_table_rename_in_cache(table,
old_name, FALSE));
trx->error_state = DB_SUCCESS;
@@ -2987,7 +3027,7 @@ funct_exit:
trx_commit_for_mysql(trx);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return((int) err);
}
@@ -3125,7 +3165,7 @@ row_check_table_for_mysql(
ulint ret = DB_SUCCESS;
ulint old_isolation_level;
- prebuilt->trx->op_info = (char *) "checking table";
+ prebuilt->trx->op_info = "checking table";
old_isolation_level = prebuilt->trx->isolation_level;
@@ -3160,9 +3200,11 @@ row_check_table_for_mysql(
ret = DB_ERROR;
+ fputs("Error: ", stderr);
+ dict_index_name_print(stderr, index);
fprintf(stderr,
- "Error: index %s contains %lu entries, should be %lu\n",
- index->name, (ulong) n_rows,
+ " contains %lu entries, should be %lu\n",
+ (ulong) n_rows,
(ulong) n_rows_in_table);
}
}
@@ -3181,7 +3223,7 @@ row_check_table_for_mysql(
ret = DB_ERROR;
}
- prebuilt->trx->op_info = (char *) "";
+ prebuilt->trx->op_info = "";
return(ret);
}
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 48796c8a455..9e8e9b82f2d 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2831,7 +2831,7 @@ row_search_for_mysql(
/* PHASE 1: Try to pop the row from the prefetch cache */
if (direction == 0) {
- trx->op_info = (char *) "starting index read";
+ trx->op_info = "starting index read";
prebuilt->n_rows_fetched = 0;
prebuilt->n_fetch_cached = 0;
@@ -2842,7 +2842,7 @@ row_search_for_mysql(
row_prebuild_sel_graph(prebuilt);
}
} else {
- trx->op_info = (char *) "fetching rows";
+ trx->op_info = "fetching rows";
if (prebuilt->n_rows_fetched == 0) {
prebuilt->fetch_direction = direction;
@@ -2867,7 +2867,7 @@ row_search_for_mysql(
prebuilt->n_rows_fetched++;
srv_n_rows_read++;
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(DB_SUCCESS);
}
@@ -2879,7 +2879,7 @@ row_search_for_mysql(
cache, but the cache was not full at the time of the
popping: no more rows can exist in the result set */
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(DB_RECORD_NOT_FOUND);
}
@@ -2924,7 +2924,7 @@ row_search_for_mysql(
if (direction != 0 && !prebuilt->used_in_HANDLER) {
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(DB_RECORD_NOT_FOUND);
}
}
@@ -3005,7 +3005,7 @@ row_search_for_mysql(
trx->has_search_latch = FALSE;
}
- trx->op_info = (char *) "";
+ trx->op_info = "";
/* NOTE that we do NOT store the cursor
position */
@@ -3028,7 +3028,7 @@ row_search_for_mysql(
trx->has_search_latch = FALSE;
}
- trx->op_info = (char *) "";
+ trx->op_info = "";
/* NOTE that we do NOT store the cursor
position */
@@ -3575,7 +3575,7 @@ lock_wait_or_error:
/* fputs("Using ", stderr);
dict_index_name_print(stderr, index);
fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(err);
@@ -3598,7 +3598,7 @@ normal_return:
srv_n_rows_read++;
}
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(ret);
}
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index 724e7bf91e7..d35ae0a3e38 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -287,9 +287,7 @@ upd_node_create(
node->select = NULL;
node->heap = mem_heap_create(128);
-#ifdef UNIV_DEBUG
- node->magic_n = UPD_NODE_MAGIC_N;
-#endif /* UNIV_DEBUG */
+ node->magic_n = UPD_NODE_MAGIC_N;
node->cmpl_info = 0;
@@ -1806,7 +1804,6 @@ row_upd_step(
trx_start_if_not_started(trx);
node = thr->run_node;
- ut_ad(node->magic_n == UPD_NODE_MAGIC_N);
sel_node = node->select;
@@ -1926,7 +1923,6 @@ row_upd_in_place_in_select(
node = que_node_get_parent(sel_node);
- ut_ad(node->magic_n == UPD_NODE_MAGIC_N);
ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE);
pcur = node->pcur;
diff --git a/innobase/srv/Makefile.am b/innobase/srv/Makefile.am
index 37fd73a4bf0..752683b82b8 100644
--- a/innobase/srv/Makefile.am
+++ b/innobase/srv/Makefile.am
@@ -19,6 +19,6 @@ include ../include/Makefile.i
noinst_LIBRARIES = libsrv.a
-libsrv_a_SOURCES = srv0srv.c srv0start.c
+libsrv_a_SOURCES = srv0srv.c srv0que.c srv0start.c
EXTRA_PROGRAMS =
diff --git a/innobase/srv/srv0que.c b/innobase/srv/srv0que.c
new file mode 100644
index 00000000000..9dc9ae453d9
--- /dev/null
+++ b/innobase/srv/srv0que.c
@@ -0,0 +1,113 @@
+/******************************************************
+Server query execution
+
+(c) 1996 Innobase Oy
+
+Created 6/5/1996 Heikki Tuuri
+*******************************************************/
+
+#include "srv0que.h"
+
+#include "srv0srv.h"
+#include "sync0sync.h"
+#include "os0thread.h"
+#include "usr0sess.h"
+#include "que0que.h"
+
+/**************************************************************************
+Checks if there is work to do in the server task queue. If there is, the
+thread starts processing a task. Before leaving, it again checks the task
+queue and picks a new task if any exists. This is called by a SRV_WORKER
+thread. */
+
+void
+srv_que_task_queue_check(void)
+/*==========================*/
+{
+ que_thr_t* thr;
+
+ for (;;) {
+ mutex_enter(&kernel_mutex);
+
+ thr = UT_LIST_GET_FIRST(srv_sys->tasks);
+
+ if (thr == NULL) {
+ mutex_exit(&kernel_mutex);
+
+ return;
+ }
+
+ UT_LIST_REMOVE(queue, srv_sys->tasks, thr);
+
+ mutex_exit(&kernel_mutex);
+
+ que_run_threads(thr);
+ }
+}
+
+/**************************************************************************
+Performs round-robin on the server tasks. This is called by a SRV_WORKER
+thread every second or so. */
+
+que_thr_t*
+srv_que_round_robin(
+/*================*/
+ /* out: the new (may be == thr) query thread
+ to run */
+ que_thr_t* thr) /* in: query thread */
+{
+ que_thr_t* new_thr;
+
+ ut_ad(thr);
+ ut_ad(thr->state == QUE_THR_RUNNING);
+
+ mutex_enter(&kernel_mutex);
+
+ UT_LIST_ADD_LAST(queue, srv_sys->tasks, thr);
+
+ new_thr = UT_LIST_GET_FIRST(srv_sys->tasks);
+
+ mutex_exit(&kernel_mutex);
+
+ return(new_thr);
+}
+
+/**************************************************************************
+Enqueues a task to server task queue and releases a worker thread, if there
+is a suspended one. */
+
+void
+srv_que_task_enqueue_low(
+/*=====================*/
+ que_thr_t* thr) /* in: query thread */
+{
+ ut_ad(thr);
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
+
+ UT_LIST_ADD_LAST(queue, srv_sys->tasks, thr);
+
+ srv_release_threads(SRV_WORKER, 1);
+}
+
+/**************************************************************************
+Enqueues a task to server task queue and releases a worker thread, if there
+is a suspended one. */
+
+void
+srv_que_task_enqueue(
+/*=================*/
+ que_thr_t* thr) /* in: query thread */
+{
+ ut_ad(thr);
+
+ ut_a(0); /* Under MySQL this is never called */
+
+ mutex_enter(&kernel_mutex);
+
+ srv_que_task_enqueue_low(thr);
+
+ mutex_exit(&kernel_mutex);
+}
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 33adcaa14b8..fc46c95a8a6 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -34,6 +34,7 @@ Created 10/8/1995 Heikki Tuuri
#include "sync0sync.h"
#include "thr0loc.h"
#include "que0que.h"
+#include "srv0que.h"
#include "log0recv.h"
#include "pars0pars.h"
#include "usr0sess.h"
@@ -57,7 +58,7 @@ ulint srv_activity_count = 0;
ibool srv_lock_timeout_and_monitor_active = FALSE;
ibool srv_error_monitor_active = FALSE;
-char* srv_main_thread_op_info = (char*) "";
+const char* srv_main_thread_op_info = "";
/* Server parameters which are read from the initfile */
@@ -65,7 +66,9 @@ char* srv_main_thread_op_info = (char*) "";
names, where the file name itself may also contain a path */
char* srv_data_home = NULL;
+#ifdef UNIV_LOG_ARCHIVE
char* srv_arch_dir = NULL;
+#endif /* UNIV_LOG_ARCHIVE */
ibool srv_file_per_table = FALSE; /* store to its own file each table
created by an user; data dictionary
@@ -94,7 +97,6 @@ char** srv_log_group_home_dirs = NULL;
ulint srv_n_log_groups = ULINT_MAX;
ulint srv_n_log_files = ULINT_MAX;
ulint srv_log_file_size = ULINT_MAX; /* size in database pages */
-ibool srv_log_archive_on = FALSE;
ulint srv_log_buffer_size = ULINT_MAX; /* size in database pages */
ulint srv_flush_log_at_trx_commit = 1;
@@ -149,8 +151,11 @@ ulint srv_lock_table_size = ULINT_MAX;
ulint srv_n_file_io_threads = ULINT_MAX;
+#ifdef UNIV_LOG_ARCHIVE
+ibool srv_log_archive_on = FALSE;
ibool srv_archive_recovery = 0;
dulint srv_archive_recovery_limit_lsn;
+#endif /* UNIV_LOG_ARCHIVE */
ulint srv_lock_wait_timeout = 1024 * 1024 * 1024;
@@ -921,11 +926,11 @@ retry:
os_fast_mutex_unlock(&srv_conc_mutex);
- trx->op_info = (char*)"sleeping before joining InnoDB queue";
+ trx->op_info = "sleeping before joining InnoDB queue";
os_thread_sleep(50000);
- trx->op_info = (char*)"";
+ trx->op_info = "";
os_fast_mutex_lock(&srv_conc_mutex);
@@ -978,11 +983,11 @@ retry:
/* Go to wait for the event; when a thread leaves InnoDB it will
release this thread */
- trx->op_info = (char*)"waiting in InnoDB queue";
+ trx->op_info = "waiting in InnoDB queue";
os_event_wait(slot->event);
- trx->op_info = (char*)"";
+ trx->op_info = "";
os_fast_mutex_lock(&srv_conc_mutex);
@@ -1946,7 +1951,7 @@ loop:
/* ---- When there is database activity by users, we cycle in this
loop */
- srv_main_thread_op_info = (char*) "reserving kernel mutex";
+ srv_main_thread_op_info = "reserving kernel mutex";
n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
@@ -1970,7 +1975,7 @@ loop:
for (i = 0; i < 10; i++) {
n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
- srv_main_thread_op_info = (char*)"sleeping";
+ srv_main_thread_op_info = "sleeping";
if (!skip_sleep) {
@@ -1983,12 +1988,11 @@ loop:
can drop tables lazily after there no longer are SELECT
queries to them. */
- srv_main_thread_op_info =
- (char*)"doing background drop tables";
+ srv_main_thread_op_info = "doing background drop tables";
row_drop_tables_for_mysql_in_background();
- srv_main_thread_op_info = (char*)"";
+ srv_main_thread_op_info = "";
if (srv_fast_shutdown && srv_shutdown_state > 0) {
@@ -1999,10 +2003,10 @@ loop:
is issued or the we have specified in my.cnf no flush
at transaction commit */
- srv_main_thread_op_info = (char*)"flushing log";
+ srv_main_thread_op_info = "flushing log";
log_buffer_flush_to_disk();
- srv_main_thread_op_info = (char*)"making checkpoint";
+ srv_main_thread_op_info = "making checkpoint";
log_free_check();
/* If there were less than 5 i/os during the
@@ -2015,11 +2019,10 @@ loop:
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
if (n_pend_ios < 3 && (n_ios - n_ios_old < 5)) {
- srv_main_thread_op_info =
- (char*)"doing insert buffer merge";
+ srv_main_thread_op_info = "doing insert buffer merge";
ibuf_contract_for_n_pages(TRUE, 5);
- srv_main_thread_op_info = (char*)"flushing log";
+ srv_main_thread_op_info = "flushing log";
log_buffer_flush_to_disk();
}
@@ -2067,20 +2070,20 @@ loop:
+ buf_pool->n_pages_written;
if (n_pend_ios < 3 && (n_ios - n_ios_very_old < 200)) {
- srv_main_thread_op_info = (char*) "flushing buffer pool pages";
+ srv_main_thread_op_info = "flushing buffer pool pages";
buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
- srv_main_thread_op_info = (char*) "flushing log";
+ srv_main_thread_op_info = "flushing log";
log_buffer_flush_to_disk();
}
/* We run a batch of insert buffer merge every 10 seconds,
even if the server were active */
- srv_main_thread_op_info = (char*)"doing insert buffer merge";
+ srv_main_thread_op_info = "doing insert buffer merge";
ibuf_contract_for_n_pages(TRUE, 5);
- srv_main_thread_op_info = (char*)"flushing log";
+ srv_main_thread_op_info = "flushing log";
log_buffer_flush_to_disk();
/* We run a full purge every 10 seconds, even if the server
@@ -2097,20 +2100,20 @@ loop:
goto background_loop;
}
- srv_main_thread_op_info = (char*)"purging";
+ srv_main_thread_op_info = "purging";
n_pages_purged = trx_purge();
current_time = time(NULL);
if (difftime(current_time, last_flush_time) > 1) {
- srv_main_thread_op_info = (char*) "flushing log";
+ srv_main_thread_op_info = "flushing log";
log_buffer_flush_to_disk();
last_flush_time = current_time;
}
}
- srv_main_thread_op_info = (char*)"flushing buffer pool pages";
+ srv_main_thread_op_info = "flushing buffer pool pages";
/* Flush a few oldest pages to make a new checkpoint younger */
@@ -2131,13 +2134,13 @@ loop:
ut_dulint_max);
}
- srv_main_thread_op_info = (char*)"making checkpoint";
+ srv_main_thread_op_info = "making checkpoint";
/* Make a new checkpoint about once in 10 seconds */
log_checkpoint(TRUE, FALSE);
- srv_main_thread_op_info = (char*)"reserving kernel mutex";
+ srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);
@@ -2161,7 +2164,7 @@ background_loop:
/* The server has been quiet for a while: start running background
operations */
- srv_main_thread_op_info = (char*)"doing background drop tables";
+ srv_main_thread_op_info = "doing background drop tables";
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
@@ -2174,7 +2177,7 @@ background_loop:
os_thread_sleep(100000);
}
- srv_main_thread_op_info = (char*)"purging";
+ srv_main_thread_op_info = "purging";
/* Run a full purge */
@@ -2188,20 +2191,20 @@ background_loop:
break;
}
- srv_main_thread_op_info = (char*)"purging";
+ srv_main_thread_op_info = "purging";
n_pages_purged = trx_purge();
current_time = time(NULL);
if (difftime(current_time, last_flush_time) > 1) {
- srv_main_thread_op_info = (char*) "flushing log";
+ srv_main_thread_op_info = "flushing log";
log_buffer_flush_to_disk();
last_flush_time = current_time;
}
}
- srv_main_thread_op_info = (char*)"reserving kernel mutex";
+ srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
@@ -2210,7 +2213,7 @@ background_loop:
}
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info = (char*)"doing insert buffer merge";
+ srv_main_thread_op_info = "doing insert buffer merge";
if (srv_fast_shutdown && srv_shutdown_state > 0) {
n_bytes_merged = 0;
@@ -2218,7 +2221,7 @@ background_loop:
n_bytes_merged = ibuf_contract_for_n_pages(TRUE, 20);
}
- srv_main_thread_op_info = (char*)"reserving kernel mutex";
+ srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
@@ -2228,10 +2231,10 @@ background_loop:
mutex_exit(&kernel_mutex);
flush_loop:
- srv_main_thread_op_info = (char*)"flushing buffer pool pages";
+ srv_main_thread_op_info = "flushing buffer pool pages";
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
- srv_main_thread_op_info = (char*)"reserving kernel mutex";
+ srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
@@ -2240,15 +2243,14 @@ flush_loop:
}
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info =
- (char*) "waiting for buffer pool flush to end";
+ srv_main_thread_op_info = "waiting for buffer pool flush to end";
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
- srv_main_thread_op_info = (char*) "flushing log";
+ srv_main_thread_op_info = "flushing log";
log_buffer_flush_to_disk();
- srv_main_thread_op_info = (char*)"making checkpoint";
+ srv_main_thread_op_info = "making checkpoint";
log_checkpoint(TRUE, FALSE);
@@ -2260,7 +2262,7 @@ flush_loop:
goto flush_loop;
}
- srv_main_thread_op_info = (char*)"reserving kernel mutex";
+ srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
@@ -2269,8 +2271,7 @@ flush_loop:
}
mutex_exit(&kernel_mutex);
/*
- srv_main_thread_op_info =
- (char*)"archiving log (if log archive is on)";
+ srv_main_thread_op_info = "archiving log (if log archive is on)";
log_archive_do(FALSE, &n_bytes_archived);
*/
@@ -2301,7 +2302,7 @@ flush_loop:
master thread to wait for more server activity */
suspend_thread:
- srv_main_thread_op_info = (char*)"suspending";
+ srv_main_thread_op_info = "suspending";
mutex_enter(&kernel_mutex);
@@ -2315,7 +2316,7 @@ suspend_thread:
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info = (char*)"waiting for server activity";
+ srv_main_thread_op_info = "waiting for server activity";
os_event_wait(event);
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 68fcb82c6d8..dd38eddb20b 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -628,7 +628,7 @@ open_or_create_log_file(
fil_node_create(name, srv_log_file_size,
2 * k + SRV_LOG_SPACE_FIRST_ID, FALSE);
-#ifdef notdefined
+#ifdef UNIV_LOG_ARCHIVE
/* If this is the first log group, create the file space object
for archived logs.
Under MySQL, no archiving ever done. */
@@ -636,12 +636,11 @@ open_or_create_log_file(
if (k == 0 && i == 0) {
arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID;
- fil_space_create((char*) "arch_log_space", arch_space_id,
- FIL_LOG);
+ fil_space_create("arch_log_space", arch_space_id, FIL_LOG);
} else {
arch_space_id = ULINT_UNDEFINED;
}
-#endif
+#endif /* UNIV_LOG_ARCHIVE */
if (i == 0) {
log_group_init(k, srv_n_log_files,
srv_log_file_size * UNIV_PAGE_SIZE,
@@ -662,12 +661,14 @@ open_or_create_data_files(
/* out: DB_SUCCESS or error code */
ibool* create_new_db, /* out: TRUE if new database should be
created */
- dulint* min_flushed_lsn,/* out: min of flushed lsn values in data
- files */
+#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no,/* out: min of archived log numbers in data
files */
- dulint* max_flushed_lsn,/* out: */
ulint* max_arch_log_no,/* out: */
+#endif /* UNIV_LOG_ARCHIVE */
+ dulint* min_flushed_lsn,/* out: min of flushed lsn values in data
+ files */
+ dulint* max_flushed_lsn,/* out: */
ulint* sum_of_new_sizes)/* out: sum of sizes of the new files added */
{
ibool ret;
@@ -820,8 +821,10 @@ open_or_create_data_files(
skip_size_check:
fil_read_flushed_lsn_and_arch_log_no(files[i],
one_opened,
- min_flushed_lsn, min_arch_log_no,
- max_flushed_lsn, max_arch_log_no);
+#ifdef UNIV_LOG_ARCHIVE
+ min_arch_log_no, max_arch_log_no,
+#endif /* UNIV_LOG_ARCHIVE */
+ min_flushed_lsn, max_flushed_lsn);
one_opened = TRUE;
} else {
/* We created the data file and now write it full of
@@ -908,8 +911,10 @@ innobase_start_or_create_for_mysql(void)
ibool log_opened = FALSE;
dulint min_flushed_lsn;
dulint max_flushed_lsn;
+#ifdef UNIV_LOG_ARCHIVE
ulint min_arch_log_no;
ulint max_arch_log_no;
+#endif /* UNIV_LOG_ARCHIVE */
ulint sum_of_new_sizes;
ulint sum_of_data_file_sizes;
ulint tablespace_size_in_header;
@@ -1017,28 +1022,22 @@ innobase_start_or_create_for_mysql(void)
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
#ifndef __WIN__
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"fdatasync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"O_DSYNC")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"O_DIRECT")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"littlesync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"nosync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
#else
- } else if (0 == ut_strcmp(srv_file_flush_method_str,
- (char*)"normal")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
os_aio_use_native_aio = FALSE;
@@ -1181,6 +1180,7 @@ NetWare. */
os_thread_create(io_handler_thread, n + i, thread_ids + i);
}
+#ifdef UNIV_LOG_ARCHIVE
if (0 != ut_strcmp(srv_log_group_home_dirs[0], srv_arch_dir)) {
fprintf(stderr,
"InnoDB: Error: you must set the log group home dir in my.cnf the\n"
@@ -1188,6 +1188,7 @@ NetWare. */
return(DB_ERROR);
}
+#endif /* UNIV_LOG_ARCHIVE */
if (srv_n_log_files * srv_log_file_size >= 262144) {
fprintf(stderr,
@@ -1219,8 +1220,10 @@ NetWare. */
}
err = open_or_create_data_files(&create_new_db,
- &min_flushed_lsn, &min_arch_log_no,
- &max_flushed_lsn, &max_arch_log_no,
+#ifdef UNIV_LOG_ARCHIVE
+ &min_arch_log_no, &max_arch_log_no,
+#endif /* UNIV_LOG_ARCHIVE */
+ &min_flushed_lsn, &max_flushed_lsn,
&sum_of_new_sizes);
if (err != DB_SUCCESS) {
fprintf(stderr,
@@ -1235,8 +1238,10 @@ NetWare. */
return((int) err);
}
+#ifdef UNIV_LOG_ARCHIVE
srv_normalize_path_for_win(srv_arch_dir);
srv_arch_dir = srv_add_path_separator_if_needed(srv_arch_dir);
+#endif /* UNIV_LOG_ARCHIVE */
for (i = 0; i < srv_n_log_files; i++) {
err = open_or_create_log_file(create_new_db, &log_file_created,
@@ -1270,9 +1275,16 @@ NetWare. */
fil_open_log_and_system_tablespace_files();
- if (log_created && !create_new_db && !srv_archive_recovery) {
+ if (log_created && !create_new_db
+#ifdef UNIV_LOG_ARCHIVE
+ && !srv_archive_recovery
+#endif /* UNIV_LOG_ARCHIVE */
+ ) {
if (ut_dulint_cmp(max_flushed_lsn, min_flushed_lsn) != 0
- || max_arch_log_no != min_arch_log_no) {
+#ifdef UNIV_LOG_ARCHIVE
+ || max_arch_log_no != min_arch_log_no
+#endif /* UNIV_LOG_ARCHIVE */
+ ) {
fprintf(stderr,
"InnoDB: Cannot initialize created log files because\n"
"InnoDB: data files were not in sync with each other\n"
@@ -1295,10 +1307,14 @@ NetWare. */
mutex_enter(&(log_sys->mutex));
+#ifdef UNIV_LOG_ARCHIVE
/* Do not + 1 arch_log_no because we do not use log
archiving */
recv_reset_logs(max_flushed_lsn, max_arch_log_no, TRUE);
-
+#else
+ recv_reset_logs(max_flushed_lsn, TRUE);
+#endif /* UNIV_LOG_ARCHIVE */
+
mutex_exit(&(log_sys->mutex));
}
@@ -1313,6 +1329,7 @@ NetWare. */
dict_create();
srv_startup_is_before_trx_rollback_phase = FALSE;
+#ifdef UNIV_LOG_ARCHIVE
} else if (srv_archive_recovery) {
fprintf(stderr,
"InnoDB: Starting archive recovery from a backup...\n");
@@ -1336,6 +1353,7 @@ NetWare. */
fsp_header_get_free_limit(0);
recv_recovery_from_archive_finish();
+#endif /* UNIV_LOG_ARCHIVE */
} else {
/* We always try to do a recovery, even if the database had
been shut down normally: this is the normal startup path */
@@ -1384,7 +1402,7 @@ NetWare. */
log_make_checkpoint_at(ut_dulint_max, TRUE);
-#ifdef notdefined
+#ifdef UNIV_LOG_ARCHIVE
/* Archiving is always off under MySQL */
if (!srv_log_archive_on) {
ut_a(DB_SUCCESS == log_archive_noarchivelog());
@@ -1403,7 +1421,7 @@ NetWare. */
ut_a(DB_SUCCESS == log_archive_archivelog());
}
}
-#endif
+#endif /* UNIV_LOG_ARCHIVE */
if (!create_new_db && srv_force_recovery == 0) {
/* After a crash recovery we only check that the info in data
dictionary is consistent with what we already know about space
@@ -1460,9 +1478,7 @@ 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;
diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
index 769eb326ce2..77757685208 100644
--- a/innobase/sync/sync0rw.c
+++ b/innobase/sync/sync0rw.c
@@ -119,8 +119,8 @@ rw_lock_create_func(
lock->cfile_name = cfile_name;
lock->cline = cline;
- lock->last_s_file_name = (char *) "not yet reserved";
- lock->last_x_file_name = (char *) "not yet reserved";
+ lock->last_s_file_name = "not yet reserved";
+ lock->last_x_file_name = "not yet reserved";
lock->last_s_line = 0;
lock->last_x_line = 0;
@@ -171,7 +171,6 @@ rw_lock_free(
mutex_exit(&rw_lock_list_mutex);
}
-#ifdef UNIV_DEBUG
/**********************************************************************
Checks that the rw-lock has been initialized and that there are no
simultaneous shared and exclusive locks. */
@@ -199,7 +198,6 @@ rw_lock_validate(
return(TRUE);
}
-#endif /* UNIV_DEBUG */
/**********************************************************************
Lock an rw-lock in shared mode for the current thread. If the rw-lock is
@@ -593,7 +591,7 @@ rw_lock_add_debug_info(
rw_lock_t* lock, /* in: rw-lock */
ulint pass, /* in: pass value */
ulint lock_type, /* in: lock type */
- char* file_name, /* in: file where requested */
+ const char* file_name, /* in: file where requested */
ulint line) /* in: line where requested */
{
rw_lock_debug_t* info;
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 31f287b6341..86306e49cac 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -214,7 +214,7 @@ mutex_create_func(
mutex->magic_n = MUTEX_MAGIC_N;
#ifdef UNIV_SYNC_DEBUG
mutex->line = 0;
- mutex->file_name = (char *) "not yet reserved";
+ mutex->file_name = "not yet reserved";
#endif /* UNIV_SYNC_DEBUG */
mutex->level = SYNC_LEVEL_NONE;
mutex->cfile_name = cfile_name;
@@ -314,7 +314,6 @@ mutex_enter_nowait(
return(1);
}
-#ifdef UNIV_DEBUG
/**********************************************************************
Checks that the mutex has been initialized. */
@@ -328,7 +327,6 @@ mutex_validate(
return(TRUE);
}
-#endif /* UNIV_DEBUG */
/**********************************************************************
Sets the waiters field in a mutex. */
@@ -512,7 +510,7 @@ void
mutex_set_debug_info(
/*=================*/
mutex_t* mutex, /* in: mutex */
- char* file_name, /* in: file where requested */
+ const char* file_name, /* in: file where requested */
ulint line) /* in: line where requested */
{
ut_ad(mutex);
@@ -1077,12 +1075,8 @@ 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 */
+ ut_a(buf_debug_prints
+ || sync_thread_levels_g(array, SYNC_DICT));
} else {
ut_error;
}
diff --git a/innobase/thr/thr0loc.c b/innobase/thr/thr0loc.c
index a17d09fcca6..033bb22807f 100644
--- a/innobase/thr/thr0loc.c
+++ b/innobase/thr/thr0loc.c
@@ -46,12 +46,11 @@ struct thr_local_struct{
ibool in_ibuf;/* TRUE if the the thread is doing an ibuf
operation */
hash_node_t hash; /* hash chain node */
-#ifdef UNIV_DEBUG
ulint magic_n;
-#define THR_LOCAL_MAGIC_N 1231234
-#endif /* UNIV_DEBUG */
};
+#define THR_LOCAL_MAGIC_N 1231234
+
/***********************************************************************
Returns the local storage struct for a thread. */
static
@@ -170,9 +169,8 @@ thr_local_create(void)
local->id = os_thread_get_curr_id();
local->handle = os_thread_get_curr();
-#ifdef UNIV_DEBUG
local->magic_n = THR_LOCAL_MAGIC_N;
-#endif /* UNIV_DEBUG */
+
local->in_ibuf = FALSE;
mutex_enter(&thr_local_mutex);
@@ -211,7 +209,7 @@ thr_local_free(
mutex_exit(&thr_local_mutex);
- ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
mem_free(local);
}
diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c
index 002775eaac1..3d5f0d3f03a 100644
--- a/innobase/trx/trx0purge.c
+++ b/innobase/trx/trx0purge.c
@@ -23,6 +23,7 @@ Created 3/26/1996 Heikki Tuuri
#include "row0purge.h"
#include "row0upd.h"
#include "trx0rec.h"
+#include "srv0que.h"
#include "os0thread.h"
/* The global data structure coordinating a purge */
@@ -1059,6 +1060,8 @@ trx_purge(void)
mutex_exit(&kernel_mutex);
+/* srv_que_task_enqueue(thr2); */
+
if (srv_print_thread_releases) {
fputs("Starting purge\n", stderr);
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index 4343249764e..e65755a0f73 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -20,6 +20,7 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0rec.h"
#include "que0que.h"
#include "usr0sess.h"
+#include "srv0que.h"
#include "srv0start.h"
#include "row0undo.h"
#include "row0mysql.h"
@@ -116,11 +117,11 @@ trx_rollback_for_mysql(
return(DB_SUCCESS);
}
- trx->op_info = (char *) "rollback";
+ trx->op_info = "rollback";
err = trx_general_rollback_for_mysql(trx, FALSE, NULL);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(err);
}
@@ -141,14 +142,14 @@ trx_rollback_last_sql_stat_for_mysql(
return(DB_SUCCESS);
}
- trx->op_info = (char *) "rollback of SQL statement";
+ trx->op_info = "rollback of SQL statement";
err = trx_general_rollback_for_mysql(trx, TRUE,
&(trx->last_sql_stat_start));
/* The following call should not be needed, but we play safe: */
trx_mark_sql_stat_end(trx);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(err);
}
@@ -239,7 +240,7 @@ trx_rollback_to_savepoint_for_mysql(
*mysql_binlog_cache_pos = savep->mysql_binlog_cache_pos;
- trx->op_info = (char *) "rollback to a savepoint";
+ trx->op_info = "rollback to a savepoint";
err = trx_general_rollback_for_mysql(trx, TRUE, &(savep->savept));
@@ -248,7 +249,7 @@ trx_rollback_to_savepoint_for_mysql(
trx_mark_sql_stat_end(trx);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(err);
}
@@ -343,7 +344,7 @@ trx_rollback_or_clean_all_without_sess(void)
trx_t* trx;
dict_table_t* table;
ib_longlong rows_to_undo;
- char* unit = (char*)"";
+ const char* unit = "";
int err;
mutex_enter(&kernel_mutex);
@@ -421,7 +422,7 @@ loop:
rows_to_undo = trx_roll_max_undo_no;
if (rows_to_undo > 1000000000) {
rows_to_undo = rows_to_undo / 1000000;
- unit = (char*)"M";
+ unit = "M";
}
fprintf(stderr,
@@ -931,15 +932,21 @@ trx_undo_rec_release(
/*************************************************************************
Starts a rollback operation. */
-que_thr_t*
+void
trx_rollback(
/*=========*/
- /* out: next query thread to run */
trx_t* trx, /* in: transaction */
- trx_sig_t* sig) /* in: signal starting the rollback */
+ trx_sig_t* sig, /* in: signal starting the rollback */
+ que_thr_t** next_thr)/* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if the passed value is
+ NULL, the parameter is ignored */
{
que_t* roll_graph;
que_thr_t* thr;
+/* que_thr_t* thr2; */
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -981,7 +988,18 @@ trx_rollback(
thr = que_fork_start_command(roll_graph);
ut_ad(thr);
- return(thr);
+
+/* thr2 = que_fork_start_command(roll_graph);
+
+ ut_ad(thr2); */
+
+ if (next_thr && (*next_thr == NULL)) {
+ *next_thr = thr;
+/* srv_que_task_enqueue_low(thr2); */
+ } else {
+ srv_que_task_enqueue_low(thr);
+/* srv_que_task_enqueue_low(thr2); */
+ }
}
/********************************************************************
@@ -1053,14 +1071,17 @@ trx_finish_error_processing(
/*************************************************************************
Finishes a partial rollback operation. */
static
-que_thr_t*
+void
trx_finish_partial_rollback_off_kernel(
/*===================================*/
- /* out: next query thread to run */
- trx_t* trx) /* in: transaction */
+ trx_t* trx, /* in: transaction */
+ que_thr_t** next_thr)/* in/out: next query thread to run;
+ if the value which is passed in is a pointer
+ to a NULL pointer, then the calling function
+ can start running a new query thread; if this
+ parameter is NULL, it is ignored */
{
trx_sig_t* sig;
- que_thr_t* next_thr;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -1071,26 +1092,29 @@ trx_finish_partial_rollback_off_kernel(
/* Remove the signal from the signal queue and send reply message
to it */
- next_thr = trx_sig_reply(sig);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
trx->que_state = TRX_QUE_RUNNING;
- return(next_thr);
}
/********************************************************************
Finishes a transaction rollback. */
-que_thr_t*
+void
trx_finish_rollback_off_kernel(
/*===========================*/
- /* out: next query thread to run */
que_t* graph, /* in: undo graph which can now be freed */
- trx_t* trx) /* in: transaction */
+ trx_t* trx, /* in: transaction */
+ que_thr_t** next_thr)/* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if this parameter is
+ NULL, it is ignored */
{
trx_sig_t* sig;
trx_sig_t* next_sig;
- que_thr_t* next_thr;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -1105,21 +1129,21 @@ trx_finish_rollback_off_kernel(
if (sig->type == TRX_SIG_ROLLBACK_TO_SAVEPT) {
- return(trx_finish_partial_rollback_off_kernel(trx));
+ trx_finish_partial_rollback_off_kernel(trx, next_thr);
+
+ return;
} else if (sig->type == TRX_SIG_ERROR_OCCURRED) {
trx_finish_error_processing(trx);
- return(NULL);
+ 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);
@@ -1127,23 +1151,19 @@ trx_finish_rollback_off_kernel(
send reply messages to them */
trx->que_state = TRX_QUE_RUNNING;
-
- next_thr = NULL;
+
while (sig != NULL) {
next_sig = UT_LIST_GET_NEXT(signals, sig);
if (sig->type == TRX_SIG_TOTAL_ROLLBACK) {
- ut_a(next_thr == NULL);
- next_thr = trx_sig_reply(sig);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
}
sig = next_sig;
}
-
- return(next_thr);
}
/*************************************************************************
@@ -1176,6 +1196,7 @@ trx_rollback_step(
que_thr_t* thr) /* in: query thread */
{
roll_node_t* node;
+ ibool success;
ulint sig_no;
trx_savept_t* savept;
@@ -1202,13 +1223,19 @@ trx_rollback_step(
/* Send a rollback signal to the transaction */
- trx_sig_send(thr_get_trx(thr), sig_no, TRX_SIG_SELF,
- thr, savept);
+ success = trx_sig_send(thr_get_trx(thr),
+ sig_no, TRX_SIG_SELF,
+ thr, savept, NULL);
thr->state = QUE_THR_SIG_REPLY_WAIT;
mutex_exit(&kernel_mutex);
+ if (!success) {
+ /* Error in delivering the rollback signal */
+ que_thr_handle_error(thr, DB_ERROR, NULL, 0);
+ }
+
return(NULL);
}
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index 7e35e34f014..54bd5be01a1 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -45,6 +45,15 @@ or there was no master log position info inside InnoDB. */
char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
ib_longlong trx_sys_mysql_master_log_pos = -1;
+/* If this MySQL server uses binary logging, after InnoDB has been inited
+and if it has done a crash recovery, we store the binlog file name and position
+here. If .._pos is -1, it means there was no binlog position info inside
+InnoDB. */
+
+char trx_sys_mysql_bin_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
+ib_longlong trx_sys_mysql_bin_log_pos = -1;
+
+
/********************************************************************
Determines if a page number is located inside the doublewrite buffer. */
@@ -619,7 +628,6 @@ trx_sys_update_mysql_binlog_offset(
MLOG_4BYTES, mtr);
}
-#ifdef UNIV_HOTBACKUP
/*********************************************************************
Prints to stderr the MySQL binlog info in the system header if the
magic number shows it valid. */
@@ -647,11 +655,10 @@ trx_sys_print_mysql_binlog_offset_from_page(
sys_header + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_NAME);
}
}
-#endif /* UNIV_HOTBACKUP */
/*********************************************************************
-Prints to stderr the MySQL binlog offset info in the trx system header if
-the magic number shows it valid. */
+Stores the MySQL binlog offset info in the trx system header if
+the magic number shows it valid, and print the info to stderr */
void
trx_sys_print_mysql_binlog_offset(void)
@@ -659,7 +666,8 @@ trx_sys_print_mysql_binlog_offset(void)
{
trx_sysf_t* sys_header;
mtr_t mtr;
-
+ ulong trx_sys_mysql_bin_log_pos_high, trx_sys_mysql_bin_log_pos_low;
+
mtr_start(&mtr);
sys_header = trx_sysf_get(&mtr);
@@ -673,14 +681,22 @@ trx_sys_print_mysql_binlog_offset(void)
return;
}
- fprintf(stderr,
- "InnoDB: Last MySQL binlog file position %lu %lu, file name %s\n",
- (ulong) mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
- (ulong) mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
- sys_header + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_NAME);
+ trx_sys_mysql_bin_log_pos_high = mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
+ + TRX_SYS_MYSQL_LOG_OFFSET_HIGH);
+ trx_sys_mysql_bin_log_pos_low = mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
+ + TRX_SYS_MYSQL_LOG_OFFSET_LOW);
+
+ trx_sys_mysql_bin_log_pos = (((ib_longlong)trx_sys_mysql_bin_log_pos_high) << 32) +
+ (ib_longlong)trx_sys_mysql_bin_log_pos_low;
+
+ ut_memcpy(trx_sys_mysql_bin_log_name, sys_header + TRX_SYS_MYSQL_LOG_INFO +
+ TRX_SYS_MYSQL_LOG_NAME, TRX_SYS_MYSQL_LOG_NAME_LEN);
+ fprintf(stderr,
+ "InnoDB: Last MySQL binlog file position %lu %lu, file name %s\n",
+ trx_sys_mysql_bin_log_pos_high, trx_sys_mysql_bin_log_pos_low,
+ trx_sys_mysql_bin_log_name);
+
mtr_commit(&mtr);
}
@@ -832,7 +848,7 @@ trx_sys_init_at_db_start(void)
{
trx_sysf_t* sys_header;
ib_longlong rows_to_undo = 0;
- char* unit = (char*)"";
+ const char* unit = "";
trx_t* trx;
mtr_t mtr;
@@ -881,7 +897,7 @@ trx_sys_init_at_db_start(void)
}
if (rows_to_undo > 1000000000) {
- unit = (char*)"M";
+ unit = "M";
rows_to_undo = rows_to_undo / 1000000;
}
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 862229ef032..a9aae48dae6 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -81,7 +81,7 @@ trx_create(
trx->magic_n = TRX_MAGIC_N;
- trx->op_info = (char *) "";
+ trx->op_info = "";
trx->type = TRX_USER;
trx->conc_state = TRX_NOT_STARTED;
@@ -107,7 +107,7 @@ trx_create(
trx->mysql_log_file_name = NULL;
trx->mysql_log_offset = 0;
- trx->mysql_master_log_file_name = (char*)"";
+ trx->mysql_master_log_file_name = "";
trx->mysql_master_log_pos = 0;
mutex_create(&(trx->undo_mutex));
@@ -897,15 +897,18 @@ trx_assign_read_view(
/********************************************************************
Commits a transaction. NOTE that the kernel mutex is temporarily released. */
static
-que_thr_t*
+void
trx_handle_commit_sig_off_kernel(
/*=============================*/
- /* out: next query thread to run */
- trx_t* trx) /* in: transaction */
+ trx_t* trx, /* in: transaction */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread */
{
trx_sig_t* sig;
trx_sig_t* next_sig;
- que_thr_t* next_thr = NULL;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -927,8 +930,7 @@ trx_handle_commit_sig_off_kernel(
if (sig->type == TRX_SIG_COMMIT) {
- ut_a(next_thr == NULL);
- next_thr = trx_sig_reply(sig);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
}
@@ -936,8 +938,6 @@ trx_handle_commit_sig_off_kernel(
}
trx->que_state = TRX_QUE_RUNNING;
-
- return(next_thr);
}
/***************************************************************
@@ -999,6 +999,39 @@ trx_lock_wait_to_suspended(
trx->que_state = TRX_QUE_RUNNING;
}
+/***************************************************************
+Moves the query threads in the sig reply wait list of trx to the SUSPENDED
+state. */
+static
+void
+trx_sig_reply_wait_to_suspended(
+/*============================*/
+ trx_t* trx) /* in: transaction */
+{
+ trx_sig_t* sig;
+ que_thr_t* thr;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
+
+ sig = UT_LIST_GET_FIRST(trx->reply_signals);
+
+ while (sig != NULL) {
+ thr = sig->receiver;
+
+ ut_ad(thr->state == QUE_THR_SIG_REPLY_WAIT);
+
+ thr->state = QUE_THR_SUSPENDED;
+
+ sig->receiver = NULL;
+
+ UT_LIST_REMOVE(reply_signals, trx->reply_signals, sig);
+
+ sig = UT_LIST_GET_FIRST(trx->reply_signals);
+ }
+}
+
/*********************************************************************
Checks the compatibility of a new signal with the other signals in the
queue. */
@@ -1078,10 +1111,11 @@ trx_sig_is_compatible(
/********************************************************************
Sends a signal to a trx object. */
-que_thr_t*
+ibool
trx_sig_send(
/*=========*/
- /* out: next query thread to run */
+ /* out: TRUE if the signal was
+ successfully delivered */
trx_t* trx, /* in: trx handle */
ulint type, /* in: signal type */
ulint sender, /* in: TRX_SIG_SELF or
@@ -1089,8 +1123,14 @@ trx_sig_send(
que_thr_t* receiver_thr, /* in: query thread which wants the
reply, or NULL; if type is
TRX_SIG_END_WAIT, this must be NULL */
- trx_savept_t* savept) /* in: possible rollback savepoint, or
+ trx_savept_t* savept, /* in: possible rollback savepoint, or
NULL */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if the parameter
+ is NULL, it is ignored */
{
trx_sig_t* sig;
trx_t* receiver_trx;
@@ -1100,7 +1140,14 @@ trx_sig_send(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(trx_sig_is_compatible(trx, type, sender));
+ if (!trx_sig_is_compatible(trx, type, sender)) {
+ /* The signal is not compatible with the other signals in
+ the queue: do nothing */
+
+ ut_error;
+
+ return(FALSE);
+ }
/* Queue the signal object */
@@ -1134,6 +1181,11 @@ trx_sig_send(
sig);
}
+ if (trx->sess->state == SESS_ERROR) {
+
+ trx_sig_reply_wait_to_suspended(trx);
+ }
+
if ((sender != TRX_SIG_SELF) || (type == TRX_SIG_BREAK_EXECUTION)) {
/* The following call will add a TRX_SIG_ERROR_OCCURRED
@@ -1148,10 +1200,10 @@ trx_sig_send(
if (UT_LIST_GET_FIRST(trx->signals) == sig) {
- return(trx_sig_start_handle(trx));
+ trx_sig_start_handle(trx, next_thr);
}
- return(NULL);
+ return(TRUE);
}
/********************************************************************
@@ -1173,18 +1225,27 @@ trx_end_signal_handling(
trx->handling_signals = FALSE;
trx->graph = trx->graph_before_signal_handling;
+
+ if (trx->graph && (trx->sess->state == SESS_ERROR)) {
+
+ que_fork_error_handle(trx, trx->graph);
+ }
}
/********************************************************************
Starts handling of a trx signal. */
-que_thr_t*
+void
trx_sig_start_handle(
/*=================*/
- /* out: next query thread to run, or NULL */
- trx_t* trx) /* in: trx handle */
+ trx_t* trx, /* in: trx handle */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if the parameter
+ is NULL, it is ignored */
{
- que_thr_t* next_thr = NULL;
trx_sig_t* sig;
ulint type;
loop:
@@ -1200,7 +1261,7 @@ loop:
trx_end_signal_handling(trx);
- return(next_thr);
+ return;
}
if (trx->conc_state == TRX_NOT_STARTED) {
@@ -1216,13 +1277,23 @@ loop:
trx_lock_wait_to_suspended(trx);
}
+ /* If the session is in the error state and this trx has threads
+ waiting for reply from signals, moves these threads to the suspended
+ state, canceling wait reservations; note that if the transaction has
+ sent a commit or rollback signal to itself, and its session is not in
+ the error state, then nothing is done here. */
+
+ if (trx->sess->state == SESS_ERROR) {
+ trx_sig_reply_wait_to_suspended(trx);
+ }
+
/* If there are no running query threads, we can start processing of a
signal, otherwise we have to wait until all query threads of this
transaction are aware of the arrival of the signal. */
if (trx->n_active_thrs > 0) {
- return(NULL);
+ return;
}
if (trx->handling_signals == FALSE) {
@@ -1236,19 +1307,30 @@ loop:
if (type == TRX_SIG_COMMIT) {
- next_thr = trx_handle_commit_sig_off_kernel(trx);
+ trx_handle_commit_sig_off_kernel(trx, next_thr);
} else if ((type == TRX_SIG_TOTAL_ROLLBACK)
- || (type == TRX_SIG_ROLLBACK_TO_SAVEPT)
- || (type == TRX_SIG_ERROR_OCCURRED)) {
+ || (type == TRX_SIG_ROLLBACK_TO_SAVEPT)) {
+
+ trx_rollback(trx, sig, next_thr);
+
+ /* No further signals can be handled until the rollback
+ completes, therefore we return */
+
+ return;
+
+ } else if (type == TRX_SIG_ERROR_OCCURRED) {
+
+ trx_rollback(trx, sig, next_thr);
+
/* No further signals can be handled until the rollback
completes, therefore we return */
- return(trx_rollback(trx, sig));
+ return;
} else if (type == TRX_SIG_BREAK_EXECUTION) {
- next_thr = trx_sig_reply(sig);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
} else {
ut_error;
@@ -1261,14 +1343,17 @@ loop:
Send the reply message when a signal in the queue of the trx has been
handled. */
-que_thr_t*
+void
trx_sig_reply(
/*==========*/
- /* out: next query thread to run */
- trx_sig_t* sig) /* in: signal */
+ trx_sig_t* sig, /* in: signal */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread */
{
- trx_t* receiver_trx;
- que_thr_t* next_thr = NULL;
+ trx_t* receiver_trx;
ut_ad(sig);
#ifdef UNIV_SYNC_DEBUG
@@ -1282,13 +1367,13 @@ trx_sig_reply(
UT_LIST_REMOVE(reply_signals, receiver_trx->reply_signals,
sig);
- next_thr = que_thr_end_wait(sig->receiver);
+ ut_ad(receiver_trx->sess->state != SESS_ERROR);
+
+ que_thr_end_wait(sig->receiver, next_thr);
sig->receiver = NULL;
}
-
- return(next_thr);
}
/********************************************************************
@@ -1344,6 +1429,7 @@ trx_commit_step(
{
commit_node_t* node;
que_thr_t* next_thr;
+ ibool success;
node = thr->run_node;
@@ -1358,15 +1444,22 @@ trx_commit_step(
node->state = COMMIT_NODE_WAIT;
+ next_thr = NULL;
+
thr->state = QUE_THR_SIG_REPLY_WAIT;
/* Send the commit signal to the transaction */
- next_thr = trx_sig_send(thr_get_trx(thr), TRX_SIG_COMMIT,
- TRX_SIG_SELF, thr, NULL);
-
+ success = trx_sig_send(thr_get_trx(thr), TRX_SIG_COMMIT,
+ TRX_SIG_SELF, thr, NULL, &next_thr);
+
mutex_exit(&kernel_mutex);
+ if (!success) {
+ /* Error in delivering the commit signal */
+ que_thr_handle_error(thr, DB_ERROR, NULL, 0);
+ }
+
return(next_thr);
}
@@ -1394,7 +1487,7 @@ trx_commit_for_mysql(
ut_a(trx);
- trx->op_info = (char *) "committing";
+ trx->op_info = "committing";
trx_start_if_not_started(trx);
@@ -1404,7 +1497,7 @@ trx_commit_for_mysql(
mutex_exit(&kernel_mutex);
- trx->op_info = (char *) "";
+ trx->op_info = "";
return(0);
}
@@ -1423,7 +1516,7 @@ trx_commit_complete_for_mysql(
ut_a(trx);
- trx->op_info = (char*)"flushing log";
+ trx->op_info = "flushing log";
if (srv_flush_log_at_trx_commit == 0) {
/* Do nothing */
@@ -1447,7 +1540,7 @@ trx_commit_complete_for_mysql(
ut_error;
}
- trx->op_info = (char*)"";
+ trx->op_info = "";
return(0);
}
diff --git a/innobase/usr/usr0sess.c b/innobase/usr/usr0sess.c
index cc016f2b823..359c1552421 100644
--- a/innobase/usr/usr0sess.c
+++ b/innobase/usr/usr0sess.c
@@ -37,6 +37,8 @@ sess_open(void)
#endif /* UNIV_SYNC_DEBUG */
sess = mem_alloc(sizeof(sess_t));
+ sess->state = SESS_ACTIVE;
+
sess->trx = trx_create(sess);
UT_LIST_INIT(sess->graphs);
diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c
index 47b612d757e..9a591df9f77 100644
--- a/innobase/ut/ut0mem.c
+++ b/innobase/ut/ut0mem.c
@@ -203,6 +203,81 @@ ut_free(
}
/**************************************************************************
+Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not
+use this function because the allocation functions in mem0mem.h are the
+recommended ones in InnoDB.
+
+man realloc in Linux, 2004:
+
+ realloc() changes the size of the memory block pointed to
+ by ptr to size bytes. The contents will be unchanged to
+ the minimum of the old and new sizes; newly allocated mem­
+ ory will be uninitialized. If ptr is NULL, the call is
+ equivalent to malloc(size); if size is equal to zero, the
+ call is equivalent to free(ptr). Unless ptr is NULL, it
+ must have been returned by an earlier call to malloc(),
+ calloc() or realloc().
+
+RETURN VALUE
+ realloc() returns a pointer to the newly allocated memory,
+ which is suitably aligned for any kind of variable and may
+ be different from ptr, or NULL if the request fails. If
+ size was equal to 0, either NULL or a pointer suitable to
+ be passed to free() is returned. If realloc() fails the
+ original block is left untouched - it is not freed or
+ moved. */
+
+void*
+ut_realloc(
+/*=======*/
+ /* out, own: pointer to new mem block or NULL */
+ void* ptr, /* in: pointer to old block or NULL */
+ ulint size) /* in: desired size */
+{
+ ut_mem_block_t* block;
+ ulint old_size;
+ ulint min_size;
+ void* new_ptr;
+
+ if (ptr == NULL) {
+
+ return(ut_malloc(size));
+ }
+
+ if (size == 0) {
+ ut_free(ptr);
+
+ return(NULL);
+ }
+
+ block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
+
+ ut_a(block->magic_n == UT_MEM_MAGIC_N);
+
+ old_size = block->size - sizeof(ut_mem_block_t);
+
+ if (size < old_size) {
+ min_size = size;
+ } else {
+ min_size = old_size;
+ }
+
+ new_ptr = ut_malloc(size);
+
+ if (new_ptr == NULL) {
+
+ return(NULL);
+ }
+
+ /* Copy the old data from ptr */
+ ut_memcpy(new_ptr, ptr, min_size);
+
+ ut_free(ptr);
+
+ return(new_ptr);
+}
+
+/**************************************************************************
Frees in shutdown all allocated memory not freed yet. */
void
diff --git a/isam/_dynrec.c b/isam/_dynrec.c
index d17d34e6778..25fe01e23f2 100644
--- a/isam/_dynrec.c
+++ b/isam/_dynrec.c
@@ -430,7 +430,7 @@ uint _nisam_rec_pack(N_INFO *info, register byte *to, register const byte *from)
to+=length+blob->length;
}
blob++;
- from+=sizeof(char*); /* Skipp blob-pointer */
+ from+=sizeof(char*); /* Skip blob-pointer */
}
else if (type == FIELD_SKIP_ZERO)
{
@@ -633,7 +633,7 @@ uint _nisam_rec_unpack(register N_INFO *info, register byte *to, byte *from,
if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
{
if (type == FIELD_ZERO)
- continue; /* Skipp this */
+ continue; /* Skip this */
if (flag & bit)
{
if (type == FIELD_BLOB)
@@ -747,7 +747,7 @@ uint _calc_blob_length(uint length, const byte *pos)
return (uint) (unsigned short) j;
}
#ifdef MSDOS
- break; /* skipp microsoft warning */
+ break; /* skip microsoft warning */
#endif
case 3:
return uint3korr(pos);
diff --git a/isam/isamchk.c b/isam/isamchk.c
index 513c1ea3a5d..5dd20c14063 100644
--- a/isam/isamchk.c
+++ b/isam/isamchk.c
@@ -858,7 +858,7 @@ static int chk_size(register N_INFO *info)
#endif
if (skr != size)
{
- info->s->state.data_file_length=(ulong) size; /* Skipp other errors */
+ info->s->state.data_file_length=(ulong) size; /* Skip other errors */
if (skr > size && skr != size + MEMMAP_EXTRA_MARGIN)
{
error=1;
@@ -1800,12 +1800,12 @@ my_string name;
if (buff[0] == ',')
strmov(buff,buff+2);
#endif
- len=(uint) (int2str((long) share->rec[field].base.length,length,10) -
+ len=(uint) (int10_to_str((long) share->rec[field].base.length,length,10) -
length);
if (type == FIELD_BLOB)
{
length[len]='+';
- VOID(int2str((long) sizeof(char*),length+len+1,10));
+ VOID(int10_to_str((long) sizeof(char*),length+len+1,10));
}
printf("%-6d%-6d%-7s%-35s",field+1,start,length,buff);
#ifndef NOT_PACKED_DATABASES
@@ -2672,7 +2672,7 @@ static int sort_get_next_record()
goto try_next;
block_info.second_read=0;
searching=1;
- for (i=1 ; i < 11 ; i++) /* Skipp from read string */
+ for (i=1 ; i < 11 ; i++) /* Skip from read string */
if (block_info.header[i] >= 1 && block_info.header[i] <= 16)
break;
pos+=(ulong) i;
diff --git a/isam/isamlog.c b/isam/isamlog.c
index 75a35ef9704..5cc204b26aa 100644
--- a/isam/isamlog.c
+++ b/isam/isamlog.c
@@ -144,7 +144,7 @@ static void get_options(register int *argc, register char ***argv)
switch((option=*pos)) {
case '#':
DBUG_PUSH (++pos);
- pos=" "; /* Skipp rest of arg */
+ pos=" "; /* Skip rest of arg */
break;
case 'c':
if (! *++pos)
diff --git a/isam/pack_isam.c b/isam/pack_isam.c
index 9108070f918..aa83b2b2a96 100644
--- a/isam/pack_isam.c
+++ b/isam/pack_isam.c
@@ -28,7 +28,7 @@
#include <io.h>
#endif
#ifndef __GNU_LIBRARY__
-#define __GNU_LIBRARY__ /* Skipp warnings in getopt.h */
+#define __GNU_LIBRARY__ /* Skip warnings in getopt.h */
#endif
#include <my_getopt.h>
diff --git a/isam/test1.c b/isam/test1.c
index 9ebc7af041d..b9f4d8242c3 100644
--- a/isam/test1.c
+++ b/isam/test1.c
@@ -136,7 +136,7 @@ int main(int argc, char *argv[])
err:
printf("got error: %3d when using nisam-database\n",my_errno);
exit(1);
- return 0; /* skipp warning */
+ return 0; /* skip warning */
} /* main */
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index 883ea2b5932..b073155f02b 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -65,7 +65,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
my_pread.lo mf_cache.lo md5.lo sha1.lo\
my_getopt.lo my_gethostbyname.lo my_port.lo
sqlobjects = net.lo
-sql_cmn_objects = pack.lo client.lo
+sql_cmn_objects = pack.lo client.lo my_time.lo
# Not needed in the minimum library
mysysobjects2 = my_lib.lo
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index ad93c1b8f9e..2b941470fc3 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Error messages for MySQL clients */
-/* error messages for the daemon is in share/language/errmsg.sys */
+/* (Error messages for the daemon are in share/language/errmsg.sys) */
#include <my_global.h>
#include <my_sys.h>
@@ -31,20 +31,20 @@ const char *client_errors[]=
"Kann TCP/IP-Socket nicht anlegen (%d)",
"Unbekannter MySQL Server Host (%-.100s) (%d)",
"MySQL Server nicht vorhanden",
- "Protokolle ungleich. Server Version = % d Client Version = %d",
- "MySQL client got out of memory",
+ "Protokolle ungleich; Server Version = %d, Client Version = %d",
+ "MySQL client ran out of memory",
"Wrong host info",
"Localhost via UNIX socket",
"%-.100s via TCP/IP",
"Error in server handshake",
"Lost connection to MySQL server during query",
- "Commands out of sync; You can't run this command now",
+ "Commands out of sync; you can't run this command now",
"Verbindung ueber Named Pipe; Host: %-.100s",
"Kann nicht auf Named Pipe warten. Host: %-.64s pipe: %-.32s (%lu)",
"Kann Named Pipe nicht oeffnen. Host: %-.64s pipe: %-.32s (%lu)",
"Kann den Status der Named Pipe nicht setzen. Host: %-.64s pipe: %-.32s (%lu)",
"Can't initialize character set %-.32s (path: %-.100s)",
- "Got packet bigger than 'max_allowed_packet'",
+ "Got packet bigger than 'max_allowed_packet' bytes",
"Embedded server",
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
@@ -55,26 +55,26 @@ const char *client_errors[]=
"This client library is licensed only for use with MySQL servers having '%s' license",
"Invalid use of null pointer",
"Statement not prepared",
- "Parameters data was not supplied",
+ "No data supplied for parameters in prepared statement",
"Data truncated",
- "No parameters exists in the statement",
+ "No parameters exist in the statement",
"Invalid parameter number",
- "Can't send long data for non string or binary data types (parameter: %d)",
+ "Can't send long data for non-string/non-binary data types (parameter: %d)",
"Using unsupported buffer type: %d (parameter: %d)",
"Shared memory (%lu)",
- "Can't open shared memory. Request event don't create (%lu)",
- "Can't open shared memory. Answer event don't create (%lu)",
- "Can't open shared memory. File mapping don't create (%lu)",
- "Can't open shared memory. Map of memory don't create (%lu)",
- "Can't open shared memory. File mapping don't create for client (%lu)",
- "Can't open shared memory. Map of memory don't create for client (%lu)",
- "Can't open shared memory. %s event don't create for client (%lu)",
- "Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
- "Can't open shared memory. Can't send the request event to server (%lu)",
+ "Can't open shared memory; client could not create request event (%lu)",
+ "Can't open shared memory; no answer event received from server (%lu)",
+ "Can't open shared memory; server could not allocate file mapping (%lu)",
+ "Can't open shared memory; server could not get pointer to file mapping (%lu)",
+ "Can't open shared memory; client could not allocate file mapping (%lu)",
+ "Can't open shared memory; client could not get pointer to file mapping (%lu)",
+ "Can't open shared memory; client could not create %s event (%lu)",
+ "Can't open shared memory; no answer from server (%lu)",
+ "Can't open shared memory; cannot send request event to server (%lu)",
"Wrong or unknown protocol",
"Invalid connection handle",
- "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
- "Row retrieval was cancelled by mysql_stmt_close() call",
+ "Connection using old (pre-4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
+ "Row retrieval was canceled by mysql_stmt_close() call",
"Attempt to read column without prior row fetch"
};
@@ -90,20 +90,20 @@ const char *client_errors[]=
"Não pode criar 'socket TCP/IP' (%d)",
"'Host' servidor MySQL '%-.100s' (%d) desconhecido",
"Servidor MySQL desapareceu",
- "Incompatibilidade de protocolos. Versão do Servidor: %d - Versão do Cliente: %d",
+ "Incompatibilidade de protocolos; versão do servidor = %d, versão do cliente = %d",
"Cliente do MySQL com falta de memória",
"Informação inválida de 'host'",
"Localhost via 'UNIX socket'",
"%-.100s via 'TCP/IP'",
"Erro na negociação de acesso ao servidor",
"Conexão perdida com servidor MySQL durante 'query'",
- "Comandos fora de sincronismo. Você não pode executar este comando agora",
+ "Comandos fora de sincronismo; você não pode executar este comando agora",
"%-.100s via 'named pipe'",
"Não pode esperar pelo 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"Não pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"Não pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"Não pode inicializar conjunto de caracteres %-.32s (caminho %-.100s)",
- "Obteve pacote maior do que 'max_allowed_packet'",
+ "Obteve pacote maior do que 'max_allowed_packet' bytes",
"Embedded server"
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
@@ -114,26 +114,26 @@ const char *client_errors[]=
"This client library is licensed only for use with MySQL servers having '%s' license",
"Invalid use of null pointer",
"Statement not prepared",
- "Parameters data was not supplied",
+ "No data supplied for parameters in prepared statement",
"Data truncated",
- "No parameters exists in the statement",
+ "No parameters exist in the statement",
"Invalid parameter number",
- "Can't send long data for non string or binary data types (parameter: %d)",
+ "Can't send long data for non-string/non-binary data types (parameter: %d)",
"Using unsupported buffer type: %d (parameter: %d)",
"Shared memory (%lu)",
- "Can't open shared memory. Request event don't create (%lu)",
- "Can't open shared memory. Answer event don't create (%lu)",
- "Can't open shared memory. File mapping don't create (%lu)",
- "Can't open shared memory. Map of memory don't create (%lu)",
- "Can't open shared memory. File mapping don't create for client (%lu)",
- "Can't open shared memory. Map of memory don't create for client (%lu)",
- "Can't open shared memory. %s event don't create for client (%lu)",
- "Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
- "Can't open shared memory. Can't send the request event to server (%lu)",
+ "Can't open shared memory; client could not create request event (%lu)",
+ "Can't open shared memory; no answer event received from server (%lu)",
+ "Can't open shared memory; server could not allocate file mapping (%lu)",
+ "Can't open shared memory; server could not get pointer to file mapping (%lu)",
+ "Can't open shared memory; client could not allocate file mapping (%lu)",
+ "Can't open shared memory; client could not get pointer to file mapping (%lu)",
+ "Can't open shared memory; client could not create %s event (%lu)",
+ "Can't open shared memory; no answer from server (%lu)",
+ "Can't open shared memory; cannot send request event to server (%lu)",
"Wrong or unknown protocol",
"Invalid connection handle",
- "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
- "Row retrieval was cancelled by mysql_stmt_close() call",
+ "Connection using old (pre-4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
+ "Row retrieval was canceled by mysql_stmt_close() call",
"Attempt to read column without prior row fetch"
};
@@ -145,22 +145,22 @@ const char *client_errors[]=
"Can't connect to local MySQL server through socket '%-.100s' (%d)",
"Can't connect to MySQL server on '%-.100s' (%d)",
"Can't create TCP/IP socket (%d)",
- "Unknown MySQL Server Host '%-.100s' (%d)",
+ "Unknown MySQL server host '%-.100s' (%d)",
"MySQL server has gone away",
- "Protocol mismatch. Server Version = %d Client Version = %d",
- "MySQL client run out of memory",
+ "Protocol mismatch; server version = %d, client version = %d",
+ "MySQL client ran out of memory",
"Wrong host info",
"Localhost via UNIX socket",
"%-.100s via TCP/IP",
"Error in server handshake",
"Lost connection to MySQL server during query",
- "Commands out of sync; You can't run this command now",
+ "Commands out of sync; you can't run this command now",
"%-.100s via named pipe",
"Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)",
"Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)",
"Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
"Can't initialize character set %-.32s (path: %-.100s)",
- "Got packet bigger than 'max_allowed_packet'",
+ "Got packet bigger than 'max_allowed_packet' bytes",
"Embedded server",
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
@@ -171,26 +171,26 @@ const char *client_errors[]=
"This client library is licensed only for use with MySQL servers having '%s' license",
"Invalid use of null pointer",
"Statement not prepared",
- "Not all parameters data supplied",
+ "No data supplied for parameters in prepared statement",
"Data truncated",
- "No parameters exists in the statement",
+ "No parameters exist in the statement",
"Invalid parameter number",
- "Can't send long data for non string or binary data types (parameter: %d)",
+ "Can't send long data for non-string/non-binary data types (parameter: %d)",
"Using unsupported buffer type: %d (parameter: %d)",
"Shared memory (%lu)",
- "Can't open shared memory. Request event don't create (%lu)",
- "Can't open shared memory. Answer event don't create (%lu)",
- "Can't open shared memory. File mapping don't create (%lu)",
- "Can't open shared memory. Map of memory don't create (%lu)",
- "Can't open shared memory. File mapping don't create for client (%lu)",
- "Can't open shared memory. Map of memory don't create for client (%lu)",
- "Can't open shared memory. %s event don't create for client (%lu)",
- "Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
- "Can't open shared memory. Can't send the request event to server (%lu)",
+ "Can't open shared memory; client could not create request event (%lu)",
+ "Can't open shared memory; no answer event received from server (%lu)",
+ "Can't open shared memory; server could not allocate file mapping (%lu)",
+ "Can't open shared memory; server could not get pointer to file mapping (%lu)",
+ "Can't open shared memory; client could not allocate file mapping (%lu)",
+ "Can't open shared memory; client could not get pointer to file mapping (%lu)",
+ "Can't open shared memory; client could not create %s event (%lu)",
+ "Can't open shared memory; no answer from server (%lu)",
+ "Can't open shared memory; cannot send request event to server (%lu)",
"Wrong or unknown protocol",
"Invalid connection handle",
- "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
- "Row retrieval was cancelled by mysql_stmt_close() call",
+ "Connection using old (pre-4.1.1) authentication protocol refused (client option 'secure_auth' enabled)",
+ "Row retrieval was canceled by mysql_stmt_close() call",
"Attempt to read column without prior row fetch"
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 63f447ea1b9..fc7728c98e0 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -16,6 +16,7 @@
#include <my_global.h>
#include <my_sys.h>
+#include <my_time.h>
#include <mysys_err.h>
#include <m_string.h>
#include <m_ctype.h>
@@ -27,7 +28,6 @@
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
-#include <assert.h> /* for DBUG_ASSERT() */
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@@ -59,6 +59,9 @@
#include <sql_common.h>
#include "client_settings.h"
+#undef net_buffer_length
+#undef max_allowed_packet
+
ulong net_buffer_length=8192;
ulong max_allowed_packet= 1024L*1024L*1024L;
ulong net_read_timeout= CLIENT_NET_READ_TIMEOUT;
@@ -85,7 +88,6 @@ my_bool net_flush(NET *net);
#define MAX_LONG_DATA_LENGTH 8192
#define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
-static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
static void append_wild(char *to,char *end,const char *wild);
sig_handler pipe_sig_handler(int sig);
@@ -149,7 +151,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)),
mysql_unix_port = env;
}
mysql_debug(NullS);
-#if defined(SIGPIPE) && !defined(__WIN__)
+#if defined(SIGPIPE) && !defined(__WIN__) && !defined(__NETWARE__)
(void) signal(SIGPIPE, SIG_IGN);
#endif
#ifdef EMBEDDED_LIBRARY
@@ -183,6 +185,14 @@ void STDCALL mysql_server_end()
mysql_client_init= org_my_init_done= 0;
}
+static MYSQL_PARAMETERS mysql_internal_parameters=
+{&max_allowed_packet, &net_buffer_length};
+
+MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void)
+{
+ return &mysql_internal_parameters;
+}
+
my_bool STDCALL mysql_thread_init()
{
#ifdef THREAD
@@ -608,60 +618,10 @@ mysql_connect(MYSQL *mysql,const char *host,
#endif
-#ifdef CHECK_LICENSE
-/*
- Check server side variable 'license'.
- If the variable does not exist or does not contain 'Commercial',
- we're talking to non-commercial server from commercial client.
- SYNOPSIS
- check_license()
- RETURN VALUE
- 0 success
- !0 network error or the server is not commercial.
- Error code is saved in mysql->net.last_errno.
-*/
-
-static int check_license(MYSQL *mysql)
-{
- MYSQL_ROW row;
- MYSQL_RES *res;
- NET *net= &mysql->net;
- static const char query[]= "SELECT @@license";
- static const char required_license[]= STRINGIFY_ARG(LICENSE);
-
- if (mysql_real_query(mysql, query, sizeof(query)-1))
- {
- if (net->last_errno == ER_UNKNOWN_SYSTEM_VARIABLE)
- {
- net->last_errno= CR_WRONG_LICENSE;
- sprintf(net->last_error, ER(net->last_errno), required_license);
- }
- return 1;
- }
- if (!(res= mysql_use_result(mysql)))
- return 1;
- row= mysql_fetch_row(res);
- /*
- If no rows in result set, or column value is NULL (none of these
- two is ever true for server variables now), or column value
- mismatch, set wrong license error.
- */
- if (!net->last_errno &&
- (!row || !row[0] ||
- strncmp(row[0], required_license, sizeof(required_license))))
- {
- net->last_errno= CR_WRONG_LICENSE;
- sprintf(net->last_error, ER(net->last_errno), required_license);
- }
- mysql_free_result(res);
- return net->last_errno;
-}
-#endif /* CHECK_LICENSE */
-
-
/**************************************************************************
Change user and database
**************************************************************************/
+
int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
{
NET *net= &mysql->net;
@@ -1328,10 +1288,12 @@ mysql_drop_db(MYSQL *mysql, const char *db)
int STDCALL
-mysql_shutdown(MYSQL *mysql)
+mysql_shutdown(MYSQL *mysql, enum enum_shutdown_level shutdown_level)
{
+ uchar level[1];
DBUG_ENTER("mysql_shutdown");
- DBUG_RETURN(simple_command(mysql,COM_SHUTDOWN,0,0,0));
+ level[0]= (uchar) shutdown_level;
+ DBUG_RETURN(simple_command(mysql, COM_SHUTDOWN, (char *)level, 1, 0));
}
@@ -1682,70 +1644,72 @@ myodbc_remove_escape(MYSQL *mysql,char *name)
}
/********************************************************************
+ Implementation of new client API for 4.1 version.
- Implementation of new client-server prototypes for 4.1 version
- starts from here ..
-
- mysql_* are real prototypes used by applications
+ mysql_stmt_* are real prototypes used by applications.
+ To make API work in embedded library all functions performing
+ real I/O are prefixed with 'cli_' (abbreviated from 'Call Level
+ Interface'). This functions are invoked via pointers set in
+ MYSQL::methods structure. Embedded counterparts, prefixed with
+ 'emb_' reside in libmysqld/lib_sql.cc.
*********************************************************************/
-/********************************************************************
- Misc Utility functions
-********************************************************************/
+/******************* Declarations ***********************************/
+
/*
- Set the internal stmt error messages
+ These functions are called by function pointer MYSQL_STMT::read_row_func.
+ Each function corresponds to one of the read methods:
+ - mysql_stmt_fetch without prior mysql_stmt_store_result,
+ - mysql_stmt_fetch when result is stored,
+ - mysql_stmt_fetch when there are no rows (always returns MYSQL_NO_DATA)
*/
-static void set_stmt_error(MYSQL_STMT * stmt, int errcode,
- const char *sqlstate)
-{
- DBUG_ENTER("set_stmt_error");
- DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode)));
- DBUG_ASSERT(stmt != 0);
-
- stmt->last_errno= errcode;
- strmov(stmt->last_error, ER(errcode));
- strmov(stmt->sqlstate, sqlstate);
-
- DBUG_VOID_RETURN;
-}
+static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row);
+static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row);
+static int stmt_read_row_no_data(MYSQL_STMT *stmt, unsigned char **row);
+/*
+ This function is used in mysql_stmt_store_result if
+ STMT_ATTR_UPDATE_MAX_LENGTH attribute is set.
+*/
+static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
/*
- Copy error message to statement handler
+ Maximum sizes of MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME
+ values stored in network buffer.
*/
-void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode,
- const char *sqlstate)
-{
- DBUG_ENTER("set_stmt_error_msg");
- DBUG_PRINT("enter", ("error: %d/%s '%s'", errcode, sqlstate, err));
- DBUG_ASSERT(stmt != 0);
+/* 1 (length) + 2 (year) + 1 (month) + 1 (day) */
+#define MAX_DATE_REP_LENGTH 5
- stmt->last_errno= errcode;
- if (err && err[0])
- strmov(stmt->last_error, err);
- strmov(stmt->sqlstate, sqlstate);
+/*
+ 1 (length) + 1 (is negative) + 4 (day count) + 1 (hour)
+ + 1 (minute) + 1 (seconds) + 4 (microseconds)
+*/
+#define MAX_TIME_REP_LENGTH 13
- DBUG_VOID_RETURN;
-}
+/*
+ 1 (length) + 2 (year) + 1 (month) + 1 (day) +
+ 1 (hour) + 1 (minute) + 1 (second) + 4 (microseconds)
+*/
+#define MAX_DATETIME_REP_LENGTH 12
+/**************** Misc utility functions ****************************/
/*
Reallocate the NET package to be at least of 'length' bytes
SYNPOSIS
my_realloc_str()
- net The NET structure to modify
- int length Ensure that net->buff is at least this big
+ net The NET structure to modify
+ length Ensure that net->buff is at least this big
RETURN VALUES
0 ok
1 Error
-
*/
static my_bool my_realloc_str(NET *net, ulong length)
@@ -1761,20 +1725,54 @@ static my_bool my_realloc_str(NET *net, ulong length)
DBUG_RETURN(res);
}
-/********************************************************************
- Prepare related implementations
-********************************************************************/
-static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row);
-static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row);
-static int stmt_read_row_no_data(MYSQL_STMT *stmt, unsigned char **row);
+/*
+ Set statement error code, sqlstate, and error message
+ from given errcode and sqlstate.
+*/
+
+static void set_stmt_error(MYSQL_STMT * stmt, int errcode,
+ const char *sqlstate)
+{
+ DBUG_ENTER("set_stmt_error");
+ DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode)));
+ DBUG_ASSERT(stmt != 0);
+
+ stmt->last_errno= errcode;
+ strmov(stmt->last_error, ER(errcode));
+ strmov(stmt->sqlstate, sqlstate);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Set statement error code, sqlstate, and error message.
+*/
+
+void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode,
+ const char *sqlstate)
+{
+ DBUG_ENTER("set_stmt_errmsg");
+ DBUG_PRINT("enter", ("error: %d/%s '%s'", errcode, sqlstate, err));
+ DBUG_ASSERT(stmt != 0);
+
+ stmt->last_errno= errcode;
+ if (err && err[0])
+ strmov(stmt->last_error, err);
+ strmov(stmt->sqlstate, sqlstate);
+
+ DBUG_VOID_RETURN;
+}
/*
- Read the prepared statement results ..
+ Read and unpack server reply to COM_PREPARE command (sent from
+ mysql_stmt_prepare).
- NOTE
- This is only called for connection to servers that supports
- prepared statements (and thus the 4.1 protocol)
+ SYNOPSIS
+ cli_read_prepare_result()
+ mysql connection handle
+ stmt statement handle
RETURN VALUES
0 ok
@@ -1794,7 +1792,9 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
pos= (uchar*) mysql->net.read_pos;
stmt->stmt_id= uint4korr(pos+1); pos+= 5;
+ /* Number of columns in result set */
field_count= uint2korr(pos); pos+= 2;
+ /* Number of placeholders in the statement */
param_count= uint2korr(pos); pos+= 2;
if (param_count != 0)
@@ -1844,10 +1844,30 @@ MYSQL_STMT * STDCALL mysql_prepare(MYSQL *mysql, const char *query,
#endif
/*
- Allocate memory and init prepared statement structure
+ Allocate memory and init prepared statement structure.
+
SYNOPSIS
mysql_stmt_init()
- mysql connection handle
+ mysql connection handle
+
+ DESCRIPTION
+ This is an entry point of the new API. Returned handle stands for
+ a server-side prepared statement. Memory for this structure (~700
+ bytes) is allocated using 'malloc'. Once created, the handle can be
+ reused many times. Created statement handle is bound to connection
+ handle provided to this call: it's lifetime is limited by lifetime
+ of connection.
+ 'mysql_stmt_init()' is a pure local call, server side structure is
+ created only in mysql_stmt_prepare.
+ Next steps you may want to make:
+ - set a statement attribute (mysql_stmt_attr_set()),
+ - prepare statement handle with a query (mysql_stmt_prepare()),
+ - close statement handle and free it's memory (mysql_stmt_close()),
+ - reset statement with mysql_stmt_reset() (a no-op which will
+ just return).
+ Behaviour of the rest of API calls on this statement is not defined yet
+ (though we're working on making each wrong call sequence return
+ error).
RETURN VALUE
statement structure upon success and NULL if out of
@@ -1880,27 +1900,41 @@ mysql_stmt_init(MYSQL *mysql)
DBUG_RETURN(stmt);
}
+
/*
- Prepare server side statement with query:
+ Prepare server side statement with query.
+
SYNOPSIS
mysql_stmt_prepare()
- query statement to prepare
- length statement length
+ stmt statement handle
+ query statement to prepare
+ length statement length
DESCRIPTION
- - if this is a re-prepare of the statement, first close previous data
+ Associate statement with statement handle. This is done both on
+ client and server sides. At this point the server parses given query
+ and creates an internal structure to represent it.
+ Next steps you may want to make:
+ - find out if this statement returns a result set by
+ calling mysql_stmt_field_count(), and get result set metadata
+ with mysql_stmt_result_metadata(),
+ - if query contains placeholders, bind input parameters to placeholders
+ using mysql_stmt_bind_param(),
+ - otherwise proceed directly to mysql_stmt_execute().
+
+ IMPLEMENTATION NOTES
+ - if this is a re-prepare of the statement, first close previous data
structure on the server and free old statement data
- - send the query to server and get back number of placeholders,
+ - then send the query to server and get back number of placeholders,
number of columns in result set (if any), and result set metadata.
- At the same time allocate memory for input and output parameters
+ At the same time allocate memory for input and output parameters
to have less checks in mysql_stmt_bind_{param, result}.
RETURN VALUES
0 success
- !0 error
+ !0 error
*/
-
int STDCALL
mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
{
@@ -1921,7 +1955,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
mysql_stmt_free_result(stmt);
/*
- These members must be reset for API to
+ These members must be reset for API to
function in case of error or misuse.
*/
stmt->bind_param_done= stmt->bind_result_done= FALSE;
@@ -1960,14 +1994,14 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
}
/*
- alloc_root will return valid address even in case param_count
+ alloc_root will return valid address even in case param_count
and field_count are zero. Thus we should never rely on stmt->bind
or stmt->params when checking for existence of placeholders or
result set.
*/
if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
sizeof(MYSQL_BIND)*
- (stmt->param_count +
+ (stmt->param_count +
stmt->field_count))))
{
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
@@ -1980,8 +2014,10 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
}
/*
- Get the execute query meta information for non-select
- statements.
+ Get result set metadata from reply to mysql_stmt_execute.
+ This is used mainly for SHOW commands, as metadata for these
+ commands is sent only with result set.
+ To be removed when all commands will fully support prepared mode.
*/
static unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
@@ -1989,22 +2025,22 @@ static unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
MYSQL_FIELD *fields, *field, *end;
MEM_ROOT *alloc= &stmt->mem_root;
MYSQL *mysql= stmt->mysql->last_used_con;
-
+
stmt->field_count= mysql->field_count;
-
+
/*
- Get the field information for non-select statements
+ Get the field information for non-select statements
like SHOW and DESCRIBE commands
*/
- if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
+ if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
sizeof(MYSQL_FIELD) *
- stmt->field_count)) ||
- !(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
+ stmt->field_count)) ||
+ !(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
sizeof(MYSQL_BIND) *
stmt->field_count)))
return 0;
-
- for (fields= mysql->fields, end= fields+stmt->field_count,
+
+ for (fields= mysql->fields, end= fields+stmt->field_count,
field= stmt->fields;
field && fields < end; fields++, field++)
{
@@ -2024,9 +2060,56 @@ static unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
return stmt->field_count;
}
+
+/*
+ Update result set columns metadata if it was sent again in
+ reply to COM_EXECUTE.
+*/
+
+static void update_stmt_fields(MYSQL_STMT *stmt)
+{
+ MYSQL_FIELD *field= stmt->mysql->fields;
+ MYSQL_FIELD *field_end= field + stmt->field_count;
+ MYSQL_FIELD *stmt_field= stmt->fields;
+
+ DBUG_ASSERT(stmt->field_count == stmt->mysql->field_count);
+
+ for (; field < field_end; ++field, ++stmt_field)
+ {
+ stmt_field->charsetnr= field->charsetnr;
+ stmt_field->length = field->length;
+ stmt_field->type = field->type;
+ stmt_field->flags = field->flags;
+ stmt_field->decimals = field->decimals;
+ }
+}
+
/*
- Returns prepared meta information in the form of resultset
- to client.
+ Returns prepared statement metadata in the form of a result set.
+
+ SYNOPSIS
+ mysql_stmt_result_metadata()
+ stmt statement handle
+
+ RETURN
+ NULL statement contains no result set or out of memory.
+ In the latter case you can retreive error message
+ with mysql_stmt_error.
+ MYSQL_RES a result set with no rows
+
+ DESCRIPTION
+ This function should be used after mysql_stmt_execute().
+ You can safely check that prepared statement has a result set by calling
+ mysql_stmt_num_fields(): if number of fields is not zero, you can call
+ this function to get fields metadata.
+ Next steps you may want to make:
+ - find out number of columns in result set by calling
+ mysql_num_fields(res) (the same value is returned by
+ mysql_stmt_num_fields)
+ - fetch metadata for any column with mysql_fetch_field,
+ mysql_fetch_field_direct, mysql_fetch_fields, mysql_field_seek.
+ - free returned MYSQL_RES structure with mysql_free_result.
+ - proceed to binding of output parameters.
*/
MYSQL_RES * STDCALL
@@ -2034,7 +2117,7 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt)
{
MYSQL_RES *result;
DBUG_ENTER("mysql_stmt_result_metadata");
-
+
/*
stmt->fields is only defined if stmt->field_count is not null;
stmt->field_count is initialized in prepare.
@@ -2057,49 +2140,70 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt)
DBUG_RETURN(result);
}
+
/*
- Returns parameter columns meta information in the form of
- resultset.
+ Returns parameter columns meta information in the form of
+ result set.
+
+ SYNOPSYS
+ mysql_stmt_param_metadata()
+ stmt statement handle
+
+ DESCRIPTION
+ This function can be called after you prepared the statement handle
+ with mysql_stmt_prepare().
+ XXX: not implemented yet.
+
+ RETURN
+ MYSQL_RES on success, 0 if there is no metadata.
+ Currently this function always returns 0.
*/
MYSQL_RES * STDCALL
mysql_stmt_param_metadata(MYSQL_STMT *stmt)
{
DBUG_ENTER("mysql_stmt_param_metadata");
-
+
if (!stmt->param_count)
DBUG_RETURN(0);
/*
- TODO: Fix this when server sends the information.
- Till then keep a dummy prototype
+ TODO: Fix this when server sends the information.
+ Till then keep a dummy prototype.
*/
DBUG_RETURN(0);
}
-/********************************************************************
- Prepare-execute, and param handling
-*********************************************************************/
+/* Store type of parameter in network buffer. */
-/****************************************************************************
- Functions to store parameter data from a prepared statement.
+static void store_param_type(char **pos, MYSQL_BIND *param)
+{
+ uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0);
+ int2store(*pos, typecode);
+ *pos+= 2;
+}
- All functions have the following characteristics:
+
+/*
+ Functions to store parameter data in network packet.
SYNOPSIS
store_param_xxx()
net MySQL NET connection
param MySQL bind param
- RETURN VALUES
- 0 ok
- 1 Error (Can't alloc net->buffer)
-****************************************************************************/
+ DESCRIPTION
+ These funtions are invoked from mysql_stmt_execute by
+ MYSQL_BIND::store_param_func pointer. This pointer is set once per many
+ executions in mysql_stmt_bind_param. The caller must ensure that network
+ buffer have enough capacity to store parameter (MYSQL_BIND::buffer_length
+ contains needed number of bytes).
+*/
static void store_param_tinyint(NET *net, MYSQL_BIND *param)
{
- *(net->write_pos++)= (uchar) *param->buffer;
+ *(net->write_pos++)= *(uchar *) param->buffer;
}
static void store_param_short(NET *net, MYSQL_BIND *param)
@@ -2140,7 +2244,7 @@ static void store_param_double(NET *net, MYSQL_BIND *param)
static void store_param_time(NET *net, MYSQL_BIND *param)
{
MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
- char buff[15], *pos;
+ char buff[MAX_TIME_REP_LENGTH], *pos;
uint length;
pos= buff+1;
@@ -2151,19 +2255,19 @@ static void store_param_time(NET *net, MYSQL_BIND *param)
pos[7]= (uchar) tm->second;
int4store(pos+8, tm->second_part);
if (tm->second_part)
- length= 11;
+ length= 12;
else if (tm->hour || tm->minute || tm->second || tm->day)
length= 8;
else
length= 0;
- buff[0]= (char) length++;
+ buff[0]= (char) length++;
memcpy((char *)net->write_pos, buff, length);
net->write_pos+= length;
}
static void net_store_datetime(NET *net, MYSQL_TIME *tm)
{
- char buff[12], *pos;
+ char buff[MAX_DATETIME_REP_LENGTH], *pos;
uint length;
pos= buff+1;
@@ -2183,7 +2287,7 @@ static void net_store_datetime(NET *net, MYSQL_TIME *tm)
length= 4;
else
length= 0;
- buff[0]= (char) length++;
+ buff[0]= (char) length++;
memcpy((char *)net->write_pos, buff, length);
net->write_pos+= length;
}
@@ -2201,10 +2305,11 @@ static void store_param_datetime(NET *net, MYSQL_BIND *param)
MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
net_store_datetime(net, tm);
}
-
+
static void store_param_str(NET *net, MYSQL_BIND *param)
{
- ulong length= param->length ? *param->length : param->buffer_length;
+ /* param->length is always set in mysql_stmt_bind_param */
+ ulong length= *param->length;
char *to= (char *) net_store_length((char *) net->write_pos, length);
memcpy(to, param->buffer, length);
net->write_pos= (uchar*) to+length;
@@ -2221,7 +2326,8 @@ static void store_param_str(NET *net, MYSQL_BIND *param)
DESCRIPTION
A data package starts with a string of bits where we set a bit
- if a parameter is NULL
+ if a parameter is NULL. Unlike bit string in result set row, here
+ we don't have reserved bits for OK/error packet.
*/
static void store_param_null(NET *net, MYSQL_BIND *param)
@@ -2232,8 +2338,9 @@ static void store_param_null(NET *net, MYSQL_BIND *param)
/*
- Set parameter data by reading from input buffers from the
- client application
+ Store one parameter in network packet: data is read from
+ client buffer and saved in network packet by means of one
+ of store_param_xxxx functions.
*/
static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
@@ -2253,7 +2360,7 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
Param->length should ALWAYS point to the correct length for the type
Either to the length pointer given by the user or param->buffer_length
*/
- if ((my_realloc_str(net, 9 + *param->length)))
+ if ((my_realloc_str(net, *param->length)))
{
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(1);
@@ -2265,14 +2372,15 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
/*
- Send the prepared query to server for execution
+ Auxilary function to send COM_EXECUTE packet to server and read reply.
+ Used from cli_stmt_execute, which is in turn used by mysql_stmt_execute.
*/
-static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
+static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
{
MYSQL *mysql= stmt->mysql;
NET *net= &mysql->net;
- char buff[4 /* size of stmt id */ +
+ char buff[4 /* size of stmt id */ +
5 /* execution flags */];
DBUG_ENTER("execute");
DBUG_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length));
@@ -2292,14 +2400,6 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
stmt->insert_id= mysql->insert_id;
DBUG_RETURN(0);
}
-
-
-static void store_param_type(char **pos, MYSQL_BIND *param)
-{
- uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0);
- int2store(*pos, typecode);
- *pos+= 2;
-}
int cli_stmt_execute(MYSQL_STMT *stmt)
@@ -2342,7 +2442,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
for (param= stmt->params; param < param_end; param++)
{
- /* check if mysql_long_data() was used */
+ /* check if mysql_stmt_send_long_data() was used */
if (param->long_data_used)
param->long_data_used= 0; /* Clear for next execute call */
else if (store_param(stmt, param))
@@ -2401,16 +2501,16 @@ static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row)
0 - success; *row contains valid address of a row;
row data is stored in network buffer
1 - error; error code is written to
- stmt->last_{errno,error}; *row is not changed
+ stmt->last_{errno,error}; *row is not changed
MYSQL_NO_DATA - end of file was read from network;
- *row is to NULL
+ *row is set to NULL
*/
static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
{
int rc= 1;
MYSQL *mysql= stmt->mysql;
- /*
+ /*
This function won't be called if stmt->field_count is zero
or execution wasn't done: this is ensured by mysql_stmt_execute.
*/
@@ -2422,7 +2522,7 @@ static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
if (mysql->status != MYSQL_STATUS_GET_RESULT)
{
set_stmt_error(stmt, stmt->unbuffered_fetch_cancelled ?
- CR_FETCH_CANCELLED : CR_COMMANDS_OUT_OF_SYNC,
+ CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
unknown_sqlstate);
goto error;
}
@@ -2430,6 +2530,13 @@ static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
+ /*
+ If there was an error, there are no more pending rows:
+ reset statement status to not hang up in following
+ mysql_stmt_close (it will try to flush result set before
+ closing the statement).
+ */
+ mysql->status= MYSQL_STATUS_READY;
goto error;
}
if (!*row)
@@ -2477,7 +2584,7 @@ stmt_read_row_no_data(MYSQL_STMT *stmt __attribute__((unused)),
0 success
!0 wrong attribute type
*/
-
+
my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
enum enum_stmt_attr_type attr_type,
const void *value)
@@ -2486,14 +2593,14 @@ my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
case STMT_ATTR_UPDATE_MAX_LENGTH:
stmt->update_max_length= value ? *(const my_bool*) value : 0;
break;
- default:
+ default:
return TRUE;
}
return FALSE;
}
-my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
+my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
enum enum_stmt_attr_type attr_type,
void *value)
{
@@ -2501,7 +2608,7 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
case STMT_ATTR_UPDATE_MAX_LENGTH:
*(unsigned long *) value= stmt->update_max_length;
break;
- default:
+ default:
return TRUE;
}
return FALSE;
@@ -2509,7 +2616,47 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
/*
- Execute the prepared query
+ Send placeholders data to server (if there are placeholders)
+ and execute prepared statement.
+
+ SYNOPSIS
+ mysql_stmt_execute()
+ stmt statement handle. The handle must be created
+ with mysql_stmt_init() and prepared with
+ mysql_stmt_prepare(). If there are placeholders
+ in the statement they must be bound to local
+ variables with mysql_stmt_bind_param().
+
+ DESCRIPTION
+ This function will automatically flush pending result
+ set (if there is one), send parameters data to the server
+ and read result of statement execution.
+ If previous result set was cached with mysql_stmt_store_result()
+ it will also be freed in the beginning of this call.
+ The server can return 3 types of responses to this command:
+ - error, can be retrieved with mysql_stmt_error()
+ - ok, no result set pending. In this case we just update
+ stmt->insert_id and stmt->affected_rows.
+ - the query returns a result set: there could be 0 .. N
+ rows in it. In this case the server can also send updated
+ result set metadata.
+
+ Next steps you may want to make:
+ - find out if there is result set with mysql_stmt_field_count().
+ If there is one:
+ - optionally, cache entire result set on client to unblock
+ connection with mysql_stmt_store_result()
+ - bind client variables to result set columns and start read rows
+ with mysql_stmt_fetch().
+ - reset statement with mysql_stmt_reset() or close it with
+ mysql_stmt_close()
+ Otherwise:
+ - find out last insert id and number of affected rows with
+ mysql_stmt_insert_id(), mysql_stmt_affected_rows()
+
+ RETURN
+ 0 success
+ 1 error, message can be retrieved with mysql_stmt_error().
*/
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
@@ -2530,16 +2677,37 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
*/
if (mysql->methods->stmt_execute(stmt))
DBUG_RETURN(1);
- if (!stmt->field_count && mysql->field_count)
+ if (mysql->field_count)
{
- /*
- This is 'SHOW'/'EXPLAIN'-like query. Current implementation of
- prepared statements can't send result set metadata for this queries
- on prepare stage. Read it now.
- */
- alloc_stmt_fields(stmt);
+ /* Server has sent result set metadata */
+ if (stmt->field_count == 0)
+ {
+ /*
+ This is 'SHOW'/'EXPLAIN'-like query. Current implementation of
+ prepared statements can't send result set metadata for these queries
+ on prepare stage. Read it now.
+ */
+ alloc_stmt_fields(stmt);
+ }
+ else
+ {
+ /*
+ Update result set metadata if it for some reason changed between
+ prepare and execute, i.e.:
+ - in case of 'SELECT ?' we don't know column type unless data was
+ supplied to mysql_stmt_execute, so updated column type is sent
+ now.
+ - 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
+ previous always branch works.
+ TODO: send metadata only when it's really necessary and add a warning
+ 'Metadata changed' when it's sent twice.
+ */
+ update_stmt_fields(stmt);
+ }
}
-
stmt->state= MYSQL_STMT_EXECUTE_DONE;
if (stmt->field_count)
{
@@ -2572,7 +2740,29 @@ my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
/*
- Return last inserted id for auto_increment columns
+ Returns the number of result columns for the most recent query
+ run on this statement.
+*/
+
+unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
+{
+ return stmt->field_count;
+}
+
+/*
+ Return last inserted id for auto_increment columns.
+
+ SYNOPSIS
+ mysql_stmt_insert_id()
+ stmt statement handle
+
+ DESCRIPTION
+ Current implementation of this call has a caveat: stmt->insert_id is
+ unconditionally updated from mysql->insert_id in the end of each
+ mysql_stmt_execute(). This works OK if mysql->insert_id contains new
+ value (sent in reply to mysql_stmt_execute()), otherwise stmt->insert_id
+ value gets undefined, as it's updated from some arbitrary value saved in
+ connection structure during some other call.
*/
my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
@@ -2580,14 +2770,28 @@ my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
return stmt->insert_id;
}
+
static my_bool int_is_null_true= 1; /* Used for MYSQL_TYPE_NULL */
static my_bool int_is_null_false= 0;
+
/*
- Setup the parameter data buffers from application
+ Setup the input parameter data buffers from application
+
+ SYNOPSIS
+ mysql_stmt_bind_param()
+ stmt statement handle
+ The statement must be prepared with mysql_stmt_prepare().
+ bind Array of mysql_stmt_param_count() bind parameters.
+
+ RETURN
+ 0 success
+ 1 error, can be retrieved with mysql_stmt_error.
+ Note, that this function doesn't check that size of MYSQL_BIND
+ array is >= mysql_stmt_field_count(),
*/
-my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
+my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
{
uint count=0;
MYSQL_BIND *param, *end;
@@ -2655,15 +2859,17 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
param->store_param_func= store_param_double;
break;
case MYSQL_TYPE_TIME:
- /* Buffer length ignored for DATE, TIME and DATETIME */
param->store_param_func= store_param_time;
+ param->buffer_length= MAX_TIME_REP_LENGTH;
break;
case MYSQL_TYPE_DATE:
param->store_param_func= store_param_date;
+ param->buffer_length= MAX_DATE_REP_LENGTH;
break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
param->store_param_func= store_param_datetime;
+ param->buffer_length= MAX_DATETIME_REP_LENGTH;
break;
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
@@ -2672,6 +2878,10 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
param->store_param_func= store_param_str;
+ /*
+ For variable length types user must set either length or
+ buffer_length.
+ */
break;
default:
strmov(stmt->sqlstate, unknown_sqlstate);
@@ -2687,7 +2897,7 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
if (!param->length)
param->length= &param->buffer_length;
}
- /* We have to send/resendtype information to MySQL */
+ /* We have to send/resend type information to MySQL */
stmt->send_types_to_server= TRUE;
stmt->bind_param_done= TRUE;
DBUG_RETURN(0);
@@ -2708,12 +2918,35 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
data Data to send to server
length Length of data to send (may be 0)
+ DESCRIPTION
+ This call can be used repeatedly to send long data in pieces
+ for any string/binary placeholder. Data supplied for
+ a placeholder is saved at server side till execute, and then
+ used instead of value from MYSQL_BIND object. More precisely,
+ if long data for a parameter was supplied, MYSQL_BIND object
+ corresponding to this parameter is not sent to server. In the
+ end of execution long data states of placeholders are reset,
+ so next time values of such placeholders will be taken again
+ from MYSQL_BIND array.
+ The server does not reply to this call: if there was an error
+ in data handling (which now only can happen if server run out
+ of memory) it would be returned in reply to
+ mysql_stmt_execute().
+ You should choose type of long data carefully if you care
+ about character set conversions performed by server when the
+ statement is executed. No conversion is performed at all for
+ MYSQL_TYPE_BLOB and other binary typecodes. For
+ MYSQL_TYPE_STRING and the rest of text placeholders data is
+ converted from client character set to character set of
+ connection. If these character sets are different, this
+ conversion may require additional memory at server, equal to
+ total size of supplied pieces.
+
RETURN VALUES
0 ok
1 error
*/
-
my_bool STDCALL
mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
const char *data, ulong length)
@@ -2723,7 +2956,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
DBUG_ASSERT(stmt != 0);
DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld",
param_number, data, length));
-
+
/*
We only need to check for stmt->param_count, if it's not null
prepare was done.
@@ -2748,7 +2981,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
DBUG_RETURN(1);
}
- /*
+ /*
Send long data packet if there is data or we're sending long data
for the first time.
*/
@@ -2756,8 +2989,8 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
{
MYSQL *mysql= stmt->mysql;
/* Packet header: stmt id (4 bytes), param no (2 bytes) */
- char buff[MYSQL_LONG_DATA_HEADER];
-
+ char buff[MYSQL_LONG_DATA_HEADER];
+
int4store(buff, stmt->stmt_id);
int2store(buff + 4, param_number);
param->long_data_used= 1;
@@ -2779,72 +3012,76 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
/********************************************************************
- Fetch-bind related implementations
+ Fetch and conversion of result set rows (binary protocol).
*********************************************************************/
-/****************************************************************************
- Functions to fetch data to application buffers
-
- All functions have the following characteristics:
-
- SYNOPSIS
- fetch_result_xxx()
- param MySQL bind param
- row Row value
-
- RETURN VALUES
- 0 ok
- 1 Error (Can't alloc net->buffer)
-****************************************************************************/
-
static void set_zero_time(MYSQL_TIME *tm)
{
- tm->year= tm->month= tm->day= 0;
- tm->hour= tm->minute= tm->second= 0;
- tm->second_part= 0;
- tm->neg= (bool)0;
+ bzero((void *)tm, sizeof(*tm));
}
-/* Read TIME from binary packet and return it to MYSQL_TIME */
+
+/*
+ Read date, (time, datetime) value from network buffer and store it
+ in MYSQL_TIME structure.
+
+ SYNOPSIS
+ read_binary_{date,time,datetime}()
+ tm MYSQL_TIME structure to fill
+ pos pointer to current position in network buffer.
+ These functions increase pos to point to the beginning of this
+ field (this is just due to implementation of net_field_length
+ which is used to get length of binary representation of
+ time value).
+
+ Auxiliary functions to read time (date, datetime) values from network
+ buffer and store in MYSQL_TIME structure. Jointly used by conversion
+ and no-conversion fetching.
+*/
+
static uint read_binary_time(MYSQL_TIME *tm, uchar **pos)
{
uchar *to;
uint length;
-
+
+ /* net_field_length will set pos to the first byte of data */
if (!(length= net_field_length(pos)))
{
set_zero_time(tm);
return 0;
}
-
- to= *pos;
- tm->second_part= (length > 8 ) ? (ulong) sint4korr(to+7): 0;
+
+ to= *pos;
+ tm->neg= (bool) to[0];
tm->day= (ulong) sint4korr(to+1);
tm->hour= (uint) to[5];
tm->minute= (uint) to[6];
tm->second= (uint) to[7];
+ tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
tm->year= tm->month= 0;
- tm->neg= (bool)to[0];
return length;
}
-/* Read DATETIME from binary packet and return it to MYSQL_TIME */
static uint read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
{
uchar *to;
uint length;
-
+
if (!(length= net_field_length(pos)))
{
set_zero_time(tm);
return 0;
}
-
- to= *pos;
- tm->second_part= (length > 7 ) ? (ulong) sint4korr(to+7): 0;
-
+
+ to= *pos;
+
+ tm->neg= 0;
+ tm->year= (uint) sint2korr(to);
+ tm->month= (uint) to[2];
+ tm->day= (uint) to[3];
+
if (length > 4)
{
tm->hour= (uint) to[4];
@@ -2853,27 +3090,22 @@ static uint read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
}
else
tm->hour= tm->minute= tm->second= 0;
-
- tm->year= (uint) sint2korr(to);
- tm->month= (uint) to[2];
- tm->day= (uint) to[3];
- tm->neg= 0;
+ tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
return length;
}
-/* Read DATE from binary packet and return it to MYSQL_TIME */
static uint read_binary_date(MYSQL_TIME *tm, uchar **pos)
{
uchar *to;
uint length;
-
+
if (!(length= net_field_length(pos)))
{
set_zero_time(tm);
return 0;
}
-
- to= *pos;
+
+ to= *pos;
tm->year = (uint) sint2korr(to);
tm->month= (uint) to[2];
tm->day= (uint) to[3];
@@ -2884,67 +3116,69 @@ static uint read_binary_date(MYSQL_TIME *tm, uchar **pos)
return length;
}
-/* Convert Numeric to buffer types */
+
+/* Convert integer value to client buffer type. */
+
static void send_data_long(MYSQL_BIND *param, MYSQL_FIELD *field,
longlong value)
-{
- char *buffer= param->buffer;
+{
+ char *buffer= (char *)param->buffer;
uint field_is_unsigned= (field->flags & UNSIGNED_FLAG);
switch (param->buffer_type) {
case MYSQL_TYPE_NULL: /* do nothing */
break;
case MYSQL_TYPE_TINY:
- *param->buffer= (uchar) value;
+ *(uchar *)param->buffer= (uchar) value;
break;
case MYSQL_TYPE_SHORT:
- int2store(buffer, value);
+ shortstore(buffer, value);
break;
case MYSQL_TYPE_LONG:
- int4store(buffer, value);
+ longstore(buffer, value);
break;
case MYSQL_TYPE_LONGLONG:
- int8store(buffer, value);
+ longlongstore(buffer, value);
break;
case MYSQL_TYPE_FLOAT:
{
float data= (field_is_unsigned ? (float) ulonglong2double(value) :
(float) value);
- float4store(buffer, data);
+ floatstore(buffer, data);
break;
}
case MYSQL_TYPE_DOUBLE:
{
double data= (field_is_unsigned ? ulonglong2double(value) :
(double) value);
- float8store(buffer, data);
+ doublestore(buffer, data);
break;
}
default:
{
char tmp[22]; /* Enough for longlong */
uint length= (uint)(longlong10_to_str(value,(char *)tmp,
- field_is_unsigned ? 10: -10) -
- tmp);
+ field_is_unsigned ? 10: -10) -
+ tmp);
ulong copy_length= min((ulong)length-param->offset, param->buffer_length);
if ((long) copy_length < 0)
copy_length=0;
else
memcpy(buffer, (char *)tmp+param->offset, copy_length);
- *param->length= length;
-
+ *param->length= length;
+
if (copy_length != param->buffer_length)
*(buffer+copy_length)= '\0';
}
- }
+ }
}
/* Convert Double to buffer types */
static void send_data_double(MYSQL_BIND *param, double value)
-{
- char *buffer= param->buffer;
+{
+ char *buffer= (char *)param->buffer;
switch(param->buffer_type) {
case MYSQL_TYPE_NULL: /* do nothing */
@@ -2953,24 +3187,26 @@ static void send_data_double(MYSQL_BIND *param, double value)
*buffer= (uchar)value;
break;
case MYSQL_TYPE_SHORT:
- int2store(buffer, (short)value);
+ shortstore(buffer, (short)value);
break;
case MYSQL_TYPE_LONG:
- int4store(buffer, (long)value);
+ longstore(buffer, (long)value);
break;
case MYSQL_TYPE_LONGLONG:
- int8store(buffer, (longlong)value);
+ {
+ longlong val= (longlong) value;
+ longlongstore(buffer, val);
break;
+ }
case MYSQL_TYPE_FLOAT:
{
- float data= (float)value;
- float4store(buffer, data);
+ float data= (float) value;
+ floatstore(buffer, data);
break;
}
case MYSQL_TYPE_DOUBLE:
{
- double data= (double)value;
- float8store(buffer, data);
+ doublestore(buffer, value);
break;
}
default:
@@ -2982,20 +3218,20 @@ static void send_data_double(MYSQL_BIND *param, double value)
copy_length=0;
else
memcpy(buffer, (char *)tmp+param->offset, copy_length);
- *param->length= length;
-
+ *param->length= length;
+
if (copy_length != param->buffer_length)
*(buffer+copy_length)= '\0';
}
- }
+ }
}
/* Convert string to buffer types */
static void send_data_str(MYSQL_BIND *param, char *value, uint length)
-{
- char *buffer= param->buffer;
+{
+ char *buffer= (char *)param->buffer;
int err=0;
switch(param->buffer_type) {
@@ -3012,32 +3248,47 @@ static void send_data_str(MYSQL_BIND *param, char *value, uint length)
{
short data= (short)my_strntol(&my_charset_latin1,value,length,10,NULL,
&err);
- int2store(buffer, data);
+ shortstore(buffer, data);
break;
}
case MYSQL_TYPE_LONG:
{
int32 data= (int32)my_strntol(&my_charset_latin1,value,length,10,NULL,
&err);
- int4store(buffer, data);
+ longstore(buffer, data);
break;
}
case MYSQL_TYPE_LONGLONG:
{
longlong data= my_strntoll(&my_charset_latin1,value,length,10,NULL,&err);
- int8store(buffer, data);
+ longlongstore(buffer, data);
break;
}
case MYSQL_TYPE_FLOAT:
{
float data = (float)my_strntod(&my_charset_latin1,value,length,NULL,&err);
- float4store(buffer, data);
+ floatstore(buffer, data);
break;
}
case MYSQL_TYPE_DOUBLE:
{
double data= my_strntod(&my_charset_latin1,value,length,NULL,&err);
- float8store(buffer, data);
+ doublestore(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_TIME:
+ {
+ int dummy;
+ MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
+ str_to_time(value, length, tm, &dummy);
+ break;
+ }
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_DATETIME:
+ {
+ int dummy;
+ MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
+ str_to_datetime(value, length, tm, 0, &dummy);
break;
}
case MYSQL_TYPE_TINY_BLOB:
@@ -3062,7 +3313,7 @@ static void send_data_str(MYSQL_BIND *param, char *value, uint length)
}
-static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
+static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
uint length)
{
switch (param->buffer_type) {
@@ -3075,7 +3326,7 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
case MYSQL_TYPE_TIMESTAMP:
{
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
-
+
tm->year= ltime.year;
tm->month= ltime.month;
tm->day= ltime.day;
@@ -3086,39 +3337,39 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
tm->second_part= ltime.second_part;
tm->neg= ltime.neg;
- break;
+ break;
}
default:
{
char buff[25];
-
+
if (!length)
ltime.time_type= MYSQL_TIMESTAMP_NONE;
switch (ltime.time_type) {
case MYSQL_TIMESTAMP_DATE:
length= my_sprintf(buff,(buff, "%04d-%02d-%02d", ltime.year,
- ltime.month,ltime.day));
+ ltime.month,ltime.day));
break;
- case MYSQL_TIMESTAMP_FULL:
+ case MYSQL_TIMESTAMP_DATETIME:
length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
- ltime.year,ltime.month,ltime.day,
- ltime.hour,ltime.minute,ltime.second));
+ ltime.year,ltime.month,ltime.day,
+ ltime.hour,ltime.minute,ltime.second));
break;
case MYSQL_TIMESTAMP_TIME:
length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
- ltime.hour,ltime.minute,ltime.second));
+ ltime.hour,ltime.minute,ltime.second));
break;
default:
length= 0;
buff[0]='\0';
}
- send_data_str(param, (char *)buff, length);
+ send_data_str(param, (char *)buff, length);
}
}
}
-
-/* Fetch data to buffers */
+
+/* Fetch data to client buffers with conversion. */
static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
{
@@ -3144,7 +3395,7 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
longlong data= ((field_is_unsigned) ? (longlong) (unsigned short) value:
(longlong) value);
send_data_long(param, field, data);
- length= 2;
+ length= 2;
break;
}
case MYSQL_TYPE_LONG:
@@ -3183,7 +3434,7 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
case MYSQL_TYPE_DATE:
{
MYSQL_TIME tm;
-
+
length= read_binary_date(&tm, row);
tm.time_type= MYSQL_TIMESTAMP_DATE;
send_data_time(param, tm, length);
@@ -3192,7 +3443,7 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
case MYSQL_TYPE_TIME:
{
MYSQL_TIME tm;
-
+
length= read_binary_time(&tm, row);
tm.time_type= MYSQL_TIMESTAMP_TIME;
send_data_time(param, tm, length);
@@ -3202,14 +3453,14 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
case MYSQL_TYPE_TIMESTAMP:
{
MYSQL_TIME tm;
-
+
length= read_binary_datetime(&tm, row);
- tm.time_type= MYSQL_TIMESTAMP_FULL;
+ tm.time_type= MYSQL_TIMESTAMP_DATETIME;
send_data_time(param, tm, length);
break;
}
- default:
- length= net_field_length(row);
+ default:
+ length= net_field_length(row);
send_data_str(param,(char*) *row,length);
break;
}
@@ -3217,9 +3468,28 @@ static void fetch_results(MYSQL_BIND *param, MYSQL_FIELD *field, uchar **row)
}
+/*
+ Functions to fetch data to application buffers without conversion.
+
+ All functions have the following characteristics:
+
+ SYNOPSIS
+ fetch_result_xxx()
+ param MySQL bind param
+ pos Row value
+
+ DESCRIPTION
+ These are no-conversion functions, used in binary protocol to store
+ rows in application buffers. A function used only if type of binary data
+ is compatible with type of application buffer.
+
+ RETURN
+ none
+*/
+
static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row)
{
- *param->buffer= **row;
+ *(uchar *)param->buffer= **row;
(*row)++;
}
@@ -3238,7 +3508,7 @@ static void fetch_result_int32(MYSQL_BIND *param, uchar **row)
}
static void fetch_result_int64(MYSQL_BIND *param, uchar **row)
-{
+{
longlong value= (longlong)sint8korr(*row);
longlongstore(param->buffer, value);
*row+= 8;
@@ -3279,11 +3549,11 @@ static void fetch_result_datetime(MYSQL_BIND *param, uchar **row)
}
static void fetch_result_bin(MYSQL_BIND *param, uchar **row)
-{
+{
ulong length= net_field_length(row);
ulong copy_length= min(length, param->buffer_length);
memcpy(param->buffer, (char *)*row, copy_length);
- *param->length= length;
+ *param->length= length;
*row+= length;
}
@@ -3294,7 +3564,7 @@ static void fetch_result_str(MYSQL_BIND *param, uchar **row)
memcpy(param->buffer, (char *)*row, copy_length);
/* Add an end null if there is room in the buffer */
if (copy_length != param->buffer_length)
- *(param->buffer+copy_length)= '\0';
+ ((uchar *)param->buffer)[copy_length]= '\0';
*param->length= length; /* return total length */
*row+= length;
}
@@ -3364,7 +3634,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
We only need to check that stmt->field_count - if it is not null
stmt->bind was initialized in mysql_stmt_prepare
*/
-
+
memcpy((char*) stmt->bind, (char*) bind, sizeof(MYSQL_BIND) * bind_count);
for (param= stmt->bind, end= param + bind_count, field= stmt->fields ;
@@ -3526,16 +3796,16 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
/* If output parameters were not bound we should just return success */
return 0;
}
-
- null_ptr= row;
+
+ null_ptr= row;
row+= (stmt->field_count+9)/8; /* skip null bits */
bit= 4; /* first 2 bits are reserved */
-
+
/* Copy complete row to application buffers */
for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ;
bind < end ;
bind++, field++)
- {
+ {
if (*null_ptr & bit)
{
/*
@@ -3549,12 +3819,12 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
*bind->is_null= 1;
}
else
- {
+ {
*bind->is_null= 0;
bind->inter_buffer= row;
if (field->type == bind->buffer_type)
(*bind->fetch_result)(bind, &row);
- else
+ else
fetch_results(bind, field, &row);
}
if (!((bit<<=1) & 255))
@@ -3614,15 +3884,15 @@ int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
column Column to fetch (first column is 0)
ulong offset Offset in result data (to fetch blob in pieces)
This is normally 0
- RETURN
+ RETURN
0 ok
1 error
*/
-int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
+int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
uint column, ulong offset)
{
- MYSQL_BIND *param= stmt->bind+column;
+ MYSQL_BIND *param= stmt->bind+column;
DBUG_ENTER("mysql_stmt_fetch_column");
if ((int) stmt->state < (int) MYSQL_STMT_FETCH_DONE)
@@ -3638,7 +3908,7 @@ int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
if (param->inter_buffer)
{
- MYSQL_FIELD *field= stmt->fields+column;
+ MYSQL_FIELD *field= stmt->fields+column;
uchar *row= param->inter_buffer;
bind->offset= offset;
if (bind->is_null)
@@ -3709,6 +3979,49 @@ err:
/*
+ Update meta data for statement
+
+ SYNOPSIS
+ stmt_update_metadata()
+ stmt Statement handler
+ row Binary data
+
+ NOTES
+ Only updates MYSQL_FIELD->max_length for strings
+*/
+
+static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data)
+{
+ MYSQL_BIND *bind, *end;
+ MYSQL_FIELD *field;
+ uchar *null_ptr, bit;
+ uchar *row= (uchar*) data->data;
+#ifndef DBUG_OFF
+ uchar *row_end= row + data->length;
+#endif
+
+ null_ptr= row;
+ row+= (stmt->field_count+9)/8; /* skip null bits */
+ bit= 4; /* first 2 bits are reserved */
+
+ /* Go throw all fields and calculate metadata */
+ for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ;
+ bind < end ;
+ bind++, field++)
+ {
+ if (!(*null_ptr & bit))
+ (*bind->skip_result)(bind, field, &row);
+ DBUG_ASSERT(row <= row_end);
+ if (!((bit<<=1) & 255))
+ {
+ bit= 1; /* To next byte */
+ null_ptr++;
+ }
+ }
+}
+
+
+/*
Store or buffer the binary results to stmt
*/
@@ -3763,6 +4076,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
result->data= NULL;
result->rows= 0;
+ mysql->status= MYSQL_STATUS_READY;
DBUG_RETURN(1);
}
@@ -3791,7 +4105,7 @@ mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
{
MYSQL_ROW_OFFSET offset= stmt->data_cursor;
DBUG_ENTER("mysql_stmt_row_seek");
-
+
stmt->data_cursor= row;
DBUG_RETURN(offset);
}
@@ -3801,11 +4115,11 @@ mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
Return the current statement row cursor position
*/
-MYSQL_ROW_OFFSET STDCALL
+MYSQL_ROW_OFFSET STDCALL
mysql_stmt_row_tell(MYSQL_STMT *stmt)
{
DBUG_ENTER("mysql_stmt_row_tell");
-
+
DBUG_RETURN(stmt->data_cursor);
}
@@ -3820,7 +4134,7 @@ mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
MYSQL_ROWS *tmp= stmt->result.data;
DBUG_ENTER("mysql_stmt_data_seek");
DBUG_PRINT("enter",("row id to seek: %ld",(long) row));
-
+
for (; tmp && row; --row, tmp= tmp->next)
;
stmt->data_cursor= tmp;
@@ -3835,7 +4149,7 @@ mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
{
DBUG_ENTER("mysql_stmt_num_rows");
-
+
DBUG_RETURN(stmt->result.rows);
}
@@ -3845,7 +4159,7 @@ my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
DBUG_ENTER("mysql_stmt_free_result");
DBUG_ASSERT(stmt != 0);
-
+
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
{
MYSQL *mysql= stmt->mysql;
@@ -3913,7 +4227,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
mysql->unbuffered_fetch_owner= 0;
if (mysql->status != MYSQL_STATUS_READY)
{
- /*
+ /*
Flush result set of the connection. If it does not belong
to this statement, set a warning.
*/
@@ -3951,13 +4265,13 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
/* If statement hasnt been prepared there is nothing to reset */
if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
DBUG_RETURN(0);
-
+
mysql= stmt->mysql->last_used_con;
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff,
sizeof(buff), 0, 0, 0))
{
- set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
+ set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
DBUG_RETURN(1);
}
@@ -3998,50 +4312,6 @@ const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt)
}
-/*
- Update meta data for statement
-
- SYNOPSIS
- stmt_update_metadata()
- stmt Statement handler
- row Binary data
-
- NOTES
- Only updates MYSQL_FIELD->max_length for strings
-
-*/
-
-static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data)
-{
- MYSQL_BIND *bind, *end;
- MYSQL_FIELD *field;
- uchar *null_ptr, bit;
- uchar *row= (uchar*) data->data;
-#ifndef DBUG_OFF
- uchar *row_end= row + data->length;
-#endif
-
- null_ptr= row;
- row+= (stmt->field_count+9)/8; /* skip null bits */
- bit= 4; /* first 2 bits are reserved */
-
- /* Go throw all fields and calculate metadata */
- for (bind= stmt->bind, end= bind + stmt->field_count, field= stmt->fields ;
- bind < end ;
- bind++, field++)
- {
- if (!(*null_ptr & bit))
- (*bind->skip_result)(bind, field, &row);
- DBUG_ASSERT(row <= row_end);
- if (!((bit<<=1) & 255))
- {
- bit= 1; /* To next byte */
- null_ptr++;
- }
- }
-}
-
-
/********************************************************************
Transactional APIs
*********************************************************************/
@@ -4095,10 +4365,10 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql)
{
my_bool res;
DBUG_ENTER("mysql_more_results");
-
- res= ((mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ?
+
+ res= ((mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ?
1: 0);
- DBUG_PRINT("exit",("More results exists ? %d", res));
+ DBUG_PRINT("exit",("More results exists ? %d", res));
DBUG_RETURN(res);
}
@@ -4109,7 +4379,7 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql)
int STDCALL mysql_next_result(MYSQL *mysql)
{
DBUG_ENTER("mysql_next_result");
-
+
if (mysql->status != MYSQL_STATUS_READY)
{
strmov(mysql->net.sqlstate, unknown_sqlstate);
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 1790b0fa888..bbd5af6558d 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -2,7 +2,8 @@ LIBRARY LIBMYSQL
DESCRIPTION 'MySQL 4.1 Client Library'
VERSION 6.0
EXPORTS
- _dig_vec
+ _dig_vec_lower
+ _dig_vec_upper
bmove_upp
delete_dynamic
free_defaults
@@ -16,7 +17,6 @@ EXPORTS
list_add
list_delete
load_defaults
- max_allowed_packet
my_end
my_getopt_print_errors
my_init
@@ -24,6 +24,7 @@ EXPORTS
my_memdup
my_no_flags_free
my_path
+ mysql_get_parameters
my_print_help
my_print_variables
my_realloc
@@ -81,7 +82,6 @@ EXPORTS
mysql_stmt_param_count
mysql_stmt_param_metadata
mysql_ping
- mysql_prepare
mysql_stmt_result_metadata
mysql_query
mysql_read_query_result
@@ -114,7 +114,9 @@ EXPORTS
mysql_thread_safe
mysql_use_result
mysql_warning_count
- net_buffer_length
+ mysql_stmt_sqlstate
+ mysql_sqlstate
+ mysql_get_server_version
set_dynamic
strcend
strcont
@@ -129,3 +131,4 @@ EXPORTS
mysql_stmt_insert_id
mysql_stmt_attr_get
mysql_stmt_attr_set
+ mysql_stmt_field_count
diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am
index 60c29a99762..b75f65b6f78 100644
--- a/libmysql_r/Makefile.am
+++ b/libmysql_r/Makefile.am
@@ -18,7 +18,7 @@
target = libmysqlclient_r.la
-target_defs = -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@
+target_defs = -DDONT_USE_RAID -DMYSQL_CLIENT @LIB_EXTRA_CCFLAGS@
LIBS = @LIBS@ @openssl_libs@
INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include $(openssl_includes)
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index 29e88eb41f2..390dab409b3 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -22,7 +22,6 @@ MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
- -DNO_EMBEDDED_ACCESS_CHECKS \
-DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\""
@@ -34,7 +33,8 @@ noinst_LIBRARIES = libmysqld_int.a
pkglib_LIBRARIES = libmysqld.a
SUBDIRS = . examples
libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc
-libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c
+libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
+ my_time.c
noinst_HEADERS = embedded_priv.h emb_qcache.h
@@ -57,7 +57,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \
sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \
unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \
- spatial.cc gstream.cc sql_help.cc protocol_cursor.cc \
+ spatial.cc gstream.cc sql_help.cc tztime.cc protocol_cursor.cc \
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 2bbca220db9..0adf9aeb86a 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -23,6 +23,11 @@
#define mysql_unix_port mysql_inix_port1
#define mysql_port mysql_port1
+extern "C"
+{
+ extern unsigned long max_allowed_packet, net_buffer_length;
+}
+
static int fake_argc= 1;
static char *fake_argv[]= {(char *)"", 0};
static const char *fake_groups[] = { "server", "embedded", 0 };
@@ -351,6 +356,7 @@ int init_embedded_server(int argc, char **argv, char **groups)
int fake_argc = 1;
char *fake_argv[] = { (char *)"", 0 };
const char *fake_groups[] = { "server", "embedded", 0 };
+ my_bool acl_error;
if (argc)
{
argcp= &argc;
@@ -392,16 +398,17 @@ int init_embedded_server(int argc, char **argv, char **groups)
error_handler_hook = my_message_sql;
+ acl_error= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (acl_init((THD *)0, opt_noacl))
+ if (!(acl_error= acl_init((THD *)0, opt_noacl)) &&
+ !opt_noacl)
+ (void) grant_init((THD *)0);
+#endif
+ if (acl_error || my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
{
mysql_server_end();
return 1;
}
- if (!opt_noacl)
- (void) grant_init((THD *)0);
-
-#endif
init_max_user_conn();
init_update_queries();
@@ -506,6 +513,7 @@ int check_embedded_connection(MYSQL *mysql)
thd->host= (char*)my_localhost;
thd->host_or_ip= thd->host;
thd->user= my_strdup(mysql->user, MYF(0));
+ thd->priv_user= thd->user;
return check_user(thd, COM_CONNECT, NULL, 0, thd->db, true);
}
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index db9e828369d..3b9c2bab448 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -47,6 +47,9 @@
#define INADDR_NONE -1
#endif
+extern ulong net_buffer_length;
+extern ulong max_allowed_packet;
+
#if defined(MSDOS) || defined(__WIN__)
#define ERRNO WSAGetLastError()
#define perror(A)
@@ -81,7 +84,8 @@ static void end_server(MYSQL *mysql)
DBUG_VOID_RETURN;
}
-static inline int mysql_init_charset(MYSQL *mysql)
+
+static int mysql_init_charset(MYSQL *mysql)
{
char charset_name_buff[16], *charset_name;
@@ -124,6 +128,7 @@ static inline int mysql_init_charset(MYSQL *mysql)
return 0;
}
+
MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def
index 8b2ad8379d6..ac982f9110e 100644
--- a/libmysqld/libmysqld.def
+++ b/libmysqld/libmysqld.def
@@ -2,7 +2,8 @@ LIBRARY LIBMYSQLD
DESCRIPTION 'MySQL 4.1 Embedded Server Library'
VERSION 4.1
EXPORTS
- _dig_vec
+ _dig_vec_upper
+ _dig_vec_lower
bmove_upp
delete_dynamic
free_defaults
@@ -92,7 +93,6 @@ EXPORTS
mysql_thread_safe
mysql_use_result
mysql_warning_count
- net_buffer_length
set_dynamic
strcend
strcont
@@ -128,5 +128,5 @@ EXPORTS
alloc_root
free_root
my_read
- max_allowed_packet
llstr
+ mysql_get_parameters
diff --git a/man/mysqlaccess.1.in b/man/mysqlaccess.1.in
index 9a5e58541d2..cf2e0658a1c 100644
--- a/man/mysqlaccess.1.in
+++ b/man/mysqlaccess.1.in
@@ -1,7 +1,6 @@
.TH mysqlaccess 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database"
.SH NAME
-.BR mysqlaccess
- \- Create new users to mysql.
+.BR mysqlaccess \- Create new users to mysql.
.SH USAGE
mysqlaccess [host [user [db]]] OPTIONS
.SH SYNOPSIS
diff --git a/man/mysqldump.1.in b/man/mysqldump.1.in
index 34d83dbe0b3..6d1cc80c837 100644
--- a/man/mysqldump.1.in
+++ b/man/mysqldump.1.in
@@ -1,6 +1,6 @@
.TH mysqldump 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database"
.SH NAME
-mysqldump \- text-based client for dumping or backing up mysql databases , tables and or data.
+mysqldump \- text\-based client for dumping or backing up mysql databases, tables and or data.
.SH USAGE
.BR "mysqldump [\fP\fIOPTIONS\fP] database [\fP\fItables\fP]"
diff --git a/merge/mrg_open.c b/merge/mrg_open.c
index 83b776ea201..6bf75392131 100644
--- a/merge/mrg_open.c
+++ b/merge/mrg_open.c
@@ -62,7 +62,7 @@ int handle_locking)
{
if ((end=buff+length)[-1] == '\n')
end[-1]='\0';
- if (buff[0] && buff[0] != '#') /* Skipp empty lines and comments */
+ if (buff[0] && buff[0] != '#') /* Skip empty lines and comments */
{
last_isam=isam;
if (!test_if_hard_path(buff))
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 5f88122e730..196cb5c21fb 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -53,10 +53,11 @@ static double _nwghts[11]=
-3.796875000000000};
static double *nwghts=_nwghts+5; /* nwghts[i] = -0.5*1.5**i */
-#define FTB_FLAG_TRUNC 1 /* MUST be 1 */
-#define FTB_FLAG_YES 2 /* no two from these three */
-#define FTB_FLAG_NO 4 /* YES, NO, WONLY */
-#define FTB_FLAG_WONLY 8 /* should be ever set both */
+#define FTB_FLAG_TRUNC 1
+/* At most one of the following flags can be set */
+#define FTB_FLAG_YES 2
+#define FTB_FLAG_NO 4
+#define FTB_FLAG_WONLY 8
typedef struct st_ftb_expr FTB_EXPR;
struct st_ftb_expr
@@ -157,6 +158,7 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
w.len+extra));
ftbw->len=w.len+1;
ftbw->flags=0;
+ ftbw->off=0;
if (param.yesno>0) ftbw->flags|=FTB_FLAG_YES;
if (param.yesno<0) ftbw->flags|=FTB_FLAG_NO;
if (param.trunc) ftbw->flags|=FTB_FLAG_TRUNC;
@@ -203,23 +205,26 @@ static int _ftb_no_dupes_cmp(void* not_used __attribute__((unused)),
static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
{
int r;
- uint off;
int subkeys=1;
my_bool can_go_down;
MI_INFO *info=ftb->info;
+ uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength;
+ byte *lastkey_buf=ftbw->word+ftbw->off;
+
+ if (ftbw->flags & FTB_FLAG_TRUNC)
+ lastkey_buf+=ftbw->len;
if (init_search)
{
ftbw->key_root=info->s->state.key_root[ftb->keynr];
ftbw->keyinfo=info->s->keyinfo+ftb->keynr;
- ftbw->off=0;
r=_mi_search(info, ftbw->keyinfo, (uchar*) ftbw->word, ftbw->len,
SEARCH_FIND | SEARCH_BIGGER, ftbw->key_root);
}
else
{
- r=_mi_search(info, ftbw->keyinfo, (uchar*) ftbw->word+ftbw->off,
+ r=_mi_search(info, ftbw->keyinfo, (uchar*) lastkey_buf,
USE_WHOLE_KEY, SEARCH_BIGGER, ftbw->key_root);
}
@@ -230,7 +235,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
if (can_go_down)
{
/* going down ? */
- off=info->lastkey_length-HA_FT_WLEN-info->s->base.rec_reflength;
+ off=info->lastkey_length-extra;
subkeys=ft_sintXkorr(info->lastkey+off);
}
if (subkeys<0 || info->lastpos < info->state->data_file_length)
@@ -243,11 +248,11 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
if (!r && !ftbw->off)
{
r= mi_compare_text(ftb->charset,
- info->lastkey + (ftbw->flags & FTB_FLAG_TRUNC),
- ftbw->len - (ftbw->flags & FTB_FLAG_TRUNC),
- (uchar*) ftbw->word + (ftbw->flags & FTB_FLAG_TRUNC),
- ftbw->len - (ftbw->flags & FTB_FLAG_TRUNC),
- 0,0);
+ info->lastkey+1,
+ info->lastkey_length-extra-1,
+ (uchar*) ftbw->word+1,
+ ftbw->len-1,
+ (my_bool) (ftbw->flags & FTB_FLAG_TRUNC),0);
}
if (r) /* not found */
@@ -269,8 +274,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
}
/* going up to the first-level tree to continue search there */
- _mi_dpointer(info, (uchar*) (ftbw->word+ftbw->off+HA_FT_WLEN),
- ftbw->key_root);
+ _mi_dpointer(info, (uchar*) (lastkey_buf+HA_FT_WLEN), ftbw->key_root);
ftbw->key_root=info->s->state.key_root[ftb->keynr];
ftbw->keyinfo=info->s->keyinfo+ftb->keynr;
ftbw->off=0;
@@ -278,7 +282,10 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
}
/* matching key found */
- memcpy(ftbw->word+ftbw->off, info->lastkey, info->lastkey_length);
+ memcpy(lastkey_buf, info->lastkey, info->lastkey_length);
+ if (lastkey_buf == ftbw->word)
+ ftbw->len=info->lastkey_length-extra;
+
/* going down ? */
if (subkeys<0)
{
@@ -291,7 +298,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
ftbw->keyinfo=& info->s->ft2_keyinfo;
r=_mi_search_first(info, ftbw->keyinfo, ftbw->key_root);
DBUG_ASSERT(r==0); /* found something */
- memcpy(ftbw->word+off, info->lastkey, info->lastkey_length);
+ memcpy(lastkey_buf+off, info->lastkey, info->lastkey_length);
}
ftbw->docid[0]=info->lastpos;
return 0;
@@ -356,7 +363,7 @@ static void _ftb_init_index_search(FT_INFO *ftb)
else
reset_tree(& ftb->no_dupes);
}
-
+
if (_ft2_search(ftb, ftbw, 1))
return;
}
@@ -421,7 +428,7 @@ err:
}
-/* returns 1 if str0 ~= /\<str1\>/ */
+/* returns 1 if str0 ~= /\bstr1\b/ */
static int _ftb_strstr(const byte *s0, const byte *e0,
const byte *s1, const byte *e1,
CHARSET_INFO *cs)
diff --git a/myisam/ftdefs.h b/myisam/ftdefs.h
index a97485ec021..e23bc3b75ac 100644
--- a/myisam/ftdefs.h
+++ b/myisam/ftdefs.h
@@ -22,7 +22,6 @@
#include <m_ctype.h>
#include <my_tree.h>
#include <queues.h>
-#include <assert.h>
#define true_word_char(s,X) (my_isalnum(s,X) || (X)=='_')
#define misc_word_char(X) ((X)=='\'')
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index ab58a36915e..2015bcc7ec0 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -142,6 +142,8 @@ int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
empty=0;
for (i= info->state->del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--)
{
+ if (*killed_ptr(param))
+ DBUG_RETURN(1);
if (test_flag & T_VERBOSE)
printf(" %9s",llstr(next_link,buff));
if (next_link >= info->state->data_file_length)
@@ -233,6 +235,8 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
records= (ha_rows) (info->state->key_file_length / block_size);
while (next_link != HA_OFFSET_ERROR && records > 0)
{
+ if (*killed_ptr(param))
+ DBUG_RETURN(1);
if (param->testflag & T_VERBOSE)
printf("%16s",llstr(next_link,llbuff));
if (next_link > info->state->key_file_length ||
@@ -307,7 +311,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
#endif
if (skr != size)
{
- info->state->data_file_length=size; /* Skipp other errors */
+ info->state->data_file_length=size; /* Skip other errors */
if (skr > size && skr != size + MEMMAP_EXTRA_MARGIN)
{
error=1;
@@ -592,6 +596,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
}
for ( ;; )
{
+ if (*killed_ptr(param))
+ goto err;
memcpy((char*) info->lastkey,(char*) key,key_length);
info->lastkey_length=key_length;
if (nod_flag)
@@ -782,6 +788,8 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0]));
while (pos < info->state->data_file_length)
{
+ if (*killed_ptr(param))
+ goto err2;
switch (info->s->data_file_type) {
case STATIC_RECORD:
if (my_b_read(&param->read_cache,(byte*) record,
@@ -3672,7 +3680,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
if (param->language)
keyseg->language=param->language; /* change language */
}
- keyseg++; /* Skipp end pointer */
+ keyseg++; /* Skip end pointer */
}
/* Copy the unique definitions and change them to point at the new key
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 838d647ea56..683640630f6 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -242,6 +242,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_length=pointer;
if (keydef->flag & HA_SPATIAL)
{
+#ifdef HAVE_SPATIAL
/* BAR TODO to support 3D and more dimensions in the future */
uint sp_segs=SPDIMS*2;
keydef->flag=HA_SPATIAL;
@@ -270,6 +271,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_length+=SPLEN*sp_segs;
length++; /* At least one length byte */
min_key_length_skip+=SPLEN*2*SPDIMS;
+#else
+ my_errno= HA_ERR_UNSUPPORTED;
+ goto err;
+#endif /*HAVE_SPATIAL*/
}
else
if (keydef->flag & HA_FULLTEXT)
@@ -588,6 +593,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
if (mi_keyseg_write(file, &keydefs[i].seg[j]))
goto err;
+#ifdef HAVE_SPATIAL
for (j=0 ; j < sp_segs ; j++)
{
HA_KEYSEG sseg;
@@ -603,6 +609,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
if (mi_keyseg_write(file, &sseg))
goto err;
}
+#endif
}
/* Create extra keys for unique definitions */
offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c
index 19cfc050ea1..3e8ff9db009 100644
--- a/myisam/mi_delete.c
+++ b/myisam/mi_delete.c
@@ -18,7 +18,6 @@
#include "fulltext.h"
#include "rt_index.h"
-#include <assert.h>
static int d_search(MI_INFO *info,MI_KEYDEF *keyinfo,uint comp_flag,
uchar *key,uint key_length,my_off_t page,uchar *anc_buff);
@@ -266,6 +265,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
keyinfo=&info->s->ft2_keyinfo;
kpos-=keyinfo->keylength+nod_flag; /* we'll modify key entry 'in vivo' */
+ get_key_full_length_rdonly(off, key);
key+=off;
ret_value=_mi_ck_real_delete(info, &info->s->ft2_keyinfo,
key, HA_FT_WLEN, &root);
@@ -816,7 +816,7 @@ static uint remove_key(MI_KEYDEF *keyinfo, uint nod_flag,
if (!(*start & 128))
prev_length=0; /* prev key not packed */
if (keyinfo->seg[0].flag & HA_NULL_PART)
- lastkey++; /* Skipp null marker */
+ lastkey++; /* Skip null marker */
get_key_length(lastkey_length,lastkey);
if (!next_length) /* Same key after */
{
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index f64e774810d..0b8d3c97872 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -25,7 +25,6 @@
*/
#include "myisamdef.h"
-#include <assert.h>
/* Enough for comparing if number is zero */
static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 97af156e89a..d19a3130a86 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -19,7 +19,6 @@
#include "myisamdef.h"
#include "m_ctype.h"
#include "sp_defs.h"
-#include <assert.h>
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
@@ -46,7 +45,11 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
/*
TODO: nulls processing
*/
+#ifdef HAVE_SPATIAL
return sp_make_key(info,keynr,key,record,filepos);
+#else
+ DBUG_ASSERT(0); /* mi_open should check that this never happens*/
+#endif
}
start=key;
@@ -217,7 +220,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
k_length-= 2+length;
set_if_smaller(length,tmp_length); /* Safety */
store_key_length_inc(key,length);
- old+=2; /* Skipp length */
+ old+=2; /* Skip length */
memcpy((byte*) key, pos+2,(size_t) length);
key+= length;
continue;
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 53cf87b24b4..562227d2f03 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -327,9 +327,14 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
}
if (share->keyinfo[i].flag & HA_SPATIAL)
{
+#ifdef HAVE_SPATIAL
uint sp_segs=SPDIMS*2;
share->keyinfo[i].seg=pos-sp_segs;
share->keyinfo[i].keysegs--;
+#else
+ my_errno=HA_ERR_UNSUPPORTED;
+ goto err;
+#endif
}
else if (share->keyinfo[i].flag & HA_FULLTEXT)
{
@@ -726,8 +731,12 @@ static void setup_key_functions(register MI_KEYDEF *keyinfo)
{
if (keyinfo->key_alg == HA_KEY_ALG_RTREE)
{
+#ifdef HAVE_RTREE_KEYS
keyinfo->ck_insert = rtree_insert;
keyinfo->ck_delete = rtree_delete;
+#else
+ DBUG_ASSERT(0); /* mi_open should check it never happens */
+#endif
}
else
{
diff --git a/myisam/mi_range.c b/myisam/mi_range.c
index db01ada16dd..1e0fd42334e 100644
--- a/myisam/mi_range.c
+++ b/myisam/mi_range.c
@@ -65,6 +65,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
rw_rdlock(&info->s->key_root_lock[inx]);
switch(info->s->keyinfo[inx].key_alg){
+#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
{
uchar * key_buff;
@@ -79,6 +80,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
res= res ? res : 1; /* Don't return 0 */
break;
}
+#endif
case HA_KEY_ALG_BTREE:
default:
start_pos= (min_key ?
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c
index ddfac0a39a2..12db00337ee 100644
--- a/myisam/mi_rkey.c
+++ b/myisam/mi_rkey.c
@@ -74,6 +74,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
use_key_length=USE_WHOLE_KEY;
switch (info->s->keyinfo[inx].key_alg) {
+#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
if (rtree_find_first(info,inx,key_buff,use_key_length,nextflag) < 0)
{
@@ -81,6 +82,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
goto err;
}
break;
+#endif
case HA_KEY_ALG_BTREE:
default:
if (!_mi_search(info, keyinfo, key_buff, use_key_length,
diff --git a/myisam/mi_rnext.c b/myisam/mi_rnext.c
index 6e6056f98d9..69bf5c8deae 100644
--- a/myisam/mi_rnext.c
+++ b/myisam/mi_rnext.c
@@ -45,9 +45,11 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx)
if (!flag)
{
switch(info->s->keyinfo[inx].key_alg){
+#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
error=rtree_get_first(info,inx,info->lastkey_length);
break;
+#endif
case HA_KEY_ALG_BTREE:
default:
error=_mi_search_first(info,info->s->keyinfo+inx,
@@ -58,6 +60,7 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx)
else
{
switch (info->s->keyinfo[inx].key_alg) {
+#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
/*
Note that rtree doesn't support that the table
@@ -66,7 +69,7 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx)
*/
error= rtree_get_next(info,inx,info->lastkey_length);
break;
-
+#endif
case HA_KEY_ALG_BTREE:
default:
if (!changed)
diff --git a/myisam/mi_rnext_same.c b/myisam/mi_rnext_same.c
index 19190a60246..1342718d6aa 100644
--- a/myisam/mi_rnext_same.c
+++ b/myisam/mi_rnext_same.c
@@ -43,6 +43,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
switch (keyinfo->key_alg)
{
+#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
if ((error=rtree_find_next(info,inx,
myisam_read_vec[info->last_key_func])))
@@ -53,6 +54,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
break;
}
break;
+#endif
case HA_KEY_ALG_BTREE:
default:
memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index 1c4342ff39a..1b03acddbc1 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -18,7 +18,6 @@
#include "fulltext.h"
#include "m_ctype.h"
-#include <assert.h>
static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
uchar *key, uchar *keypos,
@@ -761,7 +760,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
}
if (keyseg->flag & HA_NULL_PART)
{
- key++; /* Skipp null marker*/
+ key++; /* Skip null marker*/
start++;
}
@@ -1395,7 +1394,7 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
if (prev_key && !*prev_key++)
org_key=prev_key=0; /* Can't pack against prev */
else if (org_key)
- org_key++; /* Skipp NULL */
+ org_key++; /* Skip NULL */
}
else
s_temp->store_not_null=0;
diff --git a/myisam/mi_static.c b/myisam/mi_static.c
index f7d008ffbb7..f41aeff8453 100644
--- a/myisam/mi_static.c
+++ b/myisam/mi_static.c
@@ -38,7 +38,7 @@ my_bool myisam_concurrent_insert=1;
#else
my_bool myisam_concurrent_insert=0;
#endif
-my_off_t myisam_max_extra_temp_length= MI_MAX_TEMP_LENGTH;
+my_off_t myisam_max_extra_temp_length= (my_off_t)MI_MAX_TEMP_LENGTH;
my_off_t myisam_max_temp_length= MAX_FILE_SIZE;
ulong myisam_bulk_insert_tree_size=8192*1024;
ulong myisam_data_pointer_size=4;
diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c
index 38b4ed93311..ad685f4cbdc 100644
--- a/myisam/mi_unique.c
+++ b/myisam/mi_unique.c
@@ -69,7 +69,8 @@ my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, byte *record,
ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
{
const byte *pos, *end;
- ha_checksum crc=0;
+ ha_checksum crc= 0;
+ ulong seed1=0, seed2= 4;
HA_KEYSEG *keyseg;
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
@@ -108,9 +109,10 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
end= pos+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{
- ulong nr=1, nr2=4;
- keyseg->charset->coll->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2);
- crc=nr;
+ keyseg->charset->coll->hash_sort(keyseg->charset,
+ (const uchar*) pos, length, &seed1,
+ &seed2);
+ crc^= seed1;
}
else
while (pos != end)
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index c17f47fc1ae..dc596672a84 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -18,7 +18,6 @@
#include "fulltext.h"
#include "rt_index.h"
-#include <assert.h>
#define MAX_POINTER_LENGTH 8
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 545aadebae8..6dcfe2cfa21 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -362,13 +362,13 @@ static void usage(void)
this option is deprecated; you can set variables\n\
directly with '--variable-name=value'.\n\
-t, --tmpdir=path Path for temporary files. Multiple paths can be\n\
- specified, separated by "
-#if defined( __WIN__) || defined(OS2)
- "semicolon (;)"
+ specified, separated by ");
+#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
+ puts("semicolon (;)");
#else
- "colon (:)"
+ puts("colon (:)");
#endif
- ", they will be used\n\
+ puts(", they will be used\n\
in a round-robin fashion.\n\
-s, --silent Only print errors. One can use two -s to make\n\
myisamchk very silent.\n\
@@ -1389,7 +1389,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, my_string name)
}
if (buff[0] == ',')
strmov(buff,buff+2);
- int2str((long) share->rec[field].length,length,10);
+ int10_to_str((long) share->rec[field].length,length,10);
null_bit[0]=null_pos[0]=0;
if (share->rec[field].null_bit)
{
@@ -1685,7 +1685,17 @@ err:
DBUG_RETURN(1);
} /* sort_record_index */
-int *killed_ptr(void *thd)
+
+
+/*
+ Check if myisamchk was killed by a signal
+ This is overloaded by other programs that want to be able to abort
+ sorting
+*/
+
+static my_bool not_killed= 0;
+
+volatile int *killed_ptr(MI_CHECK *param)
{
return (int *)thd; /* always NULL */
}
diff --git a/myisam/myisamlog.c b/myisam/myisamlog.c
index 82f6277ce25..6679510227e 100644
--- a/myisam/myisamlog.c
+++ b/myisam/myisamlog.c
@@ -145,7 +145,7 @@ static void get_options(register int *argc, register char ***argv)
switch((option=*pos)) {
case '#':
DBUG_PUSH (++pos);
- pos=" "; /* Skipp rest of arg */
+ pos=" "; /* Skip rest of arg */
break;
case 'c':
if (! *++pos)
diff --git a/myisam/rt_index.c b/myisam/rt_index.c
index 30146b9fd67..4fffd848624 100644
--- a/myisam/rt_index.c
+++ b/myisam/rt_index.c
@@ -17,11 +17,15 @@
#include "myisamdef.h"
+#ifdef HAVE_RTREE_KEYS
+
#include "rt_index.h"
#include "rt_key.h"
#include "rt_mbr.h"
#define REINSERT_BUFFER_INC 10
+#define PICK_BY_AREA
+/*#define PICK_BY_PERIMETER*/
typedef struct st_page_level
{
@@ -437,6 +441,84 @@ int rtree_get_next(MI_INFO *info, uint keynr, uint key_length)
/*
+ Choose non-leaf better key for insertion
+*/
+
+#ifdef PICK_BY_PERIMETER
+static uchar *rtree_pick_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, uchar *page_buf, uint nod_flag)
+{
+ double increase;
+ double best_incr = DBL_MAX;
+ double perimeter;
+ double best_perimeter;
+ uchar *best_key;
+ uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+ uchar *last = rt_PAGE_END(page_buf);
+
+ LINT_INIT(best_perimeter);
+ LINT_INIT(best_key);
+
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
+ {
+ if ((increase = rtree_perimeter_increase(keyinfo->seg, k, key, key_length,
+ &perimeter)) == -1)
+ return NULL;
+ if ((increase < best_incr)||
+ (increase == best_incr && perimeter < best_perimeter))
+ {
+ best_key = k;
+ best_perimeter= perimeter;
+ best_incr = increase;
+ }
+ }
+ return best_key;
+}
+
+#endif /*PICK_BY_PERIMETER*/
+
+#ifdef PICK_BY_AREA
+static uchar *rtree_pick_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
+ uint key_length, uchar *page_buf, uint nod_flag)
+{
+ double increase;
+ double best_incr = DBL_MAX;
+ double area;
+ double best_area;
+ uchar *best_key;
+ uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+ uchar *last = rt_PAGE_END(page_buf);
+
+ LINT_INIT(best_area);
+ LINT_INIT(best_key);
+
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
+ {
+ if ((increase = rtree_area_increase(keyinfo->seg, k, key, key_length,
+ &area)) == -1)
+ return NULL;
+ if (increase < best_incr)
+ {
+ best_key = k;
+ best_area = area;
+ best_incr = increase;
+ }
+ else
+ {
+ if ((increase == best_incr) && (area < best_area))
+ {
+ best_key = k;
+ best_area = area;
+ best_incr = increase;
+ }
+ }
+ }
+ return best_key;
+}
+
+#endif /*PICK_BY_AREA*/
+
+/*
Go down and insert key into tree
RETURN
@@ -467,7 +549,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
if ((ins_level == -1 && nod_flag) || /* key: go down to leaf */
(ins_level > -1 && ins_level > level)) /* branch: go down to ins_level */
{
- if ((k = rtree_choose_key(info, keyinfo, key, key_length, page_buf,
+ if ((k = rtree_pick_key(info, keyinfo, key, key_length, page_buf,
nod_flag)) == NULL)
goto err1;
switch ((res = rtree_insert_req(info, keyinfo, key, key_length,
@@ -577,7 +659,7 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key,
mi_putint(new_root_buf, 2, nod_flag);
if ((new_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) ==
- HA_OFFSET_ERROR)
+ HA_OFFSET_ERROR)
goto err1;
new_key = new_root_buf + keyinfo->block_length + nod_flag;
@@ -991,3 +1073,6 @@ err1:
my_afree((byte*)page_buf);
return HA_POS_ERROR;
}
+
+#endif /*HAVE_RTREE_KEYS*/
+
diff --git a/myisam/rt_index.h b/myisam/rt_index.h
index 1a0fce72a82..d3fcd934719 100644
--- a/myisam/rt_index.h
+++ b/myisam/rt_index.h
@@ -18,12 +18,14 @@
#ifndef _rt_index_h
#define _rt_index_h
+#ifdef HAVE_RTREE_KEYS
+
#define rt_PAGE_FIRST_KEY(page, nod_flag) (page + 2 + nod_flag)
#define rt_PAGE_NEXT_KEY(key, key_length, nod_flag) (key + key_length + \
(nod_flag ? nod_flag : info->s->base.rec_reflength))
#define rt_PAGE_END(page) (page + mi_getint(page))
-#define rt_PAGE_MIN_SIZE(block_length) ((uint)(block_length) / 2)
+#define rt_PAGE_MIN_SIZE(block_length) ((uint)(block_length) / 3)
int rtree_insert(MI_INFO *info, uint keynr, uchar *key, uint key_length);
int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length);
@@ -41,4 +43,5 @@ ha_rows rtree_estimate(MI_INFO *info, uint keynr, uchar *key,
int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
uint key_length, my_off_t *new_page_offs);
+#endif /*HAVE_RTREE_KEYS*/
#endif /* _rt_index_h */
diff --git a/myisam/rt_key.c b/myisam/rt_key.c
index f18d13af8d8..e2a402fbefd 100644
--- a/myisam/rt_key.c
+++ b/myisam/rt_key.c
@@ -16,6 +16,7 @@
#include "myisamdef.h"
+#ifdef HAVE_RTREE_KEYS
#include "rt_index.h"
#include "rt_key.h"
#include "rt_mbr.h"
@@ -35,7 +36,8 @@ int rtree_add_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
uint page_size = mi_getint(page_buf);
uint nod_flag = mi_test_if_nod(page_buf);
- if (page_size + key_length + nod_flag <= keyinfo->block_length)
+ if (page_size + key_length + info->s->base.rec_reflength <=
+ keyinfo->block_length)
{
/* split won't be necessary */
if (nod_flag)
@@ -95,45 +97,4 @@ int rtree_set_key_mbr(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
return rtree_page_mbr(info, keyinfo->seg, info->buff, key, key_length);
}
-
-/*
- Choose non-leaf better key for insertion
-*/
-
-uchar *rtree_choose_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
- uint key_length, uchar *page_buf, uint nod_flag)
-{
- double increase;
- double best_incr = DBL_MAX;
- double area;
- double best_area;
- uchar *best_key;
- uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
- uchar *last = rt_PAGE_END(page_buf);
-
- LINT_INIT(best_area);
- LINT_INIT(best_key);
-
- for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
- {
- if ((increase = rtree_area_increase(keyinfo->seg, key, k, key_length,
- &area)) == -1)
- return NULL;
- if (increase < best_incr)
- {
- best_key = k;
- best_area = area;
- best_incr = increase;
- }
- else
- {
- if ((increase == best_incr) && (area < best_area))
- {
- best_key = k;
- best_area = area;
- best_incr = increase;
- }
- }
- }
- return best_key;
-}
+#endif /*HAVE_RTREE_KEYS*/
diff --git a/myisam/rt_key.h b/myisam/rt_key.h
index dfd7b874b54..df4f8aa03a2 100644
--- a/myisam/rt_key.h
+++ b/myisam/rt_key.h
@@ -20,12 +20,14 @@
#ifndef _rt_key_h
#define _rt_key_h
+#ifdef HAVE_RTREE_KEYS
+
int rtree_add_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
uint key_length, uchar *page_buf, my_off_t *new_page);
int rtree_delete_key(MI_INFO *info, uchar *page, uchar *key,
uint key_length, uint nod_flag);
int rtree_set_key_mbr(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
uint key_length, my_off_t child_page);
-uchar *rtree_choose_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
- uint key_length, uchar *page_buf, uint nod_flag);
+
+#endif /*HAVE_RTREE_KEYS*/
#endif /* _rt_key_h */
diff --git a/myisam/rt_mbr.c b/myisam/rt_mbr.c
index bb13c0769b3..7b556979904 100644
--- a/myisam/rt_mbr.c
+++ b/myisam/rt_mbr.c
@@ -17,6 +17,8 @@
#include "myisamdef.h"
+#ifdef HAVE_RTREE_KEYS
+
#include "rt_index.h"
#include "rt_mbr.h"
@@ -24,7 +26,7 @@
#define CONTAIN_CMP(amin, amax, bmin, bmax) ((bmin > amin) || (bmax < amax))
#define WITHIN_CMP(amin, amax, bmin, bmax) ((amin > bmin) || (amax < bmax))
#define DISJOINT_CMP(amin, amax, bmin, bmax) ((amin <= bmax) && (bmin <= amax))
-#define EQUAL_CMP(amix, amax, bmin, bmax) ((amix != bmin) || (amax != bmax))
+#define EQUAL_CMP(amin, amax, bmin, bmax) ((amin != bmin) || (amax != bmax))
#define FCMP(A, B) ((int)(A) - (int)(B))
#define p_inc(A, B, X) {A += X; B += X;}
@@ -61,12 +63,9 @@
type amin, amax, bmin, bmax; \
amin = korr_func(a); \
bmin = korr_func(b); \
- p_inc(a, b, len); \
- amax = korr_func(a); \
- bmax = korr_func(b); \
+ amax = korr_func(a+len); \
+ bmax = korr_func(b+len); \
RT_CMP(nextflag); \
- p_inc(a, b, len); \
- break; \
}
#define RT_CMP_GET(type, get_func, len, nextflag) \
@@ -74,12 +73,9 @@
type amin, amax, bmin, bmax; \
get_func(amin, a); \
get_func(bmin, b); \
- p_inc(a, b, len); \
- get_func(amax, a); \
- get_func(bmax, b); \
+ get_func(amax, a+len); \
+ get_func(bmax, b+len); \
RT_CMP(nextflag); \
- p_inc(a, b, len); \
- break; \
}
/*
@@ -98,54 +94,55 @@ int rtree_key_cmp(HA_KEYSEG *keyseg, uchar *b, uchar *a, uint key_length,
{
for (; (int) key_length > 0; keyseg += 2 )
{
- key_length -= keyseg->length * 2;
-
+ uint32 keyseg_length;
switch ((enum ha_base_keytype) keyseg->type) {
- case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_INT8:
+ RT_CMP_KORR(int8, mi_sint1korr, 1, nextflag);
+ break;
case HA_KEYTYPE_BINARY:
- case HA_KEYTYPE_VARTEXT:
- case HA_KEYTYPE_VARBINARY:
- case HA_KEYTYPE_NUM:
- default:
- return 1;
+ RT_CMP_KORR(uint8, mi_uint1korr, 1, nextflag);
break;
- case HA_KEYTYPE_INT8:
- {
- int amin,amax,bmin,bmax;
- amin = (int)*((signed char *)a);
- bmin = (int)*((signed char *)b);
- p_inc(a, b, 1);
- amax = (int)*((signed char *)a);
- bmax = (int)*((signed char *)b);
- RT_CMP(nextflag);
- p_inc(a, b, 1);
- break;
- }
case HA_KEYTYPE_SHORT_INT:
RT_CMP_KORR(int16, mi_sint2korr, 2, nextflag);
+ break;
case HA_KEYTYPE_USHORT_INT:
RT_CMP_KORR(uint16, mi_uint2korr, 2, nextflag);
+ break;
case HA_KEYTYPE_INT24:
RT_CMP_KORR(int32, mi_sint3korr, 3, nextflag);
+ break;
case HA_KEYTYPE_UINT24:
RT_CMP_KORR(uint32, mi_uint3korr, 3, nextflag);
+ break;
case HA_KEYTYPE_LONG_INT:
RT_CMP_KORR(int32, mi_sint4korr, 4, nextflag);
+ break;
case HA_KEYTYPE_ULONG_INT:
RT_CMP_KORR(uint32, mi_uint4korr, 4, nextflag);
+ break;
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
RT_CMP_KORR(longlong, mi_sint8korr, 8, nextflag)
+ break;
case HA_KEYTYPE_ULONGLONG:
RT_CMP_KORR(ulonglong, mi_uint8korr, 8, nextflag)
+ break;
#endif
case HA_KEYTYPE_FLOAT:
RT_CMP_GET(float, mi_float4get, 4, nextflag);
+ break;
case HA_KEYTYPE_DOUBLE:
RT_CMP_GET(double, mi_float8get, 8, nextflag);
+ break;
case HA_KEYTYPE_END:
goto end;
+ default:
+ return 1;
}
+ keyseg_length= keyseg->length * 2;
+ key_length-= keyseg_length;
+ a+= keyseg_length;
+ b+= keyseg_length;
}
end:
@@ -165,22 +162,16 @@ end:
{ \
type amin, amax; \
amin = korr_func(a); \
- a += len; \
- amax = korr_func(a); \
- a += len; \
+ amax = korr_func(a+len); \
res *= (cast(amax) - cast(amin)); \
- break; \
}
#define RT_VOL_GET(type, get_func, len, cast) \
{ \
type amin, amax; \
get_func(amin, a); \
- a += len; \
- get_func(amax, a); \
- a += len; \
+ get_func(amax, a+len); \
res *= (cast(amax) - cast(amin)); \
- break; \
}
/*
@@ -191,53 +182,55 @@ double rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length)
double res = 1;
for (; (int)key_length > 0; keyseg += 2)
{
- key_length -= keyseg->length * 2;
-
+ uint32 keyseg_length;
switch ((enum ha_base_keytype) keyseg->type) {
- case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_INT8:
+ RT_VOL_KORR(int8, mi_sint1korr, 1, (double));
+ break;
case HA_KEYTYPE_BINARY:
- case HA_KEYTYPE_VARTEXT:
- case HA_KEYTYPE_VARBINARY:
- case HA_KEYTYPE_NUM:
- default:
- return 1;
+ RT_VOL_KORR(uint8, mi_uint1korr, 1, (double));
break;
- case HA_KEYTYPE_INT8:
- {
- int amin, amax;
- amin = (int)*((signed char *)a);
- a += 1;
- amax = (int)*((signed char *)a);
- a += 1;
- res *= ((double)amax - (double)amin);
- break;
- }
case HA_KEYTYPE_SHORT_INT:
RT_VOL_KORR(int16, mi_sint2korr, 2, (double));
+ break;
case HA_KEYTYPE_USHORT_INT:
RT_VOL_KORR(uint16, mi_uint2korr, 2, (double));
+ break;
case HA_KEYTYPE_INT24:
RT_VOL_KORR(int32, mi_sint3korr, 3, (double));
+ break;
case HA_KEYTYPE_UINT24:
RT_VOL_KORR(uint32, mi_uint3korr, 3, (double));
+ break;
case HA_KEYTYPE_LONG_INT:
RT_VOL_KORR(int32, mi_sint4korr, 4, (double));
+ break;
case HA_KEYTYPE_ULONG_INT:
RT_VOL_KORR(uint32, mi_uint4korr, 4, (double));
+ break;
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
RT_VOL_KORR(longlong, mi_sint8korr, 8, (double));
+ break;
case HA_KEYTYPE_ULONGLONG:
RT_VOL_KORR(longlong, mi_sint8korr, 8, ulonglong2double);
+ break;
#endif
case HA_KEYTYPE_FLOAT:
RT_VOL_GET(float, mi_float4get, 4, (double));
+ break;
case HA_KEYTYPE_DOUBLE:
RT_VOL_GET(double, mi_float8get, 8, (double));
+ break;
case HA_KEYTYPE_END:
key_length = 0;
break;
+ default:
+ return -1;
}
+ keyseg_length= keyseg->length * 2;
+ key_length-= keyseg_length;
+ a+= keyseg_length;
}
return res;
}
@@ -246,81 +239,78 @@ double rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length)
{ \
type amin, amax; \
amin = korr_func(a); \
- a += len; \
- amax = korr_func(a); \
- a += len; \
+ amax = korr_func(a+len); \
*res++ = cast(amin); \
*res++ = cast(amax); \
- break; \
}
#define RT_D_MBR_GET(type, get_func, len, cast) \
{ \
type amin, amax; \
get_func(amin, a); \
- a += len; \
- get_func(amax, a); \
- a += len; \
+ get_func(amax, a+len); \
*res++ = cast(amin); \
*res++ = cast(amax); \
- break; \
}
+
/*
- Creates an MBR as an array of doubles.
+ Creates an MBR as an array of doubles.
*/
+
int rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res)
{
for (; (int)key_length > 0; keyseg += 2)
{
- key_length -= keyseg->length * 2;
-
+ uint32 keyseg_length;
switch ((enum ha_base_keytype) keyseg->type) {
- case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_INT8:
+ RT_D_MBR_KORR(int8, mi_sint1korr, 1, (double));
+ break;
case HA_KEYTYPE_BINARY:
- case HA_KEYTYPE_VARTEXT:
- case HA_KEYTYPE_VARBINARY:
- case HA_KEYTYPE_NUM:
- default:
- return 1;
+ RT_D_MBR_KORR(uint8, mi_uint1korr, 1, (double));
break;
- case HA_KEYTYPE_INT8:
- {
- int amin, amax;
- amin = (int)*((signed char *)a);
- a += 1;
- amax = (int)*((signed char *)a);
- a += 1;
- *res++ = (double)amin;
- *res++ = (double)amax;
- break;
- }
case HA_KEYTYPE_SHORT_INT:
RT_D_MBR_KORR(int16, mi_sint2korr, 2, (double));
+ break;
case HA_KEYTYPE_USHORT_INT:
RT_D_MBR_KORR(uint16, mi_uint2korr, 2, (double));
+ break;
case HA_KEYTYPE_INT24:
RT_D_MBR_KORR(int32, mi_sint3korr, 3, (double));
+ break;
case HA_KEYTYPE_UINT24:
RT_D_MBR_KORR(uint32, mi_uint3korr, 3, (double));
+ break;
case HA_KEYTYPE_LONG_INT:
RT_D_MBR_KORR(int32, mi_sint4korr, 4, (double));
+ break;
case HA_KEYTYPE_ULONG_INT:
RT_D_MBR_KORR(uint32, mi_uint4korr, 4, (double));
+ break;
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
RT_D_MBR_KORR(longlong, mi_sint8korr, 8, (double));
+ break;
case HA_KEYTYPE_ULONGLONG:
RT_D_MBR_KORR(longlong, mi_sint8korr, 8, ulonglong2double);
+ break;
#endif
case HA_KEYTYPE_FLOAT:
RT_D_MBR_GET(float, mi_float4get, 4, (double));
+ break;
case HA_KEYTYPE_DOUBLE:
RT_D_MBR_GET(double, mi_float8get, 8, (double));
+ break;
case HA_KEYTYPE_END:
key_length = 0;
break;
+ default:
+ return 1;
}
+ keyseg_length= keyseg->length * 2;
+ key_length-= keyseg_length;
+ a+= keyseg_length;
}
return 0;
}
@@ -330,17 +320,12 @@ int rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res)
type amin, amax, bmin, bmax; \
amin = korr_func(a); \
bmin = korr_func(b); \
- p_inc(a, b, len); \
- amax = korr_func(a); \
- bmax = korr_func(b); \
- p_inc(a, b, len); \
+ amax = korr_func(a+len); \
+ bmax = korr_func(b+len); \
amin = min(amin, bmin); \
amax = max(amax, bmax); \
store_func(c, amin); \
- c += len; \
- store_func(c, amax); \
- c += len; \
- break; \
+ store_func(c+len, amax); \
}
#define RT_COMB_GET(type, get_func, store_func, len) \
@@ -348,17 +333,12 @@ int rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res)
type amin, amax, bmin, bmax; \
get_func(amin, a); \
get_func(bmin, b); \
- p_inc(a, b, len); \
- get_func(amax, a); \
- get_func(bmax, b); \
- p_inc(a, b, len); \
+ get_func(amax, a+len); \
+ get_func(bmax, b+len); \
amin = min(amin, bmin); \
amax = max(amax, bmax); \
store_func(c, amin); \
- c += len; \
- store_func(c, amax); \
- c += len; \
- break; \
+ store_func(c+len, amax); \
}
/*
@@ -370,81 +350,75 @@ int rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res)
int rtree_combine_rect(HA_KEYSEG *keyseg, uchar* a, uchar* b, uchar* c,
uint key_length)
{
-
for ( ; (int) key_length > 0 ; keyseg += 2)
{
- key_length -= keyseg->length * 2;
-
+ uint32 keyseg_length;
switch ((enum ha_base_keytype) keyseg->type) {
- case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_INT8:
+ RT_COMB_KORR(int8, mi_sint1korr, mi_int1store, 1);
+ break;
case HA_KEYTYPE_BINARY:
- case HA_KEYTYPE_VARTEXT:
- case HA_KEYTYPE_VARBINARY:
- case HA_KEYTYPE_NUM:
- default:
- return 1;
+ RT_COMB_KORR(uint8, mi_uint1korr, mi_int1store, 1);
break;
- case HA_KEYTYPE_INT8:
- {
- int amin, amax, bmin, bmax;
- amin = (int)*((signed char *)a);
- bmin = (int)*((signed char *)b);
- p_inc(a, b, 1);
- amax = (int)*((signed char *)a);
- bmax = (int)*((signed char *)b);
- p_inc(a, b, 1);
- amin = min(amin, bmin);
- amax = max(amax, bmax);
- *((signed char*)c) = amin;
- c += 1;
- *((signed char*)c) = amax;
- c += 1;
- break;
- }
case HA_KEYTYPE_SHORT_INT:
RT_COMB_KORR(int16, mi_sint2korr, mi_int2store, 2);
+ break;
case HA_KEYTYPE_USHORT_INT:
RT_COMB_KORR(uint16, mi_uint2korr, mi_int2store, 2);
+ break;
case HA_KEYTYPE_INT24:
RT_COMB_KORR(int32, mi_sint3korr, mi_int3store, 3);
+ break;
case HA_KEYTYPE_UINT24:
RT_COMB_KORR(uint32, mi_uint3korr, mi_int3store, 3);
+ break;
case HA_KEYTYPE_LONG_INT:
RT_COMB_KORR(int32, mi_sint4korr, mi_int4store, 4);
+ break;
case HA_KEYTYPE_ULONG_INT:
RT_COMB_KORR(uint32, mi_uint4korr, mi_int4store, 4);
+ break;
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
RT_COMB_KORR(longlong, mi_sint8korr, mi_int8store, 8);
+ break;
case HA_KEYTYPE_ULONGLONG:
RT_COMB_KORR(ulonglong, mi_uint8korr, mi_int8store, 8);
+ break;
#endif
case HA_KEYTYPE_FLOAT:
RT_COMB_GET(float, mi_float4get, mi_float4store, 4);
+ break;
case HA_KEYTYPE_DOUBLE:
RT_COMB_GET(double, mi_float8get, mi_float8store, 8);
+ break;
case HA_KEYTYPE_END:
return 0;
+ default:
+ return 1;
}
+ keyseg_length= keyseg->length * 2;
+ key_length-= keyseg_length;
+ a+= keyseg_length;
+ b+= keyseg_length;
+ c+= keyseg_length;
}
return 0;
}
+
#define RT_OVL_AREA_KORR(type, korr_func, len) \
{ \
type amin, amax, bmin, bmax; \
amin = korr_func(a); \
bmin = korr_func(b); \
- p_inc(a, b, len); \
- amax = korr_func(a); \
- bmax = korr_func(b); \
- p_inc(a, b, len); \
+ amax = korr_func(a+len); \
+ bmax = korr_func(b+len); \
amin = max(amin, bmin); \
amax = min(amax, bmax); \
if (amin >= amax) \
return 0; \
res *= amax - amin; \
- break; \
}
#define RT_OVL_AREA_GET(type, get_func, len) \
@@ -452,16 +426,13 @@ int rtree_combine_rect(HA_KEYSEG *keyseg, uchar* a, uchar* b, uchar* c,
type amin, amax, bmin, bmax; \
get_func(amin, a); \
get_func(bmin, b); \
- p_inc(a, b, len); \
- get_func(amax, a); \
- get_func(bmax, b); \
- p_inc(a, b, len); \
+ get_func(amax, a+len); \
+ get_func(bmax, b+len); \
amin = max(amin, bmin); \
amax = min(amax, bmax); \
if (amin >= amax) \
return 0; \
res *= amax - amin; \
- break; \
}
/*
@@ -473,58 +444,55 @@ double rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b,
double res = 1;
for (; (int) key_length > 0 ; keyseg += 2)
{
- key_length -= keyseg->length * 2;
-
+ uint32 keyseg_length;
switch ((enum ha_base_keytype) keyseg->type) {
- case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_INT8:
+ RT_OVL_AREA_KORR(int8, mi_sint1korr, 1);
+ break;
case HA_KEYTYPE_BINARY:
- case HA_KEYTYPE_VARTEXT:
- case HA_KEYTYPE_VARBINARY:
- case HA_KEYTYPE_NUM:
- default:
- return -1;
+ RT_OVL_AREA_KORR(uint8, mi_uint1korr, 1);
break;
- case HA_KEYTYPE_INT8:
- {
- int amin, amax, bmin, bmax;
- amin = (int)*((signed char *)a);
- bmin = (int)*((signed char *)b);
- p_inc(a, b, 1);
- amax = (int)*((signed char *)a);
- bmax = (int)*((signed char *)b);
- p_inc(a, b, 1);
- amin = max(amin, bmin);
- amax = min(amax, bmax);
- if (amin >= amax)
- return 0;
- res *= amax - amin;
- break;
- }
case HA_KEYTYPE_SHORT_INT:
RT_OVL_AREA_KORR(int16, mi_sint2korr, 2);
+ break;
case HA_KEYTYPE_USHORT_INT:
RT_OVL_AREA_KORR(uint16, mi_uint2korr, 2);
+ break;
case HA_KEYTYPE_INT24:
RT_OVL_AREA_KORR(int32, mi_sint3korr, 3);
+ break;
case HA_KEYTYPE_UINT24:
RT_OVL_AREA_KORR(uint32, mi_uint3korr, 3);
+ break;
case HA_KEYTYPE_LONG_INT:
RT_OVL_AREA_KORR(int32, mi_sint4korr, 4);
+ break;
case HA_KEYTYPE_ULONG_INT:
RT_OVL_AREA_KORR(uint32, mi_uint4korr, 4);
+ break;
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
RT_OVL_AREA_KORR(longlong, mi_sint8korr, 8);
+ break;
case HA_KEYTYPE_ULONGLONG:
RT_OVL_AREA_KORR(longlong, mi_sint8korr, 8);
+ break;
#endif
case HA_KEYTYPE_FLOAT:
RT_OVL_AREA_GET(float, mi_float4get, 4);
+ break;
case HA_KEYTYPE_DOUBLE:
RT_OVL_AREA_GET(double, mi_float8get, 8);
+ break;
case HA_KEYTYPE_END:
return res;
+ default:
+ return -1;
}
+ keyseg_length= keyseg->length * 2;
+ key_length-= keyseg_length;
+ a+= keyseg_length;
+ b+= keyseg_length;
}
return res;
}
@@ -534,13 +502,10 @@ double rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b,
type amin, amax, bmin, bmax; \
amin = korr_func(a); \
bmin = korr_func(b); \
- p_inc(a, b, len); \
- amax = korr_func(a); \
- bmax = korr_func(b); \
- p_inc(a, b, len); \
+ amax = korr_func(a+len); \
+ bmax = korr_func(b+len); \
a_area *= (((double)amax) - ((double)amin)); \
*ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin)); \
- break; \
}
#define RT_AREA_INC_GET(type, get_func, len)\
@@ -548,13 +513,10 @@ double rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b,
type amin, amax, bmin, bmax; \
get_func(amin, a); \
get_func(bmin, b); \
- p_inc(a, b, len); \
- get_func(amax, a); \
- get_func(bmax, b); \
- p_inc(a, b, len); \
+ get_func(amax, a+len); \
+ get_func(bmax, b+len); \
a_area *= (((double)amax) - ((double)amin)); \
*ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin)); \
- break; \
}
/*
@@ -563,70 +525,159 @@ Calculates MBR_AREA(a+b) - MBR_AREA(a)
double rtree_area_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
uint key_length, double *ab_area)
{
- double a_area = 1;
+ double a_area= 1.0;
- *ab_area = 1;
+ *ab_area= 1.0;
for (; (int)key_length > 0; keyseg += 2)
{
- key_length -= keyseg->length * 2;
-
- /* Handle NULL part */
- if (keyseg->null_bit)
- {
+ uint32 keyseg_length;
+
+ if (keyseg->null_bit) /* Handle NULL part */
return -1;
- }
switch ((enum ha_base_keytype) keyseg->type) {
- case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_INT8:
+ RT_AREA_INC_KORR(int8, mi_sint1korr, 1);
+ break;
case HA_KEYTYPE_BINARY:
- case HA_KEYTYPE_VARTEXT:
- case HA_KEYTYPE_VARBINARY:
- case HA_KEYTYPE_NUM:
- default:
- return 1;
+ RT_AREA_INC_KORR(uint8, mi_uint1korr, 1);
break;
- case HA_KEYTYPE_INT8:
- {
- int amin, amax, bmin, bmax;
- amin = (int)*((signed char *)a);
- bmin = (int)*((signed char *)b);
- p_inc(a, b, 1);
- amax = (int)*((signed char *)a);
- bmax = (int)*((signed char *)b);
- p_inc(a, b, 1);
- a_area *= (((double)amax) - ((double)amin));
- *ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin));
- break;
- }
case HA_KEYTYPE_SHORT_INT:
RT_AREA_INC_KORR(int16, mi_sint2korr, 2);
+ break;
case HA_KEYTYPE_USHORT_INT:
RT_AREA_INC_KORR(uint16, mi_uint2korr, 2);
+ break;
case HA_KEYTYPE_INT24:
RT_AREA_INC_KORR(int32, mi_sint3korr, 3);
+ break;
case HA_KEYTYPE_UINT24:
RT_AREA_INC_KORR(int32, mi_uint3korr, 3);
+ break;
case HA_KEYTYPE_LONG_INT:
RT_AREA_INC_KORR(int32, mi_sint4korr, 4);
+ break;
case HA_KEYTYPE_ULONG_INT:
RT_AREA_INC_KORR(uint32, mi_uint4korr, 4);
+ break;
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
RT_AREA_INC_KORR(longlong, mi_sint8korr, 8);
+ break;
case HA_KEYTYPE_ULONGLONG:
RT_AREA_INC_KORR(longlong, mi_sint8korr, 8);
+ break;
#endif
case HA_KEYTYPE_FLOAT:
RT_AREA_INC_GET(float, mi_float4get, 4);
+ break;
case HA_KEYTYPE_DOUBLE:
RT_AREA_INC_GET(double, mi_float8get, 8);
+ break;
case HA_KEYTYPE_END:
return *ab_area - a_area;
+ default:
+ return -1;
}
+ keyseg_length= keyseg->length * 2;
+ key_length-= keyseg_length;
+ a+= keyseg_length;
+ b+= keyseg_length;
}
return *ab_area - a_area;
}
+#define RT_PERIM_INC_KORR(type, korr_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(a); \
+ bmin = korr_func(b); \
+ amax = korr_func(a+len); \
+ bmax = korr_func(b+len); \
+ a_perim+= (((double)amax) - ((double)amin)); \
+ *ab_perim+= ((double)max(amax, bmax) - (double)min(amin, bmin)); \
+}
+
+#define RT_PERIM_INC_GET(type, get_func, len)\
+{\
+ type amin, amax, bmin, bmax; \
+ get_func(amin, a); \
+ get_func(bmin, b); \
+ get_func(amax, a+len); \
+ get_func(bmax, b+len); \
+ a_perim+= (((double)amax) - ((double)amin)); \
+ *ab_perim+= ((double)max(amax, bmax) - (double)min(amin, bmin)); \
+}
+
+/*
+Calculates MBR_PERIMETER(a+b) - MBR_PERIMETER(a)
+*/
+double rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
+ uint key_length, double *ab_perim)
+{
+ double a_perim = 0.0;
+
+ *ab_perim= 0.0;
+ for (; (int)key_length > 0; keyseg += 2)
+ {
+ uint32 keyseg_length;
+
+ if (keyseg->null_bit) /* Handle NULL part */
+ return -1;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_INT8:
+ RT_PERIM_INC_KORR(int8, mi_sint1korr, 1);
+ break;
+ case HA_KEYTYPE_BINARY:
+ RT_PERIM_INC_KORR(uint8, mi_uint1korr, 1);
+ break;
+ case HA_KEYTYPE_SHORT_INT:
+ RT_PERIM_INC_KORR(int16, mi_sint2korr, 2);
+ break;
+ case HA_KEYTYPE_USHORT_INT:
+ RT_PERIM_INC_KORR(uint16, mi_uint2korr, 2);
+ break;
+ case HA_KEYTYPE_INT24:
+ RT_PERIM_INC_KORR(int32, mi_sint3korr, 3);
+ break;
+ case HA_KEYTYPE_UINT24:
+ RT_PERIM_INC_KORR(int32, mi_uint3korr, 3);
+ break;
+ case HA_KEYTYPE_LONG_INT:
+ RT_PERIM_INC_KORR(int32, mi_sint4korr, 4);
+ break;
+ case HA_KEYTYPE_ULONG_INT:
+ RT_PERIM_INC_KORR(uint32, mi_uint4korr, 4);
+ break;
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_PERIM_INC_KORR(longlong, mi_sint8korr, 8);
+ break;
+ case HA_KEYTYPE_ULONGLONG:
+ RT_PERIM_INC_KORR(longlong, mi_sint8korr, 8);
+ break;
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_PERIM_INC_GET(float, mi_float4get, 4);
+ break;
+ case HA_KEYTYPE_DOUBLE:
+ RT_PERIM_INC_GET(double, mi_float8get, 8);
+ break;
+ case HA_KEYTYPE_END:
+ return *ab_perim - a_perim;
+ default:
+ return -1;
+ }
+ keyseg_length= keyseg->length * 2;
+ key_length-= keyseg_length;
+ a+= keyseg_length;
+ b+= keyseg_length;
+ }
+ return *ab_perim - a_perim;
+}
+
+
#define RT_PAGE_MBR_KORR(type, korr_func, store_func, len) \
{ \
type amin, amax, bmin, bmax; \
@@ -647,7 +698,6 @@ double rtree_area_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
store_func(c, amax); \
c += len; \
inc += 2 * len; \
- break; \
}
#define RT_PAGE_MBR_GET(type, get_func, store_func, len) \
@@ -670,7 +720,6 @@ double rtree_area_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
store_func(c, amax); \
c += len; \
inc += 2 * len; \
- break; \
}
/*
@@ -698,62 +747,51 @@ int rtree_page_mbr(MI_INFO *info, HA_KEYSEG *keyseg, uchar *page_buf,
k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
switch ((enum ha_base_keytype) keyseg->type) {
- case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_INT8:
+ RT_PAGE_MBR_KORR(int8, mi_sint1korr, mi_int1store, 1);
+ break;
case HA_KEYTYPE_BINARY:
- case HA_KEYTYPE_VARTEXT:
- case HA_KEYTYPE_VARBINARY:
- case HA_KEYTYPE_NUM:
- default:
- return 1;
+ RT_PAGE_MBR_KORR(uint8, mi_uint1korr, mi_int1store, 1);
break;
- case HA_KEYTYPE_INT8:
- {
- int amin, amax, bmin, bmax;
- amin = (int)*((signed char *)(k + inc));
- amax = (int)*((signed char *)(k + inc + 1));
- k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
- for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag))
- {
- bmin = (int)*((signed char *)(k + inc));
- bmax = (int)*((signed char *)(k + inc + 1));
-
- if (amin > bmin)
- amin = bmin;
- if (amax < bmax)
- amax = bmax;
- }
- *((signed char*)c) = amin;
- c += 1;
- *((signed char*)c) = amax;
- c += 1;
- inc += 1 * 2;
- break;
- }
case HA_KEYTYPE_SHORT_INT:
RT_PAGE_MBR_KORR(int16, mi_sint2korr, mi_int2store, 2);
+ break;
case HA_KEYTYPE_USHORT_INT:
RT_PAGE_MBR_KORR(uint16, mi_uint2korr, mi_int2store, 2);
+ break;
case HA_KEYTYPE_INT24:
RT_PAGE_MBR_KORR(int32, mi_sint3korr, mi_int3store, 3);
+ break;
case HA_KEYTYPE_UINT24:
RT_PAGE_MBR_KORR(uint32, mi_uint3korr, mi_int3store, 3);
+ break;
case HA_KEYTYPE_LONG_INT:
RT_PAGE_MBR_KORR(int32, mi_sint4korr, mi_int4store, 4);
+ break;
case HA_KEYTYPE_ULONG_INT:
RT_PAGE_MBR_KORR(uint32, mi_uint4korr, mi_int4store, 4);
+ break;
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
RT_PAGE_MBR_KORR(longlong, mi_sint8korr, mi_int8store, 8);
+ break;
case HA_KEYTYPE_ULONGLONG:
RT_PAGE_MBR_KORR(ulonglong, mi_uint8korr, mi_int8store, 8);
+ break;
#endif
case HA_KEYTYPE_FLOAT:
RT_PAGE_MBR_GET(float, mi_float4get, mi_float4store, 4);
+ break;
case HA_KEYTYPE_DOUBLE:
RT_PAGE_MBR_GET(double, mi_float8get, mi_float8store, 8);
+ break;
case HA_KEYTYPE_END:
return 0;
+ default:
+ return 1;
}
}
return 0;
}
+
+#endif /*HAVE_RTREE_KEYS*/
diff --git a/myisam/rt_mbr.h b/myisam/rt_mbr.h
index a68807370f9..2153faad2b4 100644
--- a/myisam/rt_mbr.h
+++ b/myisam/rt_mbr.h
@@ -18,6 +18,8 @@
#ifndef _rt_mbr_h
#define _rt_mbr_h
+#ifdef HAVE_RTREE_KEYS
+
int rtree_key_cmp(HA_KEYSEG *keyseg, uchar *a, uchar *b, uint key_length,
uint nextflag);
int rtree_combine_rect(HA_KEYSEG *keyseg,uchar *, uchar *, uchar*,
@@ -28,6 +30,9 @@ double rtree_overlapping_area(HA_KEYSEG *keyseg, uchar *a, uchar *b,
uint key_length);
double rtree_area_increase(HA_KEYSEG *keyseg, uchar *a, uchar *b,
uint key_length, double *ab_area);
+double rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
+ uint key_length, double *ab_perim);
int rtree_page_mbr(MI_INFO *info, HA_KEYSEG *keyseg, uchar *page_buf,
uchar* c, uint key_length);
+#endif /*HAVE_RTREE_KEYS*/
#endif /* _rt_mbr_h */
diff --git a/myisam/rt_split.c b/myisam/rt_split.c
index 62b8ea6a65b..005e86805bb 100644
--- a/myisam/rt_split.c
+++ b/myisam/rt_split.c
@@ -17,6 +17,8 @@
#include "myisamdef.h"
+#ifdef HAVE_RTREE_KEYS
+
#include "rt_index.h"
#include "rt_key.h"
#include "rt_mbr.h"
@@ -265,12 +267,12 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
n_dim = keyinfo->keysegs / 2;
- if (!my_multi_malloc(MYF(0),
- &coord_buf, n_dim * 2 * sizeof(double) * (max_keys + 1 + 4),
- &task, sizeof(SplitStruct) * (max_keys + 1),
- NullS))
+ if (!(coord_buf= my_alloca(n_dim * 2 * sizeof(double) * (max_keys + 1 + 4) +
+ sizeof(SplitStruct) * (max_keys + 1))))
return -1;
+ task= (SplitStruct *)(coord_buf + n_dim * 2 * (max_keys + 1 + 4));
+
next_coord = coord_buf;
stop = task + max_keys;
@@ -343,6 +345,8 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
my_afree((byte*)new_page);
split_err:
- my_free((gptr) coord_buf, MYF(0));
+ my_afree((byte*) coord_buf);
return err_code;
}
+
+#endif /*HAVE_RTREE_KEYS*/
diff --git a/myisam/rt_test.c b/myisam/rt_test.c
index 41cc56d4d78..5e883e223b3 100644
--- a/myisam/rt_test.c
+++ b/myisam/rt_test.c
@@ -19,6 +19,9 @@
#include "myisam.h"
+
+#ifdef HAVE_RTREE_KEYS
+
#include "rt_index.h"
#define MAX_REC_LENGTH 1024
@@ -31,6 +34,51 @@ static void create_record1(char *record,uint rownr);
static void print_record(char * record,my_off_t offs,const char * tail);
static int run_test(const char *filename);
+static double rt_data[]=
+{
+ /*1*/ 0,10,0,10,
+ /*2*/ 5,15,0,10,
+ /*3*/ 0,10,5,15,
+ /*4*/ 10,20,10,20,
+ /*5*/ 0,10,0,10,
+ /*6*/ 5,15,0,10,
+ /*7*/ 0,10,5,15,
+ /*8*/ 10,20,10,20,
+ /*9*/ 0,10,0,10,
+ /*10*/ 5,15,0,10,
+ /*11*/ 0,10,5,15,
+ /*12*/ 10,20,10,20,
+ /*13*/ 0,10,0,10,
+ /*14*/ 5,15,0,10,
+ /*15*/ 0,10,5,15,
+ /*16*/ 10,20,10,20,
+ /*17*/ 5,15,0,10,
+ /*18*/ 0,10,5,15,
+ /*19*/ 10,20,10,20,
+ /*20*/ 0,10,0,10,
+
+ /*1*/ 100,110,0,10,
+ /*2*/ 105,115,0,10,
+ /*3*/ 100,110,5,15,
+ /*4*/ 110,120,10,20,
+ /*5*/ 100,110,0,10,
+ /*6*/ 105,115,0,10,
+ /*7*/ 100,110,5,15,
+ /*8*/ 110,120,10,20,
+ /*9*/ 100,110,0,10,
+ /*10*/ 105,115,0,10,
+ /*11*/ 100,110,5,15,
+ /*12*/ 110,120,10,20,
+ /*13*/ 100,110,0,10,
+ /*14*/ 105,115,0,10,
+ /*15*/ 100,110,5,15,
+ /*16*/ 110,120,10,20,
+ /*17*/ 105,115,0,10,
+ /*18*/ 100,110,5,15,
+ /*19*/ 110,120,10,20,
+ /*20*/ 100,110,0,10,
+ -1
+};
int main(int argc __attribute__((unused)),char *argv[] __attribute__((unused)))
{
@@ -55,7 +103,7 @@ static int run_test(const char *filename)
int key_type=HA_KEYTYPE_DOUBLE;
int key_length=8;
int null_fields=0;
- int nrecords=300;
+ int nrecords=sizeof(rt_data)/(sizeof(double)*4);/* 3000;*/
int rec_length=0;
int uniques=0;
int i;
@@ -378,7 +426,7 @@ static void create_record1(char *record,uint rownr)
}
-static void create_record(char *record,uint rownr)
+static void create_record0(char *record,uint rownr)
{
int i;
char * pos;
@@ -398,3 +446,23 @@ static void create_record(char *record,uint rownr)
pos+=sizeof(c);
}
}
+
+static void create_record(char *record,uint rownr)
+{
+ int i;
+ char *pos;
+ double *data= rt_data+rownr*4;
+ record[0]=0x01; /* DEL marker */
+ for ( pos=record+1, i=0; i<ndims*2; i++)
+ {
+ float8store(pos,data[i]);
+ pos+=8;
+ }
+}
+
+#else
+int main(int argc __attribute__((unused)),char *argv[] __attribute__((unused)))
+{
+ exit(0);
+}
+#endif /*HAVE_RTREE_KEYS*/
diff --git a/myisam/sort.c b/myisam/sort.c
index 1a9daa7df64..334f735599f 100644
--- a/myisam/sort.c
+++ b/myisam/sort.c
@@ -874,7 +874,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
count+= buffpek->count;
buffpek->base= strpos;
buffpek->max_keys=maxcount;
- strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek,sort_length));
+ strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek,
+ sort_length));
if (error == -1)
goto err; /* purecov: inspected */
queue_insert(&queue,(char*) buffpek);
@@ -891,7 +892,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
buffpek=(BUFFPEK*) queue_top(&queue);
if (to_file)
{
- if (info->write_key(info,to_file,(byte*) buffpek->key,(uint) sort_length,1))
+ if (info->write_key(info,to_file,(byte*) buffpek->key,
+ (uint) sort_length,1))
{
error=1; goto err; /* purecov: inspected */
}
diff --git a/myisam/sp_defs.h b/myisam/sp_defs.h
index 0acefe32f80..4cc2267a1bd 100644
--- a/myisam/sp_defs.h
+++ b/myisam/sp_defs.h
@@ -22,6 +22,8 @@
#define SPTYPE HA_KEYTYPE_DOUBLE
#define SPLEN 8
+#ifdef HAVE_SPATIAL
+
enum wkbType
{
wkbPoint = 1,
@@ -42,4 +44,5 @@ enum wkbByteOrder
uint sp_make_key(register MI_INFO *info, uint keynr, uchar *key,
const byte *record, my_off_t filepos);
+#endif /*HAVE_SPATIAL*/
#endif /* _SP_DEFS_H */
diff --git a/myisam/sp_key.c b/myisam/sp_key.c
index f669d217026..0e424a9e193 100644
--- a/myisam/sp_key.c
+++ b/myisam/sp_key.c
@@ -15,6 +15,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "myisamdef.h"
+
+#ifdef HAVE_SPATIAL
+
#include "sp_defs.h"
static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims,
@@ -284,3 +287,5 @@ static int sp_get_geometry_mbr(uchar *(*wkb), uchar *end, uint n_dims,
}
return res;
}
+
+#endif /*HAVE_SPATIAL*/
diff --git a/myisam/sp_test.c b/myisam/sp_test.c
index 29c5f47471a..f0b48dbd5d8 100644
--- a/myisam/sp_test.c
+++ b/myisam/sp_test.c
@@ -18,6 +18,8 @@
/* Written by Alex Barkov, who has a shared copyright to this code */
#include "myisam.h"
+
+#ifdef HAVE_SPATIAL
#include "sp_defs.h"
#define MAX_REC_LENGTH 1024
@@ -553,3 +555,11 @@ static void rtree_PrintWKB(uchar *wkb, uint n_dims)
}
}
}
+
+#else
+int main(int argc __attribute__((unused)),char *argv[] __attribute__((unused)))
+{
+ exit(0);
+}
+#endif /*HAVE_SPATIAL*/
+
diff --git a/myisammrg/myrg_write.c b/myisammrg/myrg_write.c
index 0f191edc23c..532709e361d 100644
--- a/myisammrg/myrg_write.c
+++ b/myisammrg/myrg_write.c
@@ -22,9 +22,9 @@ int myrg_write(register MYRG_INFO *info, byte *rec)
{
/* [phi] MERGE_WRITE_DISABLED is handled by the else case */
if (info->merge_insert_method == MERGE_INSERT_TO_FIRST)
- return mi_write(info->open_tables[0].table,rec);
+ return mi_write((info->current_table=info->open_tables)->table,rec);
else if (info->merge_insert_method == MERGE_INSERT_TO_LAST)
- return mi_write(info->end_table[-1].table,rec);
+ return mi_write((info->current_table=info->end_table-1)->table,rec);
else /* unsupported insertion method */
return (my_errno= HA_ERR_WRONG_COMMAND);
}
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index d23a9919b48..e10c0739cb4 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -17,6 +17,17 @@
## Process this file with automake to create Makefile.in
+if HAVE_NDBCLUSTER_DB
+SUBDIRS = ndb
+DIST_SUBDIRS=ndb
+else
+# If one uses automake conditionals, automake will automatically
+# include all possible branches to DIST_SUBDIRS goal.
+# Reset DIST_SUBDIRS if we don't use NDB
+SUBDIRS=
+DIST_SUBDIRS=
+endif
+
benchdir_root= $(prefix)
testdir = $(benchdir_root)/mysql-test
EXTRA_SCRIPTS = mysql-test-run.sh install_test_db.sh
@@ -72,8 +83,10 @@ SUFFIXES = .sh
-e 's!@''libexecdir''@!$(libexecdir)!g' \
-e 's!@''PERL''@!@PERL@!' \
-e 's!@''VERSION''@!@VERSION@!' \
+ -e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \
-e 's!@''MYSQL_BASE_VERSION''@!@MYSQL_BASE_VERSION@!' \
-e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \
+ -e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \
-e 's!@''MYSQL_NO_DASH_VERSION''@!@MYSQL_NO_DASH_VERSION@!' \
-e 's!@''MYSQL_SERVER_SUFFIX''@!@MYSQL_SERVER_SUFFIX@!' \
$< > $@-t
diff --git a/mysql-test/README b/mysql-test/README
index 7c6efe7940e..bccb05c555c 100644
--- a/mysql-test/README
+++ b/mysql-test/README
@@ -12,7 +12,7 @@ conflict with it.
All tests must pass. If one or more of them fail on your system, please
read the following manual section of how to report the problem:
-http://www.mysql.com/doc/M/y/MySQL_test_suite.html
+http://dev.mysql.com/doc/mysql/en/MySQL_test_suite.html
You can create your own test cases. To create a test case:
diff --git a/mysql-test/include/have_archive.inc b/mysql-test/include/have_archive.inc
new file mode 100644
index 00000000000..f7fb942e83e
--- /dev/null
+++ b/mysql-test/include/have_archive.inc
@@ -0,0 +1,4 @@
+-- require r/have_archive.require
+disable_query_log;
+show variables like "have_archive";
+enable_query_log;
diff --git a/mysql-test/include/have_debug.inc b/mysql-test/include/have_debug.inc
new file mode 100644
index 00000000000..ff59037b6eb
--- /dev/null
+++ b/mysql-test/include/have_debug.inc
@@ -0,0 +1,4 @@
+-- require r/have_debug.require
+disable_query_log;
+select (version() like "%debug%") as debug;
+enable_query_log;
diff --git a/mysql-test/include/have_geometry.inc b/mysql-test/include/have_geometry.inc
new file mode 100644
index 00000000000..169c3a41ee7
--- /dev/null
+++ b/mysql-test/include/have_geometry.inc
@@ -0,0 +1,4 @@
+-- require r/have_geometry.require
+disable_query_log;
+show variables like "have_geometry";
+enable_query_log;
diff --git a/mysql-test/include/ps_create.inc b/mysql-test/include/ps_create.inc
new file mode 100644
index 00000000000..7c457572d61
--- /dev/null
+++ b/mysql-test/include/ps_create.inc
@@ -0,0 +1,29 @@
+############### include/ps_create.inc ##################
+# #
+# drop + create the tables used in most PS test cases #
+# #
+########################################################
+
+--disable_warnings
+drop table if exists t1, t_many_col_types ;
+--enable_warnings
+
+eval create table t1
+(
+ a int, b varchar(30),
+ primary key(a)
+) engine = $type ;
+
+eval create table t_many_col_types
+(
+ 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,
+ 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,
+ c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+ c32 set('monday', 'tuesday', 'wednesday'),
+ primary key(c1)
+) engine = $type ;
diff --git a/mysql-test/include/ps_modify.inc b/mysql-test/include/ps_modify.inc
new file mode 100644
index 00000000000..85e9690cf04
--- /dev/null
+++ b/mysql-test/include/ps_modify.inc
@@ -0,0 +1,207 @@
+###################### ps_modify.inc #########################
+# #
+# Tests for prepared statements: INSERT/DELETE/UPDATE... #
+# #
+##############################################################
+
+--disable_query_log
+select '------ delete tests ------' as test_sequence ;
+--enable_query_log
+--source include/ps_renew.inc
+
+## delete without parameter
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+# delete with row not found
+execute stmt1;
+
+## delete with one parameter in the where clause
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+
+## truncate a table
+--error 1295
+prepare stmt1 from 'truncate table t1' ;
+
+
+--disable_query_log
+select '------ update tests ------' as test_sequence ;
+--enable_query_log
+--source include/ps_renew.inc
+
+## update without parameter
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+# dummy update
+execute stmt1;
+select a,b from t1 where a=2;
+
+## update with one parameter in the set clause
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+
+## update with one parameter in the where cause
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+update t1 set b='two' where a=@arg00;
+# row not found in update
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+
+## update on primary key column (two parameters)
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+# dummy update
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+select a,b from t1;
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1;
+
+## update with subquery and several parameters
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+--disable_warnings
+drop table if exists t2;
+--enable_warnings
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+select a,b from t1 where a = @arg00 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+select a,b from t1 ;
+drop table t2 ;
+
+## update with parameters in limit
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+# currently (May 2004, Version 4.1) it is impossible
+-- error 1064
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+
+--disable_query_log
+select '------ insert tests ------' as test_sequence ;
+--enable_query_log
+--source include/ps_renew.inc
+
+## insert without parameter
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+
+## insert with one parameter in values part
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+# the second insert fails, because the first column is primary key
+--error 1062
+execute stmt1 using @arg00;
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+
+## insert with two parameter in values part
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+
+## insert with two rows in values part
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+
+## insert with two parameter in the set part
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+
+## insert with parameters in the ON DUPLICATE KEY part
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1;
+set @arg00=81 ;
+set @arg01=1 ;
+--error 1062
+execute stmt1 using @arg00, @arg01;
+
+## many parameters
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+ on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 ;
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+delete from t1 where a >= 1000 ;
+
+## replace
+--error 1295
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
diff --git a/mysql-test/include/ps_modify1.inc b/mysql-test/include/ps_modify1.inc
new file mode 100644
index 00000000000..3608e726648
--- /dev/null
+++ b/mysql-test/include/ps_modify1.inc
@@ -0,0 +1,60 @@
+###################### ps_modify1.inc ########################
+# #
+# Tests for prepared statements: big INSERT .. SELECTs #
+# #
+##############################################################
+
+## big insert select statements
+set @duplicate='duplicate ' ;
+set @1000=1000 ;
+set @5=5 ;
+select a,b from t1 where a < 5 ;
+--enable_info
+insert into t1 select a + @1000, concat(@duplicate,b) from t1
+where a < @5 ;
+--disable_info
+select a,b from t1 where a >= 1000 ;
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' insert into t1 select a + ?, concat(?,b) from t1
+where a < ? ' ;
+--enable_info
+execute stmt1 using @1000, @duplicate, @5;
+--disable_info
+select a,b from t1 where a >= 1000 ;
+delete from t1 where a >= 1000 ;
+
+set @float=1.00;
+set @five='five' ;
+--disable_warnings
+drop table if exists t2;
+--enable_warnings
+create table t2 like t1 ;
+--enable_info
+insert into t2 (b,a)
+select @duplicate, sum(first.a) from t1 first, t1 second
+ where first.a <> @5 and second.b = first.b
+ and second.b <> @five
+ group by second.b
+ having sum(second.a) > @2
+union
+select b, a + @100 from t1
+ where (a,b) in ( select sqrt(a+@1)+CAST(@float AS signed),b
+ from t1);
+--disable_info
+select a,b from t2;
+delete from t2 ;
+prepare stmt1 from ' insert into t2 (b,a)
+select ?, sum(first.a)
+ from t1 first, t1 second
+ where first.a <> ? and second.b = first.b and second.b <> ?
+ group by second.b
+ having sum(second.a) > ?
+union
+select b, a + ? from t1
+ where (a,b) in ( select sqrt(a+?)+CAST(? AS signed),b
+ from t1 ) ' ;
+--enable_info
+execute stmt1 using @duplicate, @5, @five, @2, @100, @1, @float ;
+--disable_info
+select a,b from t2;
+drop table t2;
diff --git a/mysql-test/include/ps_query.inc b/mysql-test/include/ps_query.inc
new file mode 100644
index 00000000000..819ec4add06
--- /dev/null
+++ b/mysql-test/include/ps_query.inc
@@ -0,0 +1,587 @@
+####################### ps_query.inc #########################
+# #
+# Tests for prepared statements: SELECTs #
+# #
+##############################################################
+
+
+# Please do not modify (INSERT/UPDATE/DELETE) the content of the tables
+# t1 and t_many_col_types.
+# Such tests should be done in include/ps_modify.inc
+
+--disable_query_log
+select '------ simple select tests ------' as test_sequence ;
+--enable_query_log
+
+##### parameter used for keyword like SELECT (must fail)
+set @arg00='SELECT' ;
+# mysqltest gives no output for the next statement, Why ??
+--error 1064
+@arg00 a from t1 where a=1;
+--error 1064
+prepare stmt1 from ' ? a from t1 where a=1 ';
+
+##### parameter in select column list
+## parameter is not NULL
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+## parameter is NULL
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+## parameter within an expression
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+## parameter is within a function
+# variations on 'substr'
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+# variations on 'concat'
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 ;
+# BUG#3796
+prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+execute stmt1 using @arg00;
+#
+select a , concat(b,@arg00) from t1 ;
+prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+execute stmt1 using @arg00;
+
+# variations on 'group_concat'
+set @arg00='MySQL' ;
+select group_concat(@arg00,b) from t1
+group by 'a' ;
+prepare stmt1 from ' select group_concat(?,b) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+#
+select group_concat(b,@arg00) from t1
+group by 'a' ;
+prepare stmt1 from ' select group_concat(b,?) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+
+## two parameters
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+# NULL as first and/or last parameter
+execute stmt1 using @arg02, @arg01 ;
+execute stmt1 using @arg00, @arg02 ;
+execute stmt1 using @arg02, @arg02 ;
+# case derived from client_test.c: test_ps_conj_select()
+# for BUG#3420: select returned all rows of the table
+--disable_warnings
+drop table if exists new_tab ;
+--enable_warnings
+create table new_tab (id1 int(11) not null default '0',
+ value2 varchar(100), value1 varchar(100)) ;
+insert into new_tab values (1,'hh','hh'),(2,'hh','hh'),
+ (1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from new_tab where id1=? or value1=? ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+drop table new_tab ;
+# case derived from client_test.c: test_bug1180()
+# for BUG#1180 optimized away part of WHERE clause
+--disable_warnings
+drop table if exists new_tab ;
+--enable_warnings
+create table new_tab(session_id char(9) not null) ;
+insert into new_tab values ('abc') ;
+prepare stmt1 from ' select * from new_tab
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+drop table new_tab ;
+
+
+##### parameter used for keyword FROM (must fail)
+set @arg00='FROM' ;
+--error 1064
+select a @arg00 t1 where a=1 ;
+--error 1064
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+##### parameter used for tablename (must fail)
+set @arg00='t1' ;
+--error 1064
+select a from @arg00 where a=1 ;
+--error 1064
+prepare stmt1 from ' select a from ? where a=1 ' ;
+##### parameter used for keyword WHERE tablename (must fail)
+set @arg00='WHERE' ;
+--error 1064
+select a from t1 @arg00 a=1 ;
+--error 1064
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+
+##### parameter used in where clause
+# parameter is not NULL
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+set @arg00=1000 ;
+# row not found
+execute stmt1 using @arg00 ;
+# parameter is NULL
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+# parameter is not NULL within a function
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+# parameter is NULL within a function
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+# parameter in IN
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01);
+prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+execute stmt1 using @arg00, @arg01;
+# parameter in LIKE
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+
+##### parameter used for operator in WHERE clause (must fail)
+set @arg00='>' ;
+--error 1064
+select a FROM t1 where a @arg00 1 ;
+--error 1064
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+
+##### parameter used in group by clause
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+
+##### parameter used in having clause
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 ;
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? ' ;
+execute stmt1 using @arg00 ;
+
+##### parameter used in order clause
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+## What is the semantic of a single parameter (integer >0)
+# after order by? column number or constant
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+
+##### parameter used in limit clause
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1
+limit 1 ';
+execute stmt1 ;
+# currently (May 2004, Version 4.1) it is impossible
+-- error 1064
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+
+##### parameter used in many places
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+
+
+--disable_query_log
+select '------ join tests ------' as test_sequence ;
+--enable_query_log
+
+# no parameter
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a ;
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a ';
+execute stmt1 ;
+
+# some parameters
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02;
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ? ';
+execute stmt1 using @arg00, @arg01, @arg02;
+
+
+
+--disable_query_log
+select '------ subquery tests ------' as test_sequence ;
+--enable_query_log
+
+# no parameter
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+
+###### parameter in the outer part
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+###### parameter in the inner part
+set @arg00='two' ;
+# Bug#4000 (only BDB tables)
+select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = @arg00 ) and b='two' ;
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+
+###### parameters in the both parts
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+# Bug#4000 (only BDB tables)
+select a, @arg00, b FROM t1 outer_table where
+ b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+
+######## correlated subquery
+# no parameter
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) ';
+# also Bug#4000 (only BDB tables) ??
+execute stmt1 ;
+
+###### parameter in the outer part
+set @arg00='two' ;
+# Bug#4000 (only BDB tables)
+select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+# also Bug#4000 (only BDB tables) ??
+execute stmt1 using @arg00;
+
+###### parameter in the inner part
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+
+###### parameters in the both parts
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+# Bug#4000 (only BDB tables)
+select a, @arg00, b FROM t1 outer_table where
+ b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+ and outer_table.a=a ) ;
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+# also Bug#4000 (only BDB tables) ??
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+
+###### subquery after from
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+
+###### heavy modified case derived from client_test.c: test_distinct()
+## no parameters
+--disable_warnings
+drop table if exists t2 ;
+--enable_warnings
+create table t2 as select * from t_many_col_types;
+#insert into t2 select * from t_many_col_types;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t_many_col_types.c2 - 0e-3) = t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t_many_col_types.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+--enable_metadata
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+--disable_metadata
+execute stmt1 ;
+set @stmt= concat('explain ',@stmt);
+--enable_metadata
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+--disable_metadata
+execute stmt1 ;
+## many parameters
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t_many_col_types.c2-?)=t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t_many_col_types.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+--enable_metadata
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+ @arg07, @arg08, @arg09 ;
+--disable_metadata
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+ @arg07, @arg08, @arg09 ;
+set @stmt= concat('explain ',@stmt);
+--enable_metadata
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+ @arg07, @arg08, @arg09 ;
+--disable_metadata
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+ @arg07, @arg08, @arg09 ;
+drop table t2 ;
+
+
+--disable_query_log
+select '------ union tests ------' as test_sequence ;
+--enable_query_log
+
+# no parameter
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+# Bug#3577: the second execute crashes mysqld
+execute stmt1 ;
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+
+##### everything in the first table
+# one parameter as constant in the first table
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+
+##### everything in the second table
+# one parameter as constant
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+
+# one parameter in every table
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+# BUG#3811 wrong result, prepared statement, union,
+# parameter in result column list
+execute stmt1 using @arg00, @arg00;
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+
+# many parameters
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+
+## increased complexity
+
+set @arg00=1 ;
+# Bug#3686 the wrong server response was 1140 Mixing of GROUP columns ..
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+
+## union + group by
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+
+
+## union + where + group by
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+
+## union + where + group by + having
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+
+
+--disable_query_log
+select '------ explain select tests ------' as test_sequence ;
+--enable_query_log
+prepare stmt1 from ' select * from t_many_col_types ' ;
+--enable_metadata
+execute stmt1;
+--disable_metadata
+
+
diff --git a/mysql-test/include/ps_renew.inc b/mysql-test/include/ps_renew.inc
new file mode 100644
index 00000000000..1441638f257
--- /dev/null
+++ b/mysql-test/include/ps_renew.inc
@@ -0,0 +1,34 @@
+################ include/ps_renew.inc #################
+# #
+# renew the content of t1 and t_many_col_types #
+# #
+#######################################################
+
+# truncate could not be used, because it is not supported
+# in tables of type MERGE
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+ c10= 1, c11= 1, c12 = 1,
+ c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+ c16= '11:11:11', c17= '2004',
+ c18= 1, c19=true, c20= 'a', c21= '123456789a',
+ c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+ c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+ c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+ c10= 9, c11= 9, c12 = 9,
+ c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+ c16= '11:11:11', c17= '2004',
+ c18= 1, c19=false, c20= 'a', c21= '123456789a',
+ c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+ c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+ c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
diff --git a/mysql-test/misc/kill_master.sh b/mysql-test/misc/kill_master.sh
new file mode 100644
index 00000000000..7938c9d3ac2
--- /dev/null
+++ b/mysql-test/misc/kill_master.sh
@@ -0,0 +1,4 @@
+kill -9 `cat var/run/master.pid`
+# The kill may fail if process has already gone away,
+# so don't use the exit code of the kill. Use 0.
+exit 0
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 2d189d1b10b..52938c8a2ee 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -16,6 +16,7 @@ USE_MANAGER=0
MY_TZ=GMT-3
TZ=$MY_TZ; export TZ # for UNIX_TIMESTAMP tests to work
LOCAL_SOCKET=@MYSQL_UNIX_ADDR@
+MYSQL_TCP_PORT=@MYSQL_TCP_PORT@
# For query_cache test
case `uname` in
@@ -201,6 +202,7 @@ MASTER_MYPORT=9306
SLAVE_RUNNING=0
SLAVE_MYPORT=9307
MYSQL_MANAGER_PORT=9305 # needs to be out of the way of slaves
+NDBCLUSTER_PORT=9350
MYSQL_MANAGER_PW_FILE=$MYSQL_TEST_DIR/var/tmp/manager.pwd
MYSQL_MANAGER_LOG=$MYSQL_TEST_DIR/var/log/manager.log
MYSQL_MANAGER_USER=root
@@ -257,6 +259,7 @@ while test $# -gt 0; do
--master_port=*) MASTER_MYPORT=`$ECHO "$1" | $SED -e "s;--master_port=;;"` ;;
--slave_port=*) SLAVE_MYPORT=`$ECHO "$1" | $SED -e "s;--slave_port=;;"` ;;
--manager-port=*) MYSQL_MANAGER_PORT=`$ECHO "$1" | $SED -e "s;--manager_port=;;"` ;;
+ --ndbcluster_port=*) NDBCLUSTER_PORT=`$ECHO "$1" | $SED -e "s;--ndbcluster_port=;;"` ;;
--with-openssl)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
--ssl-ca=$BASEDIR/SSL/cacert.pem \
@@ -433,7 +436,7 @@ SLAVE_MYERR="$MYSQL_TEST_DIR/var/log/slave.err"
CURRENT_TEST="$MYSQL_TEST_DIR/var/log/current_test"
SMALL_SERVER="--key_buffer_size=1M --sort_buffer=256K --max_heap_table_size=1M"
-export MASTER_MYPORT SLAVE_MYPORT
+export MASTER_MYPORT SLAVE_MYPORT MYSQL_TCP_PORT
if [ x$SOURCE_DIST = x1 ] ; then
MY_BASEDIR=$MYSQL_TEST_DIR
@@ -688,7 +691,7 @@ report_stats () {
#
$RM -f $MY_LOG_DIR/warnings $MY_LOG_DIR/warnings.tmp
# Remove some non fatal warnings from the log files
- $SED -e 's!Warning: Table:.* on delete!!g' \
+ $SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' \
$MY_LOG_DIR/*.err \
| $SED -e 's!Warning: Table:.* on rename!!g' \
> $MY_LOG_DIR/warnings.tmp
@@ -881,8 +884,12 @@ start_master()
if [ x$MASTER_RUNNING = x1 ] || [ x$LOCAL_MASTER = x1 ] ; then
return
fi
- # Remove stale binary logs
- $RM -f $MYSQL_TEST_DIR/var/log/master-bin.*
+ # Remove stale binary logs except for 2 tests which need them
+ if [ "$tname" != "rpl_crash_binlog_ib_1b" ] && [ "$tname" != "rpl_crash_binlog_ib_2b" ] && [ "$tname" != "rpl_crash_binlog_ib_3b" ]
+ then
+ $RM -f $MYSQL_TEST_DIR/var/log/master-bin.*
+ fi
+
# Remove old master.info and relay-log.info files
$RM -f $MYSQL_TEST_DIR/var/master-data/master.info $MYSQL_TEST_DIR/var/master-data/relay-log.info
@@ -1004,8 +1011,12 @@ start_slave()
slave_sock="$SLAVE_MYSOCK"
fi
# Remove stale binary logs and old master.info files
- $RM -f $MYSQL_TEST_DIR/var/log/$slave_ident-*bin.*
- $RM -f $slave_datadir/master.info $slave_datadir/relay-log.info
+ # except for too tests which need them
+ if [ "$tname" != "rpl_crash_binlog_ib_1b" ] && [ "$tname" != "rpl_crash_binlog_ib_2b" ] && [ "$tname" != "rpl_crash_binlog_ib_3b" ]
+ then
+ $RM -f $MYSQL_TEST_DIR/var/log/$slave_ident-*bin.*
+ $RM -f $slave_datadir/master.info $slave_datadir/relay-log.info
+ fi
#run slave initialization shell script if one exists
if [ -f "$slave_init_script" ] ;
@@ -1417,7 +1428,7 @@ then
if [ -z "$USE_RUNNING_NDBCLUSTER" ]
then
# Kill any running ndbcluster stuff
- ./ndb/stop_ndbcluster
+ ./ndb/ndbcluster --port-base=$NDBCLUSTER_PORT --stop
fi
fi
@@ -1438,7 +1449,7 @@ then
if [ -z "$USE_RUNNING_NDBCLUSTER" ]
then
echo "Starting ndbcluster"
- ./ndb/install_ndbcluster --initial --data-dir=$MYSQL_TEST_DIR/var || exit 1
+ ./ndb/ndbcluster --port-base=$NDBCLUSTER_PORT --small --discless --initial --data-dir=$MYSQL_TEST_DIR/var || exit 1
export NDB_CONNECTSTRING=`cat Ndb.cfg`
else
export NDB_CONNECTSTRING="$USE_RUNNING_NDBCLUSTER"
@@ -1470,16 +1481,23 @@ $ECHO "Starting Tests"
#
if [ "$DO_BENCH" = 1 ]
then
+ start_master
+
+ if [ ! -z "$USE_NDBCLUSTER" ]
+ then
+ EXTRA_BENCH_ARGS="--create-options=TYPE=ndb"
+ fi
+
BENCHDIR=$BASEDIR/sql-bench/
savedir=`pwd`
cd $BENCHDIR
if [ -z "$1" ]
then
- ./run-all-tests --socket=$MASTER_MYSOCK --user=root
+ ./run-all-tests --socket=$MASTER_MYSOCK --user=root $EXTRA_BENCH_ARGS
else
if [ -x "./$1" ]
then
- ./$1 --socket=$MASTER_MYSOCK --user=root
+ ./$1 --socket=$MASTER_MYSOCK --user=root $EXTRA_BENCH_ARGS
else
echo "benchmark $1 not found"
fi
@@ -1531,7 +1549,7 @@ then
if [ -z "$USE_RUNNING_NDBCLUSTER" ]
then
# Kill any running ndbcluster stuff
- ./ndb/stop_ndbcluster
+ ./ndb/ndbcluster --port-base=$NDBCLUSTER_PORT --stop
fi
fi
diff --git a/mysql-test/ndb/Makefile.am b/mysql-test/ndb/Makefile.am
new file mode 100644
index 00000000000..3ed222344a6
--- /dev/null
+++ b/mysql-test/ndb/Makefile.am
@@ -0,0 +1,23 @@
+
+benchdir_root= $(prefix)
+testdir = $(benchdir_root)/mysql-test/ndb
+
+test_SCRIPTS = ndbcluster
+
+noinst_HEADERS = ndbcluster.sh
+
+dist_test_DATA = ndb_config_2_node.ini
+
+SUFFIXES = .sh
+
+.sh:
+ @RM@ -f $@ $@-t
+ @SED@ \
+ -e 's!@''ndbbindir''@!$(ndbbindir)!g' \
+ -e 's!@''ndbtoolsdir''@!$(ndbtoolsdir)!g' \
+ $< > $@-t
+ @CHMOD@ +x $@-t
+ @MV@ $@-t $@
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/mysql-test/ndb/install_ndbcluster b/mysql-test/ndb/install_ndbcluster
deleted file mode 100755
index 6cb3985b831..00000000000
--- a/mysql-test/ndb/install_ndbcluster
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/bin/sh
-# Copyright (C) 2004 MySQL AB
-# For a more info consult the file COPYRIGHT distributed with this file
-
-# This scripts starts the table handler ndbcluster
-
-# configurable parameters, make sure to change in mysqlcluterd as well
-port_base="22" # using ports port_base{"00","01", etc}
-fsdir=`pwd`
-# end configurable parameters
-
-libdir=`pwd`/../ndb/lib
-bindir=`pwd`/../ndb/bin
-
-pidfile=ndbcluster.pid
-
-while test $# -gt 0; do
- case "$1" in
- --initial)
- flags_ndb=$flags_ndb" -i"
- initial_ndb=1
- ;;
- --data-dir=*)
- fsdir=`echo "$1" | sed -e "s;--data-dir=;;"`
- ;;
- --port-base=*)
- port_base=`echo "$1" | sed -e "s;--port-base=;;"`
- ;;
- -- ) shift; break ;;
- --* ) $ECHO "Unrecognized option: $1"; exit 1 ;;
- * ) break ;;
- esac
- shift
-done
-
-exec_ndb=$bindir/ndb
-exec_mgmtsrvr=$bindir/mgmtsrvr
-fs_ndb=$fsdir/ndbcluster
-fs_mgm_1=$fs_ndb/1.ndb_mgm
-fs_ndb_2=$fs_ndb/2.ndb_db
-fs_ndb_3=$fs_ndb/3.ndb_db
-fs_name_2=$fs_ndb/node-2-fs
-fs_name_3=$fs_ndb/node-3-fs
-
-NDB_HOME=
-export NDB_CONNECTSTRING
-if [ ! -x $fsdir ]; then
- echo "$fsdir missing"
- exit 1
-fi
-if [ ! -x $exec_ndb ]; then
- echo "$exec_ndb missing"
- exit 1
-fi
-if [ ! -x $exec_mgmtsrv ]; then
- echo "$exec_mgmtsrvr missing"
- exit 1
-fi
-
-start_default_ndbcluster() {
-
-# do some checks
-
-NDB_CONNECTSTRING=
-
-if [ $initial_ndb ] ; then
- [ -d $fs_ndb ] || mkdir $fs_ndb
- [ -d $fs_mgm_1 ] || mkdir $fs_mgm_1
- [ -d $fs_ndb_2 ] || mkdir $fs_ndb_2
- [ -d $fs_ndb_3 ] || mkdir $fs_ndb_3
- [ -d $fs_name_2 ] || mkdir $fs_name_2
- [ -d $fs_name_3 ] || mkdir $fs_name_3
-fi
-if [ -d "$fs_ndb" -a -d "$fs_mgm_1" -a -d "$fs_ndb_2" -a -d "$fs_ndb_3" -a -d "$fs_name_2" -a -d "$fs_name_3" ]; then :; else
- echo "$fs_ndb filesystem directory does not exist"
- exit 1
-fi
-
-# set som help variables
-
-ndb_host="localhost"
-ndb_port=$port_base"00"
-NDB_CONNECTSTRING_BASE="host=$ndb_host:$ndb_port;nodeid="
-
-
-# Start management server as deamon
-
-NDB_ID="1"
-NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
-
-# Edit file system path and ports in config file
-
-if [ $initial_ndb ] ; then
-sed \
- -e s,"CHOOSE_HOSTNAME_".*,"$ndb_host",g \
- -e s,"CHOOSE_FILESYSTEM_NODE_2","$fs_name_2",g \
- -e s,"CHOOSE_FILESYSTEM_NODE_3","$fs_name_3",g \
- -e s,"CHOOSE_PORT_BASE",$port_base,g \
- < ndb/ndb_config_2_node.ini \
- > "$fs_mgm_1/config.ini"
-fi
-
-if ( cd $fs_mgm_1 ; echo $NDB_CONNECTSTRING > Ndb.cfg ; $exec_mgmtsrvr -d -c config.ini ) ; then :; else
- echo "Unable to start $exec_mgmtsrvr from `pwd`"
- exit 1
-fi
-
-cat `find $fs_ndb -name 'node*.pid'` > $pidfile
-
-# Start database node
-
-NDB_ID="2"
-NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
-( cd $fs_ndb_2 ; echo $NDB_CONNECTSTRING > Ndb.cfg ; $exec_ndb -d $flags_ndb & )
-
-cat `find $fs_ndb -name 'node*.pid'` > $pidfile
-
-# Start database node
-
-NDB_ID="3"
-NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
-( cd $fs_ndb_3 ; echo $NDB_CONNECTSTRING > Ndb.cfg ; $exec_ndb -d $flags_ndb & )
-
-cat `find $fs_ndb -name 'node*.pid'` > $pidfile
-
-# Start management client
-
-sleep 5
-echo "show" | $bindir/mgmtclient $ndb_host $ndb_port
-
-# test if Ndb Cluster starts properly
-
-NDB_ID="11"
-NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
-#if ( export LD_LIBRARY_PATH=$libdir ; $bindir/list_tables ) | grep "NDBT_ProgramExit: 0 - OK"; then :; else
-if ( export LD_LIBRARY_PATH=$libdir ; $bindir/waiter ) | grep "NDBT_ProgramExit: 0 - OK"; then :; else
- echo "Ndbcluster startup failed"
- exit 1
-fi
-
-echo $NDB_CONNECTSTRING > Ndb.cfg
-
-cat `find $fs_ndb -name 'node*.pid'` > $pidfile
-}
-
-start_default_ndbcluster
-
-exit 0
diff --git a/mysql-test/ndb/ndb_config_2_node.ini b/mysql-test/ndb/ndb_config_2_node.ini
index 9e0f8254c78..82c65c98866 100644
--- a/mysql-test/ndb/ndb_config_2_node.ini
+++ b/mysql-test/ndb/ndb_config_2_node.ini
@@ -1,7 +1,9 @@
[DB DEFAULT]
-#NoOfFragmentLogfiles: 1
-#TimeBetweenLocalCheckpoints: 31
NoOfReplicas: 2
+MaxNoOfConcurrentOperations: CHOOSE_MaxNoOfConcurrentOperations
+DataMemory: CHOOSE_DataMemory
+IndexMemory: CHOOSE_IndexMemory
+Discless: CHOOSE_Discless
[COMPUTER]
Id: 1
@@ -41,9 +43,7 @@ HostName: CHOOSE_HOSTNAME_7
[MGM]
Id: 1
ExecuteOnComputer: 1
-PortNumber: CHOOSE_PORT_BASE00
-PortNumberStats: CHOOSE_PORT_BASE01
-
+PortNumber: CHOOSE_PORT_MGM
[DB]
Id: 2
@@ -71,63 +71,5 @@ ExecuteOnComputer: 6
Id: 14
ExecuteOnComputer: 7
-# Mgmtsrvr connections
-
-[TCP]
-NodeId1: 1
-NodeId2: 2
-PortNumber: CHOOSE_PORT_BASE02
-
-[TCP]
-NodeId1: 1
-NodeId2: 3
-PortNumber: CHOOSE_PORT_BASE03
-
-# Ndb nodes connections
-
-[TCP]
-NodeId1: 2
-NodeId2: 3
-PortNumber: CHOOSE_PORT_BASE04
-
-# Api connections
-
-[TCP]
-NodeId1: 11
-NodeId2: 2
-PortNumber: CHOOSE_PORT_BASE05
-
-[TCP]
-NodeId1: 11
-NodeId2: 3
-PortNumber: CHOOSE_PORT_BASE06
-
-[TCP]
-NodeId1: 12
-NodeId2: 2
-PortNumber: CHOOSE_PORT_BASE07
-
-[TCP]
-NodeId1: 12
-NodeId2: 3
-PortNumber: CHOOSE_PORT_BASE08
-
-[TCP]
-NodeId1: 13
-NodeId2: 2
-PortNumber: CHOOSE_PORT_BASE09
-
-[TCP]
-NodeId1: 13
-NodeId2: 3
-PortNumber: CHOOSE_PORT_BASE10
-
-[TCP]
-NodeId1: 14
-NodeId2: 2
-PortNumber: CHOOSE_PORT_BASE11
-
-[TCP]
-NodeId1: 14
-NodeId2: 3
-PortNumber: CHOOSE_PORT_BASE12
+[TCP DEFAULT]
+PortNumber: CHOOSE_PORT_TRANSPORTER
diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh
new file mode 100644
index 00000000000..e51f6f6b076
--- /dev/null
+++ b/mysql-test/ndb/ndbcluster.sh
@@ -0,0 +1,244 @@
+#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+# For a more info consult the file COPYRIGHT distributed with this file
+
+# This scripts starts the table handler ndbcluster
+
+# configurable parameters, make sure to change in mysqlcluterd as well
+port_base="2200"
+fsdir=`pwd`
+# end configurable parameters
+
+#BASEDIR is always one above mysql-test directory
+CWD=`pwd`
+cd ..
+BASEDIR=`pwd`
+cd $CWD
+
+# Are we using a source or a binary distribution?
+if [ -d ../sql ] ; then
+ SOURCE_DIST=1
+ ndbtop=$BASEDIR/ndb
+ exec_ndb=$ndbtop/src/kernel/ndbd
+ exec_mgmtsrvr=$ndbtop/src/mgmsrv/ndb_mgmd
+ exec_waiter=$ndbtop/tools/ndb_waiter
+ exec_mgmtclient=$ndbtop/src/mgmclient/ndb_mgm
+else
+ BINARY_DIST=1
+ if test -x "$BASEDIR/libexec/ndbd"
+ then
+ exec_ndb=$BASEDIR/libexec/ndbd
+ exec_mgmtsrvr=$BASEDIR/libexec/ndb_mgmd
+ else
+ exec_ndb=$BASEDIR/bin/ndbd
+ exec_mgmtsrvr=$BASEDIR/bin/ndb_mgmd
+ fi
+ exec_waiter=$BASEDIR/bin/ndb_waiter
+ exec_mgmtclient=$BASEDIR/bin/ndb_mgm
+fi
+
+pidfile=ndbcluster.pid
+cfgfile=Ndb.cfg
+stop_ndb=
+initial_ndb=
+status_ndb=
+ndb_discless=0
+
+ndb_con_op=100000
+ndb_dmem=80M
+ndb_imem=24M
+
+while test $# -gt 0; do
+ case "$1" in
+ --stop)
+ stop_ndb=1
+ ;;
+ --initial)
+ flags_ndb=$flags_ndb" -i"
+ initial_ndb=1
+ ;;
+ --status)
+ status_ndb=1
+ ;;
+ --small)
+ ndb_con_op=10000
+ ndb_dmem=40M
+ ndb_imem=12M
+ ;;
+ --discless)
+ ndb_discless=1
+ ;;
+ --data-dir=*)
+ fsdir=`echo "$1" | sed -e "s;--data-dir=;;"`
+ ;;
+ --port-base=*)
+ port_base=`echo "$1" | sed -e "s;--port-base=;;"`
+ ;;
+ -- ) shift; break ;;
+ --* ) $ECHO "Unrecognized option: $1"; exit 1 ;;
+ * ) break ;;
+ esac
+ shift
+done
+
+fs_ndb=$fsdir/ndbcluster
+fs_mgm_1=$fs_ndb/1.ndb_mgm
+fs_ndb_2=$fs_ndb/2.ndb_db
+fs_ndb_3=$fs_ndb/3.ndb_db
+fs_name_2=$fs_ndb/node-2-fs-$port_base
+fs_name_3=$fs_ndb/node-3-fs-$port_base
+
+NDB_HOME=
+export NDB_CONNECTSTRING
+if [ ! -x $fsdir ]; then
+ echo "$fsdir missing"
+ exit 1
+fi
+if [ ! -x $exec_ndb ]; then
+ echo "$exec_ndb missing"
+ exit 1
+fi
+if [ ! -x $exec_mgmtsrv ]; then
+ echo "$exec_mgmtsrvr missing"
+ exit 1
+fi
+
+start_default_ndbcluster() {
+
+# do some checks
+
+NDB_CONNECTSTRING=
+
+if [ $initial_ndb ] ; then
+ [ -d $fs_ndb ] || mkdir $fs_ndb
+ [ -d $fs_mgm_1 ] || mkdir $fs_mgm_1
+ [ -d $fs_ndb_2 ] || mkdir $fs_ndb_2
+ [ -d $fs_ndb_3 ] || mkdir $fs_ndb_3
+ [ -d $fs_name_2 ] || mkdir $fs_name_2
+ [ -d $fs_name_3 ] || mkdir $fs_name_3
+fi
+if [ -d "$fs_ndb" -a -d "$fs_mgm_1" -a -d "$fs_ndb_2" -a -d "$fs_ndb_3" -a -d "$fs_name_2" -a -d "$fs_name_3" ]; then :; else
+ echo "$fs_ndb filesystem directory does not exist"
+ exit 1
+fi
+
+# set som help variables
+
+ndb_host="localhost"
+ndb_mgmd_port=$port_base
+port_transporter=`expr $ndb_mgmd_port + 2`
+NDB_CONNECTSTRING_BASE="host=$ndb_host:$ndb_mgmd_port;nodeid="
+
+
+# Start management server as deamon
+
+NDB_ID="1"
+NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
+
+# Edit file system path and ports in config file
+
+if [ $initial_ndb ] ; then
+sed \
+ -e s,"CHOOSE_MaxNoOfConcurrentOperations",$ndb_con_op,g \
+ -e s,"CHOOSE_DataMemory",$ndb_dmem,g \
+ -e s,"CHOOSE_IndexMemory",$ndb_imem,g \
+ -e s,"CHOOSE_Discless",$ndb_discless,g \
+ -e s,"CHOOSE_HOSTNAME_".*,"$ndb_host",g \
+ -e s,"CHOOSE_FILESYSTEM_NODE_2","$fs_name_2",g \
+ -e s,"CHOOSE_FILESYSTEM_NODE_3","$fs_name_3",g \
+ -e s,"CHOOSE_PORT_MGM",$ndb_mgmd_port,g \
+ -e s,"CHOOSE_PORT_TRANSPORTER",$port_transporter,g \
+ < ndb/ndb_config_2_node.ini \
+ > "$fs_mgm_1/config.ini"
+fi
+
+if ( cd $fs_mgm_1 ; echo $NDB_CONNECTSTRING > $cfgfile ; $exec_mgmtsrvr -d -c config.ini ) ; then :; else
+ echo "Unable to start $exec_mgmtsrvr from `pwd`"
+ exit 1
+fi
+
+cat `find $fs_ndb -name 'node*.pid'` > $pidfile
+
+# Start database node
+
+NDB_ID="2"
+NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
+echo "Starting ndbd connectstring=\""$NDB_CONNECTSTRING\"
+( cd $fs_ndb_2 ; echo $NDB_CONNECTSTRING > $cfgfile ; $exec_ndb -d $flags_ndb & )
+
+cat `find $fs_ndb -name 'node*.pid'` > $pidfile
+
+# Start database node
+
+NDB_ID="3"
+NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
+echo "Starting ndbd connectstring=\""$NDB_CONNECTSTRING\"
+( cd $fs_ndb_3 ; echo $NDB_CONNECTSTRING > $cfgfile ; $exec_ndb -d $flags_ndb & )
+
+cat `find $fs_ndb -name 'node*.pid'` > $pidfile
+
+# test if Ndb Cluster starts properly
+
+echo "Waiting for started..."
+NDB_ID="11"
+NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
+if ( $exec_waiter ) | grep "NDBT_ProgramExit: 0 - OK"; then :; else
+ echo "Ndbcluster startup failed"
+ exit 1
+fi
+
+echo $NDB_CONNECTSTRING > $cfgfile
+
+cat `find $fs_ndb -name 'node*.pid'` > $pidfile
+
+status_ndbcluster
+}
+
+status_ndbcluster() {
+# Start management client
+
+echo "show" | $exec_mgmtclient $ndb_host $ndb_mgmd_port
+}
+
+stop_default_ndbcluster() {
+
+#if [ ! -f $pidfile ] ; then
+# exit 0
+#fi
+
+if [ ! -f $cfgfile ] ; then
+ echo "$cfgfile missing"
+ exit 1
+fi
+
+ndb_host=`cat $cfgfile | sed -e "s,.*host=\(.*\)\:.*,\1,1"`
+ndb_mgmd_port=`cat $cfgfile | sed -e "s,.*host=$ndb_host\:\([0-9]*\).*,\1,1"`
+
+# Start management client
+
+exec_mgmtclient="$exec_mgmtclient --try-reconnect=1 $ndb_host $ndb_mgmd_port"
+
+echo "$exec_mgmtclient"
+echo "all stop" | $exec_mgmtclient
+
+sleep 5
+
+if [ -f $pidfile ] ; then
+ kill `cat $pidfile` 2> /dev/null
+ rm $pidfile
+fi
+
+}
+
+if [ $status_ndb ] ; then
+ status_ndbcluster
+ exit 0
+fi
+
+if [ $stop_ndb ] ; then
+ stop_default_ndbcluster
+else
+ start_default_ndbcluster
+fi
+
+exit 0
diff --git a/mysql-test/ndb/stop_ndbcluster b/mysql-test/ndb/stop_ndbcluster
deleted file mode 100755
index 09e22cf69c4..00000000000
--- a/mysql-test/ndb/stop_ndbcluster
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/sh
-# Copyright (C) 2004 MySQL AB
-# For a more info consult the file COPYRIGHT distributed with this file
-
-# This scripts stops the table handler ndbcluster
-
-bindir=`pwd`/../ndb/bin
-pidfile=ndbcluster.pid
-cfgfile=Ndb.cfg
-
-while test $# -gt 0; do
- case "$1" in
- --port-base=*)
- port_base=`echo "$1" | sed -e "s;--port-base=;;"`
- ;;
- -- ) shift; break ;;
- --* ) $ECHO "Unrecognized option: $1"; exit 1 ;;
- * ) break ;;
- esac
- shift
-done
-
-stop_default_ndbcluster() {
-
-if [ ! -f $pidfile ] ; then
- exit 0
-fi
-
-if [ ! -f $cfgfile ] ; then
- echo "$cfgfile missing"
- exit 1
-fi
-
-ndb_host=`cat $cfgfile | sed -e "s,.*host=\(.*\)\:.*,\1,1"`
-ndb_port=`cat $cfgfile | sed -e "s,.*host=$ndb_host\:\([0-9]*\).*,\1,1"`
-
-# Start management client
-
-exec_mgmtclient="$bindir/mgmtclient --try-reconnect=1 $ndb_host $ndb_port"
-
-echo "$exec_mgmtclient"
-echo "all stop" | $exec_mgmtclient
-
-sleep 5
-
-kill `cat $pidfile`
-rm $pidfile
-}
-
-stop_default_ndbcluster
-
-exit 0
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index a7c1dbde697..1441b3c3600 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -121,7 +121,7 @@ create database mysqltest;
create table mysqltest.t1 (a int,b int,c int);
grant all on mysqltest.t1 to mysqltest_1@localhost;
alter table t1 rename t2;
-ERROR 42000: insert command denied to user: 'mysqltest_1'@'localhost' for table 't2'
+ERROR 42000: insert command denied to user 'mysqltest_1'@'localhost' for table 't2'
revoke all privileges on mysqltest.t1 from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1';
drop database mysqltest;
@@ -468,5 +468,11 @@ t1 CREATE TABLE `t1` (
UNIQUE KEY `b` (`b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
ALTER TABLE t1 DROP PRIMARY KEY;
-ERROR 42000: Can't DROP 'PRIMARY'. Check that column/key exists
+ERROR 42000: Can't DROP 'PRIMARY'; check that column/key exists
DROP TABLE t1;
+create table t1 (a int, b int, key(a));
+insert into t1 values (1,1), (2,2);
+alter table t1 drop key no_such_key;
+ERROR 42000: Can't DROP 'no_such_key'; check that column/key exists
+alter table t1 drop key a;
+drop table t1;
diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result
new file mode 100644
index 00000000000..b380ea910de
--- /dev/null
+++ b/mysql-test/r/archive.result
@@ -0,0 +1,1396 @@
+drop table if exists t1,t2;
+CREATE TABLE t1 (
+Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
+Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
+) ENGINE=archive;
+INSERT INTO t1 VALUES (9410,9412);
+select period from t1;
+period
+9410
+select * from t1;
+Period Varor_period
+9410 9412
+select t1.* from t1;
+Period Varor_period
+9410 9412
+CREATE TABLE t2 (
+auto int,
+fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL,
+companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL,
+fld3 char(30) DEFAULT '' NOT NULL,
+fld4 char(35) DEFAULT '' NOT NULL,
+fld5 char(35) DEFAULT '' NOT NULL,
+fld6 char(4) DEFAULT '' NOT NULL
+) ENGINE=archive;
+select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%";
+fld3
+imaginable
+select fld3 from t2 where fld3 like "%cultivation" ;
+fld3
+cultivation
+select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3;
+fld3 companynr
+concoct 58
+druggists 58
+engrossing 58
+Eurydice 58
+exclaimers 58
+ferociousness 58
+hopelessness 58
+Huey 58
+imaginable 58
+judges 58
+merging 58
+ostrich 58
+peering 58
+Phelps 58
+presumes 58
+Ruth 58
+sentences 58
+Shylock 58
+straggled 58
+synergy 58
+thanking 58
+tying 58
+unlocks 58
+select fld3,companynr from t2 where companynr = 58 order by fld3;
+fld3 companynr
+concoct 58
+druggists 58
+engrossing 58
+Eurydice 58
+exclaimers 58
+ferociousness 58
+hopelessness 58
+Huey 58
+imaginable 58
+judges 58
+merging 58
+ostrich 58
+peering 58
+Phelps 58
+presumes 58
+Ruth 58
+sentences 58
+Shylock 58
+straggled 58
+synergy 58
+thanking 58
+tying 58
+unlocks 58
+select fld3 from t2 order by fld3 desc limit 10;
+fld3
+youthfulness
+yelped
+Wotan
+workers
+Witt
+witchcraft
+Winsett
+Willy
+willed
+wildcats
+select fld3 from t2 order by fld3 desc limit 5;
+fld3
+youthfulness
+yelped
+Wotan
+workers
+Witt
+select fld3 from t2 order by fld3 desc limit 5,5;
+fld3
+witchcraft
+Winsett
+Willy
+willed
+wildcats
+select t2.fld3 from t2 where fld3 = 'honeysuckle';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'h%le';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_';
+fld3
+select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%';
+fld3
+select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
+fld3
+honeysuckle
+honoring
+select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3;
+fld1 fld3
+148504 Colombo
+068305 Colombo
+000000 nondecreasing
+select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%';
+fld1 fld3
+012001 flanking
+013602 foldout
+013606 fingerings
+018007 fanatic
+018017 featherweight
+018054 fetters
+018103 flint
+018104 flopping
+036002 funereal
+038017 fetched
+038205 firearm
+058004 Fenton
+088303 feminine
+186002 freakish
+188007 flurried
+188505 fitting
+198006 furthermore
+202301 Fitzpatrick
+208101 fiftieth
+208113 freest
+218008 finishers
+218022 feed
+218401 faithful
+226205 foothill
+226209 furnishings
+228306 forthcoming
+228311 fated
+231315 freezes
+232102 forgivably
+238007 filial
+238008 fixedly
+select fld3 from t2 where fld3 like "L%" and fld3 = "ok";
+fld3
+select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly");
+fld3
+Chantilly
+select fld1,fld3 from t2 where fld1 like "25050%";
+fld1 fld3
+250501 poisoning
+250502 Iraqis
+250503 heaving
+250504 population
+250505 bomb
+select fld1,fld3 from t2 where fld1 like "25050_";
+fld1 fld3
+250501 poisoning
+250502 Iraqis
+250503 heaving
+250504 population
+250505 bomb
+INSERT INTO t2 VALUES (1,000001,00,'Omaha','teethe','neat','');
+INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W');
+INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring','');
+INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
+SELECT * FROM t2;
+auto fld1 companynr fld3 fld4 fld5 fld6
+1 000001 00 Omaha teethe neat
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+5 011501 37 bewilderingly wallet balled
+6 011701 37 astound parters persist W
+7 011702 37 admonishing eschew attainments
+8 011703 37 sumac quitter fanatic
+9 012001 37 flanking neat measures FAS
+10 012003 37 combed Steinberg rightfulness
+11 012004 37 subjective jarring capably
+12 012005 37 scatterbrain tinily impulsive
+13 012301 37 Eulerian balled starlet
+14 012302 36 dubbed persist terminators
+15 012303 37 Kane attainments untying
+16 012304 37 overlay fanatic announces FAS
+17 012305 37 perturb measures featherweight FAS
+18 012306 37 goblins rightfulness pessimist FAS
+19 012501 37 annihilates capably daughter
+20 012602 37 Wotan impulsive decliner FAS
+21 012603 37 snatching starlet lawgiver
+22 012604 37 concludes terminators stated
+23 012605 37 laterally untying readable
+24 012606 37 yelped announces attrition
+25 012701 37 grazing featherweight cascade FAS
+26 012702 37 Baird pessimist motors FAS
+27 012703 37 celery daughter interrogate
+28 012704 37 misunderstander decliner pests W
+29 013601 37 handgun lawgiver stairway
+30 013602 37 foldout stated dopers FAS
+31 013603 37 mystic readable testicle W
+32 013604 37 succumbed attrition Parsifal W
+33 013605 37 Nabisco cascade leavings
+34 013606 37 fingerings motors postulation W
+35 013607 37 aging interrogate squeaking
+36 013608 37 afield pests contrasted
+37 013609 37 ammonium stairway leftover
+38 013610 37 boat dopers whiteners
+39 013801 37 intelligibility testicle erases W
+40 013802 37 Augustine Parsifal Punjab W
+41 013803 37 teethe leavings Merritt
+42 013804 37 dreaded postulation Quixotism
+43 013901 37 scholastics squeaking sweetish FAS
+44 016001 37 audiology contrasted dogging FAS
+45 016201 37 wallet leftover scornfully FAS
+46 016202 37 parters whiteners bellow
+47 016301 37 eschew erases bills
+48 016302 37 quitter Punjab cupboard FAS
+49 016303 37 neat Merritt sureties FAS
+50 016304 37 Steinberg Quixotism puddings
+51 018001 37 jarring sweetish tapestry
+52 018002 37 tinily dogging fetters
+53 018003 37 balled scornfully bivalves
+54 018004 37 persist bellow incurring
+55 018005 37 attainments bills Adolph
+56 018007 37 fanatic cupboard pithed
+57 018008 37 measures sureties emergency
+58 018009 37 rightfulness puddings Miles
+59 018010 37 capably tapestry trimmings
+60 018012 37 impulsive fetters tragedies W
+61 018013 37 starlet bivalves skulking W
+62 018014 37 terminators incurring flint
+63 018015 37 untying Adolph flopping W
+64 018016 37 announces pithed relaxing FAS
+65 018017 37 featherweight emergency offload FAS
+66 018018 37 pessimist Miles suites W
+67 018019 37 daughter trimmings lists FAS
+68 018020 37 decliner tragedies animized FAS
+69 018021 37 lawgiver skulking multilayer W
+70 018022 37 stated flint standardizes FAS
+71 018023 37 readable flopping Judas
+72 018024 37 attrition relaxing vacuuming W
+73 018025 37 cascade offload dentally W
+74 018026 37 motors suites humanness W
+75 018027 37 interrogate lists inch W
+76 018028 37 pests animized Weissmuller W
+77 018029 37 stairway multilayer irresponsibly W
+78 018030 37 dopers standardizes luckily FAS
+79 018032 37 testicle Judas culled W
+80 018033 37 Parsifal vacuuming medical FAS
+81 018034 37 leavings dentally bloodbath FAS
+82 018035 37 postulation humanness subschema W
+83 018036 37 squeaking inch animals W
+84 018037 37 contrasted Weissmuller Micronesia
+85 018038 37 leftover irresponsibly repetitions
+86 018039 37 whiteners luckily Antares
+87 018040 37 erases culled ventilate W
+88 018041 37 Punjab medical pityingly
+89 018042 37 Merritt bloodbath interdependent
+90 018043 37 Quixotism subschema Graves FAS
+91 018044 37 sweetish animals neonatal
+92 018045 37 dogging Micronesia scribbled FAS
+93 018046 37 scornfully repetitions chafe W
+94 018048 37 bellow Antares honoring
+95 018049 37 bills ventilate realtor
+96 018050 37 cupboard pityingly elite
+97 018051 37 sureties interdependent funereal
+98 018052 37 puddings Graves abrogating
+99 018053 50 tapestry neonatal sorters
+100 018054 37 fetters scribbled Conley
+101 018055 37 bivalves chafe lectured
+102 018056 37 incurring honoring Abraham
+103 018057 37 Adolph realtor Hawaii W
+104 018058 37 pithed elite cage
+105 018059 36 emergency funereal hushes
+106 018060 37 Miles abrogating Simla
+107 018061 37 trimmings sorters reporters
+108 018101 37 tragedies Conley Dutchman FAS
+109 018102 37 skulking lectured descendants FAS
+110 018103 37 flint Abraham groupings FAS
+111 018104 37 flopping Hawaii dissociate
+112 018201 37 relaxing cage coexist W
+113 018202 37 offload hushes Beebe
+114 018402 37 suites Simla Taoism
+115 018403 37 lists reporters Connally
+116 018404 37 animized Dutchman fetched FAS
+117 018405 37 multilayer descendants checkpoints FAS
+118 018406 37 standardizes groupings rusting
+119 018409 37 Judas dissociate galling
+120 018601 37 vacuuming coexist obliterates
+121 018602 37 dentally Beebe traitor
+122 018603 37 humanness Taoism resumes FAS
+123 018801 37 inch Connally analyzable FAS
+124 018802 37 Weissmuller fetched terminator FAS
+125 018803 37 irresponsibly checkpoints gritty FAS
+126 018804 37 luckily rusting firearm W
+127 018805 37 culled galling minima
+128 018806 37 medical obliterates Selfridge
+129 018807 37 bloodbath traitor disable
+130 018808 37 subschema resumes witchcraft W
+131 018809 37 animals analyzable betroth W
+132 018810 37 Micronesia terminator Manhattanize
+133 018811 37 repetitions gritty imprint
+134 018812 37 Antares firearm peeked
+135 019101 37 ventilate minima swelling
+136 019102 37 pityingly Selfridge interrelationships W
+137 019103 37 interdependent disable riser
+138 019201 37 Graves witchcraft Gandhian W
+139 030501 37 neonatal betroth peacock A
+140 030502 50 scribbled Manhattanize bee A
+141 030503 37 chafe imprint kanji
+142 030504 37 honoring peeked dental
+143 031901 37 realtor swelling scarf FAS
+144 036001 37 elite interrelationships chasm A
+145 036002 37 funereal riser insolence A
+146 036004 37 abrogating Gandhian syndicate
+147 036005 37 sorters peacock alike
+148 038001 37 Conley bee imperial A
+149 038002 37 lectured kanji convulsion A
+150 038003 37 Abraham dental railway A
+151 038004 37 Hawaii scarf validate A
+152 038005 37 cage chasm normalizes A
+153 038006 37 hushes insolence comprehensive
+154 038007 37 Simla syndicate chewing
+155 038008 37 reporters alike denizen
+156 038009 37 Dutchman imperial schemer
+157 038010 37 descendants convulsion chronicle
+158 038011 37 groupings railway Kline
+159 038012 37 dissociate validate Anatole
+160 038013 37 coexist normalizes partridges
+161 038014 37 Beebe comprehensive brunch
+162 038015 37 Taoism chewing recruited
+163 038016 37 Connally denizen dimensions W
+164 038017 37 fetched schemer Chicana W
+165 038018 37 checkpoints chronicle announced
+166 038101 37 rusting Kline praised FAS
+167 038102 37 galling Anatole employing
+168 038103 37 obliterates partridges linear
+169 038104 37 traitor brunch quagmire
+170 038201 37 resumes recruited western A
+171 038202 37 analyzable dimensions relishing
+172 038203 37 terminator Chicana serving A
+173 038204 37 gritty announced scheduling
+174 038205 37 firearm praised lore
+175 038206 37 minima employing eventful
+176 038208 37 Selfridge linear arteriole A
+177 042801 37 disable quagmire disentangle
+178 042802 37 witchcraft western cured A
+179 046101 37 betroth relishing Fenton W
+180 048001 37 Manhattanize serving avoidable A
+181 048002 37 imprint scheduling drains A
+182 048003 37 peeked lore detectably FAS
+183 048004 37 swelling eventful husky
+184 048005 37 interrelationships arteriole impelling
+185 048006 37 riser disentangle undoes
+186 048007 37 Gandhian cured evened
+187 048008 37 peacock Fenton squeezes
+188 048101 37 bee avoidable destroyer FAS
+189 048102 37 kanji drains rudeness
+190 048201 37 dental detectably beaner FAS
+191 048202 37 scarf husky boorish
+192 048203 37 chasm impelling Everhart
+193 048204 37 insolence undoes encompass A
+194 048205 37 syndicate evened mushrooms
+195 048301 37 alike squeezes Alison A
+196 048302 37 imperial destroyer externally FAS
+197 048303 37 convulsion rudeness pellagra
+198 048304 37 railway beaner cult
+199 048305 37 validate boorish creek A
+200 048401 37 normalizes Everhart Huffman
+201 048402 37 comprehensive encompass Majorca FAS
+202 048403 37 chewing mushrooms governing A
+203 048404 37 denizen Alison gadfly FAS
+204 048405 37 schemer externally reassigned FAS
+205 048406 37 chronicle pellagra intentness W
+206 048407 37 Kline cult craziness
+207 048408 37 Anatole creek psychic
+208 048409 37 partridges Huffman squabbled
+209 048410 37 brunch Majorca burlesque
+210 048411 37 recruited governing capped
+211 048412 37 dimensions gadfly extracted A
+212 048413 37 Chicana reassigned DiMaggio
+213 048601 37 announced intentness exclamation FAS
+214 048602 37 praised craziness subdirectory
+215 048603 37 employing psychic fangs
+216 048604 37 linear squabbled buyer A
+217 048801 37 quagmire burlesque pithing A
+218 050901 37 western capped transistorizing A
+219 051201 37 relishing extracted nonbiodegradable
+220 056002 37 serving DiMaggio dislocate
+221 056003 37 scheduling exclamation monochromatic FAS
+222 056004 37 lore subdirectory batting
+223 056102 37 eventful fangs postcondition A
+224 056203 37 arteriole buyer catalog FAS
+225 056204 37 disentangle pithing Remus
+226 058003 37 cured transistorizing devices A
+227 058004 37 Fenton nonbiodegradable bike A
+228 058005 37 avoidable dislocate qualify
+229 058006 37 drains monochromatic detained
+230 058007 37 detectably batting commended
+231 058101 37 husky postcondition civilize
+232 058102 37 impelling catalog Elmhurst
+233 058103 37 undoes Remus anesthetizing
+234 058105 37 evened devices deaf
+235 058111 37 squeezes bike Brigham
+236 058112 37 destroyer qualify title
+237 058113 37 rudeness detained coarse
+238 058114 37 beaner commended combinations
+239 058115 37 boorish civilize grayness
+240 058116 37 Everhart Elmhurst innumerable FAS
+241 058117 37 encompass anesthetizing Caroline A
+242 058118 37 mushrooms deaf fatty FAS
+243 058119 37 Alison Brigham eastbound
+244 058120 37 externally title inexperienced
+245 058121 37 pellagra coarse hoarder A
+246 058122 37 cult combinations scotch W
+247 058123 37 creek grayness passport A
+248 058124 37 Huffman innumerable strategic FAS
+249 058125 37 Majorca Caroline gated
+250 058126 37 governing fatty flog
+251 058127 37 gadfly eastbound Pipestone
+252 058128 37 reassigned inexperienced Dar
+253 058201 37 intentness hoarder Corcoran
+254 058202 37 craziness scotch flyers A
+255 058303 37 psychic passport competitions W
+256 058304 37 squabbled strategic suppliers FAS
+257 058602 37 burlesque gated skips
+258 058603 37 capped flog institutes
+259 058604 37 extracted Pipestone troop A
+260 058605 37 DiMaggio Dar connective W
+261 058606 37 exclamation Corcoran denies
+262 058607 37 subdirectory flyers polka
+263 060401 36 fangs competitions observations FAS
+264 061701 36 buyer suppliers askers
+265 066201 36 pithing skips homeless FAS
+266 066501 36 transistorizing institutes Anna
+267 068001 36 nonbiodegradable troop subdirectories W
+268 068002 36 dislocate connective decaying FAS
+269 068005 36 monochromatic denies outwitting W
+270 068006 36 batting polka Harpy W
+271 068007 36 postcondition observations crazed
+272 068008 36 catalog askers suffocate
+273 068009 36 Remus homeless provers FAS
+274 068010 36 devices Anna technically
+275 068011 36 bike subdirectories Franklinizations
+276 068202 36 qualify decaying considered
+277 068302 36 detained outwitting tinnily
+278 068303 36 commended Harpy uninterruptedly
+279 068401 36 civilize crazed whistled A
+280 068501 36 Elmhurst suffocate automate
+281 068502 36 anesthetizing provers gutting W
+282 068503 36 deaf technically surreptitious
+283 068602 36 Brigham Franklinizations Choctaw
+284 068603 36 title considered cooks
+285 068701 36 coarse tinnily millivolt FAS
+286 068702 36 combinations uninterruptedly counterpoise
+287 068703 36 grayness whistled Gothicism
+288 076001 36 innumerable automate feminine
+289 076002 36 Caroline gutting metaphysically W
+290 076101 36 fatty surreptitious sanding A
+291 076102 36 eastbound Choctaw contributorily
+292 076103 36 inexperienced cooks receivers FAS
+293 076302 36 hoarder millivolt adjourn
+294 076303 36 scotch counterpoise straggled A
+295 076304 36 passport Gothicism druggists
+296 076305 36 strategic feminine thanking FAS
+297 076306 36 gated metaphysically ostrich
+298 076307 36 flog sanding hopelessness FAS
+299 076402 36 Pipestone contributorily Eurydice
+300 076501 36 Dar receivers excitation W
+301 076502 36 Corcoran adjourn presumes FAS
+302 076701 36 flyers straggled imaginable FAS
+303 078001 36 competitions druggists concoct W
+304 078002 36 suppliers thanking peering W
+305 078003 36 skips ostrich Phelps FAS
+306 078004 36 institutes hopelessness ferociousness FAS
+307 078005 36 troop Eurydice sentences
+308 078006 36 connective excitation unlocks
+309 078007 36 denies presumes engrossing W
+310 078008 36 polka imaginable Ruth
+311 078101 36 observations concoct tying
+312 078103 36 askers peering exclaimers
+313 078104 36 homeless Phelps synergy
+314 078105 36 Anna ferociousness Huey W
+315 082101 36 subdirectories sentences merging
+316 083401 36 decaying unlocks judges A
+317 084001 36 outwitting engrossing Shylock W
+318 084002 36 Harpy Ruth Miltonism
+319 086001 36 crazed tying hen W
+320 086102 36 suffocate exclaimers honeybee FAS
+321 086201 36 provers synergy towers
+322 088001 36 technically Huey dilutes W
+323 088002 36 Franklinizations merging numerals FAS
+324 088003 36 considered judges democracy FAS
+325 088004 36 tinnily Shylock Ibero-
+326 088101 36 uninterruptedly Miltonism invalids
+327 088102 36 whistled hen behavior
+328 088103 36 automate honeybee accruing
+329 088104 36 gutting towers relics A
+330 088105 36 surreptitious dilutes rackets
+331 088106 36 Choctaw numerals Fischbein W
+332 088201 36 cooks democracy phony W
+333 088203 36 millivolt Ibero- cross FAS
+334 088204 36 counterpoise invalids cleanup
+335 088302 37 Gothicism behavior conspirator
+336 088303 37 feminine accruing label FAS
+337 088305 37 metaphysically relics university
+338 088402 37 sanding rackets cleansed FAS
+339 088501 36 contributorily Fischbein ballgown
+340 088502 36 receivers phony starlet
+341 088503 36 adjourn cross aqueous
+342 098001 58 straggled cleanup portrayal A
+343 098002 58 druggists conspirator despising W
+344 098003 58 thanking label distort W
+345 098004 58 ostrich university palmed
+346 098005 58 hopelessness cleansed faced
+347 098006 58 Eurydice ballgown silverware
+348 141903 29 excitation starlet assessor
+349 098008 58 presumes aqueous spiders
+350 098009 58 imaginable portrayal artificially
+351 098010 58 concoct despising reminiscence
+352 098011 58 peering distort Mexican
+353 098012 58 Phelps palmed obnoxious
+354 098013 58 ferociousness faced fragile
+355 098014 58 sentences silverware apprehensible
+356 098015 58 unlocks assessor births
+357 098016 58 engrossing spiders garages
+358 098017 58 Ruth artificially panty
+359 098018 58 tying reminiscence anteater
+360 098019 58 exclaimers Mexican displacement A
+361 098020 58 synergy obnoxious drovers A
+362 098021 58 Huey fragile patenting A
+363 098022 58 merging apprehensible far A
+364 098023 58 judges births shrieks
+365 098024 58 Shylock garages aligning W
+366 098025 37 Miltonism panty pragmatism
+367 106001 36 hen anteater fevers W
+368 108001 36 honeybee displacement reexamines A
+369 108002 36 towers drovers occupancies
+370 108003 36 dilutes patenting sweats FAS
+371 108004 36 numerals far modulators
+372 108005 36 democracy shrieks demand W
+373 108007 36 Ibero- aligning Madeira
+374 108008 36 invalids pragmatism Viennese W
+375 108009 36 behavior fevers chillier W
+376 108010 36 accruing reexamines wildcats FAS
+377 108011 36 relics occupancies gentle
+378 108012 36 rackets sweats Angles W
+379 108101 36 Fischbein modulators accuracies
+380 108102 36 phony demand toggle
+381 108103 36 cross Madeira Mendelssohn W
+382 108111 50 cleanup Viennese behaviorally
+383 108105 36 conspirator chillier Rochford
+384 108106 36 label wildcats mirror W
+385 108107 36 university gentle Modula
+386 108108 50 cleansed Angles clobbering
+387 108109 36 ballgown accuracies chronography
+388 108110 36 starlet toggle Eskimoizeds
+389 108201 36 aqueous Mendelssohn British W
+390 108202 36 portrayal behaviorally pitfalls
+391 108203 36 despising Rochford verify W
+392 108204 36 distort mirror scatter FAS
+393 108205 36 palmed Modula Aztecan
+394 108301 36 faced clobbering acuity W
+395 108302 36 silverware chronography sinking W
+396 112101 36 assessor Eskimoizeds beasts FAS
+397 112102 36 spiders British Witt W
+398 113701 36 artificially pitfalls physicists FAS
+399 116001 36 reminiscence verify folksong A
+400 116201 36 Mexican scatter strokes FAS
+401 116301 36 obnoxious Aztecan crowder
+402 116302 36 fragile acuity merry
+403 116601 36 apprehensible sinking cadenced
+404 116602 36 births beasts alimony A
+405 116603 36 garages Witt principled A
+406 116701 36 panty physicists golfing
+407 116702 36 anteater folksong undiscovered
+408 118001 36 displacement strokes irritates
+409 118002 36 drovers crowder patriots A
+410 118003 36 patenting merry rooms FAS
+411 118004 36 far cadenced towering W
+412 118005 36 shrieks alimony displease
+413 118006 36 aligning principled photosensitive
+414 118007 36 pragmatism golfing inking
+415 118008 36 fevers undiscovered gainers
+416 118101 36 reexamines irritates leaning A
+417 118102 36 occupancies patriots hydrant A
+418 118103 36 sweats rooms preserve
+419 118202 36 modulators towering blinded A
+420 118203 36 demand displease interactions A
+421 118204 36 Madeira photosensitive Barry
+422 118302 36 Viennese inking whiteness A
+423 118304 36 chillier gainers pastimes W
+424 118305 36 wildcats leaning Edenization
+425 118306 36 gentle hydrant Muscat
+426 118307 36 Angles preserve assassinated
+427 123101 36 accuracies blinded labeled
+428 123102 36 toggle interactions glacial A
+429 123301 36 Mendelssohn Barry implied W
+430 126001 36 behaviorally whiteness bibliographies W
+431 126002 36 Rochford pastimes Buchanan
+432 126003 36 mirror Edenization forgivably FAS
+433 126101 36 Modula Muscat innuendo A
+434 126301 36 clobbering assassinated den FAS
+435 126302 36 chronography labeled submarines W
+436 126402 36 Eskimoizeds glacial mouthful A
+437 126601 36 British implied expiring
+438 126602 36 pitfalls bibliographies unfulfilled FAS
+439 126702 36 verify Buchanan precession
+440 128001 36 scatter forgivably nullified
+441 128002 36 Aztecan innuendo affects
+442 128003 36 acuity den Cynthia
+443 128004 36 sinking submarines Chablis A
+444 128005 36 beasts mouthful betterments FAS
+445 128007 36 Witt expiring advertising
+446 128008 36 physicists unfulfilled rubies A
+447 128009 36 folksong precession southwest FAS
+448 128010 36 strokes nullified superstitious A
+449 128011 36 crowder affects tabernacle W
+450 128012 36 merry Cynthia silk A
+451 128013 36 cadenced Chablis handsomest A
+452 128014 36 alimony betterments Persian A
+453 128015 36 principled advertising analog W
+454 128016 36 golfing rubies complex W
+455 128017 36 undiscovered southwest Taoist
+456 128018 36 irritates superstitious suspend
+457 128019 36 patriots tabernacle relegated
+458 128020 36 rooms silk awesome W
+459 128021 36 towering handsomest Bruxelles
+460 128022 36 displease Persian imprecisely A
+461 128023 36 photosensitive analog televise
+462 128101 36 inking complex braking
+463 128102 36 gainers Taoist true FAS
+464 128103 36 leaning suspend disappointing FAS
+465 128104 36 hydrant relegated navally W
+466 128106 36 preserve awesome circus
+467 128107 36 blinded Bruxelles beetles
+468 128108 36 interactions imprecisely trumps
+469 128202 36 Barry televise fourscore W
+470 128203 36 whiteness braking Blackfoots
+471 128301 36 pastimes true Grady
+472 128302 36 Edenization disappointing quiets FAS
+473 128303 36 Muscat navally floundered FAS
+474 128304 36 assassinated circus profundity W
+475 128305 36 labeled beetles Garrisonian W
+476 128307 36 glacial trumps Strauss
+477 128401 36 implied fourscore cemented FAS
+478 128502 36 bibliographies Blackfoots contrition A
+479 128503 36 Buchanan Grady mutations
+480 128504 36 forgivably quiets exhibits W
+481 128505 36 innuendo floundered tits
+482 128601 36 den profundity mate A
+483 128603 36 submarines Garrisonian arches
+484 128604 36 mouthful Strauss Moll
+485 128702 36 expiring cemented ropers
+486 128703 36 unfulfilled contrition bombast
+487 128704 36 precession mutations difficultly A
+488 138001 36 nullified exhibits adsorption
+489 138002 36 affects tits definiteness FAS
+490 138003 36 Cynthia mate cultivation A
+491 138004 36 Chablis arches heals A
+492 138005 36 betterments Moll Heusen W
+493 138006 36 advertising ropers target FAS
+494 138007 36 rubies bombast cited A
+495 138008 36 southwest difficultly congresswoman W
+496 138009 36 superstitious adsorption Katherine
+497 138102 36 tabernacle definiteness titter A
+498 138103 36 silk cultivation aspire A
+499 138104 36 handsomest heals Mardis
+500 138105 36 Persian Heusen Nadia W
+501 138201 36 analog target estimating FAS
+502 138302 36 complex cited stuck A
+503 138303 36 Taoist congresswoman fifteenth A
+504 138304 36 suspend Katherine Colombo
+505 138401 29 relegated titter survey A
+506 140102 29 awesome aspire staffing
+507 140103 29 Bruxelles Mardis obtain
+508 140104 29 imprecisely Nadia loaded
+509 140105 29 televise estimating slaughtered
+510 140201 29 braking stuck lights A
+511 140701 29 true fifteenth circumference
+512 141501 29 disappointing Colombo dull A
+513 141502 29 navally survey weekly A
+514 141901 29 circus staffing wetness
+515 141902 29 beetles obtain visualized
+516 142101 29 trumps loaded Tannenbaum
+517 142102 29 fourscore slaughtered moribund
+518 142103 29 Blackfoots lights demultiplex
+519 142701 29 Grady circumference lockings
+520 143001 29 quiets dull thugs FAS
+521 143501 29 floundered weekly unnerves
+522 143502 29 profundity wetness abut
+523 148001 29 Garrisonian visualized Chippewa A
+524 148002 29 Strauss Tannenbaum stratifications A
+525 148003 29 cemented moribund signaled
+526 148004 29 contrition demultiplex Italianizes A
+527 148005 29 mutations lockings algorithmic A
+528 148006 29 exhibits thugs paranoid FAS
+529 148007 29 tits unnerves camping A
+530 148009 29 mate abut signifying A
+531 148010 29 arches Chippewa Patrice W
+532 148011 29 Moll stratifications search A
+533 148012 29 ropers signaled Angeles A
+534 148013 29 bombast Italianizes semblance
+535 148023 36 difficultly algorithmic taxed
+536 148015 29 adsorption paranoid Beatrice
+537 148016 29 definiteness camping retrace
+538 148017 29 cultivation signifying lockout
+539 148018 29 heals Patrice grammatic
+540 148019 29 Heusen search helmsman
+541 148020 29 target Angeles uniform W
+542 148021 29 cited semblance hamming
+543 148022 29 congresswoman taxed disobedience
+544 148101 29 Katherine Beatrice captivated A
+545 148102 29 titter retrace transferals A
+546 148201 29 aspire lockout cartographer A
+547 148401 29 Mardis grammatic aims FAS
+548 148402 29 Nadia helmsman Pakistani
+549 148501 29 estimating uniform burglarized FAS
+550 148502 29 stuck hamming saucepans A
+551 148503 29 fifteenth disobedience lacerating A
+552 148504 29 Colombo captivated corny
+553 148601 29 survey transferals megabytes FAS
+554 148602 29 staffing cartographer chancellor
+555 150701 29 obtain aims bulk A
+556 152101 29 loaded Pakistani commits A
+557 152102 29 slaughtered burglarized meson W
+558 155202 36 lights saucepans deputies
+559 155203 29 circumference lacerating northeaster A
+560 155204 29 dull corny dipole
+561 155205 29 weekly megabytes machining 0
+562 156001 29 wetness chancellor therefore
+563 156002 29 visualized bulk Telefunken
+564 156102 29 Tannenbaum commits salvaging
+565 156301 29 moribund meson Corinthianizes A
+566 156302 29 demultiplex deputies restlessly A
+567 156303 29 lockings northeaster bromides
+568 156304 29 thugs dipole generalized A
+569 156305 29 unnerves machining mishaps
+570 156306 29 abut therefore quelling
+571 156501 29 Chippewa Telefunken spiritual A
+572 158001 29 stratifications salvaging beguiles FAS
+573 158002 29 signaled Corinthianizes Trobriand FAS
+574 158101 29 Italianizes restlessly fleeing A
+575 158102 29 algorithmic bromides Armour A
+576 158103 29 paranoid generalized chin A
+577 158201 29 camping mishaps provers A
+578 158202 29 signifying quelling aeronautic A
+579 158203 29 Patrice spiritual voltage W
+580 158204 29 search beguiles sash
+581 158301 29 Angeles Trobriand anaerobic A
+582 158302 29 semblance fleeing simultaneous A
+583 158303 29 taxed Armour accumulating A
+584 158304 29 Beatrice chin Medusan A
+585 158305 29 retrace provers shouted A
+586 158306 29 lockout aeronautic freakish
+587 158501 29 grammatic voltage index FAS
+588 160301 29 helmsman sash commercially
+589 166101 50 uniform anaerobic mistiness A
+590 166102 50 hamming simultaneous endpoint
+591 168001 29 disobedience accumulating straight A
+592 168002 29 captivated Medusan flurried
+593 168003 29 transferals shouted denotative A
+594 168101 29 cartographer freakish coming FAS
+595 168102 29 aims index commencements FAS
+596 168103 29 Pakistani commercially gentleman
+597 168104 29 burglarized mistiness gifted
+598 168202 29 saucepans endpoint Shanghais
+599 168301 29 lacerating straight sportswriting A
+600 168502 29 corny flurried sloping A
+601 168503 29 megabytes denotative navies
+602 168601 29 chancellor coming leaflet A
+603 173001 40 bulk commencements shooter
+604 173701 40 commits gentleman Joplin FAS
+605 173702 40 meson gifted babies
+606 176001 40 deputies Shanghais subdivision FAS
+607 176101 40 northeaster sportswriting burstiness W
+608 176201 40 dipole sloping belted FAS
+609 176401 40 machining navies assails FAS
+610 176501 40 therefore leaflet admiring W
+611 176601 40 Telefunken shooter swaying 0
+612 176602 40 salvaging Joplin Goldstine FAS
+613 176603 40 Corinthianizes babies fitting
+614 178001 40 restlessly subdivision Norwalk W
+615 178002 40 bromides burstiness weakening W
+616 178003 40 generalized belted analogy FAS
+617 178004 40 mishaps assails deludes
+618 178005 40 quelling admiring cokes
+619 178006 40 spiritual swaying Clayton
+620 178007 40 beguiles Goldstine exhausts
+621 178008 40 Trobriand fitting causality
+622 178101 40 fleeing Norwalk sating FAS
+623 178102 40 Armour weakening icon
+624 178103 40 chin analogy throttles
+625 178201 40 provers deludes communicants FAS
+626 178202 40 aeronautic cokes dehydrate FAS
+627 178301 40 voltage Clayton priceless FAS
+628 178302 40 sash exhausts publicly
+629 178401 40 anaerobic causality incidentals FAS
+630 178402 40 simultaneous sating commonplace
+631 178403 40 accumulating icon mumbles
+632 178404 40 Medusan throttles furthermore W
+633 178501 40 shouted communicants cautioned W
+634 186002 37 freakish dehydrate parametrized A
+635 186102 37 index priceless registration A
+636 186201 40 commercially publicly sadly FAS
+637 186202 40 mistiness incidentals positioning
+638 186203 40 endpoint commonplace babysitting
+639 186302 37 straight mumbles eternal A
+640 188007 37 flurried furthermore hoarder
+641 188008 37 denotative cautioned congregates
+642 188009 37 coming parametrized rains
+643 188010 37 commencements registration workers W
+644 188011 37 gentleman sadly sags A
+645 188012 37 gifted positioning unplug W
+646 188013 37 Shanghais babysitting garage A
+647 188014 37 sportswriting eternal boulder A
+648 188015 37 sloping hoarder hollowly A
+649 188016 37 navies congregates specifics
+650 188017 37 leaflet rains Teresa
+651 188102 37 shooter workers Winsett
+652 188103 37 Joplin sags convenient A
+653 188202 37 babies unplug buckboards FAS
+654 188301 40 subdivision garage amenities
+655 188302 40 burstiness boulder resplendent FAS
+656 188303 40 belted hollowly priding FAS
+657 188401 37 assails specifics configurations
+658 188402 37 admiring Teresa untidiness A
+659 188503 37 swaying Winsett Brice W
+660 188504 37 Goldstine convenient sews FAS
+661 188505 37 fitting buckboards participated
+662 190701 37 Norwalk amenities Simon FAS
+663 190703 50 weakening resplendent certificates
+664 191701 37 analogy priding Fitzpatrick
+665 191702 37 deludes configurations Evanston A
+666 191703 37 cokes untidiness misted
+667 196001 37 Clayton Brice textures A
+668 196002 37 exhausts sews save
+669 196003 37 causality participated count
+670 196101 37 sating Simon rightful A
+671 196103 37 icon certificates chaperone
+672 196104 37 throttles Fitzpatrick Lizzy A
+673 196201 37 communicants Evanston clenched A
+674 196202 37 dehydrate misted effortlessly
+675 196203 37 priceless textures accessed
+676 198001 37 publicly save beaters A
+677 198003 37 incidentals count Hornblower FAS
+678 198004 37 commonplace rightful vests A
+679 198005 37 mumbles chaperone indulgences FAS
+680 198006 37 furthermore Lizzy infallibly A
+681 198007 37 cautioned clenched unwilling FAS
+682 198008 37 parametrized effortlessly excrete FAS
+683 198009 37 registration accessed spools A
+684 198010 37 sadly beaters crunches FAS
+685 198011 37 positioning Hornblower overestimating FAS
+686 198012 37 babysitting vests ineffective
+687 198013 37 eternal indulgences humiliation A
+688 198014 37 hoarder infallibly sophomore
+689 198015 37 congregates unwilling star
+690 198017 37 rains excrete rifles
+691 198018 37 workers spools dialysis
+692 198019 37 sags crunches arriving
+693 198020 37 unplug overestimating indulge
+694 198021 37 garage ineffective clockers
+695 198022 37 boulder humiliation languages
+696 198023 50 hollowly sophomore Antarctica A
+697 198024 37 specifics star percentage
+698 198101 37 Teresa rifles ceiling A
+699 198103 37 Winsett dialysis specification
+700 198105 37 convenient arriving regimented A
+701 198106 37 buckboards indulge ciphers
+702 198201 37 amenities clockers pictures A
+703 198204 37 resplendent languages serpents A
+704 198301 53 priding Antarctica allot A
+705 198302 53 configurations percentage realized A
+706 198303 53 untidiness ceiling mayoral A
+707 198304 53 Brice specification opaquely A
+708 198401 37 sews regimented hostess FAS
+709 198402 37 participated ciphers fiftieth
+710 198403 37 Simon pictures incorrectly
+711 202101 37 certificates serpents decomposition FAS
+712 202301 37 Fitzpatrick allot stranglings
+713 202302 37 Evanston realized mixture FAS
+714 202303 37 misted mayoral electroencephalography FAS
+715 202304 37 textures opaquely similarities FAS
+716 202305 37 save hostess charges W
+717 202601 37 count fiftieth freest FAS
+718 202602 37 rightful incorrectly Greenberg FAS
+719 202605 37 chaperone decomposition tinting
+720 202606 37 Lizzy stranglings expelled W
+721 202607 37 clenched mixture warm
+722 202901 37 effortlessly electroencephalography smoothed
+723 202902 37 accessed similarities deductions FAS
+724 202903 37 beaters charges Romano W
+725 202904 37 Hornblower freest bitterroot
+726 202907 37 vests Greenberg corset
+727 202908 37 indulgences tinting securing
+728 203101 37 infallibly expelled environing FAS
+729 203103 37 unwilling warm cute
+730 203104 37 excrete smoothed Crays
+731 203105 37 spools deductions heiress FAS
+732 203401 37 crunches Romano inform FAS
+733 203402 37 overestimating bitterroot avenge
+734 203404 37 ineffective corset universals
+735 203901 37 humiliation securing Kinsey W
+736 203902 37 sophomore environing ravines FAS
+737 203903 37 star cute bestseller
+738 203906 37 rifles Crays equilibrium
+739 203907 37 dialysis heiress extents 0
+740 203908 37 arriving inform relatively
+741 203909 37 indulge avenge pressure FAS
+742 206101 37 clockers universals critiques FAS
+743 206201 37 languages Kinsey befouled
+744 206202 37 Antarctica ravines rightfully FAS
+745 206203 37 percentage bestseller mechanizing FAS
+746 206206 37 ceiling equilibrium Latinizes
+747 206207 37 specification extents timesharing
+748 206208 37 regimented relatively Aden
+749 208001 37 ciphers pressure embassies
+750 208002 37 pictures critiques males FAS
+751 208003 37 serpents befouled shapelessly FAS
+752 208004 37 allot rightfully genres FAS
+753 208008 37 realized mechanizing mastering
+754 208009 37 mayoral Latinizes Newtonian
+755 208010 37 opaquely timesharing finishers FAS
+756 208011 37 hostess Aden abates
+757 208101 37 fiftieth embassies teem
+758 208102 37 incorrectly males kiting FAS
+759 208103 37 decomposition shapelessly stodgy FAS
+760 208104 37 stranglings genres scalps FAS
+761 208105 37 mixture mastering feed FAS
+762 208110 37 electroencephalography Newtonian guitars
+763 208111 37 similarities finishers airships
+764 208112 37 charges abates store
+765 208113 37 freest teem denounces
+766 208201 37 Greenberg kiting Pyle FAS
+767 208203 37 tinting stodgy Saxony
+768 208301 37 expelled scalps serializations FAS
+769 208302 37 warm feed Peruvian FAS
+770 208305 37 smoothed guitars taxonomically FAS
+771 208401 37 deductions airships kingdom A
+772 208402 37 Romano store stint A
+773 208403 37 bitterroot denounces Sault A
+774 208404 37 corset Pyle faithful
+775 208501 37 securing Saxony Ganymede FAS
+776 208502 37 environing serializations tidiness FAS
+777 208503 37 cute Peruvian gainful FAS
+778 208504 37 Crays taxonomically contrary FAS
+779 208505 37 heiress kingdom Tipperary FAS
+780 210101 37 inform stint tropics W
+781 210102 37 avenge Sault theorizers
+782 210103 37 universals faithful renew 0
+783 210104 37 Kinsey Ganymede already
+784 210105 37 ravines tidiness terminal
+785 210106 37 bestseller gainful Hegelian
+786 210107 37 equilibrium contrary hypothesizer
+787 210401 37 extents Tipperary warningly FAS
+788 213201 37 relatively tropics journalizing FAS
+789 213203 37 pressure theorizers nested
+790 213204 37 critiques renew Lars
+791 213205 37 befouled already saplings
+792 213206 37 rightfully terminal foothill
+793 213207 37 mechanizing Hegelian labeled
+794 216101 37 Latinizes hypothesizer imperiously FAS
+795 216103 37 timesharing warningly reporters FAS
+796 218001 37 Aden journalizing furnishings FAS
+797 218002 37 embassies nested precipitable FAS
+798 218003 37 males Lars discounts FAS
+799 218004 37 shapelessly saplings excises FAS
+800 143503 50 genres foothill Stalin
+801 218006 37 mastering labeled despot FAS
+802 218007 37 Newtonian imperiously ripeness FAS
+803 218008 37 finishers reporters Arabia
+804 218009 37 abates furnishings unruly
+805 218010 37 teem precipitable mournfulness
+806 218011 37 kiting discounts boom FAS
+807 218020 37 stodgy excises slaughter A
+808 218021 50 scalps Stalin Sabine
+809 218022 37 feed despot handy FAS
+810 218023 37 guitars ripeness rural
+811 218024 37 airships Arabia organizer
+812 218101 37 store unruly shipyard FAS
+813 218102 37 denounces mournfulness civics FAS
+814 218103 37 Pyle boom inaccuracy FAS
+815 218201 37 Saxony slaughter rules FAS
+816 218202 37 serializations Sabine juveniles FAS
+817 218203 37 Peruvian handy comprised W
+818 218204 37 taxonomically rural investigations
+819 218205 37 kingdom organizer stabilizes A
+820 218301 37 stint shipyard seminaries FAS
+821 218302 37 Sault civics Hunter A
+822 218401 37 faithful inaccuracy sporty FAS
+823 218402 37 Ganymede rules test FAS
+824 218403 37 tidiness juveniles weasels
+825 218404 37 gainful comprised CERN
+826 218407 37 contrary investigations tempering
+827 218408 37 Tipperary stabilizes afore FAS
+828 218409 37 tropics seminaries Galatean
+829 218410 37 theorizers Hunter techniques W
+830 226001 37 renew sporty error
+831 226002 37 already test veranda
+832 226003 37 terminal weasels severely
+833 226004 37 Hegelian CERN Cassites FAS
+834 226005 37 hypothesizer tempering forthcoming
+835 226006 37 warningly afore guides
+836 226007 37 journalizing Galatean vanish FAS
+837 226008 37 nested techniques lied A
+838 226203 37 Lars error sawtooth FAS
+839 226204 37 saplings veranda fated FAS
+840 226205 37 foothill severely gradually
+841 226206 37 labeled Cassites widens
+842 226207 37 imperiously forthcoming preclude
+843 226208 37 reporters guides Jobrel
+844 226209 37 furnishings vanish hooker
+845 226210 37 precipitable lied rainstorm
+846 226211 37 discounts sawtooth disconnects
+847 228001 37 excises fated cruelty
+848 228004 37 Stalin gradually exponentials A
+849 228005 37 despot widens affective A
+850 228006 37 ripeness preclude arteries
+851 228007 37 Arabia Jobrel Crosby FAS
+852 228008 37 unruly hooker acquaint
+853 228009 37 mournfulness rainstorm evenhandedly
+854 228101 37 boom disconnects percentage
+855 228108 37 slaughter cruelty disobedience
+856 228109 37 Sabine exponentials humility
+857 228110 37 handy affective gleaning A
+858 228111 37 rural arteries petted A
+859 228112 37 organizer Crosby bloater A
+860 228113 37 shipyard acquaint minion A
+861 228114 37 civics evenhandedly marginal A
+862 228115 37 inaccuracy percentage apiary A
+863 228116 37 rules disobedience measures
+864 228117 37 juveniles humility precaution
+865 228118 37 comprised gleaning repelled
+866 228119 37 investigations petted primary FAS
+867 228120 37 stabilizes bloater coverings
+868 228121 37 seminaries minion Artemia A
+869 228122 37 Hunter marginal navigate
+870 228201 37 sporty apiary spatial
+871 228206 37 test measures Gurkha
+872 228207 37 weasels precaution meanwhile A
+873 228208 37 CERN repelled Melinda A
+874 228209 37 tempering primary Butterfield
+875 228210 37 afore coverings Aldrich A
+876 228211 37 Galatean Artemia previewing A
+877 228212 37 techniques navigate glut A
+878 228213 37 error spatial unaffected
+879 228214 37 veranda Gurkha inmate
+880 228301 37 severely meanwhile mineral
+881 228305 37 Cassites Melinda impending A
+882 228306 37 forthcoming Butterfield meditation A
+883 228307 37 guides Aldrich ideas
+884 228308 37 vanish previewing miniaturizes W
+885 228309 37 lied glut lewdly
+886 228310 37 sawtooth unaffected title
+887 228311 37 fated inmate youthfulness
+888 228312 37 gradually mineral creak FAS
+889 228313 37 widens impending Chippewa
+890 228314 37 preclude meditation clamored
+891 228401 65 Jobrel ideas freezes
+892 228402 65 hooker miniaturizes forgivably FAS
+893 228403 65 rainstorm lewdly reduce FAS
+894 228404 65 disconnects title McGovern W
+895 228405 65 cruelty youthfulness Nazis W
+896 228406 65 exponentials creak epistle W
+897 228407 65 affective Chippewa socializes W
+898 228408 65 arteries clamored conceptions
+899 228409 65 Crosby freezes Kevin
+900 228410 65 acquaint forgivably uncovering
+901 230301 37 evenhandedly reduce chews FAS
+902 230302 37 percentage McGovern appendixes FAS
+903 230303 37 disobedience Nazis raining
+904 018062 37 humility epistle infest
+905 230501 37 gleaning socializes compartment
+906 230502 37 petted conceptions minting
+907 230503 37 bloater Kevin ducks
+908 230504 37 minion uncovering roped A
+909 230505 37 marginal chews waltz
+910 230506 37 apiary appendixes Lillian
+911 230507 37 measures raining repressions A
+912 230508 37 precaution infest chillingly
+913 230509 37 repelled compartment noncritical
+914 230901 37 primary minting lithograph
+915 230902 37 coverings ducks spongers
+916 230903 37 Artemia roped parenthood
+917 230904 37 navigate waltz posed
+918 230905 37 spatial Lillian instruments
+919 230906 37 Gurkha repressions filial
+920 230907 37 meanwhile chillingly fixedly
+921 230908 37 Melinda noncritical relives
+922 230909 37 Butterfield lithograph Pandora
+923 230910 37 Aldrich spongers watering A
+924 230911 37 previewing parenthood ungrateful
+925 230912 37 glut posed secures
+926 230913 37 unaffected instruments chastisers
+927 230914 37 inmate filial icon
+928 231304 37 mineral fixedly reuniting A
+929 231305 37 impending relives imagining A
+930 231306 37 meditation Pandora abiding A
+931 231307 37 ideas watering omnisciently
+932 231308 37 miniaturizes ungrateful Britannic
+933 231309 37 lewdly secures scholastics A
+934 231310 37 title chastisers mechanics A
+935 231311 37 youthfulness icon humidly A
+936 231312 37 creak reuniting masterpiece
+937 231313 37 Chippewa imagining however
+938 231314 37 clamored abiding Mendelian
+939 231315 37 freezes omnisciently jarred
+940 232102 37 forgivably Britannic scolds
+941 232103 37 reduce scholastics infatuate
+942 232104 37 McGovern mechanics willed A
+943 232105 37 Nazis humidly joyfully
+944 232106 37 epistle masterpiece Microsoft
+945 232107 37 socializes however fibrosities
+946 232108 37 conceptions Mendelian Baltimorean
+947 232601 37 Kevin jarred equestrian
+948 232602 37 uncovering scolds Goodrich
+949 232603 37 chews infatuate apish A
+950 232605 37 appendixes willed Adlerian
+5950 1232605 37 appendixes willed Adlerian
+5951 1232606 37 appendixes willed Adlerian
+5952 1232607 37 appendixes willed Adlerian
+5953 1232608 37 appendixes willed Adlerian
+5954 1232609 37 appendixes willed Adlerian
+951 232606 37 raining joyfully Tropez
+952 232607 37 infest Microsoft nouns
+953 232608 37 compartment fibrosities distracting
+954 232609 37 minting Baltimorean mutton
+955 236104 37 ducks equestrian bridgeable A
+956 236105 37 roped Goodrich stickers A
+957 236106 37 waltz apish transcontinental A
+958 236107 37 Lillian Adlerian amateurish
+959 236108 37 repressions Tropez Gandhian
+960 236109 37 chillingly nouns stratified
+961 236110 37 noncritical distracting chamberlains
+962 236111 37 lithograph mutton creditably
+963 236112 37 spongers bridgeable philosophic
+964 236113 37 parenthood stickers ores
+965 238005 37 posed transcontinental Carleton
+966 238006 37 instruments amateurish tape A
+967 238007 37 filial Gandhian afloat A
+968 238008 37 fixedly stratified goodness A
+969 238009 37 relives chamberlains welcoming
+970 238010 37 Pandora creditably Pinsky FAS
+971 238011 37 watering philosophic halting
+972 238012 37 ungrateful ores bibliography
+973 238013 37 secures Carleton decoding
+974 240401 41 chastisers tape variance A
+975 240402 41 icon afloat allowed A
+976 240901 41 reuniting goodness dire A
+977 240902 41 imagining welcoming dub A
+978 241801 41 abiding Pinsky poisoning
+979 242101 41 omnisciently halting Iraqis A
+980 242102 41 Britannic bibliography heaving
+981 242201 41 scholastics decoding population A
+982 242202 41 mechanics variance bomb A
+983 242501 41 humidly allowed Majorca A
+984 242502 41 masterpiece dire Gershwins
+985 246201 41 however dub explorers
+986 246202 41 Mendelian poisoning libretto A
+987 246203 41 jarred Iraqis occurred
+988 246204 41 scolds heaving Lagos
+989 246205 41 infatuate population rats
+990 246301 41 willed bomb bankruptcies A
+991 246302 41 joyfully Majorca crying
+992 248001 41 Microsoft Gershwins unexpected
+993 248002 41 fibrosities explorers accessed A
+994 248003 41 Baltimorean libretto colorful A
+995 248004 41 equestrian occurred versatility A
+996 248005 41 Goodrich Lagos cosy
+997 248006 41 apish rats Darius A
+998 248007 41 Adlerian bankruptcies mastering A
+999 248008 41 Tropez crying Asiaticizations A
+1000 248009 41 nouns unexpected offerers A
+1001 248010 41 distracting accessed uncles A
+1002 248011 41 mutton colorful sleepwalk
+1003 248012 41 bridgeable versatility Ernestine
+1004 248013 41 stickers cosy checksumming
+1005 248014 41 transcontinental Darius stopped
+1006 248015 41 amateurish mastering sicker
+1007 248016 41 Gandhian Asiaticizations Italianization
+1008 248017 41 stratified offerers alphabetic
+1009 248018 41 chamberlains uncles pharmaceutic
+1010 248019 41 creditably sleepwalk creator
+1011 248020 41 philosophic Ernestine chess
+1012 248021 41 ores checksumming charcoal
+1013 248101 41 Carleton stopped Epiphany A
+1014 248102 41 tape sicker bulldozes A
+1015 248201 41 afloat Italianization Pygmalion A
+1016 248202 41 goodness alphabetic caressing A
+1017 248203 41 welcoming pharmaceutic Palestine A
+1018 248204 41 Pinsky creator regimented A
+1019 248205 41 halting chess scars A
+1020 248206 41 bibliography charcoal realest A
+1021 248207 41 decoding Epiphany diffusing A
+1022 248208 41 variance bulldozes clubroom A
+1023 248209 41 allowed Pygmalion Blythe A
+1024 248210 41 dire caressing ahead
+1025 248211 50 dub Palestine reviver
+1026 250501 34 poisoning regimented retransmitting A
+1027 250502 34 Iraqis scars landslide
+1028 250503 34 heaving realest Eiffel
+1029 250504 34 population diffusing absentee
+1030 250505 34 bomb clubroom aye
+1031 250601 34 Majorca Blythe forked A
+1032 250602 34 Gershwins ahead Peruvianizes
+1033 250603 34 explorers reviver clerked
+1034 250604 34 libretto retransmitting tutor
+1035 250605 34 occurred landslide boulevard
+1036 251001 34 Lagos Eiffel shuttered
+1037 251002 34 rats absentee quotes A
+1038 251003 34 bankruptcies aye Caltech
+1039 251004 34 crying forked Mossberg
+1040 251005 34 unexpected Peruvianizes kept
+1041 251301 34 accessed clerked roundly
+1042 251302 34 colorful tutor features A
+1043 251303 34 versatility boulevard imaginable A
+1044 251304 34 cosy shuttered controller
+1045 251305 34 Darius quotes racial
+1046 251401 34 mastering Caltech uprisings A
+1047 251402 34 Asiaticizations Mossberg narrowed A
+1048 251403 34 offerers kept cannot A
+1049 251404 34 uncles roundly vest
+1050 251405 34 sleepwalk features famine
+1051 251406 34 Ernestine imaginable sugars
+1052 251801 34 checksumming controller exterminated A
+1053 251802 34 stopped racial belays
+1054 252101 34 sicker uprisings Hodges A
+1055 252102 34 Italianization narrowed translatable
+1056 252301 34 alphabetic cannot duality A
+1057 252302 34 pharmaceutic vest recording A
+1058 252303 34 creator famine rouses A
+1059 252304 34 chess sugars poison
+1060 252305 34 charcoal exterminated attitude
+1061 252306 34 Epiphany belays dusted
+1062 252307 34 bulldozes Hodges encompasses
+1063 252308 34 Pygmalion translatable presentation
+1064 252309 34 caressing duality Kantian
+1065 256001 34 Palestine recording imprecision A
+1066 256002 34 regimented rouses saving
+1067 256003 34 scars poison maternal
+1068 256004 34 realest attitude hewed
+1069 256005 34 diffusing dusted kerosene
+1070 258001 34 clubroom encompasses Cubans
+1071 258002 34 Blythe presentation photographers
+1072 258003 34 ahead Kantian nymph A
+1073 258004 34 reviver imprecision bedlam A
+1074 258005 34 retransmitting saving north A
+1075 258006 34 landslide maternal Schoenberg A
+1076 258007 34 Eiffel hewed botany A
+1077 258008 34 absentee kerosene curs
+1078 258009 34 aye Cubans solidification
+1079 258010 34 forked photographers inheritresses
+1080 258011 34 Peruvianizes nymph stiller
+1081 258101 68 clerked bedlam t1 A
+1082 258102 68 tutor north suite A
+1083 258103 34 boulevard Schoenberg ransomer
+1084 258104 68 shuttered botany Willy
+1085 258105 68 quotes curs Rena A
+1086 258106 68 Caltech solidification Seattle A
+1087 258107 68 Mossberg inheritresses relaxes A
+1088 258108 68 kept stiller exclaim
+1089 258109 68 roundly t1 implicated A
+1090 258110 68 features suite distinguish
+1091 258111 68 imaginable ransomer assayed
+1092 258112 68 controller Willy homeowner
+1093 258113 68 racial Rena and
+1094 258201 34 uprisings Seattle stealth
+1095 258202 34 narrowed relaxes coinciding A
+1096 258203 34 cannot exclaim founder A
+1097 258204 34 vest implicated environing
+1098 258205 34 famine distinguish jewelry
+1099 258301 34 sugars assayed lemons A
+1100 258401 34 exterminated homeowner brokenness A
+1101 258402 34 belays and bedpost A
+1102 258403 34 Hodges stealth assurers A
+1103 258404 34 translatable coinciding annoyers
+1104 258405 34 duality founder affixed
+1105 258406 34 recording environing warbling
+1106 258407 34 rouses jewelry seriously
+1107 228123 37 poison lemons boasted
+1108 250606 34 attitude brokenness Chantilly
+1109 208405 37 dusted bedpost Iranizes
+1110 212101 37 encompasses assurers violinist
+1111 218206 37 presentation annoyers extramarital
+1112 150401 37 Kantian affixed spates
+1113 248212 41 imprecision warbling cloakroom
+1114 128026 00 saving seriously gazer
+1115 128024 00 maternal boasted hand
+1116 128027 00 hewed Chantilly tucked
+1117 128025 00 kerosene Iranizes gems
+1118 128109 00 Cubans violinist clinker
+1119 128705 00 photographers extramarital refiner
+1120 126303 00 nymph spates callus
+1121 128308 00 bedlam cloakroom leopards
+1122 128204 00 north gazer comfortingly
+1123 128205 00 Schoenberg hand generically
+1124 128206 00 botany tucked getters
+1125 128207 00 curs gems sexually
+1126 118205 00 solidification clinker spear
+1127 116801 00 inheritresses refiner serums
+1128 116803 00 stiller callus Italianization
+1129 116804 00 t1 leopards attendants
+1130 116802 00 suite comfortingly spies
+1131 128605 00 ransomer generically Anthony
+1132 118308 00 Willy getters planar
+1133 113702 00 Rena sexually cupped
+1134 113703 00 Seattle spear cleanser
+1135 112103 00 relaxes serums commuters
+1136 118009 00 exclaim Italianization honeysuckle
+5136 1118009 00 exclaim Italianization honeysuckle
+1137 138011 00 implicated attendants orphanage
+1138 138010 00 distinguish spies skies
+1139 138012 00 assayed Anthony crushers
+1140 068304 00 homeowner planar Puritan
+1141 078009 00 and cupped squeezer
+1142 108013 00 stealth cleanser bruises
+1143 084004 00 coinciding commuters bonfire
+1144 083402 00 founder honeysuckle Colombo
+1145 084003 00 environing orphanage nondecreasing
+1146 088504 00 jewelry skies innocents
+1147 088005 00 lemons crushers masked
+1148 088007 00 brokenness Puritan file
+1149 088006 00 bedpost squeezer brush
+1150 148025 00 assurers bruises mutilate
+1151 148024 00 annoyers bonfire mommy
+1152 138305 00 affixed Colombo bulkheads
+1153 138306 00 warbling nondecreasing undeclared
+1154 152701 00 seriously innocents displacements
+1155 148505 00 boasted masked nieces
+1156 158003 00 Chantilly file coeducation
+1157 156201 00 Iranizes brush brassy
+1158 156202 00 violinist mutilate authenticator
+1159 158307 00 extramarital mommy Washoe
+1160 158402 00 spates bulkheads penny
+1161 158401 00 cloakroom undeclared Flagler
+1162 068013 00 gazer displacements stoned
+1163 068012 00 hand nieces cranes
+1164 068203 00 tucked coeducation masterful
+1165 088205 00 gems brassy biracial
+1166 068704 00 clinker authenticator steamships
+1167 068604 00 refiner Washoe windmills
+1168 158502 00 callus penny exploit
+1169 123103 00 leopards Flagler riverfront
+1170 148026 00 comfortingly stoned sisterly
+1171 123302 00 generically cranes sharpshoot
+1172 076503 00 getters masterful mittens
+1173 126304 00 sexually biracial interdependency
+1174 068306 00 spear steamships policy
+1175 143504 00 serums windmills unleashing
+1176 160201 00 Italianization exploit pretenders
+1177 148028 00 attendants riverfront overstatements
+1178 148027 00 spies sisterly birthed
+1179 143505 00 Anthony sharpshoot opportunism
+1180 108014 00 planar mittens showroom
+1181 076104 00 cupped interdependency compromisingly
+1182 078106 00 cleanser policy Medicare
+1183 126102 00 commuters unleashing corresponds
+1184 128029 00 honeysuckle pretenders hardware
+1185 128028 00 orphanage overstatements implant
+1186 018410 00 skies birthed Alicia
+1187 128110 00 crushers opportunism requesting
+1188 148506 00 Puritan showroom produced
+1189 123303 00 squeezer compromisingly criticizes
+1190 123304 00 bruises Medicare backer
+1191 068504 00 bonfire corresponds positively
+1192 068305 00 Colombo hardware colicky
+1193 000000 00 nondecreasing implant thrillingly
+1 000001 00 Omaha teethe neat
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+drop table t1, t2;
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index 66b24248cf9..6bc59d4771f 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -1,4 +1,5 @@
drop table if exists t1;
+drop table if exists t2;
SET SQL_WARNINGS=1;
create table t1 (a int not null auto_increment,b int, primary key (a)) engine=myisam auto_increment=3;
insert into t1 values (1,1),(NULL,3),(NULL,4);
@@ -162,7 +163,7 @@ last_insert_id()
255
insert into t1 set i = null;
Warnings:
-Warning 1264 Data truncated, out of range for column 'i' at row 1
+Warning 1264 Data truncated; out of range for column 'i' at row 1
select last_insert_id();
last_insert_id()
255
@@ -213,7 +214,7 @@ a b
delete from t1 where a=0;
update t1 set a=NULL where b=6;
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'a' at row 4
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 4
update t1 set a=300 where b=7;
SET SQL_MODE='';
insert into t1(a,b)values(NULL,8);
@@ -255,7 +256,7 @@ a b
delete from t1 where a=0;
update t1 set a=NULL where b=13;
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'a' at row 9
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 9
update t1 set a=500 where b=14;
select * from t1 order by b;
a b
diff --git a/mysql-test/r/bdb-deadlock.result b/mysql-test/r/bdb-deadlock.result
index c5871ff282a..9394c90ff00 100644
--- a/mysql-test/r/bdb-deadlock.result
+++ b/mysql-test/r/bdb-deadlock.result
@@ -9,7 +9,7 @@ set autocommit=0;
update t2 set x = 1 where id = 0;
select x from t1 where id = 0;
select x from t2 where id = 0;
-ERROR 40001: Deadlock found when trying to get lock; Try restarting transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
commit;
x
1
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 9a279f702a2..d510ec53dfc 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -1181,3 +1181,73 @@ a
A
a
drop table t1;
+create table t1(
+pk1 text not null, pk2 text not null, pk3 char(4),
+key1 int, key2 int,
+primary key(pk1(4), pk2(4), pk3), key(key1), key(key2)
+) engine=bdb;
+insert into t1 values (concat('aaa-', repeat('A', 4000)),
+concat('eee-', repeat('e', 4000)), 'a++a', 1, 1);
+insert into t1 values (concat('bbb-', repeat('B', 4000)),
+concat('ggg-', repeat('G', 4000)), 'b++b', 1, 1);
+select substring(pk1, 1, 4), substring(pk1, 4001),
+substring(pk2, 1, 4), substring(pk2, 4001), pk3, key1, key2
+from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+substring(pk1, 1, 4) substring(pk1, 4001) substring(pk2, 1, 4) substring(pk2, 4001) pk3 key1 key2
+aaa- AAAA eee- eeee a++a 1 1
+bbb- BBBB ggg- GGGG b++b 1 1
+drop table t1;
+create table t1 (
+pk1 varchar(8) not null default '',
+pk2 varchar(4) not null default '',
+key1 int(11) default null,
+key2 int(11) default null,
+primary key (pk1,pk2),
+key key1 (key1),
+key key2 (key2)) engine=bdb;
+insert into t1 values ('','empt',2,2), ('a','a--a',2,2),
+('bb','b--b',2,2), ('ccc','c--c',2,2), ('dddd','d--d',2,2);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 pk2 key1 key2
+ empt 2 2
+a a--a 2 2
+bb b--b 2 2
+ccc c--c 2 2
+dddd d--d 2 2
+drop table t1;
+set autocommit=0;
+create table t1(b varchar(30)) engine=bdb;
+insert into t1 values ('one');
+commit;
+select b FROM t1 outer_table where
+exists (select 'two' from t1 where 'two' = outer_table.b);
+b
+drop table t1;
+set autocommit=1;
+create table t1(a int primary key, b varchar(30)) engine=bdb;
+insert into t1 values (1,'one'), (2,'two'), (3,'three'), (4,'four');
+create table t2 like t1;
+insert t2 select * from t1;
+select a from t1 where a in (select a from t2);
+a
+1
+2
+3
+4
+delete from t2;
+insert into t2 (a, b)
+select a, b from t1 where (a, b) in (select a, b from t1);
+select * from t2;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t1, t2;
+create table t1 (a int, b varchar(30), primary key(a)) engine = bdb;
+insert into t1 values (1,'one');
+commit;
+truncate t1;
+select * from t1;
+a b
+drop table t1;
diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result
index 635c9fd5242..b51a0a57ac0 100644
--- a/mysql-test/r/connect.result
+++ b/mysql-test/r/connect.result
@@ -10,6 +10,11 @@ help_topic
host
proc
tables_priv
+time_zone
+time_zone_leap_second
+time_zone_name
+time_zone_transition
+time_zone_transition_type
user
show tables;
Tables_in_test
@@ -27,6 +32,11 @@ help_topic
host
proc
tables_priv
+time_zone
+time_zone_leap_second
+time_zone_name
+time_zone_transition
+time_zone_transition_type
user
show tables;
Tables_in_test
@@ -45,6 +55,11 @@ help_topic
host
proc
tables_priv
+time_zone
+time_zone_leap_second
+time_zone_name
+time_zone_transition
+time_zone_transition_type
user
show tables;
Tables_in_test
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index b5f7da30bb3..699485ff3f7 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -11,7 +11,7 @@ create table t1 (b char(0) not null);
create table if not exists t1 (b char(0) not null);
insert into t1 values (""),(null);
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'b' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'b' at row 2
select * from t1;
b
@@ -35,7 +35,7 @@ drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) engine=heap;
-ERROR 42000: Incorrect table definition; There can only be one auto column and it must be defined as a key
+ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key
create table not_existing_database.test (a int);
Got one of the listed errors
create table `a/a` (a int);
@@ -47,7 +47,7 @@ ERROR 42000: Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
create table test (a datetime default now());
ERROR 42000: Invalid default value for 'a'
create table test (a datetime on update now());
-ERROR HY000: Invalid ON UPDATE clause for 'a' field
+ERROR HY000: Invalid ON UPDATE clause for 'a' column
create table test (a int default 100 auto_increment);
ERROR 42000: Invalid default value for 'a'
create table 1ea10 (1a20 int,1e int);
@@ -275,11 +275,11 @@ ERROR 42000: Incorrect database name 'db1 '
create table t1(`a ` int);
ERROR 42000: Incorrect column name 'a '
create table t1 (a int,);
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
create table t1 (a int,,b int);
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'b int)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'b int)' at line 1
create table t1 (,b int);
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'b int)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'b int)' at line 1
create table t1 (a int, key(a));
create table t2 (b int, foreign key(b) references t1(a), key(b));
drop table if exists t1,t2;
diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result
new file mode 100644
index 00000000000..cb6fbecb6e8
--- /dev/null
+++ b/mysql-test/r/ctype_uca.result
@@ -0,0 +1,1657 @@
+DROP TABLE IF EXISTS t1;
+set names utf8;
+create table t1 (c1 char(10) character set utf8 collate utf8_bin);
+insert into t1 values ('A'),('a');
+insert into t1 values ('B'),('b');
+insert into t1 values ('C'),('c');
+insert into t1 values ('D'),('d');
+insert into t1 values ('E'),('e');
+insert into t1 values ('F'),('f');
+insert into t1 values ('G'),('g');
+insert into t1 values ('H'),('h');
+insert into t1 values ('I'),('i');
+insert into t1 values ('J'),('j');
+insert into t1 values ('K'),('k');
+insert into t1 values ('L'),('l');
+insert into t1 values ('M'),('m');
+insert into t1 values ('N'),('n');
+insert into t1 values ('O'),('o');
+insert into t1 values ('P'),('p');
+insert into t1 values ('Q'),('q');
+insert into t1 values ('R'),('r');
+insert into t1 values ('S'),('s');
+insert into t1 values ('T'),('t');
+insert into t1 values ('U'),('u');
+insert into t1 values ('V'),('v');
+insert into t1 values ('W'),('w');
+insert into t1 values ('X'),('x');
+insert into t1 values ('Y'),('y');
+insert into t1 values ('Z'),('z');
+insert into t1 values (_ucs2 0x00e0),(_ucs2 0x00c0);
+insert into t1 values (_ucs2 0x00e1),(_ucs2 0x00c1);
+insert into t1 values (_ucs2 0x00e2),(_ucs2 0x00c2);
+insert into t1 values (_ucs2 0x00e3),(_ucs2 0x00c3);
+insert into t1 values (_ucs2 0x00e4),(_ucs2 0x00c4);
+insert into t1 values (_ucs2 0x00e5),(_ucs2 0x00c5);
+insert into t1 values (_ucs2 0x00e6),(_ucs2 0x00c6);
+insert into t1 values (_ucs2 0x00e7),(_ucs2 0x00c7);
+insert into t1 values (_ucs2 0x00e8),(_ucs2 0x00c8);
+insert into t1 values (_ucs2 0x00e9),(_ucs2 0x00c9);
+insert into t1 values (_ucs2 0x00ea),(_ucs2 0x00ca);
+insert into t1 values (_ucs2 0x00eb),(_ucs2 0x00cb);
+insert into t1 values (_ucs2 0x00ec),(_ucs2 0x00cc);
+insert into t1 values (_ucs2 0x00ed),(_ucs2 0x00cd);
+insert into t1 values (_ucs2 0x00ee),(_ucs2 0x00ce);
+insert into t1 values (_ucs2 0x00ef),(_ucs2 0x00cf);
+insert into t1 values (_ucs2 0x00f0),(_ucs2 0x00d0);
+insert into t1 values (_ucs2 0x00f1),(_ucs2 0x00d1);
+insert into t1 values (_ucs2 0x00f2),(_ucs2 0x00d2);
+insert into t1 values (_ucs2 0x00f3),(_ucs2 0x00d3);
+insert into t1 values (_ucs2 0x00f4),(_ucs2 0x00d4);
+insert into t1 values (_ucs2 0x00f5),(_ucs2 0x00d5);
+insert into t1 values (_ucs2 0x00f6),(_ucs2 0x00d6);
+insert into t1 values (_ucs2 0x00f7),(_ucs2 0x00d7);
+insert into t1 values (_ucs2 0x00f8),(_ucs2 0x00d8);
+insert into t1 values (_ucs2 0x00f9),(_ucs2 0x00d9);
+insert into t1 values (_ucs2 0x00fa),(_ucs2 0x00da);
+insert into t1 values (_ucs2 0x00fb),(_ucs2 0x00db);
+insert into t1 values (_ucs2 0x00fc),(_ucs2 0x00dc);
+insert into t1 values (_ucs2 0x00fd),(_ucs2 0x00dd);
+insert into t1 values (_ucs2 0x00fe),(_ucs2 0x00de);
+insert into t1 values (_ucs2 0x00ff),(_ucs2 0x00df);
+insert into t1 values (_ucs2 0x0100),(_ucs2 0x0101),(_ucs2 0x0102),(_ucs2 0x0103);
+insert into t1 values (_ucs2 0x0104),(_ucs2 0x0105),(_ucs2 0x0106),(_ucs2 0x0107);
+insert into t1 values (_ucs2 0x0108),(_ucs2 0x0109),(_ucs2 0x010a),(_ucs2 0x010b);
+insert into t1 values (_ucs2 0x010c),(_ucs2 0x010d),(_ucs2 0x010e),(_ucs2 0x010f);
+insert into t1 values (_ucs2 0x0110),(_ucs2 0x0111),(_ucs2 0x0112),(_ucs2 0x0113);
+insert into t1 values (_ucs2 0x0114),(_ucs2 0x0115),(_ucs2 0x0116),(_ucs2 0x0117);
+insert into t1 values (_ucs2 0x0118),(_ucs2 0x0119),(_ucs2 0x011a),(_ucs2 0x011b);
+insert into t1 values (_ucs2 0x011c),(_ucs2 0x011d),(_ucs2 0x011e),(_ucs2 0x011f);
+insert into t1 values (_ucs2 0x0120),(_ucs2 0x0121),(_ucs2 0x0122),(_ucs2 0x0123);
+insert into t1 values (_ucs2 0x0124),(_ucs2 0x0125),(_ucs2 0x0126),(_ucs2 0x0127);
+insert into t1 values (_ucs2 0x0128),(_ucs2 0x0129),(_ucs2 0x012a),(_ucs2 0x012b);
+insert into t1 values (_ucs2 0x012c),(_ucs2 0x012d),(_ucs2 0x012e),(_ucs2 0x012f);
+insert into t1 values (_ucs2 0x0130),(_ucs2 0x0131),(_ucs2 0x0132),(_ucs2 0x0133);
+insert into t1 values (_ucs2 0x0134),(_ucs2 0x0135),(_ucs2 0x0136),(_ucs2 0x0137);
+insert into t1 values (_ucs2 0x0138),(_ucs2 0x0139),(_ucs2 0x013a),(_ucs2 0x013b);
+insert into t1 values (_ucs2 0x013c),(_ucs2 0x013d),(_ucs2 0x013e),(_ucs2 0x013f);
+insert into t1 values (_ucs2 0x0140),(_ucs2 0x0141),(_ucs2 0x0142),(_ucs2 0x0143);
+insert into t1 values (_ucs2 0x0144),(_ucs2 0x0145),(_ucs2 0x0146),(_ucs2 0x0147);
+insert into t1 values (_ucs2 0x0148),(_ucs2 0x0149),(_ucs2 0x014a),(_ucs2 0x014b);
+insert into t1 values (_ucs2 0x014c),(_ucs2 0x014d),(_ucs2 0x014e),(_ucs2 0x014f);
+insert into t1 values (_ucs2 0x0150),(_ucs2 0x0151),(_ucs2 0x0152),(_ucs2 0x0153);
+insert into t1 values (_ucs2 0x0154),(_ucs2 0x0155),(_ucs2 0x0156),(_ucs2 0x0157);
+insert into t1 values (_ucs2 0x0158),(_ucs2 0x0159),(_ucs2 0x015a),(_ucs2 0x015b);
+insert into t1 values (_ucs2 0x015c),(_ucs2 0x015d),(_ucs2 0x015e),(_ucs2 0x015f);
+insert into t1 values (_ucs2 0x0160),(_ucs2 0x0161),(_ucs2 0x0162),(_ucs2 0x0163);
+insert into t1 values (_ucs2 0x0164),(_ucs2 0x0165),(_ucs2 0x0166),(_ucs2 0x0167);
+insert into t1 values (_ucs2 0x0168),(_ucs2 0x0169),(_ucs2 0x016a),(_ucs2 0x016b);
+insert into t1 values (_ucs2 0x016c),(_ucs2 0x016d),(_ucs2 0x016e),(_ucs2 0x016f);
+insert into t1 values (_ucs2 0x0170),(_ucs2 0x0171),(_ucs2 0x0172),(_ucs2 0x0173);
+insert into t1 values (_ucs2 0x0174),(_ucs2 0x0175),(_ucs2 0x0176),(_ucs2 0x0177);
+insert into t1 values (_ucs2 0x0178),(_ucs2 0x0179),(_ucs2 0x017a),(_ucs2 0x017b);
+insert into t1 values (_ucs2 0x017c),(_ucs2 0x017d),(_ucs2 0x017e),(_ucs2 0x017f);
+insert into t1 values (_ucs2 0x0180),(_ucs2 0x0181),(_ucs2 0x0182),(_ucs2 0x0183);
+insert into t1 values (_ucs2 0x0184),(_ucs2 0x0185),(_ucs2 0x0186),(_ucs2 0x0187);
+insert into t1 values (_ucs2 0x0188),(_ucs2 0x0189),(_ucs2 0x018a),(_ucs2 0x018b);
+insert into t1 values (_ucs2 0x018c),(_ucs2 0x018d),(_ucs2 0x018e),(_ucs2 0x018f);
+insert into t1 values (_ucs2 0x0190),(_ucs2 0x0191),(_ucs2 0x0192),(_ucs2 0x0193);
+insert into t1 values (_ucs2 0x0194),(_ucs2 0x0195),(_ucs2 0x0196),(_ucs2 0x0197);
+insert into t1 values (_ucs2 0x0198),(_ucs2 0x0199),(_ucs2 0x019a),(_ucs2 0x019b);
+insert into t1 values (_ucs2 0x019c),(_ucs2 0x019d),(_ucs2 0x019e),(_ucs2 0x019f);
+insert into t1 values (_ucs2 0x01a0),(_ucs2 0x01a1),(_ucs2 0x01a2),(_ucs2 0x01a3);
+insert into t1 values (_ucs2 0x01a4),(_ucs2 0x01a5),(_ucs2 0x01a6),(_ucs2 0x01a7);
+insert into t1 values (_ucs2 0x01a8),(_ucs2 0x01a9),(_ucs2 0x01aa),(_ucs2 0x01ab);
+insert into t1 values (_ucs2 0x01ac),(_ucs2 0x01ad),(_ucs2 0x01ae),(_ucs2 0x01af);
+insert into t1 values (_ucs2 0x01b0),(_ucs2 0x01b1),(_ucs2 0x01b2),(_ucs2 0x01b3);
+insert into t1 values (_ucs2 0x01b4),(_ucs2 0x01b5),(_ucs2 0x01b6),(_ucs2 0x01b7);
+insert into t1 values (_ucs2 0x01b8),(_ucs2 0x01b9),(_ucs2 0x01ba),(_ucs2 0x01bb);
+insert into t1 values (_ucs2 0x01bc),(_ucs2 0x01bd),(_ucs2 0x01be),(_ucs2 0x01bf);
+insert into t1 values (_ucs2 0x01c0),(_ucs2 0x01c1),(_ucs2 0x01c2),(_ucs2 0x01c3);
+insert into t1 values (_ucs2 0x01c4),(_ucs2 0x01c5),(_ucs2 0x01c6),(_ucs2 0x01c7);
+insert into t1 values (_ucs2 0x01c8),(_ucs2 0x01c9),(_ucs2 0x01ca),(_ucs2 0x01cb);
+insert into t1 values (_ucs2 0x01cc),(_ucs2 0x01cd),(_ucs2 0x01ce),(_ucs2 0x01cf);
+insert into t1 values (_ucs2 0x01d0),(_ucs2 0x01d1),(_ucs2 0x01d2),(_ucs2 0x01d3);
+insert into t1 values (_ucs2 0x01d4),(_ucs2 0x01d5),(_ucs2 0x01d6),(_ucs2 0x01d7);
+insert into t1 values (_ucs2 0x01d8),(_ucs2 0x01d9),(_ucs2 0x01da),(_ucs2 0x01db);
+insert into t1 values (_ucs2 0x01dc),(_ucs2 0x01dd),(_ucs2 0x01de),(_ucs2 0x01df);
+insert into t1 values (_ucs2 0x01e0),(_ucs2 0x01e1),(_ucs2 0x01e2),(_ucs2 0x01e3);
+insert into t1 values (_ucs2 0x01e4),(_ucs2 0x01e5),(_ucs2 0x01e6),(_ucs2 0x01e7);
+insert into t1 values (_ucs2 0x01e8),(_ucs2 0x01e9),(_ucs2 0x01ea),(_ucs2 0x01eb);
+insert into t1 values (_ucs2 0x01ec),(_ucs2 0x01ed),(_ucs2 0x01ee),(_ucs2 0x01ef);
+insert into t1 values (_ucs2 0x01f0),(_ucs2 0x01f1),(_ucs2 0x01f2),(_ucs2 0x01f3);
+insert into t1 values (_ucs2 0x01f4),(_ucs2 0x01f5),(_ucs2 0x01f6),(_ucs2 0x01f7);
+insert into t1 values (_ucs2 0x01f8),(_ucs2 0x01f9),(_ucs2 0x01fa),(_ucs2 0x01fb);
+insert into t1 values (_ucs2 0x01fc),(_ucs2 0x01fd),(_ucs2 0x01fe),(_ucs2 0x01ff);
+insert into t1 values ('AA'),('Aa'),('aa'),('aA');
+insert into t1 values ('CH'),('Ch'),('ch'),('cH');
+insert into t1 values ('DZ'),('Dz'),('dz'),('dZ');
+insert into t1 values ('IJ'),('Ij'),('ij'),('iJ');
+insert into t1 values ('LJ'),('Lj'),('lj'),('lJ');
+insert into t1 values ('LL'),('Ll'),('ll'),('lL');
+insert into t1 values ('NJ'),('Nj'),('nj'),('nJ');
+insert into t1 values ('OE'),('Oe'),('oe'),('oE');
+insert into t1 values ('SS'),('Ss'),('ss'),('sS');
+insert into t1 values ('RR'),('Rr'),('rr'),('rR');
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_unicode_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_icelandic_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Â,Ã,à,â,ã,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Ã,á
+Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ã,ð
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+E,e,È,Ê,Ë,è,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+É,é
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,ÃŽ,Ã,ì,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+Ã,í
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ô,Õ,ò,ô,õ,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ó,ó
+Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Û,Ü,ù,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ú,ú
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,ÿ,Ŷ,ŷ,Ÿ
+Ã,ý
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Þ,þ
+Ä,Æ,ä,æ
+Ö,Ø,ö,ø
+Ã…,Ã¥
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_latvian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,Ċ,ċ
+CH,Ch,cH,ch
+ÄŒ,Ä
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ǧ,ǧ,Ç´,ǵ
+Ä¢,Ä£
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+Y,y
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ǩ,ǩ
+Ķ,ķ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Ļ,ļ
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Ņ,ņ
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ř,ř
+RR,Rr,rR,rr
+Å–,Å—
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż
+Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_romanian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Ã,Ä,Ã…,à,á,ã,ä,Ã¥,Ä€,Ä,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Ă,ă
+Â,â
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,Ã,ì,í,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+Î,î
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Åž,ÅŸ
+Æ©
+ƪ
+T,t,Ť,ť
+ƾ
+Å¢,Å£
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_slovenian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,Ċ,ċ
+CH,Ch,cH,ch
+ÄŒ,Ä
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż
+Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_polish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Ä„,Ä…
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ć,ć
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ě,ě
+Ę,ę
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Ń,ń
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ô,Õ,Ö,ò,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ó,ó
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Åš,Å›
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ž,ž
+Ź,ź
+Ż,ż
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_estonian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ã…,à,á,â,ã,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz
+DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,ò,ó,ô,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Z,z
+Ž,ž
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,ù,ú,û,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+Õ,õ
+Ä,ä
+Ö,ö
+Ü,ü
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Ź,ź,Ż,ż
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_spanish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Ñ,ñ
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_swedish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,à,á,â,ã,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,ò,ó,ô,õ,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,ù,ú,û,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ãœ,Ã,ü,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ã…,Ã¥
+Ä,Æ,ä,æ
+Ö,Ø,ö,ø
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_turkish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ç,ç
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Äž,ÄŸ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+I,ı
+IJ,Ij
+ƕ,Ƕ
+Ħ,ħ
+i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+iJ,ij,IJ,ij
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,ò,ó,ô,õ,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ö,ö
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Åž,ÅŸ
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,ù,ú,û,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ü,ü
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_czech_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,Ċ,ċ
+cH
+ÄŒ,Ä
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+CH,Ch,ch
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Å”,Å•,Å–,Å—
+RR,Rr,rR,rr
+Ř,ř
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż
+Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_danish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,à,á,â,ã,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+aA
+Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,ò,ó,ô,õ,ÅŒ,Å,ÅŽ,Å,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,ù,ú,û,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ãœ,Ã,ü,ý,ÿ,Å°,ű,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ä,Æ,ä,æ
+Ö,Ø,ö,ø,Å,Å‘
+AA,Aa,aa,Ã…,Ã¥
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_lithuanian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,CH,Ch,c,ch,Ç,ç,Ć,ć,Ĉ,ĉ,Ċ,ċ
+cH
+ÄŒ,Ä
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,Y,i,y,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż
+Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_spanish2_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+cH
+CH,Ch,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,Ä°,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+lL
+LL,Ll,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Ñ,ñ
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,RR,Rr,r,rr,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+rR
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 9b955667e69..4ab8cc83d0c 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -47,6 +47,15 @@ t1 CREATE TABLE `t1` (
`r` char(10) character set ucs2 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
+create table t2(f1 Char(30));
+insert into t2 values ("103000"), ("22720000"), ("3401200"), ("78000");
+select lpad(f1, 12, "-o-/") from t2;
+lpad(f1, 12, "-o-/")
+-o-/-o103000
+-o-/22720000
+-o-/-3401200
+-o-/-o-78000
+drop table t2;
SET NAMES koi8r;
SET character_set_connection=ucs2;
create table t1 (a varchar(10) character set ucs2, key(a));
diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result
index cc062094535..7c3ae52cbc9 100644
--- a/mysql-test/r/ctype_ujis.result
+++ b/mysql-test/r/ctype_ujis.result
@@ -111,3 +111,18 @@ no index
¤¢
¤¢
drop table t1;
+CREATE TABLE t1 (
+a char(1) NOT NULL default '',
+b enum('¤¢','¤¤') default NULL
+) CHARACTER SET ujis;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(1) NOT NULL default '',
+ `b` enum('¤¢','¤¤') default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=ujis
+SHOW COLUMNS FROM t1;
+Field Type Null Key Default Extra
+a char(1)
+b enum('¤¢','¤¤') YES NULL
+DROP TABLE t1;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 28af71b7681..6c11dd210aa 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -218,3 +218,25 @@ b
select * from t1 where a = 'b' and a != 'b';
a
drop table t1;
+set names utf8;
+select 'ваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+'ваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]'
+1
+select 'ваÑÑ ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+'ваÑÑ ' rlike '[[:<:]]ваÑÑ[[:>:]]'
+1
+select ' ваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+' ваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]'
+1
+select ' ваÑÑ ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+' ваÑÑ ' rlike '[[:<:]]ваÑÑ[[:>:]]'
+1
+select 'ваÑÑz' rlike '[[:<:]]ваÑÑ[[:>:]]';
+'ваÑÑz' rlike '[[:<:]]ваÑÑ[[:>:]]'
+0
+select 'zваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+'zваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]'
+0
+select 'zваÑÑz' rlike '[[:<:]]ваÑÑ[[:>:]]';
+'zваÑÑz' rlike '[[:<:]]ваÑÑ[[:>:]]'
+0
diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result
index b73953823ca..6a4935ef3f8 100644
--- a/mysql-test/r/date_formats.result
+++ b/mysql-test/r/date_formats.result
@@ -303,14 +303,14 @@ date format str_to_date
2003-01-02 10:11:12 %Y-%m-%d %h:%i:%S 2003-01-02 10:11:12
03-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 0003-01-02 22:11:12
Warnings:
-Note 1292 Truncated wrong string value: '10:20:10AM'
+Warning 1292 Truncated incorrect datetime value: '10:20:10AM'
select date,format,concat(str_to_date(date, format),'') as con from t1;
date format con
10:20:10AM %h:%i:%s 0000-00-00 10:20:10
2003-01-02 10:11:12 %Y-%m-%d %h:%i:%S 2003-01-02 10:11:12
03-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 0003-01-02 22:11:12
Warnings:
-Note 1292 Truncated wrong string value: '10:20:10AM'
+Warning 1292 Truncated incorrect datetime value: '10:20:10AM'
drop table t1;
select get_format(DATE, 'USA') as a;
a
@@ -374,7 +374,7 @@ str_to_date("02 10", "%d %f") as f6;
f1 f2 f3 f4 f5 f6
2003-01-02 10:11:12.001200 2003-01-02 10:11:12 2003-01-02 58:11:12 58:11:12 48:00:00.100000
Warnings:
-Note 1292 Truncated wrong datetime value: '2003-01-02 10:11:12.0012'
+Warning 1292 Truncated incorrect datetime value: '2003-01-02 10:11:12.0012'
drop table t1, t2;
select str_to_date("2003-01-02 10:11:12.0012ABCD", "%Y-%m-%d %H:%i:%S.%f") as f1,
addtime("-01:01:01.01 GGG", "-23:59:59.1") as f2,
@@ -382,13 +382,13 @@ microsecond("1997-12-31 23:59:59.01XXXX") as f3;
f1 f2 f3
2003-01-02 10:11:12.001200 -25:01:00.110000 10000
Warnings:
-Note 1292 Truncated wrong datetime value: '2003-01-02 10:11:12.0012ABCD'
-Note 1292 Truncated wrong time value: '-01:01:01.01 GG'
-Note 1292 Truncated wrong datetime value: '1997-12-31 23:59:59.01XXXX'
+Warning 1292 Truncated incorrect datetime value: '2003-01-02 10:11:12.0012ABCD'
+Warning 1292 Truncated incorrect time value: '-01:01:01.01 GGG'
+Warning 1292 Truncated incorrect time value: '1997-12-31 23:59:59.01XXXX'
select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1,
str_to_date("2003-04-05 10:11:12.101010234567", "%Y-%m-%d %H:%i:%S.%f") as f2;
f1 f2
2003-04-05 2003-04-05 10:11:12.101010
Warnings:
-Note 1292 Truncated wrong date value: '2003-04-05 g'
-Note 1292 Truncated wrong datetime value: '2003-04-05 10:11:12.101010234567'
+Warning 1292 Truncated incorrect date value: '2003-04-05 g'
+Warning 1292 Truncated incorrect datetime value: '2003-04-05 10:11:12.101010234567'
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index f1acc5d2dfa..c6b7a40214d 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -120,3 +120,13 @@ a b
0 10
1 11
drop table t11, t12, t2;
+create table t1 (a int, b int, unique key (a), key (b));
+insert into t1 values (3, 3), (7, 7);
+delete t1 from t1 where a = 3;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+select * from t1;
+a b
+7 7
+drop table t1;
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index c374a334d3d..ddd8f82de2c 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -27,7 +27,7 @@ a y
SELECT a FROM (SELECT 1 FROM (SELECT 1) a HAVING a=1) b;
ERROR 42S22: Unknown column 'a' in 'having clause'
SELECT a,b as a FROM (SELECT '1' as a,'2' as b) b HAVING a=1;
-ERROR 23000: Column: 'a' in having clause is ambiguous
+ERROR 23000: Column 'a' in having clause is ambiguous
SELECT a,2 as a FROM (SELECT '1' as a) b HAVING a=2;
a a
1 2
@@ -204,22 +204,22 @@ x
1
create table t1 select 1 as a;
select 2 as a from (select * from t1) b;
-ERROR 3D000: No Database Selected
+ERROR 3D000: No database selected
use test;
select 2 as a from (select * from t1) b;
a
2
drop table t1;
select mail_id, if(folder.f_description!='', folder.f_description, folder.f_name) as folder_name, date, address_id, phrase, address, subject from folder, (select mail.mail_id as mail_id, date_format(mail.h_date, '%b %e, %Y %h:%i') as date, mail.folder_id, sender.address_id as address_id, sender.phrase as phrase, sender.address as address, mail.h_subject as subject from mail left join mxa as mxa_sender on mail.mail_id=mxa_sender.mail_id and mxa_sender.type='from' left join address as sender on mxa_sender.address_id=sender.address_id mxa as mxa_recipient, address as recipient, where 1 and mail.mail_id=mxa_recipient.mail_id and mxa_recipient.address_id=recipient.address_id and mxa_recipient.type='to' and match(sender.phrase, sender.address, sender.comment) against ('jeremy' in boolean mode) and match(recipient.phrase, recipient.address, recipient.comment) against ('monty' in boolean mode) order by mail.h_date desc limit 0, 25 ) as query where query.folder_id=folder.folder_id;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'mxa as mxa_recipient, address as recipient, where 1 and mail.mail_id=mxa_r' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'mxa as mxa_recipient, address as recipient, where 1 and mail.mail_id=mxa_r' at line 1
create table t1 (a int);
insert into t1 values (1),(2),(3);
update (select * from t1) as t1 set a = 5;
ERROR HY000: The target table t1 of the UPDATE is not updatable
delete from (select * from t1);
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '(select * from t1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(select * from t1)' at line 1
insert into (select * from t1) values (5);
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '(select * from t1) values (5)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(select * from t1) values (5)' at line 1
drop table t1;
create table t1 (E1 INTEGER UNSIGNED NOT NULL, E2 INTEGER UNSIGNED NOT NULL, E3 INTEGER UNSIGNED NOT NULL, PRIMARY KEY(E1)
);
diff --git a/mysql-test/r/flush_table.result b/mysql-test/r/flush_table.result
new file mode 100644
index 00000000000..257f69fa6d9
--- /dev/null
+++ b/mysql-test/r/flush_table.result
@@ -0,0 +1,66 @@
+drop table if exists t1,t2;
+create table t1 (a int not null auto_increment primary key);
+insert into t1 values(0);
+lock table t1 read;
+flush table t1;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
+create table t1(table_id char(20) primary key);
+create table t2(table_id char(20) primary key);
+insert into t1 values ('test.t1');
+insert into t1 values ('');
+insert into t2 values ('test.t2');
+insert into t2 values ('');
+handler t1 open as a1;
+handler t1 open as a2;
+handler t2 open;
+handler a1 read first limit 9;
+table_id
+test.t1
+
+handler a2 read first limit 9;
+table_id
+test.t1
+
+handler t2 read first limit 9;
+table_id
+test.t2
+
+flush tables;
+handler a1 read first limit 9;
+ERROR 42S02: Unknown table 'a1' in HANDLER
+handler a2 read first limit 9;
+ERROR 42S02: Unknown table 'a2' in HANDLER
+handler t2 read first limit 9;
+ERROR 42S02: Unknown table 't2' in HANDLER
+handler t1 open as a1;
+handler t1 open as a2;
+handler t2 open;
+handler a1 read first limit 9;
+table_id
+test.t1
+
+handler a2 read first limit 9;
+table_id
+test.t1
+
+handler t2 read first limit 9;
+table_id
+test.t2
+
+flush table t1;
+handler a1 read first limit 9;
+ERROR 42S02: Unknown table 'a1' in HANDLER
+handler a2 read first limit 9;
+ERROR 42S02: Unknown table 'a2' in HANDLER
+handler t2 read first limit 9;
+table_id
+test.t2
+
+flush table t2;
+handler t2 close;
+ERROR 42S02: Unknown table 't2' in HANDLER
+drop table t1;
+drop table t2;
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index 3106602e718..30c4c75f3d1 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -7,8 +7,8 @@ INSERT INTO t1 VALUES('MySQL has now support', 'for full-text search'),
('Full-text search in MySQL', 'implements vector space model');
SHOW INDEX FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
-t1 1 a 1 a A NULL NULL NULL YES FULLTEXT
-t1 1 a 2 b A NULL NULL NULL YES FULLTEXT
+t1 1 a 1 a NULL NULL NULL NULL YES FULLTEXT
+t1 1 a 2 b NULL NULL NULL NULL YES FULLTEXT
select * from t1 where MATCH(a,b) AGAINST ("collections");
a b
Only MyISAM tables support collections
@@ -223,7 +223,7 @@ id
show keys from t2;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t2 1 tig 1 ticket A NULL NULL NULL YES BTREE
-t2 1 tix 1 inhalt A NULL NULL NULL YES FULLTEXT
+t2 1 tix 1 inhalt NULL NULL NULL NULL YES FULLTEXT
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
@@ -253,11 +253,11 @@ KEY tig (ticket),
fulltext index tix (inhalt)
);
select * from t2 where MATCH inhalt AGAINST (t2.inhalt);
-ERROR HY000: Wrong arguments to AGAINST
+ERROR HY000: Incorrect arguments to AGAINST
select * from t2 where MATCH ticket AGAINST ('foobar');
ERROR HY000: Can't find FULLTEXT index matching the column list
select * from t2,t3 where MATCH (t2.inhalt,t3.inhalt) AGAINST ('foobar');
-ERROR HY000: Wrong arguments to MATCH
+ERROR HY000: Incorrect arguments to MATCH
drop table t1,t2,t3;
CREATE TABLE t1 (
id int(11) auto_increment,
@@ -363,3 +363,14 @@ SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrueck');
t collation(t)
aus Osnabrück latin1_german2_ci
DROP TABLE t1;
+CREATE TABLE t1 (s varchar(255), FULLTEXT (s)) DEFAULT CHARSET=utf8;
+insert into t1 (s) values ('pära para para'),('para para para');
+select * from t1 where match(s) against('para' in boolean mode);
+s
+pära para para
+para para para
+select * from t1 where match(s) against('par*' in boolean mode);
+s
+pära para para
+para para para
+DROP TABLE t1;
diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result
index ef03ec71c69..a3d28471993 100644
--- a/mysql-test/r/func_compress.result
+++ b/mysql-test/r/func_compress.result
@@ -66,5 +66,5 @@ NULL
NULL
Warnings:
Error 1259 ZLIB: Input data corrupted
-Error 1256 Too big size of uncompressed data. The maximum size is 1048576. (probably, length of uncompressed data was corrupted)
+Error 1256 Uncompressed data size too large; the maximum size is 1048576 (probably, length of uncompressed data was corrupted)
drop table t1;
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 60a28e5018f..0c8054c1f03 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -149,19 +149,19 @@ grp group_concat(c order by c)
3 D,D,E
4
5 NULL
-set group_concat_max_len = 5;
+set group_concat_max_len = 4;
select grp,group_concat(c) from t1 group by grp;
grp group_concat(c)
1 NULL
2 b
-3 D,D,E
+3 D,D,
4
5 NULL
Warnings:
-Warning 1260 1 line(s) was(were) cut by group_concat()
+Warning 1260 1 line(s) were cut by GROUP_CONCAT()
show warnings;
Level Code Message
-Warning 1260 1 line(s) was(were) cut by group_concat()
+Warning 1260 1 line(s) were cut by GROUP_CONCAT()
set group_concat_max_len = 1024;
select group_concat(sum(a)) from t1 group by grp;
ERROR HY000: Invalid use of group function
@@ -172,7 +172,7 @@ create table t1 ( URL_ID int(11), URL varchar(80));
create table t2 ( REQ_ID int(11), URL_ID int(11));
insert into t1 values (4,'www.host.com'), (5,'www.google.com'),(5,'www.help.com');
insert into t2 values (1,4), (5,4), (5,5);
-select REQ_ID, Group_Concat(URL) as URL from t1, t2 where
+select REQ_ID, Group_Concat(URL) as URL from t1, t2 where
t2.URL_ID = t1.URL_ID group by REQ_ID;
REQ_ID URL
1 X
@@ -310,3 +310,14 @@ GROUP_CONCAT(t1.a*t2.a ORDER BY t2.a)
1,2
2,4
DROP TABLE t1, t2;
+CREATE TABLE t1 (a char(4));
+INSERT INTO t1 VALUES ('John'), ('Anna'), ('Bill');
+SELECT GROUP_CONCAT(a SEPARATOR '||') AS names FROM t1
+HAVING names LIKE '%An%';
+names
+John||Anna||Bill
+SELECT GROUP_CONCAT(a SEPARATOR '###') AS names FROM t1
+HAVING LEFT(names, 1) ='J';
+names
+John###Anna###Bill
+DROP TABLE t1;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index 453110dc305..ee364bee56c 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -656,3 +656,31 @@ select stddev(2) from t1;
stddev(2)
NULL
drop table t1;
+create table t1 (a int);
+insert into t1 values (1),(2);
+prepare stmt1 from 'SELECT COUNT(*) FROM t1';
+execute stmt1;
+COUNT(*)
+2
+execute stmt1;
+COUNT(*)
+2
+execute stmt1;
+COUNT(*)
+2
+deallocate prepare stmt1;
+drop table t1;
+create table t1 (a int, primary key(a));
+insert into t1 values (1),(2);
+prepare stmt1 from 'SELECT max(a) FROM t1';
+execute stmt1;
+max(a)
+2
+execute stmt1;
+max(a)
+2
+execute stmt1;
+max(a)
+2
+deallocate prepare stmt1;
+drop table t1;
diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result
index ce26a0bf30a..4c8a0561b0a 100644
--- a/mysql-test/r/func_if.result
+++ b/mysql-test/r/func_if.result
@@ -77,3 +77,9 @@ select min(if(y -x > 5,y,NULL)), max(if(y - x > 5,y,NULL)) from t1;
min(if(y -x > 5,y,NULL)) max(if(y - x > 5,y,NULL))
6 56
drop table t1;
+create table t1 (a int);
+insert t1 values (1),(2);
+select if(1>2,a,avg(a)) from t1;
+if(1>2,a,avg(a))
+1.5000
+drop table t1;
diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result
index d4819cbe949..e32a4dcd85a 100644
--- a/mysql-test/r/func_like.result
+++ b/mysql-test/r/func_like.result
@@ -45,6 +45,12 @@ a\b
select * from t1 where a like 'a\\%' escape '#' and a like 'a\\\\b';
a
a\b
+prepare stmt1 from 'select * from t1 where a like \'a\\%\' escape ?';
+set @esc='#';
+execute stmt1 using @esc;
+a
+a\b
+deallocate prepare stmt1;
drop table t1;
create table t1 (a datetime);
insert into t1 values ('2004-03-11 12:00:21');
diff --git a/mysql-test/r/func_regexp.result b/mysql-test/r/func_regexp.result
index 7f977e2782b..8228d6982d3 100644
--- a/mysql-test/r/func_regexp.result
+++ b/mysql-test/r/func_regexp.result
@@ -81,3 +81,20 @@ _latin1'a' regexp _latin1'A' collate latin1_general_ci
select _latin1'a' regexp _latin1'A' collate latin1_bin;
_latin1'a' regexp _latin1'A' collate latin1_bin
0
+create table t1 (a varchar(40));
+insert into t1 values ('C1'),('C2'),('R1'),('C3'),('R2'),('R3');
+prepare stmt1 from 'select a from t1 where a rlike ? order by a';
+set @a="^C.*";
+execute stmt1 using @a;
+a
+C1
+C2
+C3
+set @a="^R.*";
+execute stmt1 using @a;
+a
+R1
+R2
+R3
+deallocate prepare stmt1;
+drop table t1;
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index 3ea4e7f678d..26fd688c312 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -119,6 +119,8 @@ timestamp("2001-12-01", "01:01:01.999999")
select timestamp("2001-13-01", "01:01:01.000001");
timestamp("2001-13-01", "01:01:01.000001")
NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2001-13-01'
select timestamp("2001-12-01", "25:01:01");
timestamp("2001-12-01", "25:01:01")
2001-12-02 01:01:01
@@ -137,12 +139,16 @@ date("1997-12-31 23:59:59.000001")
select date("1997-13-31 23:59:59.000001");
date("1997-13-31 23:59:59.000001")
NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '1997-13-31 23:59:59.000001'
select time("1997-12-31 23:59:59.000001");
time("1997-12-31 23:59:59.000001")
23:59:59.000001
select time("1997-12-31 25:59:59.000001");
time("1997-12-31 25:59:59.000001")
NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '1997-12-31 25:59:59.000001'
select microsecond("1997-12-31 23:59:59.000001");
microsecond("1997-12-31 23:59:59.000001")
1
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 569b4da0f85..f91691853b9 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -528,6 +528,9 @@ latin2_general_ci 3
select collation(replace(_latin2'abcd',_latin2'b',_latin2'B')), coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B'));
collation(replace(_latin2'abcd',_latin2'b',_latin2'B')) coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B'))
latin2_general_ci 3
+select collation(encode('abcd','ab')), coercibility(encode('abcd','ab'));
+collation(encode('abcd','ab')) coercibility(encode('abcd','ab'))
+binary 3
create table t1
select
bin(130),
@@ -559,7 +562,8 @@ quote(_latin2'ab'),
soundex(_latin2'ab'),
substring(_latin2'ab',1),
insert(_latin2'abcd',2,3,_latin2'ef'),
-replace(_latin2'abcd',_latin2'b',_latin2'B')
+replace(_latin2'abcd',_latin2'b',_latin2'B'),
+encode('abcd','ab')
;
Warnings:
Warning 1265 Data truncated for column 'format(130,10)' at row 1
@@ -595,7 +599,8 @@ t1 CREATE TABLE `t1` (
`soundex(_latin2'ab')` char(4) character set latin2 NOT NULL default '',
`substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '',
`insert(_latin2'abcd',2,3,_latin2'ef')` char(6) character set latin2 NOT NULL default '',
- `replace(_latin2'abcd',_latin2'b',_latin2'B')` char(4) character set latin2 NOT NULL default ''
+ `replace(_latin2'abcd',_latin2'b',_latin2'B')` char(4) character set latin2 NOT NULL default '',
+ `encode('abcd','ab')` binary(4) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select SUBSTR('abcdefg',3,2);
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index c0c2a29772b..64ace522fe6 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -411,9 +411,13 @@ INSERT INTO t1 VALUES ('');
SELECT month(updated) from t1;
month(updated)
NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: ''
SELECT year(updated) from t1;
year(updated)
NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: ''
drop table t1;
create table t1 (d date, dt datetime, t timestamp, c char(10));
insert into t1 values ("0000-00-00", "0000-00-00", "0000-00-00", "0000-00-00");
@@ -585,7 +589,9 @@ a1 a2 a3 a4
28 28 29 29
select date_add(time,INTERVAL 1 SECOND) from t1;
date_add(time,INTERVAL 1 SECOND)
-2006-07-08 00:00:01
+NULL
+Warnings:
+Warning 1264 Data truncated; out of range for column 'time' at row 1
drop table t1;
select last_day('2000-02-05') as f1, last_day('2002-12-31') as f2,
last_day('2003-03-32') as f3, last_day('2003-04-01') as f4,
@@ -593,6 +599,8 @@ last_day('2001-01-01 01:01:01') as f5, last_day(NULL),
last_day('2001-02-12');
f1 f2 f3 f4 f5 last_day(NULL) last_day('2001-02-12')
2000-02-29 2002-12-31 NULL 2003-04-30 2001-01-31 NULL 2001-02-28
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2003-03-32'
create table t1 select last_day('2000-02-05') as a,
from_days(to_days("960101")) as b;
describe t1;
diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index b66ef6d6a31..3fb1a5dd31c 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -167,12 +167,10 @@ count(*)
150
EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range g g 32 NULL 4 Using where
+1 SIMPLE t1 range g g 32 NULL 7 Using where
SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
fid AsText(g)
1 LINESTRING(150 150,150 150)
-11 LINESTRING(140 140,160 160)
-2 LINESTRING(149 149,151 151)
3 LINESTRING(148 148,152 152)
4 LINESTRING(147 147,153 153)
5 LINESTRING(146 146,154 154)
@@ -181,6 +179,8 @@ fid AsText(g)
8 LINESTRING(143 143,157 157)
9 LINESTRING(142 142,158 158)
10 LINESTRING(141 141,159 159)
+11 LINESTRING(140 140,160 160)
+2 LINESTRING(149 149,151 151)
DROP TABLE t1;
CREATE TABLE t2 (
fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
@@ -305,10 +305,10 @@ id select_type table type possible_keys key key_len ref rows Extra
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
fid AsText(g)
+46 LINESTRING(51 41,60 50)
+56 LINESTRING(41 41,50 50)
45 LINESTRING(51 51,60 60)
55 LINESTRING(41 51,50 60)
-56 LINESTRING(41 41,50 50)
-46 LINESTRING(51 41,60 50)
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(LineString(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10)))));
SELECT count(*) FROM t2;
count(*)
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index c47530cdc46..0ae4ec8dee1 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -129,7 +129,7 @@ delete from mysql.columns_priv where user='mysqltest_1' or user="mysqltest_2" or
flush privileges;
drop table t1;
GRANT FILE on mysqltest.* to mysqltest_1@localhost;
-ERROR HY000: Wrong usage of DB GRANT and GLOBAL PRIVILEGES
+ERROR HY000: Incorrect usage of DB GRANT and GLOBAL PRIVILEGES
select 1;
1
1
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index d0765e2721f..6f341e12344 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -10,7 +10,7 @@ current_user
mysqltest_1@localhost
grant all privileges on `my\_1`.* to mysqltest_2@localhost with grant option;
grant all privileges on `my_%`.* to mysqltest_3@localhost with grant option;
-ERROR 42000: Access denied for user: 'mysqltest_1'@'localhost' to database 'my_%'
+ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'my_%'
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result
index 48068c0f68d..b890f2e454e 100644
--- a/mysql-test/r/grant_cache.result
+++ b/mysql-test/r/grant_cache.result
@@ -134,7 +134,7 @@ a b c a
1 1 1 test.t1
2 2 2 test.t1
select * from t2;
-ERROR 42000: select command denied to user: 'mysqltest_2'@'localhost' for table 't2'
+ERROR 42000: select command denied to user 'mysqltest_2'@'localhost' for table 't2'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
@@ -148,17 +148,17 @@ select "user3";
user3
user3
select * from t1;
-ERROR 42000: select command denied to user: 'mysqltest_3'@'localhost' for column 'b' in table 't1'
+ERROR 42000: select command denied to user 'mysqltest_3'@'localhost' for column 'b' in table 't1'
select a from t1;
a
1
2
select c from t1;
-ERROR 42000: SELECT command denied to user: 'mysqltest_3'@'localhost' for column 'c' in table 't1'
+ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'c' in table 't1'
select * from t2;
-ERROR 42000: select command denied to user: 'mysqltest_3'@'localhost' for table 't2'
+ERROR 42000: select command denied to user 'mysqltest_3'@'localhost' for table 't2'
select mysqltest.t1.c from test.t1,mysqltest.t1;
-ERROR 42000: SELECT command denied to user: 'mysqltest_3'@'localhost' for column 'c' in table 't1'
+ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'c' in table 't1'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
@@ -176,7 +176,7 @@ Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
select a from t1;
-ERROR 3D000: No Database Selected
+ERROR 3D000: No database selected
select * from mysqltest.t1,test.t1;
a b c a
1 1 1 test.t1
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
index fddad8dba51..f66e9f1759d 100644
--- a/mysql-test/r/handler.result
+++ b/mysql-test/r/handler.result
@@ -6,7 +6,7 @@ insert into t1 values
(20,"ggg"),(21,"hhh"),(22,"iii");
handler t1 open as t2;
handler t2 read a=(SELECT 1);
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1
handler t2 read a first;
a b
14 aaa
@@ -51,7 +51,7 @@ handler t2 read a=(16);
a b
16 ccc
handler t2 read a=(19,"fff");
-ERROR 42000: Too many key parts specified. Max 1 parts allowed
+ERROR 42000: Too many key parts specified; max 1 parts allowed
handler t2 read b=(19,"fff");
a b
19 fff
@@ -135,7 +135,7 @@ handler t2 read next;
a b
19 fff
handler t2 read last;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
handler t2 close;
handler t1 open as t2;
drop table t1;
@@ -173,7 +173,7 @@ handler t1 open;
handler t1 read a=(W);
ERROR 42S22: Unknown column 'W' in 'field list'
handler t1 read a=(a);
-ERROR HY000: Wrong arguments to HANDLER ... READ
+ERROR HY000: Incorrect arguments to HANDLER ... READ
drop table t1;
create table t1 (a char(5));
insert into t1 values ("Ok");
diff --git a/mysql-test/r/have_archive.require b/mysql-test/r/have_archive.require
new file mode 100644
index 00000000000..c4b4ba24fcd
--- /dev/null
+++ b/mysql-test/r/have_archive.require
@@ -0,0 +1,2 @@
+Variable_name Value
+have_archive YES
diff --git a/mysql-test/r/have_debug.require b/mysql-test/r/have_debug.require
new file mode 100644
index 00000000000..714922cee63
--- /dev/null
+++ b/mysql-test/r/have_debug.require
@@ -0,0 +1,2 @@
+debug
+1
diff --git a/mysql-test/r/have_geometry.require b/mysql-test/r/have_geometry.require
new file mode 100644
index 00000000000..ba515a4bbb6
--- /dev/null
+++ b/mysql-test/r/have_geometry.require
@@ -0,0 +1,2 @@
+Variable_name Value
+have_geometry YES
diff --git a/mysql-test/r/innodb_cache.result b/mysql-test/r/innodb_cache.result
index 5c5e0bb6dfe..ec43cbe10b2 100644
--- a/mysql-test/r/innodb_cache.result
+++ b/mysql-test/r/innodb_cache.result
@@ -98,7 +98,7 @@ commit;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
-drop table if exists t1;
+drop table t3,t2,t1;
CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) ENGINE=InnoDB;
select count(*) from t1;
count(*)
@@ -108,3 +108,22 @@ select count(*) from t1;
count(*)
1
drop table t1;
+set GLOBAL query_cache_size=1355776;
+CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY a (a)) ENGINE=innodb;
+CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY b (b)) ENGINE=innodb;
+CREATE TABLE t3 ( id int(10) NOT NULL auto_increment, t1_id int(10) NOT NULL default '0', t2_id int(10) NOT NULL default '0', state int(11) default NULL, PRIMARY KEY (id), UNIQUE KEY t1_id (t1_id,t2_id), KEY t2_id (t2_id,t1_id), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`t2_id`) REFERENCES `t2` (`id`)) ENGINE=innodb;
+INSERT INTO t1 VALUES (1,'me');
+INSERT INTO t2 VALUES (1,'you');
+INSERT INTO t3 VALUES (2,1,1,2);
+delete from t3 where t1_id = 1 and t2_id = 1;
+select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc;
+id a
+begin;
+insert into t3 VALUES ( NULL, 1, 1, 2 );
+insert into t3 VALUES ( NULL, 1, 1, 2 );
+ERROR 23000: Duplicate entry '1-1' for key 2
+commit;
+select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc;
+id a
+1 me
+drop table t3,t2,t1;
diff --git a/mysql-test/r/innodb_handler.result b/mysql-test/r/innodb_handler.result
index a608e5c71ab..7f4960ffa35 100644
--- a/mysql-test/r/innodb_handler.result
+++ b/mysql-test/r/innodb_handler.result
@@ -49,7 +49,7 @@ handler t2 read a=(16);
a b
16 ccc
handler t2 read a=(19,"fff");
-ERROR 42000: Too many key parts specified. Max 1 parts allowed
+ERROR 42000: Too many key parts specified; max 1 parts allowed
handler t2 read b=(19,"fff");
a b
19 fff
@@ -130,7 +130,7 @@ handler t2 read next;
a b
18 eee
handler t2 read last;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
handler t2 close;
handler t1 open as t2;
handler t2 read first;
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 0aaf77cd623..a666e016348 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -63,7 +63,7 @@ insert into t1 values(NULL);
ERROR 23000: Column 'id' cannot be null
insert into t1 values (1), (NULL), (2);
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'id' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'id' at row 2
select * from t1;
id
1
@@ -159,18 +159,18 @@ insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@val
Warnings:
Warning 1265 Data truncated for column 'f_double' at row 1
Warning 1265 Data truncated for column 'f_float' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float' at row 1
Warning 1265 Data truncated for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
Warning 1265 Data truncated for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
Warning 1265 Data truncated for column 'f_double_u' at row 1
Warning 1265 Data truncated for column 'f_float_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
Warning 1265 Data truncated for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
Warning 1265 Data truncated for column 'f_float_3_1_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
number 4
original_value 1e+1111111111a
@@ -187,19 +187,19 @@ insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@val
Warnings:
Warning 1265 Data truncated for column 'f_double' at row 1
Warning 1265 Data truncated for column 'f_float' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float' at row 1
Warning 1265 Data truncated for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
Warning 1265 Data truncated for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
Warning 1265 Data truncated for column 'f_double_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_u' at row 1
Warning 1265 Data truncated for column 'f_float_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
Warning 1265 Data truncated for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
Warning 1265 Data truncated for column 'f_float_3_1_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
number 5
original_value -1e+1111111111a
@@ -214,12 +214,12 @@ f_float_3_1_u 0.0
set @value= 1e+1111111111;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings:
-Warning 1264 Data truncated, out of range for column 'f_float' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
number 6
original_value 1.7976931348623e+308
@@ -234,13 +234,13 @@ f_float_3_1_u 99.9
set @value= -1e+1111111111;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings:
-Warning 1264 Data truncated, out of range for column 'f_float' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
number 7
original_value -1.7976931348623e+308
@@ -255,12 +255,12 @@ f_float_3_1_u 0.0
set @value= 1e+111;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings:
-Warning 1264 Data truncated, out of range for column 'f_float' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
number 8
original_value 1e+111
@@ -275,13 +275,13 @@ f_float_3_1_u 99.9
set @value= -1e+111;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings:
-Warning 1264 Data truncated, out of range for column 'f_float' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
number 9
original_value -1e+111
@@ -309,10 +309,10 @@ f_float_3_1_u 1.0
set @value= -1;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings:
-Warning 1264 Data truncated, out of range for column 'f_double_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated, out of range for column 'f_float_3_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
+Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
number 11
original_value -1
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index eb8c389e38f..83e47639fe3 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -622,8 +622,8 @@ NULL 2 100
create table t2(No int not null, Field int not null, Count int not null);
insert into t2 Select null, Field, Count From t1 Where Month=20030901 and Type=2;
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'No' at row 1
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'No' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'No' at row 1
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'No' at row 2
select * from t2;
No Field Count
0 1 100
diff --git a/mysql-test/r/isam.result b/mysql-test/r/isam.result
index 2c7b3a4a568..52eb2d73ed5 100644
--- a/mysql-test/r/isam.result
+++ b/mysql-test/r/isam.result
@@ -34,7 +34,7 @@ ERROR 42000: Column 'a' is used with UNIQUE or INDEX but is not defined as NOT N
create table t1 (a int,b text, index(b)) engine=isam;
ERROR 42000: BLOB column 'b' can't be used in key specification with the used table type
create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) engine=isam;
-ERROR 42000: Incorrect table definition; There can only be one auto column and it must be defined as a key
+ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key
create table t1 (ordid int(8), unique (ordid)) engine=isam;
ERROR 42000: Column 'ordid' is used with UNIQUE or INDEX but is not defined as NOT NULL
drop table if exists t1;
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index f9e49c40dc1..db9b051a58f 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -126,7 +126,7 @@ a
1
2
select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a);
-ERROR HY000: Too many tables. MySQL can only use XX tables in a join
+ERROR HY000: Too many tables; MySQL can only use XX tables in a join
drop table t1;
CREATE TABLE t1 (
a int(11) NOT NULL,
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index f8083c9cf70..7915521a9b7 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -106,11 +106,11 @@ grp a c id a c d a
3 6 D 3 6 C 6 6
NULL NULL NULL NULL NULL NULL NULL
explain select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
-ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions
+ERROR 42000: Cross dependency found in OUTER JOIN; examine your ON conditions
select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
-ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions
+ERROR 42000: Cross dependency found in OUTER JOIN; examine your ON conditions
select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
-ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions
+ERROR 42000: Cross dependency found in OUTER JOIN; examine your ON conditions
select t1.*,t2.* from t1 inner join t2 using (a);
grp a c id a c d
1 1 a 1 1 a 1
@@ -400,7 +400,7 @@ insert into t3 values (1);
insert into t4 values (1,1);
insert into t5 values (1,1);
explain select * from t3 left join t4 on t4.seq_1_id = t2.t2_id left join t1 on t1.t1_id = t4.seq_0_id left join t5 on t5.seq_0_id = t1.t1_id left join t2 on t2.t2_id = t5.seq_1_id where t3.t3_id = 23;
-ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions
+ERROR 42000: Cross dependency found in OUTER JOIN; examine your ON conditions
drop table t1,t2,t3,t4,t5;
create table t1 (n int, m int, o int, key(n));
create table t2 (n int not null, m int, o int, primary key(n));
diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result
index 2ea60114066..dd03ef73883 100644
--- a/mysql-test/r/key.result
+++ b/mysql-test/r/key.result
@@ -156,8 +156,8 @@ CREATE TABLE t1 (c CHAR(10) NOT NULL,i INT NOT NULL AUTO_INCREMENT,
UNIQUE (c,i));
INSERT INTO t1 (c) VALUES (NULL),(NULL);
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'c' at row 1
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'c' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'c' at row 1
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'c' at row 2
SELECT * FROM t1;
c i
1
diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
index 1580f51975e..fe8708f882d 100644
--- a/mysql-test/r/key_cache.result
+++ b/mysql-test/r/key_cache.result
@@ -39,9 +39,9 @@ SELECT @@medium.key_buffer_size;
0
SET @@global.key_buffer_size=@save_key_buffer;
SELECT @@default.key_buffer_size;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'default.key_buffer_size' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'default.key_buffer_size' at line 1
SELECT @@skr.storage_engine="test";
-ERROR HY000: Variable 'storage_engine' is not a variable component (Can't be used as XXXX.variable_name)
+ERROR HY000: Variable 'storage_engine' is not a variable component (can't be used as XXXX.variable_name)
select @@keycache1.key_cache_block_size;
@@keycache1.key_cache_block_size
0
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
index 5718397e1ec..c0baabcc507 100644
--- a/mysql-test/r/loaddata.result
+++ b/mysql-test/r/loaddata.result
@@ -44,9 +44,9 @@ create table t1 (a int, b char(10));
load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
Warnings:
Warning 1265 Data truncated for column 'a' at row 3
-Warning 1262 Row 3 was truncated; It contained more data than there were input columns
+Warning 1262 Row 3 was truncated; it contained more data than there were input columns
Warning 1265 Data truncated for column 'a' at row 5
-Warning 1262 Row 5 was truncated; It contained more data than there were input columns
+Warning 1262 Row 5 was truncated; it contained more data than there were input columns
select * from t1;
a b
1 row 1
diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result
index d43a18c6a96..3be73f6cc6a 100644
--- a/mysql-test/r/lowercase_table2.result
+++ b/mysql-test/r/lowercase_table2.result
@@ -32,7 +32,7 @@ T1
ALTER TABLE T1 add b int;
SHOW TABLES LIKE "T1";
Tables_in_test (T1)
-t1
+T1
ALTER TABLE T1 RENAME T2;
SHOW TABLES LIKE "T2";
Tables_in_test (T2)
@@ -41,7 +41,7 @@ LOCK TABLE T2 WRITE;
ALTER TABLE T2 drop b;
SHOW TABLES LIKE "T2";
Tables_in_test (T2)
-t2
+T2
UNLOCK TABLES;
RENAME TABLE T2 TO T1;
SHOW TABLES LIKE "T1";
@@ -121,3 +121,13 @@ LOCATION
Mic-5
Mic-6
drop table T1;
+create table T1 (A int);
+alter table T1 add index (A);
+show tables like 'T1%';
+Tables_in_test (T1%)
+T1
+alter table t1 add index (A);
+show tables like 't1%';
+Tables_in_test (t1%)
+t1
+drop table t1;
diff --git a/mysql-test/r/lowercase_table3.result b/mysql-test/r/lowercase_table3.result
index 362d17e0461..a645e46be9e 100644
--- a/mysql-test/r/lowercase_table3.result
+++ b/mysql-test/r/lowercase_table3.result
@@ -4,7 +4,7 @@ SELECT * from T1;
a
drop table t1;
flush tables;
-CREATE TABLE t1 (a int) type=INNODB;
+CREATE TABLE t1 (a int) ENGINE=INNODB;
SELECT * from T1;
-Can't open file: 'T1.InnoDB'. (errno: 1)
+ERROR HY000: Can't open file: 'T1.InnoDB' (errno: 1)
drop table t1;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 63e0a228aa5..83f8230f11c 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -544,6 +544,24 @@ insert into t1 values (99,NULL);
select * from t4 where a+0 > 90;
a b
99 1
+insert t5 values (1,1);
+ERROR 23000: Duplicate entry '1-1' for key 1
+insert t6 values (2,1);
+ERROR 23000: Duplicate entry '2-1' for key 1
+insert t5 values (1,1) on duplicate key update b=b+10;
+insert t6 values (2,1) on duplicate key update b=b+20;
+select * from t5 where a < 3;
+a b
+1 2
+1 3
+1 4
+1 5
+1 11
+2 2
+2 3
+2 4
+2 5
+2 21
drop table t6, t5, t4, t3, t2, t1;
CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1,1), (2,1);
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index 4668f1262f9..36ed1c6d51d 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -191,7 +191,7 @@ n d unix_timestamp(t)
1 10 1038401397
2 20 1038401397
UPDATE t1,t2 SET 1=2 WHERE t1.n=t2.n;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '1=2 WHERE t1.n=t2.n' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1=2 WHERE t1.n=t2.n' at line 1
drop table t1,t2;
set timestamp=0;
set sql_safe_updates=0;
@@ -446,6 +446,7 @@ grant update on mysqltest.t1 to mysqltest_1@localhost;
update t1, t2 set t1.b=1 where t1.a=t2.a;
update t1, t2 set t1.b=(select t3.b from t3 where t1.a=t3.a) where t1.a=t2.a;
revoke all privileges on mysqltest.t1 from mysqltest_1@localhost;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1';
drop database mysqltest;
create table t1 (a int, primary key (a));
diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result
index f54f233d929..72d7af2ec4f 100644
--- a/mysql-test/r/mysqlbinlog.result
+++ b/mysql-test/r/mysqlbinlog.result
@@ -1,5 +1,5 @@
-drop table if exists t1,t2;
set timestamp=1000000000;
+drop table if exists t1,t2;
create table t1 (word varchar(20));
create table t2 (id int auto_increment not null primary key);
insert into t1 values ("abirvalg");
@@ -16,9 +16,12 @@ flush logs;
--- Local --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
use test;
-SET TIMESTAMP=1000000000;
+
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
SET @@session.sql_mode=0;
+SET TIMESTAMP=1000000000;
+drop table if exists t1,t2;
+SET TIMESTAMP=1000000000;
create table t1 (word varchar(20));
SET TIMESTAMP=1000000000;
create table t2 (id int auto_increment not null primary key);
@@ -57,6 +60,8 @@ insert into t1 values ("Alas");
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
use test;
SET TIMESTAMP=1000000000;
+drop table if exists t1,t2;
+SET TIMESTAMP=1000000000;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
SET @@session.sql_mode=0;
create table t1 (word varchar(20));
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index 01114104088..7e69620394b 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -54,7 +54,10 @@ CREATE TABLE `t1` (
);
INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456);
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!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" */;
@@ -75,6 +78,8 @@ UNLOCK TABLES;
/*!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 */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
@@ -136,9 +141,12 @@ INSERT INTO t1 VALUES ("1\""), ("\"2");
</mysqldump>
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r;
-INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5');
+INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL);
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!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" */;
@@ -151,6 +159,7 @@ CREATE TABLE `t1` (
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
LOCK TABLES `t1` WRITE;
INSERT INTO `t1` VALUES ('абцде');
+INSERT INTO `t1` VALUES (NULL);
UNLOCK TABLES;
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
@@ -158,6 +167,8 @@ UNLOCK TABLES;
/*!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 */;
DROP TABLE t1;
CREATE TABLE t1 (a int) ENGINE=MYISAM;
@@ -208,7 +219,10 @@ CREATE TABLE ```a` (
drop table ```a`;
create table t1(a int);
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!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" */;
@@ -227,6 +241,8 @@ UNLOCK TABLES;
/*!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 */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
@@ -248,7 +264,10 @@ UNLOCK TABLES;
set global sql_mode='ANSI_QUOTES';
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!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" */;
@@ -267,6 +286,8 @@ UNLOCK TABLES;
/*!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 */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
@@ -291,7 +312,10 @@ drop table t1;
create table t1(a int);
insert into t1 values (1),(2),(3);
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!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 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="" */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
@@ -301,6 +325,8 @@ CREATE TABLE `t1` (
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!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 */;
1
2
diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result
new file mode 100644
index 00000000000..6cc6a89d5ad
--- /dev/null
+++ b/mysql-test/r/ndb_alter_table.result
@@ -0,0 +1,29 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+a INT NOT NULL,
+b INT NOT NULL
+) ENGINE=ndbcluster;
+INSERT INTO t1 VALUES (9410,9412);
+ALTER TABLE t1 ADD COLUMN c int not null;
+SELECT * FROM t1;
+a b c
+9410 9412 0
+DROP TABLE t1;
+create table t1 (
+col1 int not null auto_increment primary key,
+col2 varchar(30) not null,
+col3 varchar (20) not null,
+col4 varchar(4) not null,
+col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null,
+col6 int not null, to_be_deleted int);
+insert into t1 values (2,4,3,5,"PENDING",1,7);
+alter table t1
+add column col4_5 varchar(20) not null after col4,
+add column col7 varchar(30) not null after col5,
+add column col8 datetime not null, drop column to_be_deleted,
+change column col2 fourth varchar(30) not null after col3,
+modify column col6 int not null first;
+select * from t1;
+col6 col1 col3 fourth col4 col4_5 col5 col7 col8
+1 2 3 4 5 PENDING 0000-00-00 00:00:00
+drop table t1;
diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result
new file mode 100644
index 00000000000..b0e2aa04f3e
--- /dev/null
+++ b/mysql-test/r/ndb_autodiscover.result
@@ -0,0 +1,183 @@
+drop table if exists t1,t2,t3,t4,t5,t6,t9;
+flush status;
+create table t1(
+id int not null primary key,
+name char(20)
+) engine=ndb;
+insert into t1 values(1, "Autodiscover");
+flush tables;
+select * from t1;
+id name
+1 Autodiscover
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 1
+flush tables;
+insert into t1 values (2, "Auto 2");
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 2
+insert into t1 values (3, "Discover 3");
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 2
+flush tables;
+select * from t1 order by id;
+id name
+1 Autodiscover
+2 Auto 2
+3 Discover 3
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 3
+flush tables;
+update t1 set name="Autodiscover" where id = 2;
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 4
+select * from t1 order by name;
+id name
+2 Autodiscover
+1 Autodiscover
+3 Discover 3
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 4
+flush tables;
+delete from t1 where id = 3;
+select * from t1 order by id;
+id name
+1 Autodiscover
+2 Autodiscover
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 5
+drop table t1;
+flush status;
+create table t2(
+id int not null primary key,
+name char(22)
+) engine=ndb;
+insert into t2 values (1, "Discoverer");
+select * from t2;
+id name
+1 Discoverer
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 0
+flush tables;
+select * from t2;
+id name
+1 Discoverer
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 1
+drop table t2;
+flush status;
+create table t3(
+id int not null primary key,
+name char(255)
+) engine=ndb;
+insert into t3 values (1, "Explorer");
+select * from t3;
+id name
+1 Explorer
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 0
+flush tables;
+create table t3(
+id int not null primary key,
+name char(20), a int, b float, c char(24)
+) engine=ndb;
+ERROR 42S01: Table 't3' already exists
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 1
+SHOW TABLES FROM test;
+Tables_in_test
+create table IF NOT EXISTS t3(
+id int not null primary key,
+id2 int not null,
+name char(20)
+) engine=ndb;
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 2
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `id` int(11) NOT NULL default '0',
+ `name` char(255) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+select * from t3;
+id name
+1 Explorer
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 2
+drop table t3;
+flush status;
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 0
+create table t5(
+id int not null primary key,
+name char(200)
+) engine=ndb;
+insert into t5 values (1, "Magnus");
+select * from t5;
+id name
+1 Magnus
+ALTER TABLE t5 ADD COLUMN adress char(255) FIRST;
+select * from t5;
+adress id name
+NULL 1 Magnus
+insert into t5 values
+("Adress for record 2", 2, "Carl-Gustav"),
+("Adress for record 3", 3, "Karl-Emil");
+update t5 set name="Bertil" where id = 2;
+select * from t5 order by id;
+adress id name
+NULL 1 Magnus
+Adress for record 2 2 Bertil
+Adress for record 3 3 Karl-Emil
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 0
+drop table t5;
+flush status;
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 0
+create table t6(
+id int not null primary key,
+name char(20)
+) engine=ndb;
+insert into t6 values (1, "Magnus");
+select * from t6;
+id name
+1 Magnus
+ALTER TABLE t6 ADD COLUMN adress char(255) FIRST;
+select * from t6;
+adress id name
+NULL 1 Magnus
+insert into t6 values
+("Adress for record 2", 2, "Carl-Gustav"),
+("Adress for record 3", 3, "Karl-Emil");
+update t6 set name="Bertil" where id = 2;
+select * from t6 order by id;
+adress id name
+NULL 1 Magnus
+Adress for record 2 2 Bertil
+Adress for record 3 3 Karl-Emil
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 0
+drop table t6;
+CREATE TABLE t9 (
+a int NOT NULL PRIMARY KEY,
+b int
+) engine=ndb;
+insert t9 values(1, 2), (2,3), (3, 4), (4, 5);
diff --git a/mysql-test/r/ndb_autodiscover2.result b/mysql-test/r/ndb_autodiscover2.result
new file mode 100644
index 00000000000..08803d997a5
--- /dev/null
+++ b/mysql-test/r/ndb_autodiscover2.result
@@ -0,0 +1,10 @@
+select * from t9 order by a;
+a b
+1 2
+2 3
+3 4
+4 5
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 1
+drop table t9;
diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result
index ac550937146..0e7b039a5f9 100644
--- a/mysql-test/r/ndb_basic.result
+++ b/mysql-test/r/ndb_basic.result
@@ -1,4 +1,4 @@
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7;
CREATE TABLE t1 (
pk1 INT NOT NULL PRIMARY KEY,
attr1 INT NOT NULL
@@ -25,11 +25,59 @@ pk1 attr1
DELETE FROM t1;
SELECT * FROM t1;
pk1 attr1
-INSERT INTO t1 VALUES (9410,9412);
+INSERT INTO t1 VALUES (9410,9412), (9411, 9413), (9408, 8765),
+(7,8), (8,9), (9,10), (10,11), (11,12), (12,13), (13,14);
+UPDATE t1 SET attr1 = 9999;
+SELECT * FROM t1 ORDER BY pk1;
+pk1 attr1
+7 9999
+8 9999
+9 9999
+10 9999
+11 9999
+12 9999
+13 9999
+9408 9999
+9410 9999
+9411 9999
+UPDATE t1 SET attr1 = 9998 WHERE pk1 < 1000;
+SELECT * FROM t1 ORDER BY pk1;
+pk1 attr1
+7 9998
+8 9998
+9 9998
+10 9998
+11 9998
+12 9998
+13 9998
+9408 9999
+9410 9999
+9411 9999
+UPDATE t1 SET attr1 = 9997 WHERE attr1 = 9999;
+SELECT * FROM t1 ORDER BY pk1;
+pk1 attr1
+7 9998
+8 9998
+9 9998
+10 9998
+11 9998
+12 9998
+13 9998
+9408 9997
+9410 9997
+9411 9997
DELETE FROM t1 WHERE pk1 = 9410;
-SELECT * FROM t1;
+SELECT * FROM t1 ORDER BY pk1;
pk1 attr1
-INSERT INTO t1 VALUES (9410,9412), (9411, 9413), (9408, 8765);
+7 9998
+8 9998
+9 9998
+10 9998
+11 9998
+12 9998
+13 9998
+9408 9997
+9411 9997
DELETE FROM t1;
SELECT * FROM t1;
pk1 attr1
@@ -80,3 +128,213 @@ attr1 INT NOT NULL
) ENGINE=NDB;
INSERT INTO t1 values(1, 9999);
DROP TABLE t1;
+CREATE TABLE t2 (
+a bigint unsigned NOT NULL PRIMARY KEY,
+b int unsigned not null,
+c int unsigned
+) engine=ndbcluster;
+CREATE TABLE t3 (
+a bigint unsigned NOT NULL,
+b bigint unsigned not null,
+c bigint unsigned,
+PRIMARY KEY(a)
+) engine=ndbcluster;
+CREATE TABLE t4 (
+a bigint unsigned NOT NULL,
+b bigint unsigned not null,
+c bigint unsigned NOT NULL,
+d int unsigned,
+PRIMARY KEY(a, b, c)
+) engine=ndbcluster;
+select * from t2 where a = 7 order by b;
+a b c
+7 16 5
+select * from t2 where a = 7 order by a;
+a b c
+7 16 5
+select * from t2 where a = 7 order by 2;
+a b c
+7 16 5
+select * from t2 where a = 7 order by c;
+a b c
+7 16 5
+select * from t2 where a = 7 and b = 16 order by b;
+a b c
+7 16 5
+select * from t2 where a = 7 and b = 16 order by a;
+a b c
+7 16 5
+select * from t2 where a = 7 and b = 17 order by a;
+a b c
+select * from t2 where a = 7 and b != 16 order by b;
+a b c
+select * from t2 where a = 7 and b = 16 and c = 5 order by b;
+a b c
+7 16 5
+select * from t2 where a = 7 and b = 16 and c = 5 order by a;
+a b c
+7 16 5
+select * from t2 where a = 7 and b = 16 and c = 6 order by a;
+a b c
+select * from t2 where a = 7 and b != 16 and c = 5 order by b;
+a b c
+select * from t3 where a = 7 order by b;
+a b c
+7 16 5
+select * from t3 where a = 7 order by a;
+a b c
+7 16 5
+select * from t3 where a = 7 order by 2;
+a b c
+7 16 5
+select * from t3 where a = 7 order by c;
+a b c
+7 16 5
+select * from t3 where a = 7 and b = 16 order by b;
+a b c
+7 16 5
+select * from t3 where a = 7 and b = 16 order by a;
+a b c
+7 16 5
+select * from t3 where a = 7 and b = 17 order by a;
+a b c
+select * from t3 where a = 7 and b != 16 order by b;
+a b c
+select * from t4 where a = 7 order by b;
+a b c d
+7 16 5 26007
+select * from t4 where a = 7 order by a;
+a b c d
+7 16 5 26007
+select * from t4 where a = 7 order by 2;
+a b c d
+7 16 5 26007
+select * from t4 where a = 7 order by c;
+a b c d
+7 16 5 26007
+select * from t4 where a = 7 and b = 16 order by b;
+a b c d
+7 16 5 26007
+select * from t4 where a = 7 and b = 16 order by a;
+a b c d
+7 16 5 26007
+select * from t4 where a = 7 and b = 17 order by a;
+a b c d
+select * from t4 where a = 7 and b != 16 order by b;
+a b c d
+delete from t2;
+delete from t3;
+delete from t4;
+drop table t2;
+drop table t3;
+drop table t4;
+CREATE TABLE t5 (
+a bigint unsigned NOT NULL,
+b bigint unsigned not null,
+c bigint unsigned NOT NULL,
+d int unsigned,
+PRIMARY KEY(a, b, c)
+) engine=ndbcluster;
+insert into t5 values(10, 19, 5, 26010);
+delete from t5 where a=10 and b=19 and c=5;
+select * from t5;
+a b c d
+insert into t5 values(10, 19, 5, 26010);
+update t5 set d=21997 where a=10 and b=19 and c=5;
+select * from t5;
+a b c d
+10 19 5 21997
+delete from t5;
+drop table t5;
+CREATE TABLE t6 (
+adress char(255),
+a int NOT NULL PRIMARY KEY,
+b int
+) engine = NDB;
+insert into t6 values
+("Nice road 3456", 1, 23),
+("Street Road 78", 3, 92),
+("Road street 89C", 5, 71),
+(NULL, 7, NULL);
+select * from t6 order by a;
+adress a b
+Nice road 3456 1 23
+Street Road 78 3 92
+Road street 89C 5 71
+NULL 7 NULL
+select a, b from t6 order by a;
+a b
+1 23
+3 92
+5 71
+7 NULL
+update t6 set adress="End of road 09" where a=3;
+update t6 set b=181, adress="Street 76" where a=7;
+select * from t6 order by a;
+adress a b
+Nice road 3456 1 23
+End of road 09 3 92
+Road street 89C 5 71
+Street 76 7 181
+select * from t6 where a=1;
+adress a b
+Nice road 3456 1 23
+delete from t6 where a=1;
+select * from t6 order by a;
+adress a b
+End of road 09 3 92
+Road street 89C 5 71
+Street 76 7 181
+delete from t6 where b=71;
+select * from t6 order by a;
+adress a b
+End of road 09 3 92
+Street 76 7 181
+drop table t6;
+CREATE TABLE t7 (
+adress char(255),
+a int NOT NULL,
+b int,
+c int NOT NULL,
+PRIMARY KEY(a, c)
+) engine = NDB;
+insert into t7 values
+("Highway 3456", 1, 23, 2),
+("Street Road 78", 3, 92, 3),
+("Main street 89C", 5, 71, 4),
+(NULL, 8, NULL, 12);
+select * from t7 order by a;
+adress a b c
+Highway 3456 1 23 2
+Street Road 78 3 92 3
+Main street 89C 5 71 4
+NULL 8 NULL 12
+select a, b from t7 order by a;
+a b
+1 23
+3 92
+5 71
+8 NULL
+update t7 set adress="End of road 09" where a=3;
+update t7 set adress="Gatuvägen 90C" where a=5 and c=4;
+update t7 set adress="No adress" where adress is NULL;
+select * from t7 order by a;
+adress a b c
+Highway 3456 1 23 2
+End of road 09 3 92 3
+Gatuvägen 90C 5 71 4
+No adress 8 NULL 12
+select * from t7 where a=1 and c=2;
+adress a b c
+Highway 3456 1 23 2
+delete from t7 where a=1;
+delete from t7 where a=3 and c=3;
+delete from t7 where a=5 and c=4;
+select * from t7;
+adress a b c
+No adress 8 NULL 12
+delete from t7 where b=23;
+select * from t7;
+adress a b c
+No adress 8 NULL 12
+drop table t7;
diff --git a/mysql-test/r/ndb_index.result b/mysql-test/r/ndb_index.result
new file mode 100644
index 00000000000..dd92c237ace
--- /dev/null
+++ b/mysql-test/r/ndb_index.result
@@ -0,0 +1,154 @@
+drop table if exists t1;
+CREATE TABLE t1 (
+PORT varchar(16) NOT NULL,
+ACCESSNODE varchar(16) NOT NULL,
+POP varchar(48) NOT NULL,
+ACCESSTYPE int unsigned NOT NULL,
+CUSTOMER_ID varchar(20) NOT NULL,
+PROVIDER varchar(16),
+TEXPIRE int unsigned,
+NUM_IP int unsigned,
+LEASED_NUM_IP int unsigned,
+LOCKED_IP int unsigned,
+STATIC_DNS int unsigned,
+SUSPENDED_SERVICE int unsigned,
+SUSPENDED_REASON int unsigned,
+BGP_COMMUNITY int unsigned,
+INDEX CUSTOMER_ID_INDEX(CUSTOMER_ID),
+INDEX FQPN_INDEX(POP,ACCESSNODE,PORT),
+PRIMARY KEY(POP,ACCESSNODE,PORT,ACCESSTYPE)
+) engine=ndbcluster;
+INSERT INTO t1 VALUES ('port67', 'node78', 'pop98', 1, 'kllopmn', 'pr_43', 121212, 1, 2, 3, 8, NULL, NULL, NULL);
+INSERT INTO t1 VALUES ('port67', 'node78', 'pop99', 2, 'klkighh', 'pr_44', 121213, 3, 3, 6, 7, NULL, NULL, NULL);
+INSERT INTO t1 VALUES ('port79', 'node79', 'pop79', 2, 'kpongfaa', 'pr_44', 981213, 2, 4, 10, 11, 2, 99, 1278);
+select port, accessnode, pop, accesstype from t1 where port='port67' order by accesstype;
+port accessnode pop accesstype
+port67 node78 pop98 1
+port67 node78 pop99 2
+select port, accessnode, pop, accesstype from t1 where port='foo';
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where accessnode='node78' order by accesstype;
+port accessnode pop accesstype
+port67 node78 pop98 1
+port67 node78 pop99 2
+select port, accessnode, pop, accesstype from t1 where accessnode='foo';
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where pop='pop98';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where pop='pop98';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where pop='pop98';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where pop='pop98' order by accesstype;
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where pop='foo';
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where accesstype=1;
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where accesstype=2 order by port;
+port accessnode pop accesstype
+port67 node78 pop99 2
+port79 node79 pop79 2
+select port, accessnode, pop, accesstype from t1 where accesstype=98 order by port;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where customer_id='kllopmn';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where customer_id='KLLOPMN';
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where customer_id='kLLoPMn';
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where customer_id='foo';
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where provider='pr_43';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where provider='foo';
+port accessnode pop accesstype
+select port, accessnode from t1 where texpire=121212;
+port accessnode
+port67 node78
+select port, accessnode from t1 where texpire=2323;
+port accessnode
+select port, accessnode, pop, accesstype from t1 where num_ip=1;
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where num_ip=89;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where leased_num_ip=2;
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where leased_num_ip=89;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where locked_ip=3;
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where locked_ip=89;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where static_dns=8;
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where static_dns=89;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where suspended_service=8;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where suspended_service=89;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where suspended_reason=NULL;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where suspended_reason=89;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where suspended_reason=0;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where bgp_community=NULL;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where bgp_community=89;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where bgp_community=0;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where port='port67' and accessnode='node78' and pop='pop98' and accesstype=1;
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where port='port67' and accesstype=1 and accessnode='node78' and pop='pop98';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where pop='pop98' and port='port67' and accesstype=1 and accessnode='node78';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode from t1 where port='foo' and accessnode='foo' and pop='foo' and accesstype=99;
+port accessnode
+select port, accessnode, pop, accesstype from t1 where port='port67' and pop='pop98' and accesstype=1;
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where accesstype=1 and accessnode='node78' and pop='pop98';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where port='port67' and accesstype=1 and accessnode='node78';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode from t1 where port='foo' and accessnode='foo' and pop='foo';
+port accessnode
+select port, accessnode, pop, accesstype from t1 where customer_id='kllopmn';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where customer_id='kllopmn' and accesstype=1;
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where customer_id='kllopmn' and accesstype=2;
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where accesstype=2 and customer_id='kllopmn';
+port accessnode pop accesstype
+select port, accessnode, pop, accesstype from t1 where pop='pop98' and accessnode='node78' and port='port67';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where pop='pop98' and accessnode='node78' and port='port67' and customer_id='kllopmn';
+port accessnode pop accesstype
+port67 node78 pop98 1
+select port, accessnode, pop, accesstype from t1 where pop='pop98' and accessnode='node78' and port='port67' and customer_id='foo';
+port accessnode pop accesstype
+drop table t1;
diff --git a/mysql-test/r/ndb_index_ordered.result b/mysql-test/r/ndb_index_ordered.result
new file mode 100644
index 00000000000..79472c70e8e
--- /dev/null
+++ b/mysql-test/r/ndb_index_ordered.result
@@ -0,0 +1,190 @@
+drop table if exists t1;
+CREATE TABLE t1 (
+a int unsigned NOT NULL PRIMARY KEY,
+b int unsigned not null,
+c int unsigned,
+KEY(b)
+) engine=ndbcluster;
+insert t1 values(1, 2, 3), (2,3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
+select * from t1 order by b;
+a b c
+1 2 3
+2 3 5
+3 4 6
+4 5 8
+5 6 2
+6 7 2
+select * from t1 where b >= 4 order by b;
+a b c
+3 4 6
+4 5 8
+5 6 2
+6 7 2
+select * from t1 where b = 4 order by b;
+a b c
+3 4 6
+select * from t1 where b > 4 order by b;
+a b c
+4 5 8
+5 6 2
+6 7 2
+select * from t1 where b < 4 order by b;
+a b c
+1 2 3
+2 3 5
+select * from t1 where b <= 4 order by b;
+a b c
+1 2 3
+2 3 5
+3 4 6
+update t1 set c = 3 where b = 3;
+select * from t1 order by a;
+a b c
+1 2 3
+2 3 3
+3 4 6
+4 5 8
+5 6 2
+6 7 2
+update t1 set c = 10 where b >= 6;
+select * from t1 order by a;
+a b c
+1 2 3
+2 3 3
+3 4 6
+4 5 8
+5 6 10
+6 7 10
+update t1 set c = 11 where b < 5;
+select * from t1 order by a;
+a b c
+1 2 11
+2 3 11
+3 4 11
+4 5 8
+5 6 10
+6 7 10
+update t1 set c = 12 where b > 0;
+select * from t1 order by a;
+a b c
+1 2 12
+2 3 12
+3 4 12
+4 5 12
+5 6 12
+6 7 12
+update t1 set c = 13 where b <= 3;
+select * from t1 order by a;
+a b c
+1 2 13
+2 3 13
+3 4 12
+4 5 12
+5 6 12
+6 7 12
+drop table t1;
+CREATE TABLE t1 (
+a int unsigned NOT NULL PRIMARY KEY,
+b int unsigned not null,
+c int unsigned,
+KEY(b)
+) engine=ndbcluster;
+insert t1 values(1, 2, 13), (2,3, 13), (3, 4, 12), (4, 5, 12), (5,6, 12), (6,7, 12);
+delete from t1 where b = 3;
+select * from t1 order by a;
+a b c
+1 2 13
+3 4 12
+4 5 12
+5 6 12
+6 7 12
+delete from t1 where b >= 6;
+select * from t1 order by a;
+a b c
+1 2 13
+3 4 12
+4 5 12
+delete from t1 where b < 4;
+select * from t1 order by a;
+a b c
+3 4 12
+4 5 12
+delete from t1 where b > 5;
+select * from t1 order by a;
+a b c
+3 4 12
+4 5 12
+delete from t1 where b <= 4;
+select * from t1 order by a;
+a b c
+4 5 12
+drop table t1;
+CREATE TABLE t1 (
+a int unsigned NOT NULL PRIMARY KEY,
+b int unsigned not null,
+c int unsigned not null
+) engine = ndb;
+create index a1 on t1 (b, c);
+insert into t1 values (1, 2, 13);
+insert into t1 values (2,3, 13);
+insert into t1 values (3, 4, 12);
+insert into t1 values (4, 5, 12);
+insert into t1 values (5,6, 12);
+insert into t1 values (6,7, 12);
+insert into t1 values (7, 2, 1);
+insert into t1 values (8,3, 6);
+insert into t1 values (9, 4, 12);
+insert into t1 values (14, 5, 4);
+insert into t1 values (15,5,5);
+insert into t1 values (16,5, 6);
+insert into t1 values (17,4,4);
+insert into t1 values (18,1, 7);
+select * from t1 order by a;
+a b c
+1 2 13
+2 3 13
+3 4 12
+4 5 12
+5 6 12
+6 7 12
+7 2 1
+8 3 6
+9 4 12
+14 5 4
+15 5 5
+16 5 6
+17 4 4
+18 1 7
+select * from t1 where b<=5 order by a;
+a b c
+1 2 13
+2 3 13
+3 4 12
+4 5 12
+7 2 1
+8 3 6
+9 4 12
+14 5 4
+15 5 5
+16 5 6
+17 4 4
+18 1 7
+select * from t1 where b<=5 and c=0;
+a b c
+insert into t1 values (19,4, 0);
+select * from t1 where b<=5 and c=0;
+a b c
+19 4 0
+select * from t1 where b=4 and c<=5;
+a b c
+19 4 0
+17 4 4
+select * from t1 where b<=4 and c<=5 order by a;
+a b c
+7 2 1
+17 4 4
+19 4 0
+select * from t1 where b<=5 and c=0 or b<=5 and c=2;
+a b c
+19 4 0
+drop table t1;
diff --git a/mysql-test/r/ndb_index_unique.result b/mysql-test/r/ndb_index_unique.result
new file mode 100644
index 00000000000..ed97e0b110a
--- /dev/null
+++ b/mysql-test/r/ndb_index_unique.result
@@ -0,0 +1,413 @@
+drop table if exists t1, t2, t3, t4, t5, t6, t7;
+CREATE TABLE t1 (
+a int unsigned NOT NULL PRIMARY KEY,
+b int unsigned not null,
+c int unsigned,
+UNIQUE(b)
+) engine=ndbcluster;
+insert t1 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
+select * from t1 order by b;
+a b c
+1 2 3
+2 3 5
+3 4 6
+4 5 8
+5 6 2
+6 7 2
+select * from t1 where b = 4 order by b;
+a b c
+3 4 6
+insert into t1 values(7,8,3);
+select * from t1 where b = 4 order by a;
+a b c
+3 4 6
+drop table t1;
+CREATE TABLE t2 (
+a int unsigned NOT NULL PRIMARY KEY,
+b int unsigned not null,
+c int unsigned not null,
+UNIQUE USING HASH (b, c)
+) engine=ndbcluster;
+insert t2 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
+select * from t2 where a = 3;
+a b c
+3 4 6
+select * from t2 where b = 4;
+a b c
+3 4 6
+select * from t2 where c = 6;
+a b c
+3 4 6
+insert into t2 values(7,8,3);
+select * from t2 where b = 4 order by a;
+a b c
+3 4 6
+drop table t2;
+CREATE TABLE t3 (
+a int unsigned NOT NULL,
+b int unsigned not null,
+c int unsigned,
+PRIMARY KEY USING HASH (a, b)
+) engine=ndbcluster;
+insert t3 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
+select * from t3 where a = 3;
+a b c
+3 4 6
+select * from t3 where b = 4;
+a b c
+3 4 6
+select * from t3 where c = 6;
+a b c
+3 4 6
+insert into t3 values(7,8,3);
+select * from t3 where b = 4 order by a;
+a b c
+3 4 6
+drop table t3;
+CREATE TABLE t1 (
+cid smallint(5) unsigned NOT NULL default '0',
+cv varchar(250) NOT NULL default '',
+PRIMARY KEY (cid),
+UNIQUE KEY cv (cv)
+) engine=ndbcluster;
+INSERT INTO t1 VALUES (8,'dummy');
+CREATE TABLE t2 (
+cid bigint(20) unsigned NOT NULL auto_increment,
+cap varchar(255) NOT NULL default '',
+PRIMARY KEY (cid)
+) engine=ndbcluster;
+CREATE TABLE t3 (
+gid bigint(20) unsigned NOT NULL auto_increment,
+gn varchar(255) NOT NULL default '',
+must tinyint(4) default NULL,
+PRIMARY KEY (gid)
+) engine=ndbcluster;
+INSERT INTO t3 VALUES (1,'V1',NULL);
+CREATE TABLE t4 (
+uid bigint(20) unsigned NOT NULL default '0',
+gid bigint(20) unsigned NOT NULL,
+rid bigint(20) unsigned NOT NULL default '-1',
+cid bigint(20) unsigned NOT NULL default '-1',
+UNIQUE KEY m (uid,gid,rid,cid)
+) engine=ndbcluster;
+INSERT INTO t4 VALUES (1,1,2,4);
+INSERT INTO t4 VALUES (1,1,2,3);
+INSERT INTO t4 VALUES (1,1,5,7);
+INSERT INTO t4 VALUES (1,1,10,8);
+CREATE TABLE t5 (
+rid bigint(20) unsigned NOT NULL auto_increment,
+rl varchar(255) NOT NULL default '',
+PRIMARY KEY (rid)
+) engine=ndbcluster;
+CREATE TABLE t6 (
+uid bigint(20) unsigned NOT NULL auto_increment,
+un varchar(250) NOT NULL default '',
+uc smallint(5) unsigned NOT NULL default '0',
+PRIMARY KEY (uid),
+UNIQUE KEY nc (un,uc)
+) engine=ndbcluster;
+INSERT INTO t6 VALUES (1,'test',8);
+INSERT INTO t6 VALUES (2,'test2',9);
+INSERT INTO t6 VALUES (3,'tre',3);
+CREATE TABLE t7 (
+mid bigint(20) unsigned NOT NULL PRIMARY KEY,
+uid bigint(20) unsigned NOT NULL default '0',
+gid bigint(20) unsigned NOT NULL,
+rid bigint(20) unsigned NOT NULL default '-1',
+cid bigint(20) unsigned NOT NULL default '-1',
+UNIQUE KEY m (uid,gid,rid,cid)
+) engine=ndbcluster;
+INSERT INTO t7 VALUES(1, 1, 1, 1, 1);
+INSERT INTO t7 VALUES(2, 2, 1, 1, 1);
+INSERT INTO t7 VALUES(3, 3, 1, 1, 1);
+INSERT INTO t7 VALUES(4, 4, 1, 1, 1);
+INSERT INTO t7 VALUES(5, 5, 1, 1, 1);
+INSERT INTO t7 VALUES(6, 1, 1, 1, 6);
+INSERT INTO t7 VALUES(7, 2, 1, 1, 7);
+INSERT INTO t7 VALUES(8, 3, 1, 1, 8);
+INSERT INTO t7 VALUES(9, 4, 1, 1, 9);
+INSERT INTO t7 VALUES(10, 5, 1, 1, 10);
+select * from t1 where cv = 'dummy';
+cid cv
+8 dummy
+select * from t1 where cv = 'test';
+cid cv
+select * from t4 where uid = 1 and gid=1 and rid=2 and cid=4;
+uid gid rid cid
+1 1 2 4
+select * from t4 where uid = 1 and gid=1 and rid=1 and cid=4;
+uid gid rid cid
+select * from t4 where uid = 1 order by cid;
+uid gid rid cid
+1 1 2 3
+1 1 2 4
+1 1 5 7
+1 1 10 8
+select * from t4 where rid = 2 order by cid;
+uid gid rid cid
+1 1 2 3
+1 1 2 4
+select * from t6 where un='test' and uc=8;
+uid un uc
+1 test 8
+select * from t6 where un='test' and uc=7;
+uid un uc
+select * from t6 where un='test';
+uid un uc
+1 test 8
+select * from t7 where mid = 8;
+mid uid gid rid cid
+8 3 1 1 8
+select * from t7 where uid = 8;
+mid uid gid rid cid
+select * from t7 where uid = 1 order by mid;
+mid uid gid rid cid
+1 1 1 1 1
+6 1 1 1 6
+select * from t7 where uid = 4 order by mid;
+mid uid gid rid cid
+4 4 1 1 1
+9 4 1 1 9
+select * from t7 where gid = 4;
+mid uid gid rid cid
+select * from t7 where gid = 1 order by mid;
+mid uid gid rid cid
+1 1 1 1 1
+2 2 1 1 1
+3 3 1 1 1
+4 4 1 1 1
+5 5 1 1 1
+6 1 1 1 6
+7 2 1 1 7
+8 3 1 1 8
+9 4 1 1 9
+10 5 1 1 10
+select * from t7 where cid = 4;
+mid uid gid rid cid
+select * from t7 where cid = 8;
+mid uid gid rid cid
+8 3 1 1 8
+select * from t4 where uid = 1 and gid=1 and rid=2 and cid=4;
+uid gid rid cid
+1 1 2 4
+select * from t4 where uid = 1 and gid=1 and rid=1 and cid=4;
+uid gid rid cid
+select * from t4 where uid = 1 order by gid,cid;
+uid gid rid cid
+1 1 2 3
+1 1 2 4
+1 1 5 7
+1 1 10 8
+1 1 5 12
+1 2 5 12
+1 3 9 11
+1 3 5 12
+1 4 5 12
+1 5 5 12
+1 6 5 12
+1 7 5 12
+1 8 5 12
+1 9 5 12
+1 10 5 12
+1 11 5 12
+1 12 5 12
+1 13 5 12
+1 14 5 12
+1 15 5 12
+1 16 5 12
+1 17 5 12
+1 18 5 12
+1 19 5 12
+1 20 5 12
+1 21 5 12
+1 22 5 12
+1 23 5 12
+1 24 5 12
+1 25 5 12
+1 26 5 12
+1 27 5 12
+1 28 5 12
+1 29 5 12
+1 30 5 12
+1 31 5 12
+1 32 5 12
+1 33 5 12
+1 34 5 12
+1 35 5 12
+1 36 5 12
+1 37 5 12
+1 38 5 12
+1 39 5 12
+1 40 5 12
+1 41 5 12
+1 42 5 12
+1 43 5 12
+1 44 5 12
+1 45 5 12
+1 46 5 12
+1 47 5 12
+1 48 5 12
+1 49 5 12
+1 50 5 12
+1 51 5 12
+1 52 5 12
+1 53 5 12
+1 54 5 12
+1 55 5 12
+1 56 5 12
+1 57 5 12
+1 58 5 12
+1 59 5 12
+1 60 5 12
+1 61 5 12
+1 62 5 12
+1 63 5 12
+1 64 5 12
+1 65 5 12
+1 66 5 12
+1 67 5 12
+1 68 5 12
+1 69 5 12
+1 70 5 12
+1 71 5 12
+1 72 5 12
+1 73 5 12
+1 74 5 12
+1 75 5 12
+1 76 5 12
+1 77 5 12
+1 78 5 12
+1 79 5 12
+1 80 5 12
+1 81 5 12
+1 82 5 12
+1 83 5 12
+1 84 5 12
+1 85 5 12
+1 86 5 12
+1 87 5 12
+1 88 5 12
+1 89 5 12
+1 90 5 12
+1 91 5 12
+1 92 5 12
+1 93 5 12
+1 94 5 12
+1 95 5 12
+1 96 5 12
+1 97 5 12
+1 98 5 12
+1 99 5 12
+1 100 5 12
+select * from t4 where uid = 1 order by gid,cid;
+uid gid rid cid
+1 1 2 3
+1 1 2 4
+1 1 5 7
+1 1 10 8
+1 1 5 12
+1 2 5 12
+1 3 9 11
+1 3 5 12
+1 4 5 12
+1 5 5 12
+1 6 5 12
+1 7 5 12
+1 8 5 12
+1 9 5 12
+1 10 5 12
+1 11 5 12
+1 12 5 12
+1 13 5 12
+1 14 5 12
+1 15 5 12
+1 16 5 12
+1 17 5 12
+1 18 5 12
+1 19 5 12
+1 20 5 12
+1 21 5 12
+1 22 5 12
+1 23 5 12
+1 24 5 12
+1 25 5 12
+1 26 5 12
+1 27 5 12
+1 28 5 12
+1 29 5 12
+1 30 5 12
+1 31 5 12
+1 32 5 12
+1 33 5 12
+1 34 5 12
+1 35 5 12
+1 36 5 12
+1 37 5 12
+1 38 5 12
+1 39 5 12
+1 40 5 12
+1 41 5 12
+1 42 5 12
+1 43 5 12
+1 44 5 12
+1 45 5 12
+1 46 5 12
+1 47 5 12
+1 48 5 12
+1 49 5 12
+1 50 5 12
+1 51 5 12
+1 52 5 12
+1 53 5 12
+1 54 5 12
+1 55 5 12
+1 56 5 12
+1 57 5 12
+1 58 5 12
+1 59 5 12
+1 60 5 12
+1 61 5 12
+1 62 5 12
+1 63 5 12
+1 64 5 12
+1 65 5 12
+1 66 5 12
+1 67 5 12
+1 68 5 12
+1 69 5 12
+1 70 5 12
+1 71 5 12
+1 72 5 12
+1 73 5 12
+1 74 5 12
+1 75 5 12
+1 76 5 12
+1 77 5 12
+1 78 5 12
+1 79 5 12
+1 80 5 12
+1 81 5 12
+1 82 5 12
+1 83 5 12
+1 84 5 12
+1 85 5 12
+1 86 5 12
+1 87 5 12
+1 88 5 12
+1 89 5 12
+1 90 5 12
+1 91 5 12
+1 92 5 12
+1 93 5 12
+1 94 5 12
+1 95 5 12
+1 96 5 12
+1 97 5 12
+1 98 5 12
+1 99 5 12
+1 100 5 12
+select * from t4 where rid = 2 order by cid;
+uid gid rid cid
+1 1 2 3
+1 1 2 4
+drop table t1,t2,t3,t4,t5,t6,t7;
diff --git a/mysql-test/r/ndb_insert.result b/mysql-test/r/ndb_insert.result
new file mode 100644
index 00000000000..93f46c85499
--- /dev/null
+++ b/mysql-test/r/ndb_insert.result
@@ -0,0 +1,419 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+pk1 INT NOT NULL PRIMARY KEY,
+b INT NOT NULL,
+c INT NOT NULL
+) ENGINE=ndbcluster;
+INSERT INTO t1 VALUES (0, 0, 0);
+SELECT * FROM t1;
+pk1 b c
+0 0 0
+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),
+(11,11,11),(12,12,12),(13,13,13),(14,14,14),(15,15,15),
+(16,16,16),(17,17,17),(18,18,18),(19,19,19),(20,20,20),
+(21,21,21),(22,22,22),(23,23,23),(24,24,24),(25,25,25),
+(26,26,26),(27,27,27),(28,28,28),(29,29,29),(30,30,30),
+(31,31,31),(32,32,32),(33,33,33),(34,34,34),(35,35,35),
+(36,36,36),(37,37,37),(38,38,38),(39,39,39),(40,40,40),
+(41,41,41),(42,42,42),(43,43,43),(44,44,44),(45,45,45),
+(46,46,46),(47,47,47),(48,48,48),(49,49,49),(50,50,50),
+(51,51,51),(52,52,52),(53,53,53),(54,54,54),(55,55,55),
+(56,56,56),(57,57,57),(58,58,58),(59,59,59),(60,60,60),
+(61,61,61),(62,62,62),(63,63,63),(64,64,64),(65,65,65),
+(66,66,66),(67,67,67),(68,68,68),(69,69,69),(70,70,70),
+(71,71,71),(72,72,72),(73,73,73),(74,74,74),(75,75,75),
+(76,76,76),(77,77,77),(78,78,78),(79,79,79),(80,80,80),
+(81,81,81),(82,82,82),(83,83,83),(84,84,84),(85,85,85),
+(86,86,86),(87,87,87),(88,88,88),(89,89,89),(90,90,90),
+(91,91,91),(92,92,92),(93,93,93),(94,94,94),(95,95,95),
+(96,96,96),(97,97,97),(98,98,98),(99,99,99),(100,100,100),
+(101,101,101),(102,102,102),(103,103,103),(104,104,104),(105,105,105),
+(106,106,106),(107,107,107),(108,108,108),(109,109,109),(110,110,110),
+(111,111,111),(112,112,112),(113,113,113),(114,114,114),(115,115,115),
+(116,116,116),(117,117,117),(118,118,118),(119,119,119),(120,120,120),
+(121,121,121),(122,122,122),(123,123,123),(124,124,124),(125,125,125),
+(126,126,126),(127,127,127),(128,128,128),(129,129,129),(130,130,130),
+(131,131,131),(132,132,132),(133,133,133),(134,134,134),(135,135,135),
+(136,136,136),(137,137,137),(138,138,138),(139,139,139),(140,140,140),
+(141,141,141),(142,142,142),(143,143,143),(144,144,144),(145,145,145),
+(146,146,146),(147,147,147),(148,148,148),(149,149,149),(150,150,150),
+(151,151,151),(152,152,152),(153,153,153),(154,154,154),(155,155,155),
+(156,156,156),(157,157,157),(158,158,158),(159,159,159),(160,160,160),
+(161,161,161),(162,162,162),(163,163,163),(164,164,164),(165,165,165),
+(166,166,166),(167,167,167),(168,168,168),(169,169,169),(170,170,170),
+(171,171,171),(172,172,172),(173,173,173),(174,174,174),(175,175,175),
+(176,176,176),(177,177,177),(178,178,178),(179,179,179),(180,180,180),
+(181,181,181),(182,182,182),(183,183,183),(184,184,184),(185,185,185),
+(186,186,186),(187,187,187),(188,188,188),(189,189,189),(190,190,190),
+(191,191,191),(192,192,192),(193,193,193),(194,194,194),(195,195,195),
+(196,196,196),(197,197,197),(198,198,198),(199,199,199),(200,200,200),
+(201,201,201),(202,202,202),(203,203,203),(204,204,204),(205,205,205),
+(206,206,206),(207,207,207),(208,208,208),(209,209,209),(210,210,210),
+(211,211,211),(212,212,212),(213,213,213),(214,214,214),(215,215,215),
+(216,216,216),(217,217,217),(218,218,218),(219,219,219),(220,220,220),
+(221,221,221),(222,222,222),(223,223,223),(224,224,224),(225,225,225),
+(226,226,226),(227,227,227),(228,228,228),(229,229,229),(230,230,230),
+(231,231,231),(232,232,232),(233,233,233),(234,234,234),(235,235,235),
+(236,236,236),(237,237,237),(238,238,238),(239,239,239),(240,240,240),
+(241,241,241),(242,242,242),(243,243,243),(244,244,244),(245,245,245),
+(246,246,246),(247,247,247),(248,248,248),(249,249,249),(250,250,250),
+(251,251,251),(252,252,252),(253,253,253),(254,254,254),(255,255,255),
+(256,256,256),(257,257,257),(258,258,258),(259,259,259),(260,260,260),
+(261,261,261),(262,262,262),(263,263,263),(264,264,264),(265,265,265),
+(266,266,266),(267,267,267),(268,268,268),(269,269,269),(270,270,270),
+(271,271,271),(272,272,272),(273,273,273),(274,274,274),(275,275,275),
+(276,276,276),(277,277,277),(278,278,278),(279,279,279),(280,280,280),
+(281,281,281),(282,282,282),(283,283,283),(284,284,284),(285,285,285),
+(286,286,286),(287,287,287),(288,288,288),(289,289,289),(290,290,290),
+(291,291,291),(292,292,292),(293,293,293),(294,294,294),(295,295,295),
+(296,296,296),(297,297,297),(298,298,298),(299,299,299),(300,300,300),
+(301,301,301),(302,302,302),(303,303,303),(304,304,304),(305,305,305),
+(306,306,306),(307,307,307),(308,308,308),(309,309,309),(310,310,310),
+(311,311,311),(312,312,312),(313,313,313),(314,314,314),(315,315,315),
+(316,316,316),(317,317,317),(318,318,318),(319,319,319),(320,320,320),
+(321,321,321),(322,322,322),(323,323,323),(324,324,324),(325,325,325),
+(326,326,326),(327,327,327),(328,328,328),(329,329,329),(330,330,330),
+(331,331,331),(332,332,332),(333,333,333),(334,334,334),(335,335,335),
+(336,336,336),(337,337,337),(338,338,338),(339,339,339),(340,340,340),
+(341,341,341),(342,342,342),(343,343,343),(344,344,344),(345,345,345),
+(346,346,346),(347,347,347),(348,348,348),(349,349,349),(350,350,350),
+(351,351,351),(352,352,352),(353,353,353),(354,354,354),(355,355,355),
+(356,356,356),(357,357,357),(358,358,358),(359,359,359),(360,360,360),
+(361,361,361),(362,362,362),(363,363,363),(364,364,364),(365,365,365),
+(366,366,366),(367,367,367),(368,368,368),(369,369,369),(370,370,370),
+(371,371,371),(372,372,372),(373,373,373),(374,374,374),(375,375,375),
+(376,376,376),(377,377,377),(378,378,378),(379,379,379),(380,380,380),
+(381,381,381),(382,382,382),(383,383,383),(384,384,384),(385,385,385),
+(386,386,386),(387,387,387),(388,388,388),(389,389,389),(390,390,390),
+(391,391,391),(392,392,392),(393,393,393),(394,394,394),(395,395,395),
+(396,396,396),(397,397,397),(398,398,398),(399,399,399),(400,400,400),
+(401,401,401),(402,402,402),(403,403,403),(404,404,404),(405,405,405),
+(406,406,406),(407,407,407),(408,408,408),(409,409,409),(410,410,410),
+(411,411,411),(412,412,412),(413,413,413),(414,414,414),(415,415,415),
+(416,416,416),(417,417,417),(418,418,418),(419,419,419),(420,420,420),
+(421,421,421),(422,422,422),(423,423,423),(424,424,424),(425,425,425),
+(426,426,426),(427,427,427),(428,428,428),(429,429,429),(430,430,430),
+(431,431,431),(432,432,432),(433,433,433),(434,434,434),(435,435,435),
+(436,436,436),(437,437,437),(438,438,438),(439,439,439),(440,440,440),
+(441,441,441),(442,442,442),(443,443,443),(444,444,444),(445,445,445),
+(446,446,446),(447,447,447),(448,448,448),(449,449,449),(450,450,450),
+(451,451,451),(452,452,452),(453,453,453),(454,454,454),(455,455,455),
+(456,456,456),(457,457,457),(458,458,458),(459,459,459),(460,460,460),
+(461,461,461),(462,462,462),(463,463,463),(464,464,464),(465,465,465),
+(466,466,466),(467,467,467),(468,468,468),(469,469,469),(470,470,470),
+(471,471,471),(472,472,472),(473,473,473),(474,474,474),(475,475,475),
+(476,476,476),(477,477,477),(478,478,478),(479,479,479),(480,480,480),
+(481,481,481),(482,482,482),(483,483,483),(484,484,484),(485,485,485),
+(486,486,486),(487,487,487),(488,488,488),(489,489,489),(490,490,490),
+(491,491,491),(492,492,492),(493,493,493),(494,494,494),(495,495,495),
+(496,496,496),(497,497,497),(498,498,498),(499,499,499),(500, 500, 500);
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+501
+INSERT INTO t1 VALUES
+(501,501,501),(502,502,502),(503,503,503),(504,504,504),(505,505,505),
+(506,506,506),(507,507,507),(508,508,508),(509,509,509),(510,510,510),
+(511,511,511),(512,512,512),(513,513,513),(514,514,514),(515,515,515),
+(516,516,516),(517,517,517),(518,518,518),(519,519,519),(520,520,520),
+(521,521,521),(522,522,522),(523,523,523),(524,524,524),(525,525,525),
+(526,526,526),(527,527,527),(528,528,528),(529,529,529),(530,530,530),
+(531,531,531),(532,532,532),(533,533,533),(534,534,534),(535,535,535),
+(536,536,536),(537,537,537),(538,538,538),(539,539,539),(540,540,540),
+(541,541,541),(542,542,542),(543,543,543),(544,544,544),(545,545,545),
+(546,546,546),(547,547,547),(548,548,548),(549,549,549),(550,550,550),
+(551,551,551),(552,552,552),(553,553,553),(554,554,554),(555,555,555),
+(556,556,556),(557,557,557),(558,558,558),(559,559,559),(560,560,560),
+(561,561,561),(562,562,562),(563,563,563),(564,564,564),(565,565,565),
+(566,566,566),(567,567,567),(568,568,568),(569,569,569),(570,570,570),
+(571,571,571),(572,572,572),(573,573,573),(574,574,574),(575,575,575),
+(576,576,576),(577,577,577),(578,578,578),(579,579,579),(580,580,580),
+(581,581,581),(582,582,582),(583,583,583),(584,584,584),(585,585,585),
+(586,586,586),(587,587,587),(588,588,588),(589,589,589),(590,590,590),
+(591,591,591),(592,592,592),(593,593,593),(594,594,594),(595,595,595),
+(596,596,596),(597,597,597),(598,598,598),(599,599,599),(600,600,600),
+(601,601,601),(602,602,602),(603,603,603),(604,604,604),(605,605,605),
+(606,606,606),(607,607,607),(608,608,608),(609,609,609),(610,610,610),
+(611,611,611),(612,612,612),(613,613,613),(614,614,614),(615,615,615),
+(616,616,616),(617,617,617),(618,618,618),(619,619,619),(620,620,620),
+(621,621,621),(622,622,622),(623,623,623),(624,624,624),(625,625,625),
+(626,626,626),(627,627,627),(628,628,628),(629,629,629),(630,630,630),
+(631,631,631),(632,632,632),(633,633,633),(634,634,634),(635,635,635),
+(636,636,636),(637,637,637),(638,638,638),(639,639,639),(640,640,640),
+(641,641,641),(642,642,642),(643,643,643),(644,644,644),(645,645,645),
+(646,646,646),(647,647,647),(648,648,648),(649,649,649),(650,650,650),
+(651,651,651),(652,652,652),(653,653,653),(654,654,654),(655,655,655),
+(656,656,656),(657,657,657),(658,658,658),(659,659,659),(660,660,660),
+(661,661,661),(662,662,662),(663,663,663),(664,664,664),(665,665,665),
+(666,666,666),(667,667,667),(668,668,668),(669,669,669),(670,670,670),
+(671,671,671),(672,672,672),(673,673,673),(674,674,674),(675,675,675),
+(676,676,676),(677,677,677),(678,678,678),(679,679,679),(680,680,680),
+(681,681,681),(682,682,682),(683,683,683),(684,684,684),(685,685,685),
+(686,686,686),(687,687,687),(688,688,688),(689,689,689),(690,690,690),
+(691,691,691),(692,692,692),(693,693,693),(694,694,694),(695,695,695),
+(696,696,696),(697,697,697),(698,698,698),(699,699,699),(700,700,700),
+(701,701,701),(702,702,702),(703,703,703),(704,704,704),(705,705,705),
+(706,706,706),(707,707,707),(708,708,708),(709,709,709),(710,710,710),
+(711,711,711),(712,712,712),(713,713,713),(714,714,714),(715,715,715),
+(716,716,716),(717,717,717),(718,718,718),(719,719,719),(720,720,720),
+(721,721,721),(722,722,722),(723,723,723),(724,724,724),(725,725,725),
+(726,726,726),(727,727,727),(728,728,728),(729,729,729),(730,730,730),
+(731,731,731),(732,732,732),(733,733,733),(734,734,734),(735,735,735),
+(736,736,736),(737,737,737),(738,738,738),(739,739,739),(740,740,740),
+(741,741,741),(742,742,742),(743,743,743),(744,744,744),(745,745,745),
+(746,746,746),(747,747,747),(748,748,748),(749,749,749),(750,750,750),
+(751,751,751),(752,752,752),(753,753,753),(754,754,754),(755,755,755),
+(756,756,756),(757,757,757),(758,758,758),(759,759,759),(760,760,760),
+(761,761,761),(762,762,762),(763,763,763),(764,764,764),(765,765,765),
+(766,766,766),(767,767,767),(768,768,768),(769,769,769),(770,770,770),
+(771,771,771),(772,772,772),(773,773,773),(774,774,774),(775,775,775),
+(776,776,776),(777,777,777),(778,778,778),(779,779,779),(780,780,780),
+(781,781,781),(782,782,782),(783,783,783),(784,784,784),(785,785,785),
+(786,786,786),(787,787,787),(788,788,788),(789,789,789),(790,790,790),
+(791,791,791),(792,792,792),(793,793,793),(794,794,794),(795,795,795),
+(796,796,796),(797,797,797),(798,798,798),(799,799,799),(800,800,800),
+(801,801,801),(802,802,802),(803,803,803),(804,804,804),(805,805,805),
+(806,806,806),(807,807,807),(808,808,808),(809,809,809),(810,810,810),
+(811,811,811),(812,812,812),(813,813,813),(814,814,814),(815,815,815),
+(816,816,816),(817,817,817),(818,818,818),(819,819,819),(820,820,820),
+(821,821,821),(822,822,822),(823,823,823),(824,824,824),(825,825,825),
+(826,826,826),(827,827,827),(828,828,828),(829,829,829),(830,830,830),
+(831,831,831),(832,832,832),(833,833,833),(834,834,834),(835,835,835),
+(836,836,836),(837,837,837),(838,838,838),(839,839,839),(840,840,840),
+(841,841,841),(842,842,842),(843,843,843),(844,844,844),(845,845,845),
+(846,846,846),(847,847,847),(848,848,848),(849,849,849),(850,850,850),
+(851,851,851),(852,852,852),(853,853,853),(854,854,854),(855,855,855),
+(856,856,856),(857,857,857),(858,858,858),(859,859,859),(860,860,860),
+(861,861,861),(862,862,862),(863,863,863),(864,864,864),(865,865,865),
+(866,866,866),(867,867,867),(868,868,868),(869,869,869),(870,870,870),
+(871,871,871),(872,872,872),(873,873,873),(874,874,874),(875,875,875),
+(876,876,876),(877,877,877),(878,878,878),(879,879,879),(880,880,880),
+(881,881,881),(882,882,882),(883,883,883),(884,884,884),(885,885,885),
+(886,886,886),(887,887,887),(888,888,888),(889,889,889),(890,890,890),
+(891,891,891),(892,892,892),(893,893,893),(894,894,894),(895,895,895),
+(896,896,896),(897,897,897),(898,898,898),(899,899,899),(900,900,900),
+(901,901,901),(902,902,902),(903,903,903),(904,904,904),(905,905,905),
+(906,906,906),(907,907,907),(908,908,908),(909,909,909),(910,910,910),
+(911,911,911),(912,912,912),(913,913,913),(914,914,914),(915,915,915),
+(916,916,916),(917,917,917),(918,918,918),(919,919,919),(920,920,920),
+(921,921,921),(922,922,922),(923,923,923),(924,924,924),(925,925,925),
+(926,926,926),(927,927,927),(928,928,928),(929,929,929),(930,930,930),
+(931,931,931),(932,932,932),(933,933,933),(934,934,934),(935,935,935),
+(936,936,936),(937,937,937),(938,938,938),(939,939,939),(940,940,940),
+(941,941,941),(942,942,942),(943,943,943),(944,944,944),(945,945,945),
+(946,946,946),(947,947,947),(948,948,948),(949,949,949),(950,950,950),
+(951,951,951),(952,952,952),(953,953,953),(954,954,954),(955,955,955),
+(956,956,956),(957,957,957),(958,958,958),(959,959,959),(960,960,960),
+(961,961,961),(962,962,962),(963,963,963),(964,964,964),(965,965,965),
+(966,966,966),(967,967,967),(968,968,968),(969,969,969),(970,970,970),
+(971,971,971),(972,972,972),(973,973,973),(974,974,974),(975,975,975),
+(976,976,976),(977,977,977),(978,978,978),(979,979,979),(980,980,980),
+(981,981,981),(982,982,982),(983,983,983),(984,984,984),(985,985,985),
+(986,986,986),(987,987,987),(988,988,988),(989,989,989),(990,990,990),
+(991,991,991),(992,992,992),(993,993,993),(994,994,994),(995,995,995),
+(996,996,996),(997,997,997),(998,998,998),(999,999,999),(1000,1000,1000),
+(1001,1001,1001),(1002,1002,1002),(1003,1003,1003),(1004,1004,1004),(1005,1005,1005),
+(1006,1006,1006),(1007,1007,1007),(1008,1008,1008),(1009,1009,1009),(1010,1010,1010),
+(1011,1011,1011),(1012,1012,1012),(1013,1013,1013),(1014,1014,1014),(1015,1015,1015),
+(1016,1016,1016),(1017,1017,1017),(1018,1018,1018),(1019,1019,1019),(1020,1020,1020),
+(1021,1021,1021),(1022,1022,1022),(1023,1023,1023),(1024,1024,1024),(1025,1025,1025),
+(1026,1026,1026),(1027,1027,1027),(1028,1028,1028),(1029,1029,1029),(1030,1030,1030),
+(1031,1031,1031),(1032,1032,1032),(1033,1033,1033),(1034,1034,1034),(1035,1035,1035),
+(1036,1036,1036),(1037,1037,1037),(1038,1038,1038),(1039,1039,1039),(1040,1040,1040),
+(1041,1041,1041),(1042,1042,1042),(1043,1043,1043),(1044,1044,1044),(1045,1045,1045),
+(1046,1046,1046),(1047,1047,1047),(1048,1048,1048),(1049,1049,1049),(1050,1050,1050),
+(1051,1051,1051),(1052,1052,1052),(1053,1053,1053),(1054,1054,1054),(1055,1055,1055),
+(1056,1056,1056),(1057,1057,1057),(1058,1058,1058),(1059,1059,1059),(1060,1060,1060),
+(1061,1061,1061),(1062,1062,1062),(1063,1063,1063),(1064,1064,1064),(1065,1065,1065),
+(1066,1066,1066),(1067,1067,1067),(1068,1068,1068),(1069,1069,1069),(1070,1070,1070),
+(1071,1071,1071),(1072,1072,1072),(1073,1073,1073),(1074,1074,1074),(1075,1075,1075),
+(1076,1076,1076),(1077,1077,1077),(1078,1078,1078),(1079,1079,1079),(1080,1080,1080),
+(1081,1081,1081),(1082,1082,1082),(1083,1083,1083),(1084,1084,1084),(1085,1085,1085),
+(1086,1086,1086),(1087,1087,1087),(1088,1088,1088),(1089,1089,1089),(1090,1090,1090),
+(1091,1091,1091),(1092,1092,1092),(1093,1093,1093),(1094,1094,1094),(1095,1095,1095),
+(1096,1096,1096),(1097,1097,1097),(1098,1098,1098),(1099,1099,1099),(1100,1100,1100),
+(1101,1101,1101),(1102,1102,1102),(1103,1103,1103),(1104,1104,1104),(1105,1105,1105),
+(1106,1106,1106),(1107,1107,1107),(1108,1108,1108),(1109,1109,1109),(1110,1110,1110),
+(1111,1111,1111),(1112,1112,1112),(1113,1113,1113),(1114,1114,1114),(1115,1115,1115),
+(1116,1116,1116),(1117,1117,1117),(1118,1118,1118),(1119,1119,1119),(1120,1120,1120),
+(1121,1121,1121),(1122,1122,1122),(1123,1123,1123),(1124,1124,1124),(1125,1125,1125),
+(1126,1126,1126),(1127,1127,1127),(1128,1128,1128),(1129,1129,1129),(1130,1130,1130),
+(1131,1131,1131),(1132,1132,1132),(1133,1133,1133),(1134,1134,1134),(1135,1135,1135),
+(1136,1136,1136),(1137,1137,1137),(1138,1138,1138),(1139,1139,1139),(1140,1140,1140),
+(1141,1141,1141),(1142,1142,1142),(1143,1143,1143),(1144,1144,1144),(1145,1145,1145),
+(1146,1146,1146),(1147,1147,1147),(1148,1148,1148),(1149,1149,1149),(1150,1150,1150),
+(1151,1151,1151),(1152,1152,1152),(1153,1153,1153),(1154,1154,1154),(1155,1155,1155),
+(1156,1156,1156),(1157,1157,1157),(1158,1158,1158),(1159,1159,1159),(1160,1160,1160),
+(1161,1161,1161),(1162,1162,1162),(1163,1163,1163),(1164,1164,1164),(1165,1165,1165),
+(1166,1166,1166),(1167,1167,1167),(1168,1168,1168),(1169,1169,1169),(1170,1170,1170),
+(1171,1171,1171),(1172,1172,1172),(1173,1173,1173),(1174,1174,1174),(1175,1175,1175),
+(1176,1176,1176),(1177,1177,1177),(1178,1178,1178),(1179,1179,1179),(1180,1180,1180),
+(1181,1181,1181),(1182,1182,1182),(1183,1183,1183),(1184,1184,1184),(1185,1185,1185),
+(1186,1186,1186),(1187,1187,1187),(1188,1188,1188),(1189,1189,1189),(1190,1190,1190),
+(1191,1191,1191),(1192,1192,1192),(1193,1193,1193),(1194,1194,1194),(1195,1195,1195),
+(1196,1196,1196),(1197,1197,1197),(1198,1198,1198),(1199,1199,1199),(1200,1200,1200),
+(1201,1201,1201),(1202,1202,1202),(1203,1203,1203),(1204,1204,1204),(1205,1205,1205),
+(1206,1206,1206),(1207,1207,1207),(1208,1208,1208),(1209,1209,1209),(1210,1210,1210),
+(1211,1211,1211),(1212,1212,1212),(1213,1213,1213),(1214,1214,1214),(1215,1215,1215),
+(1216,1216,1216),(1217,1217,1217),(1218,1218,1218),(1219,1219,1219),(1220,1220,1220),
+(1221,1221,1221),(1222,1222,1222),(1223,1223,1223),(1224,1224,1224),(1225,1225,1225),
+(1226,1226,1226),(1227,1227,1227),(1228,1228,1228),(1229,1229,1229),(1230,1230,1230),
+(1231,1231,1231),(1232,1232,1232),(1233,1233,1233),(1234,1234,1234),(1235,1235,1235),
+(1236,1236,1236),(1237,1237,1237),(1238,1238,1238),(1239,1239,1239),(1240,1240,1240),
+(1241,1241,1241),(1242,1242,1242),(1243,1243,1243),(1244,1244,1244),(1245,1245,1245),
+(1246,1246,1246),(1247,1247,1247),(1248,1248,1248),(1249,1249,1249),(1250,1250,1250),
+(1251,1251,1251),(1252,1252,1252),(1253,1253,1253),(1254,1254,1254),(1255,1255,1255),
+(1256,1256,1256),(1257,1257,1257),(1258,1258,1258),(1259,1259,1259),(1260,1260,1260),
+(1261,1261,1261),(1262,1262,1262),(1263,1263,1263),(1264,1264,1264),(1265,1265,1265),
+(1266,1266,1266),(1267,1267,1267),(1268,1268,1268),(1269,1269,1269),(1270,1270,1270),
+(1271,1271,1271),(1272,1272,1272),(1273,1273,1273),(1274,1274,1274),(1275,1275,1275),
+(1276,1276,1276),(1277,1277,1277),(1278,1278,1278),(1279,1279,1279),(1280,1280,1280),
+(1281,1281,1281),(1282,1282,1282),(1283,1283,1283),(1284,1284,1284),(1285,1285,1285),
+(1286,1286,1286),(1287,1287,1287),(1288,1288,1288),(1289,1289,1289),(1290,1290,1290),
+(1291,1291,1291),(1292,1292,1292),(1293,1293,1293),(1294,1294,1294),(1295,1295,1295),
+(1296,1296,1296),(1297,1297,1297),(1298,1298,1298),(1299,1299,1299),(1300,1300,1300),
+(1301,1301,1301),(1302,1302,1302),(1303,1303,1303),(1304,1304,1304),(1305,1305,1305),
+(1306,1306,1306),(1307,1307,1307),(1308,1308,1308),(1309,1309,1309),(1310,1310,1310),
+(1311,1311,1311),(1312,1312,1312),(1313,1313,1313),(1314,1314,1314),(1315,1315,1315),
+(1316,1316,1316),(1317,1317,1317),(1318,1318,1318),(1319,1319,1319),(1320,1320,1320),
+(1321,1321,1321),(1322,1322,1322),(1323,1323,1323),(1324,1324,1324),(1325,1325,1325),
+(1326,1326,1326),(1327,1327,1327),(1328,1328,1328),(1329,1329,1329),(1330,1330,1330),
+(1331,1331,1331),(1332,1332,1332),(1333,1333,1333),(1334,1334,1334),(1335,1335,1335),
+(1336,1336,1336),(1337,1337,1337),(1338,1338,1338),(1339,1339,1339),(1340,1340,1340),
+(1341,1341,1341),(1342,1342,1342),(1343,1343,1343),(1344,1344,1344),(1345,1345,1345),
+(1346,1346,1346),(1347,1347,1347),(1348,1348,1348),(1349,1349,1349),(1350,1350,1350),
+(1351,1351,1351),(1352,1352,1352),(1353,1353,1353),(1354,1354,1354),(1355,1355,1355),
+(1356,1356,1356),(1357,1357,1357),(1358,1358,1358),(1359,1359,1359),(1360,1360,1360),
+(1361,1361,1361),(1362,1362,1362),(1363,1363,1363),(1364,1364,1364),(1365,1365,1365),
+(1366,1366,1366),(1367,1367,1367),(1368,1368,1368),(1369,1369,1369),(1370,1370,1370),
+(1371,1371,1371),(1372,1372,1372),(1373,1373,1373),(1374,1374,1374),(1375,1375,1375),
+(1376,1376,1376),(1377,1377,1377),(1378,1378,1378),(1379,1379,1379),(1380,1380,1380),
+(1381,1381,1381),(1382,1382,1382),(1383,1383,1383),(1384,1384,1384),(1385,1385,1385),
+(1386,1386,1386),(1387,1387,1387),(1388,1388,1388),(1389,1389,1389),(1390,1390,1390),
+(1391,1391,1391),(1392,1392,1392),(1393,1393,1393),(1394,1394,1394),(1395,1395,1395),
+(1396,1396,1396),(1397,1397,1397),(1398,1398,1398),(1399,1399,1399),(1400,1400,1400),
+(1401,1401,1401),(1402,1402,1402),(1403,1403,1403),(1404,1404,1404),(1405,1405,1405),
+(1406,1406,1406),(1407,1407,1407),(1408,1408,1408),(1409,1409,1409),(1410,1410,1410),
+(1411,1411,1411),(1412,1412,1412),(1413,1413,1413),(1414,1414,1414),(1415,1415,1415),
+(1416,1416,1416),(1417,1417,1417),(1418,1418,1418),(1419,1419,1419),(1420,1420,1420),
+(1421,1421,1421),(1422,1422,1422),(1423,1423,1423),(1424,1424,1424),(1425,1425,1425),
+(1426,1426,1426),(1427,1427,1427),(1428,1428,1428),(1429,1429,1429),(1430,1430,1430),
+(1431,1431,1431),(1432,1432,1432),(1433,1433,1433),(1434,1434,1434),(1435,1435,1435),
+(1436,1436,1436),(1437,1437,1437),(1438,1438,1438),(1439,1439,1439),(1440,1440,1440),
+(1441,1441,1441),(1442,1442,1442),(1443,1443,1443),(1444,1444,1444),(1445,1445,1445),
+(1446,1446,1446),(1447,1447,1447),(1448,1448,1448),(1449,1449,1449),(1450,1450,1450),
+(1451,1451,1451),(1452,1452,1452),(1453,1453,1453),(1454,1454,1454),(1455,1455,1455),
+(1456,1456,1456),(1457,1457,1457),(1458,1458,1458),(1459,1459,1459),(1460,1460,1460),
+(1461,1461,1461),(1462,1462,1462),(1463,1463,1463),(1464,1464,1464),(1465,1465,1465),
+(1466,1466,1466),(1467,1467,1467),(1468,1468,1468),(1469,1469,1469),(1470,1470,1470),
+(1471,1471,1471),(1472,1472,1472),(1473,1473,1473),(1474,1474,1474),(1475,1475,1475),
+(1476,1476,1476),(1477,1477,1477),(1478,1478,1478),(1479,1479,1479),(1480,1480,1480),
+(1481,1481,1481),(1482,1482,1482),(1483,1483,1483),(1484,1484,1484),(1485,1485,1485),
+(1486,1486,1486),(1487,1487,1487),(1488,1488,1488),(1489,1489,1489),(1490,1490,1490),
+(1491,1491,1491),(1492,1492,1492),(1493,1493,1493),(1494,1494,1494),(1495,1495,1495),
+(1496,1496,1496),(1497,1497,1497),(1498,1498,1498),(1499,1499,1499),(1500,1500,1500),
+(1501,1501,1501),(1502,1502,1502),(1503,1503,1503),(1504,1504,1504),(1505,1505,1505),
+(1506,1506,1506),(1507,1507,1507),(1508,1508,1508),(1509,1509,1509),(1510,1510,1510),
+(1511,1511,1511),(1512,1512,1512),(1513,1513,1513),(1514,1514,1514),(1515,1515,1515),
+(1516,1516,1516),(1517,1517,1517),(1518,1518,1518),(1519,1519,1519),(1520,1520,1520),
+(1521,1521,1521),(1522,1522,1522),(1523,1523,1523),(1524,1524,1524),(1525,1525,1525),
+(1526,1526,1526),(1527,1527,1527),(1528,1528,1528),(1529,1529,1529),(1530,1530,1530),
+(1531,1531,1531),(1532,1532,1532),(1533,1533,1533),(1534,1534,1534),(1535,1535,1535),
+(1536,1536,1536),(1537,1537,1537),(1538,1538,1538),(1539,1539,1539),(1540,1540,1540),
+(1541,1541,1541),(1542,1542,1542),(1543,1543,1543),(1544,1544,1544),(1545,1545,1545),
+(1546,1546,1546),(1547,1547,1547),(1548,1548,1548),(1549,1549,1549),(1550,1550,1550),
+(1551,1551,1551),(1552,1552,1552),(1553,1553,1553),(1554,1554,1554),(1555,1555,1555),
+(1556,1556,1556),(1557,1557,1557),(1558,1558,1558),(1559,1559,1559),(1560,1560,1560),
+(1561,1561,1561),(1562,1562,1562),(1563,1563,1563),(1564,1564,1564),(1565,1565,1565),
+(1566,1566,1566),(1567,1567,1567),(1568,1568,1568),(1569,1569,1569),(1570,1570,1570),
+(1571,1571,1571),(1572,1572,1572),(1573,1573,1573),(1574,1574,1574),(1575,1575,1575),
+(1576,1576,1576),(1577,1577,1577),(1578,1578,1578),(1579,1579,1579),(1580,1580,1580),
+(1581,1581,1581),(1582,1582,1582),(1583,1583,1583),(1584,1584,1584),(1585,1585,1585),
+(1586,1586,1586),(1587,1587,1587),(1588,1588,1588),(1589,1589,1589),(1590,1590,1590),
+(1591,1591,1591),(1592,1592,1592),(1593,1593,1593),(1594,1594,1594),(1595,1595,1595),
+(1596,1596,1596),(1597,1597,1597),(1598,1598,1598),(1599,1599,1599),(1600,1600,1600),
+(1601,1601,1601),(1602,1602,1602),(1603,1603,1603),(1604,1604,1604),(1605,1605,1605),
+(1606,1606,1606),(1607,1607,1607),(1608,1608,1608),(1609,1609,1609),(1610,1610,1610),
+(1611,1611,1611),(1612,1612,1612),(1613,1613,1613),(1614,1614,1614),(1615,1615,1615),
+(1616,1616,1616),(1617,1617,1617),(1618,1618,1618),(1619,1619,1619),(1620,1620,1620),
+(1621,1621,1621),(1622,1622,1622),(1623,1623,1623),(1624,1624,1624),(1625,1625,1625),
+(1626,1626,1626),(1627,1627,1627),(1628,1628,1628),(1629,1629,1629),(1630,1630,1630),
+(1631,1631,1631),(1632,1632,1632),(1633,1633,1633),(1634,1634,1634),(1635,1635,1635),
+(1636,1636,1636),(1637,1637,1637),(1638,1638,1638),(1639,1639,1639),(1640,1640,1640),
+(1641,1641,1641),(1642,1642,1642),(1643,1643,1643),(1644,1644,1644),(1645,1645,1645),
+(1646,1646,1646),(1647,1647,1647),(1648,1648,1648),(1649,1649,1649),(1650,1650,1650),
+(1651,1651,1651),(1652,1652,1652),(1653,1653,1653),(1654,1654,1654),(1655,1655,1655),
+(1656,1656,1656),(1657,1657,1657),(1658,1658,1658),(1659,1659,1659),(1660,1660,1660),
+(1661,1661,1661),(1662,1662,1662),(1663,1663,1663),(1664,1664,1664),(1665,1665,1665),
+(1666,1666,1666),(1667,1667,1667),(1668,1668,1668),(1669,1669,1669),(1670,1670,1670),
+(1671,1671,1671),(1672,1672,1672),(1673,1673,1673),(1674,1674,1674),(1675,1675,1675),
+(1676,1676,1676),(1677,1677,1677),(1678,1678,1678),(1679,1679,1679),(1680,1680,1680),
+(1681,1681,1681),(1682,1682,1682),(1683,1683,1683),(1684,1684,1684),(1685,1685,1685),
+(1686,1686,1686),(1687,1687,1687),(1688,1688,1688),(1689,1689,1689),(1690,1690,1690),
+(1691,1691,1691),(1692,1692,1692),(1693,1693,1693),(1694,1694,1694),(1695,1695,1695),
+(1696,1696,1696),(1697,1697,1697),(1698,1698,1698),(1699,1699,1699),(1700,1700,1700),
+(1701,1701,1701),(1702,1702,1702),(1703,1703,1703),(1704,1704,1704),(1705,1705,1705),
+(1706,1706,1706),(1707,1707,1707),(1708,1708,1708),(1709,1709,1709),(1710,1710,1710),
+(1711,1711,1711),(1712,1712,1712),(1713,1713,1713),(1714,1714,1714),(1715,1715,1715),
+(1716,1716,1716),(1717,1717,1717),(1718,1718,1718),(1719,1719,1719),(1720,1720,1720),
+(1721,1721,1721),(1722,1722,1722),(1723,1723,1723),(1724,1724,1724),(1725,1725,1725),
+(1726,1726,1726),(1727,1727,1727),(1728,1728,1728),(1729,1729,1729),(1730,1730,1730),
+(1731,1731,1731),(1732,1732,1732),(1733,1733,1733),(1734,1734,1734),(1735,1735,1735),
+(1736,1736,1736),(1737,1737,1737),(1738,1738,1738),(1739,1739,1739),(1740,1740,1740),
+(1741,1741,1741),(1742,1742,1742),(1743,1743,1743),(1744,1744,1744),(1745,1745,1745),
+(1746,1746,1746),(1747,1747,1747),(1748,1748,1748),(1749,1749,1749),(1750,1750,1750),
+(1751,1751,1751),(1752,1752,1752),(1753,1753,1753),(1754,1754,1754),(1755,1755,1755),
+(1756,1756,1756),(1757,1757,1757),(1758,1758,1758),(1759,1759,1759),(1760,1760,1760),
+(1761,1761,1761),(1762,1762,1762),(1763,1763,1763),(1764,1764,1764),(1765,1765,1765),
+(1766,1766,1766),(1767,1767,1767),(1768,1768,1768),(1769,1769,1769),(1770,1770,1770),
+(1771,1771,1771),(1772,1772,1772),(1773,1773,1773),(1774,1774,1774),(1775,1775,1775),
+(1776,1776,1776),(1777,1777,1777),(1778,1778,1778),(1779,1779,1779),(1780,1780,1780),
+(1781,1781,1781),(1782,1782,1782),(1783,1783,1783),(1784,1784,1784),(1785,1785,1785),
+(1786,1786,1786),(1787,1787,1787),(1788,1788,1788),(1789,1789,1789),(1790,1790,1790),
+(1791,1791,1791),(1792,1792,1792),(1793,1793,1793),(1794,1794,1794),(1795,1795,1795),
+(1796,1796,1796),(1797,1797,1797),(1798,1798,1798),(1799,1799,1799),(1800,1800,1800),
+(1801,1801,1801),(1802,1802,1802),(1803,1803,1803),(1804,1804,1804),(1805,1805,1805),
+(1806,1806,1806),(1807,1807,1807),(1808,1808,1808),(1809,1809,1809),(1810,1810,1810),
+(1811,1811,1811),(1812,1812,1812),(1813,1813,1813),(1814,1814,1814),(1815,1815,1815),
+(1816,1816,1816),(1817,1817,1817),(1818,1818,1818),(1819,1819,1819),(1820,1820,1820),
+(1821,1821,1821),(1822,1822,1822),(1823,1823,1823),(1824,1824,1824),(1825,1825,1825),
+(1826,1826,1826),(1827,1827,1827),(1828,1828,1828),(1829,1829,1829),(1830,1830,1830),
+(1831,1831,1831),(1832,1832,1832),(1833,1833,1833),(1834,1834,1834),(1835,1835,1835),
+(1836,1836,1836),(1837,1837,1837),(1838,1838,1838),(1839,1839,1839),(1840,1840,1840),
+(1841,1841,1841),(1842,1842,1842),(1843,1843,1843),(1844,1844,1844),(1845,1845,1845),
+(1846,1846,1846),(1847,1847,1847),(1848,1848,1848),(1849,1849,1849),(1850,1850,1850),
+(1851,1851,1851),(1852,1852,1852),(1853,1853,1853),(1854,1854,1854),(1855,1855,1855),
+(1856,1856,1856),(1857,1857,1857),(1858,1858,1858),(1859,1859,1859),(1860,1860,1860),
+(1861,1861,1861),(1862,1862,1862),(1863,1863,1863),(1864,1864,1864),(1865,1865,1865),
+(1866,1866,1866),(1867,1867,1867),(1868,1868,1868),(1869,1869,1869),(1870,1870,1870),
+(1871,1871,1871),(1872,1872,1872),(1873,1873,1873),(1874,1874,1874),(1875,1875,1875),
+(1876,1876,1876),(1877,1877,1877),(1878,1878,1878),(1879,1879,1879),(1880,1880,1880),
+(1881,1881,1881),(1882,1882,1882),(1883,1883,1883),(1884,1884,1884),(1885,1885,1885),
+(1886,1886,1886),(1887,1887,1887),(1888,1888,1888),(1889,1889,1889),(1890,1890,1890),
+(1891,1891,1891),(1892,1892,1892),(1893,1893,1893),(1894,1894,1894),(1895,1895,1895),
+(1896,1896,1896),(1897,1897,1897),(1898,1898,1898),(1899,1899,1899),(1900,1900,1900),
+(1901,1901,1901),(1902,1902,1902),(1903,1903,1903),(1904,1904,1904),(1905,1905,1905),
+(1906,1906,1906),(1907,1907,1907),(1908,1908,1908),(1909,1909,1909),(1910,1910,1910),
+(1911,1911,1911),(1912,1912,1912),(1913,1913,1913),(1914,1914,1914),(1915,1915,1915),
+(1916,1916,1916),(1917,1917,1917),(1918,1918,1918),(1919,1919,1919),(1920,1920,1920),
+(1921,1921,1921),(1922,1922,1922),(1923,1923,1923),(1924,1924,1924),(1925,1925,1925),
+(1926,1926,1926),(1927,1927,1927),(1928,1928,1928),(1929,1929,1929),(1930,1930,1930),
+(1931,1931,1931),(1932,1932,1932),(1933,1933,1933),(1934,1934,1934),(1935,1935,1935),
+(1936,1936,1936),(1937,1937,1937),(1938,1938,1938),(1939,1939,1939),(1940,1940,1940),
+(1941,1941,1941),(1942,1942,1942),(1943,1943,1943),(1944,1944,1944),(1945,1945,1945),
+(1946,1946,1946),(1947,1947,1947),(1948,1948,1948),(1949,1949,1949),(1950,1950,1950),
+(1951,1951,1951),(1952,1952,1952),(1953,1953,1953),(1954,1954,1954),(1955,1955,1955),
+(1956,1956,1956),(1957,1957,1957),(1958,1958,1958),(1959,1959,1959),(1960,1960,1960),
+(1961,1961,1961),(1962,1962,1962),(1963,1963,1963),(1964,1964,1964),(1965,1965,1965),
+(1966,1966,1966),(1967,1967,1967),(1968,1968,1968),(1969,1969,1969),(1970,1970,1970),
+(1971,1971,1971),(1972,1972,1972),(1973,1973,1973),(1974,1974,1974),(1975,1975,1975),
+(1976,1976,1976),(1977,1977,1977),(1978,1978,1978),(1979,1979,1979),(1980,1980,1980),
+(1981,1981,1981),(1982,1982,1982),(1983,1983,1983),(1984,1984,1984),(1985,1985,1985),
+(1986,1986,1986),(1987,1987,1987),(1988,1988,1988),(1989,1989,1989),(1990,1990,1990),
+(1991,1991,1991),(1992,1992,1992),(1993,1993,1993),(1994,1994,1994),(1995,1995,1995),
+(1996,1996,1996),(1997,1997,1997),(1998,1998,1998),(1999,1999,1999);
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+2000
+DROP TABLE t1;
diff --git a/mysql-test/r/ndb_minmax.result b/mysql-test/r/ndb_minmax.result
new file mode 100644
index 00000000000..cc0c238ac6e
--- /dev/null
+++ b/mysql-test/r/ndb_minmax.result
@@ -0,0 +1,120 @@
+drop table if exists t1, t2;
+CREATE TABLE t1 (
+a int PRIMARY KEY
+) engine = ndb;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (6);
+select MAX(a) from t1;
+MAX(a)
+6
+select MAX(a) from t1;
+MAX(a)
+6
+select MAX(a) from t1;
+MAX(a)
+6
+select MAX(a) from t1;
+MAX(a)
+6
+select MIN(a) from t1;
+MIN(a)
+1
+select MIN(a) from t1;
+MIN(a)
+1
+select MIN(a) from t1;
+MIN(a)
+1
+select * from t1 order by a;
+a
+1
+2
+3
+4
+5
+6
+select MIN(a) from t1;
+MIN(a)
+1
+select MAX(a) from t1;
+MAX(a)
+6
+select MAX(a) from t1;
+MAX(a)
+6
+select * from t1 order by a;
+a
+1
+2
+3
+4
+5
+6
+drop table t1;
+CREATE TABLE t2 (
+a int PRIMARY KEY,
+b int not null,
+c int not null,
+KEY(b),
+UNIQUE(c)
+) engine = ndb;
+INSERT INTO t2 VALUES (1, 5, 1);
+INSERT INTO t2 VALUES (2, 2, 7);
+INSERT INTO t2 VALUES (3, 3, 3);
+INSERT INTO t2 VALUES (4, 4, 4);
+INSERT INTO t2 VALUES (5, 5, 5);
+INSERT INTO t2 VALUES (6, 6, 6);
+INSERT INTO t2 VALUES (7, 2, 10);
+INSERT INTO t2 VALUES (8, 10, 2);
+select MAX(a) from t2;
+MAX(a)
+8
+select MAX(b) from t2;
+MAX(b)
+10
+select MAX(c) from t2;
+MAX(c)
+10
+select MIN(a) from t2;
+MIN(a)
+1
+select MIN(b) from t2;
+MIN(b)
+2
+select MIN(c) from t2;
+MIN(c)
+1
+select * from t2 order by a;
+a b c
+1 5 1
+2 2 7
+3 3 3
+4 4 4
+5 5 5
+6 6 6
+7 2 10
+8 10 2
+select MIN(b) from t2;
+MIN(b)
+2
+select MAX(a) from t2;
+MAX(a)
+8
+select MAX(c) from t2;
+MAX(c)
+10
+select * from t2 order by a;
+a b c
+1 5 1
+2 2 7
+3 3 3
+4 4 4
+5 5 5
+6 6 6
+7 2 10
+8 10 2
+drop table t2;
diff --git a/mysql-test/r/ndb_replace.result b/mysql-test/r/ndb_replace.result
new file mode 100644
index 00000000000..45af0f7fcb5
--- /dev/null
+++ b/mysql-test/r/ndb_replace.result
@@ -0,0 +1,21 @@
+drop table if exists t1;
+CREATE TABLE t1 (
+gesuchnr int(11) DEFAULT '0' NOT NULL,
+benutzer_id int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (gesuchnr,benutzer_id)
+) engine=ndbcluster;
+replace into t1 (gesuchnr,benutzer_id) values (2,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+insert into t1 (gesuchnr, benutzer_id) value (3,2);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+insert into t1 (gesuchnr,benutzer_id) values (1,1);
+ERROR 23000: Can't write; duplicate key in table 't1'
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+select * from t1 order by gesuchnr;
+gesuchnr benutzer_id
+1 1
+2 1
+3 2
+drop table t1;
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index 7391f4192bf..1d76fbf2fb3 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -97,39 +97,39 @@ Warnings:
Warning 1265 Data truncated for column 'd' at row 1
UPDATE t1 SET d=NULL;
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'd' at row 1
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'd' at row 1
INSERT INTO t1 (a) values (null);
ERROR 23000: Column 'a' cannot be null
INSERT INTO t1 (a) values (1/null);
ERROR 23000: Column 'a' cannot be null
INSERT INTO t1 (a) values (null),(null);
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'a' at row 1
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'a' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 2
INSERT INTO t1 (b) values (null);
ERROR 23000: Column 'b' cannot be null
INSERT INTO t1 (b) values (1/null);
ERROR 23000: Column 'b' cannot be null
INSERT INTO t1 (b) values (null),(null);
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'b' at row 1
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'b' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'b' at row 1
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'b' at row 2
INSERT INTO t1 (c) values (null);
ERROR 23000: Column 'c' cannot be null
INSERT INTO t1 (c) values (1/null);
ERROR 23000: Column 'c' cannot be null
INSERT INTO t1 (c) values (null),(null);
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'c' at row 1
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'c' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'c' at row 1
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'c' at row 2
INSERT INTO t1 (d) values (null);
ERROR 23000: Column 'd' cannot be null
INSERT INTO t1 (d) values (1/null);
ERROR 23000: Column 'd' cannot be null
INSERT INTO t1 (d) values (null),(null);
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'd' at row 1
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'd' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'd' at row 1
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'd' at row 2
select * from t1;
a b c d
0 0000-00-00 00:00:00 0
diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result
index 11413204950..3044b188d06 100644
--- a/mysql-test/r/null_key.result
+++ b/mysql-test/r/null_key.result
@@ -337,7 +337,7 @@ index (id2)
);
insert into t1 values(null,null),(1,1);
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'id2' at row 1
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'id2' at row 1
select * from t1;
id id2
NULL 0
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index 4cf6bee6123..a87d0c33559 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -10,22 +10,22 @@ select * from t1;
f1
5
delete from t1;
-ERROR 42000: Access denied for user: 'ssl_user1'@'localhost' to database 'test'
+ERROR 42000: Access denied for user 'ssl_user1'@'localhost' to database 'test'
select * from t1;
f1
5
delete from t1;
-ERROR 42000: Access denied for user: 'ssl_user2'@'localhost' to database 'test'
+ERROR 42000: Access denied for user 'ssl_user2'@'localhost' to database 'test'
select * from t1;
f1
5
delete from t1;
-ERROR 42000: Access denied for user: 'ssl_user3'@'localhost' to database 'test'
+ERROR 42000: Access denied for user 'ssl_user3'@'localhost' to database 'test'
select * from t1;
f1
5
delete from t1;
-ERROR 42000: Access denied for user: 'ssl_user4'@'localhost' to database 'test'
+ERROR 42000: Access denied for user 'ssl_user4'@'localhost' to database 'test'
delete from mysql.user where user='ssl_user%';
delete from mysql.db where user='ssl_user%';
flush privileges;
diff --git a/mysql-test/r/packet.result b/mysql-test/r/packet.result
index 5729d7af166..29bbcf4466f 100644
--- a/mysql-test/r/packet.result
+++ b/mysql-test/r/packet.result
@@ -12,7 +12,7 @@ select @@net_buffer_length, @@max_allowed_packet;
@@net_buffer_length @@max_allowed_packet
1024 1024
SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len;
-ERROR 08S01: Got a packet bigger than 'max_allowed_packet'
+ERROR 08S01: Got a packet bigger than 'max_allowed_packet' bytes
set global max_allowed_packet=default;
set max_allowed_packet=default;
set global net_buffer_length=default;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
new file mode 100644
index 00000000000..27f4ce7f815
--- /dev/null
+++ b/mysql-test/r/ps.result
@@ -0,0 +1,221 @@
+drop table if exists t1,t2;
+create table t1
+(
+a int primary key,
+b char(10)
+);
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+set @a=2;
+prepare stmt1 from 'select * from t1 where a <= ?';
+execute stmt1 using @a;
+a b
+1 one
+2 two
+set @a=3;
+execute stmt1 using @a;
+a b
+1 one
+2 two
+3 three
+deallocate prepare no_such_statement;
+ERROR HY000: Unknown prepared statement handler (no_such_statement) given to DEALLOCATE PREPARE
+execute stmt1;
+ERROR HY000: Incorrect arguments to EXECUTE
+prepare stmt2 from 'prepare nested_stmt from "select 1"';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"select 1"' at line 1
+prepare stmt2 from 'execute stmt1';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'stmt1' at line 1
+prepare stmt2 from 'deallocate prepare z';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'z' at line 1
+prepare stmt3 from 'insert into t1 values (?,?)';
+set @arg1=5, @arg2='five';
+execute stmt3 using @arg1, @arg2;
+select * from t1 where a>3;
+a b
+4 four
+5 five
+prepare stmt4 from 'update t1 set a=? where b=?';
+set @arg1=55, @arg2='five';
+execute stmt4 using @arg1, @arg2;
+select * from t1 where a>3;
+a b
+4 four
+55 five
+prepare stmt4 from 'create table t2 (a int)';
+execute stmt4;
+prepare stmt4 from 'drop table t2';
+execute stmt4;
+execute stmt4;
+ERROR 42S02: Unknown table 't2'
+prepare stmt5 from 'select ? + a from t1';
+set @a=1;
+execute stmt5 using @a;
+? + a
+2
+3
+4
+5
+56
+execute stmt5 using @no_such_var;
+? + a
+NULL
+NULL
+NULL
+NULL
+NULL
+set @nullvar=1;
+set @nullvar=NULL;
+execute stmt5 using @nullvar;
+? + a
+NULL
+NULL
+NULL
+NULL
+NULL
+set @nullvar2=NULL;
+execute stmt5 using @nullvar2;
+? + a
+NULL
+NULL
+NULL
+NULL
+NULL
+prepare stmt6 from 'select 1; select2';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '; select2' at line 1
+prepare stmt6 from 'insert into t1 values (5,"five"); select2';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '; select2' at line 1
+explain prepare stmt6 from 'insert into t1 values (5,"five"); select2';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from 'insert into t1 values (5,"five"); select2'' at line 1
+create table t2
+(
+a int
+);
+insert into t2 values (0);
+set @arg00=NULL ;
+prepare stmt1 from 'select 1 FROM t2 where a=?' ;
+execute stmt1 using @arg00 ;
+1
+prepare stmt1 from @nosuchvar;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1
+set @ivar= 1234;
+prepare stmt1 from @ivar;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1234' at line 1
+set @fvar= 123.4567;
+prepare stmt1 from @fvar;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '123.4567' at line 1
+set @str1 = 'select ?';
+set @str2 = convert(@str1 using ucs2);
+prepare stmt1 from @str2;
+execute stmt1 using @ivar;
+?
+1234
+drop table t1,t2;
+PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?";
+set @var='A';
+EXECUTE stmt1 USING @var;
+_utf8 'A' collate utf8_bin = ?
+1
+DEALLOCATE PREPARE stmt1;
+create table t1 (id int);
+prepare stmt1 from "select FOUND_ROWS()";
+select SQL_CALC_FOUND_ROWS * from t1;
+id
+execute stmt1;
+FOUND_ROWS()
+0
+insert into t1 values (1);
+select SQL_CALC_FOUND_ROWS * from t1;
+id
+1
+execute stmt1;
+FOUND_ROWS()
+1
+execute stmt1;
+FOUND_ROWS()
+0
+deallocate prepare stmt1;
+drop table t1;
+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,
+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,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday')
+) engine = MYISAM ;
+create table t2 like t1;
+set @stmt= ' explain SELECT (SELECT SUM(c1 + c12 + 0.0) FROM t2 where (t1.c2 - 0e-3) = t2.c2 GROUP BY t1.c15 LIMIT 1) as scalar_s, exists (select 1.0e+0 from t2 where t2.c3 * 9.0000000000 = t1.c4) as exists_s, c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s, (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s FROM t1, (select c25 x, c32 y from t2) tt WHERE x * 1 = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+5 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+4 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+3 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+execute stmt1 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+5 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+4 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+3 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+explain SELECT (SELECT SUM(c1 + c12 + 0.0) FROM t2 where (t1.c2 - 0e-3) = t2.c2 GROUP BY t1.c15 LIMIT 1) as scalar_s, exists (select 1.0e+0 from t2 where t2.c3 * 9.0000000000 = t1.c4) as exists_s, c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s, (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s FROM t1, (select c25 x, c32 y from t2) tt WHERE x * 1 = c25;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+5 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+4 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+3 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+deallocate prepare stmt1;
+drop tables t1,t2;
+set @arg00=1;
+prepare stmt1 from ' create table t1 (m int) as select 1 as m ' ;
+execute stmt1 ;
+select m from t1;
+m
+1
+drop table t1;
+prepare stmt1 from ' create table t1 (m int) as select ? as m ' ;
+execute stmt1 using @arg00;
+select m from t1;
+m
+1
+deallocate prepare stmt1;
+drop table t1;
+create table t1 (id int(10) unsigned NOT NULL default '0',
+name varchar(64) NOT NULL default '',
+PRIMARY KEY (id), UNIQUE KEY `name` (`name`));
+insert into t1 values (1,'1'),(2,'2'),(3,'3'),(4,'4'),(5,'5'),(6,'6'),(7,'7');
+prepare stmt1 from 'select name from t1 where id=? or id=?';
+set @id1=1,@id2=6;
+execute stmt1 using @id1, @id2;
+name
+1
+6
+select name from t1 where id=1 or id=6;
+name
+1
+6
+deallocate prepare stmt1;
+drop table t1;
+create table t1 ( a int primary key, b varchar(30)) engine = MYISAM ;
+prepare stmt1 from ' show table status from test like ''t1%'' ';
+execute stmt1;
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 MyISAM 9 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
+show table status from test like 't1%' ;
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 MyISAM 9 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
+deallocate prepare stmt1 ;
+drop table t1;
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
new file mode 100644
index 00000000000..b9df6187a09
--- /dev/null
+++ b/mysql-test/r/ps_1general.result
@@ -0,0 +1,745 @@
+use test;
+test_sequence
+------ basic tests ------
+drop table if exists t1, t_many_col_types ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+create table t_many_col_types
+(
+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,
+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,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'MYISAM' ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+PREPARE stmt FROM ' select * from t1 where a = ? ' ;
+SET @var= 2 ;
+EXECUTE stmt USING @var ;
+a b
+2 two
+select * from t1 where a = @var ;
+a b
+2 two
+DEALLOCATE PREPARE stmt ;
+prepare stmt1 from ' select 1 as my_col ' ;
+prepare stmt1 from ' select ? as my_col ' ;
+prepare ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+prepare stmt1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+prepare stmt1 from ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+prepare_garbage stmt1 from ' select 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'prepare_garbage stmt1 from ' select 1 '' at line 1
+prepare stmt1 from_garbage ' select 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from_garbage ' select 1 '' at line 1
+prepare stmt1 from ' select_garbage 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select_garbage 1' at line 1
+prepare from ' select 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from ' select 1 '' at line 1
+prepare stmt1 ' select 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' select 1 '' at line 1
+prepare ? from ' select ? as my_col ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from ' select ? as my_col '' at line 1
+set @arg00='select 1 as my_col';
+prepare stmt1 from @arg00;
+set @arg00='';
+prepare stmt1 from @arg00;
+ERROR 42000: Query was empty
+set @arg00=NULL;
+prepare stmt1 from @arg01;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1
+prepare stmt1 from ' select * from t1 where a <= 2 ' ;
+prepare stmt1 from ' select * from t1 where x <= 2 ' ;
+ERROR 42S22: Unknown column 'x' in 'where clause'
+drop table if exists not_exist ;
+prepare stmt1 from ' select * from not_exist where a <= 2 ' ;
+ERROR 42S02: Table 'test.not_exist' doesn't exist
+prepare stmt1 from ' insert into t1 values(? ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+prepare stmt1 from ' select a, b from t1
+ where a=? and where ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where' at line 2
+execute never_prepared ;
+ERROR HY000: Unknown prepared statement handler (never_prepared) given to EXECUTE
+prepare stmt1 from ' select * from t1 where a <= 2 ' ;
+prepare stmt1 from ' select * from not_exist where a <= 2 ' ;
+ERROR 42S02: Table 'test.not_exist' doesn't exist
+execute stmt1 ;
+ERROR HY000: Unknown prepared statement handler (stmt1) given to EXECUTE
+create table to_be_dropped
+(
+a int primary key,
+b char(30),
+c int
+);
+insert into to_be_dropped( a, b, c) values( 1, 'original table', 1);
+prepare stmt2 from ' select * from to_be_dropped ' ;
+execute stmt2 ;
+a b c
+1 original table 1
+drop table to_be_dropped ;
+execute stmt2 ;
+ERROR 42S02: Table 'test.to_be_dropped' doesn't exist
+create table to_be_dropped
+(
+a int primary key,
+b char(30),
+c int
+);
+insert into to_be_dropped( a, b, c) values( 9, 'recreated table', 9);
+execute stmt2 ;
+a b c
+9 recreated table 9
+drop table to_be_dropped ;
+create table to_be_dropped
+(
+a int primary key,
+c int,
+b char(30)
+);
+insert into to_be_dropped( a, b, c) values( 9, 'recreated table', 9);
+execute stmt2 ;
+a b c
+9 recreated table 9
+drop table to_be_dropped ;
+create table to_be_dropped
+(
+a int primary key,
+b char(30),
+c int,
+d timestamp default current_timestamp
+);
+insert into to_be_dropped( a, b, c) values( 9, 'recreated table', 9);
+execute stmt2 ;
+a b c
+9 recreated table 9
+drop table to_be_dropped ;
+create table to_be_dropped
+(
+a int primary key,
+d timestamp default current_timestamp,
+b char(30),
+c int
+);
+insert into to_be_dropped( a, b, c) values( 9, 'recreated table', 9);
+execute stmt2 ;
+a b c
+9 recreated table 9
+drop table to_be_dropped ;
+create table to_be_dropped
+(
+a timestamp default '2004-02-29 18:01:59',
+b char(30),
+c int
+);
+insert into to_be_dropped( b, c) values( 'recreated table', 9);
+execute stmt2 ;
+a b c
+2004-02-29 18:01:59 recreated table 9
+drop table to_be_dropped ;
+create table to_be_dropped
+(
+f1 int primary key,
+f2 char(30),
+f3 int
+);
+insert into to_be_dropped( f1, f2, f3) values( 9, 'recreated table', 9);
+execute stmt2 ;
+ERROR 42S22: Unknown column 'to_be_dropped.a' in 'field list'
+drop table to_be_dropped ;
+prepare stmt1 from ' select * from t1 where a <= 2 ' ;
+execute stmt1 ;
+a b
+1 one
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+prepare stmt1 from ' select * from t1 where a <= ? ' ;
+execute stmt1 using @arg00;
+a b
+1 one
+execute stmt1 ;
+ERROR HY000: Incorrect arguments to EXECUTE
+execute stmt1 using @arg00, @arg01;
+ERROR HY000: Incorrect arguments to EXECUTE
+execute stmt1 using @not_set;
+a b
+deallocate prepare never_prepared ;
+ERROR HY000: Unknown prepared statement handler (never_prepared) given to DEALLOCATE PREPARE
+prepare stmt1 from ' select * from t1 where a <= 2 ' ;
+prepare stmt1 from ' select * from not_exist where a <= 2 ' ;
+ERROR 42S02: Table 'test.not_exist' doesn't exist
+deallocate prepare stmt1;
+ERROR HY000: Unknown prepared statement handler (stmt1) given to DEALLOCATE PREPARE
+create table to_be_dropped
+(
+a int primary key,
+b char(10)
+);
+prepare stmt2 from ' select a,b from to_be_dropped where a <= 2 ' ;
+drop table to_be_dropped ;
+deallocate prepare stmt2;
+prepare stmt1 from ' select a from t1 where a <= 2 ' ;
+prepare stmt2 from ' select b from t1 where a <= 2 ' ;
+execute stmt2 ;
+b
+one
+two
+execute stmt1 ;
+a
+1
+2
+prepare stmt1 from ' select a from t1 where a <= 2 ' ;
+prepare stmt2 from ' select a from t1 where a <= 2 ' ;
+execute stmt2 ;
+a
+1
+2
+execute stmt1 ;
+a
+1
+2
+deallocate prepare stmt1 ;
+execute stmt2 ;
+a
+1
+2
+test_sequence
+------ show and misc tests ------
+drop table if exists t2;
+create table t2
+(
+a int primary key, b char(10)
+);
+prepare stmt4 from ' show databases ';
+execute stmt4;
+Database
+mysql
+test
+prepare stmt4 from ' show tables from test like ''t2%'' ';
+execute stmt4;
+Tables_in_test (t2%)
+t2
+prepare stmt4 from ' show columns from t2 from test like ''a%'' ';
+execute stmt4;
+Field Type Null Key Default Extra
+a int(11) PRI 0
+create index t2_idx on t2(b);
+prepare stmt4 from ' show index from t2 from test ';
+execute stmt4;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t2 0 PRIMARY 1 a A 0 NULL NULL BTREE
+t2 1 t2_idx 1 b A NULL NULL NULL YES BTREE
+prepare stmt4 from ' show table status from test like ''t2%'' ';
+execute stmt4;
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t2 MyISAM 9 Fixed 0 0 0 64424509439 1024 0 NULL # # # latin1_swedish_ci NULL
+prepare stmt4 from ' show table status from test like ''t_many_col_types%'' ';
+execute stmt4;
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t_many_col_types MyISAM 9 Dynamic 2 220 440 4294967295 2048 0 NULL # # # latin1_swedish_ci NULL
+prepare stmt4 from ' show status like ''Threads_running'' ';
+execute stmt4;
+Variable_name Value
+Threads_running 1
+prepare stmt4 from ' show variables like ''sql_mode'' ';
+execute stmt4;
+Variable_name Value
+sql_mode
+prepare stmt4 from ' show engine bdb logs ';
+execute stmt4;
+prepare stmt4 from ' show full processlist ';
+execute stmt4;
+Id User Host db Command Time State Info
+number root localhost test Query 0 NULL show full processlist
+prepare stmt4 from ' show grants for user ';
+prepare stmt4 from ' show create table t2 ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt4 from ' show master status ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt4 from ' show master logs ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt4 from ' show slave status ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt4 from ' show warnings limit 20 ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt4 from ' show errors limit 20 ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt4 from ' show storage engines ';
+execute stmt4;
+Engine Support Comment
+MyISAM YES/NO Default type from 3.23 with great performance
+HEAP YES/NO Hash based, stored in memory, useful for temporary tables
+MEMORY YES/NO Alias for HEAP
+MERGE YES/NO Collection of identical MyISAM tables
+MRG_MYISAM YES/NO Alias for MERGE
+ISAM YES/NO Obsolete table type; Is replaced by MyISAM
+MRG_ISAM YES/NO Obsolete table type; Is replaced by MRG_MYISAM
+InnoDB YES/NO Supports transactions, row-level locking and foreign keys
+INNOBASE YES/NO Alias for INNODB
+BDB YES/NO Supports transactions and page-level locking
+BERKELEYDB YES/NO Alias for BDB
+NDBCLUSTER YES/NO Clustered, fault tolerant memory based tables
+NDB YES/NO Alias for NDBCLUSTER
+EXAMPLE YES/NO Example storage engine
+ARCHIVE YES/NO Archive storage engine
+drop table if exists tx;
+prepare stmt1 from ' drop table if exists tx ' ;
+execute stmt1 ;
+Warnings:
+Note 1051 Unknown table 'tx'
+prepare stmt1 from ' drop table tx ' ;
+execute stmt1 ;
+ERROR 42S02: Unknown table 'tx'
+prepare stmt1 from ' prepare stmt2 from '' select 1 '' ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' select 1 '' at line 1
+prepare stmt1 from ' execute stmt2 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'stmt2' at line 1
+prepare stmt1 from ' deallocate prepare never_prepared ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'never_prepared' at line 1
+prepare stmt4 from ' use test ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt3 from ' create database drop_me ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+create database drop_me ;
+prepare stmt3 from ' drop database drop_me ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+drop database drop_me ;
+prepare stmt3 from ' grant all on test.t1 to drop_user@localhost
+identified by ''looser'' ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+grant all on test.t1 to drop_user@localhost
+identified by 'looser' ;
+prepare stmt3 from ' revoke all privileges on test.t1 from
+drop_user@localhost ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+revoke all privileges on test.t1 from drop_user@localhost ;
+prepare stmt3 from ' drop user drop_user@localhost ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+drop user drop_user@localhost;
+prepare stmt3 from ' describe t2 ';
+execute stmt3;
+Field Type Null Key Default Extra
+a int(11) PRI 0
+b char(10) YES MUL NULL
+drop table t2 ;
+execute stmt3;
+ERROR 42S02: Table 'test.t2' doesn't exist
+prepare stmt3 from ' lock tables t1 read ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt3 from ' unlock tables ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' load data infile ''data.txt''
+into table t1 fields terminated by ''\t'' ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' select * into outfile ''data.txt'' from t1 ';
+execute stmt1 ;
+prepare stmt1 from ' optimize table t1 ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' analyze table t1 ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' checksum table t1 ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' repair table t1 ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' restore table t1 from ''data.txt'' ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' handler t1 open ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt3 from ' commit ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt3 from ' rollback ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt4 from ' SET sql_mode=ansi ';
+execute stmt4;
+select 'a' || 'b' ;
+'a' || 'b'
+ab
+prepare stmt4 from ' SET sql_mode="" ';
+execute stmt4;
+select 'a' || 'b' ;
+'a' || 'b'
+0
+prepare stmt5 from ' select ''a'' || ''b'' ' ;
+execute stmt5;
+'a' || 'b'
+0
+SET sql_mode=ansi;
+execute stmt5;
+'a' || 'b'
+0
+SET sql_mode="";
+prepare stmt1 from ' flush local privileges ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' reset query cache ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' KILL 0 ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt1 from ' explain select a from t1 order by b ';
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 6 N 1 31 63
+def table 253 64 2 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 14 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort
+SET @arg00=1 ;
+prepare stmt1 from ' explain select a from t1 where a > ? order by b ';
+execute stmt1 using @arg00;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 6 N 1 31 63
+def table 253 64 2 N 1 31 63
+def type 253 10 5 N 1 31 63
+def possible_keys 253 4096 7 Y 0 31 63
+def key 253 64 7 Y 0 31 63
+def key_len 8 3 1 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 27 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where; Using filesort
+test_sequence
+------ create/drop/alter/rename tests ------
+drop table if exists t2, t3;
+prepare stmt_drop from ' drop table if exists t2 ' ;
+execute stmt_drop;
+prepare stmt_create from ' create table t2 (
+ a int primary key, b char(10)) ';
+execute stmt_create;
+prepare stmt3 from ' create table t3 like t2 ';
+execute stmt3;
+drop table t3;
+set @arg00=1;
+prepare stmt3 from ' create table t3 (m int) select ? as m ' ;
+execute stmt3 using @arg00;
+select m from t3;
+m
+1
+drop table t3;
+prepare stmt3 from ' create index t2_idx on t2(b) ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt3 from ' drop index t2_idx on t2 ' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt3 from ' alter table t2 drop primary key ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+drop table if exists new_t2;
+prepare stmt3 from ' rename table t2 to new_t2 ';
+execute stmt3;
+execute stmt3;
+ERROR 42S01: Table 'new_t2' already exists
+rename table new_t2 to t2;
+drop table t2;
+test_sequence
+------ big statement tests ------
+select 'ABC' as my_const_col from t1 where
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 ;
+my_const_col
+ABC
+ABC
+ABC
+ABC
+prepare stmt1 from ' select ''ABC'' as my_const_col FROM t1 WHERE
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 ' ;
+execute stmt1 ;
+my_const_col
+ABC
+ABC
+ABC
+ABC
+execute stmt1 ;
+my_const_col
+ABC
+ABC
+ABC
+ABC
+select 'ABC' as my_const_col FROM t1 WHERE
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' ;
+my_const_col
+ABC
+ABC
+ABC
+ABC
+prepare stmt1 from ' select ''ABC'' as my_const_col FROM t1 WHERE
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' ';
+execute stmt1 ;
+my_const_col
+ABC
+ABC
+ABC
+ABC
+execute stmt1 ;
+my_const_col
+ABC
+ABC
+ABC
+ABC
+set @arg00= 1;
+set @arg01= 1;
+set @arg02= 1;
+set @arg03= 1;
+set @arg04= 1;
+set @arg05= 1;
+set @arg06= 1;
+set @arg07= 1;
+set @arg10= 1;
+set @arg11= 1;
+set @arg12= 1;
+set @arg13= 1;
+set @arg14= 1;
+set @arg15= 1;
+set @arg16= 1;
+set @arg17= 1;
+set @arg20= 1;
+set @arg21= 1;
+set @arg22= 1;
+set @arg23= 1;
+set @arg24= 1;
+set @arg25= 1;
+set @arg26= 1;
+set @arg27= 1;
+set @arg30= 1;
+set @arg31= 1;
+set @arg32= 1;
+set @arg33= 1;
+set @arg34= 1;
+set @arg35= 1;
+set @arg36= 1;
+set @arg37= 1;
+set @arg40= 1;
+set @arg41= 1;
+set @arg42= 1;
+set @arg43= 1;
+set @arg44= 1;
+set @arg45= 1;
+set @arg46= 1;
+set @arg47= 1;
+set @arg50= 1;
+set @arg51= 1;
+set @arg52= 1;
+set @arg53= 1;
+set @arg54= 1;
+set @arg55= 1;
+set @arg56= 1;
+set @arg57= 1;
+set @arg60= 1;
+set @arg61= 1;
+select 'ABC' as my_const_col FROM t1 WHERE
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 ;
+my_const_col
+ABC
+ABC
+ABC
+ABC
+prepare stmt1 from ' select ''ABC'' as my_const_col FROM t1 WHERE
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? ' ;
+execute stmt1 using
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00;
+my_const_col
+ABC
+ABC
+ABC
+ABC
+execute stmt1 using
+@arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07,
+@arg10, @arg11, @arg12, @arg13, @arg14, @arg15, @arg16, @arg17,
+@arg20, @arg21, @arg22, @arg23, @arg24, @arg25, @arg26, @arg27,
+@arg30, @arg31, @arg32, @arg33, @arg34, @arg35, @arg36, @arg37,
+@arg40, @arg41, @arg42, @arg43, @arg44, @arg45, @arg46, @arg47,
+@arg50, @arg51, @arg52, @arg53, @arg54, @arg55, @arg56, @arg57,
+@arg60, @arg61 ;
+my_const_col
+ABC
+ABC
+ABC
+ABC
+drop table t1 ;
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
new file mode 100644
index 00000000000..04c95271aad
--- /dev/null
+++ b/mysql-test/r/ps_2myisam.result
@@ -0,0 +1,1269 @@
+use test;
+drop table if exists t1, t_many_col_types ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+create table t_many_col_types
+(
+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,
+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,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'MYISAM' ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+test_sequence
+------ simple select tests ------
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 ;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b) from t1
+group by 'a' ;
+group_concat(@arg00,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00) from t1
+group by 'a' ;
+group_concat(b,@arg00)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,?) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,?)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists new_tab ;
+create table new_tab (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into new_tab values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from new_tab where id1=? or value1=? ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+2 hh
+1 ii
+drop table new_tab ;
+drop table if exists new_tab ;
+create table new_tab(session_id char(9) not null) ;
+insert into new_tab values ('abc') ;
+prepare stmt1 from ' select * from new_tab
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table new_tab ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01);
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+2 ABC 2
+2 ABC 3
+2 ABC 4
+3 ABC 1
+3 ABC 3
+4 ABC 1
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ? ';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+2 ABC 2
+2 ABC 3
+2 ABC 4
+3 ABC 1
+3 ABC 3
+4 ABC 1
+4 ABC 4
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t_many_col_types;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t_many_col_types.c2 - 0e-3) = t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t_many_col_types.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 21 7 Y 32768 4 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+execute stmt1 ;
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t_many_col_types.c2-?)=t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t_many_col_types.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 23 2 Y 32768 31 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+drop table t2 ;
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' select * from t_many_col_types ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t_many_col_types t_many_col_types c1 c1 1 4 1 N 49155 0 63
+def test t_many_col_types t_many_col_types c2 c2 2 6 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c3 c3 9 9 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c4 c4 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c5 c5 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c6 c6 8 20 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c7 c7 4 12 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c8 c8 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c9 c9 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c10 c10 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c11 c11 0 9 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c12 c12 0 10 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c13 c13 10 10 10 Y 128 0 63
+def test t_many_col_types t_many_col_types c14 c14 12 19 19 Y 128 0 63
+def test t_many_col_types t_many_col_types c15 c15 7 19 19 N 1217 0 63
+def test t_many_col_types t_many_col_types c16 c16 11 8 8 Y 128 0 63
+def test t_many_col_types t_many_col_types c17 c17 13 4 4 Y 32864 0 63
+def test t_many_col_types t_many_col_types c18 c18 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c19 c19 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c20 c20 254 1 1 Y 0 0 8
+def test t_many_col_types t_many_col_types c21 c21 253 10 10 Y 0 0 8
+def test t_many_col_types t_many_col_types c22 c22 253 30 30 Y 0 0 8
+def test t_many_col_types t_many_col_types c23 c23 252 255 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c24 c24 252 255 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c25 c25 252 65535 4 Y 144 0 63
+def test t_many_col_types t_many_col_types c26 c26 252 65535 4 Y 16 0 8
+def test t_many_col_types t_many_col_types c27 c27 252 16777215 10 Y 144 0 63
+def test t_many_col_types t_many_col_types c28 c28 252 16777215 10 Y 16 0 8
+def test t_many_col_types t_many_col_types c29 c29 252 16777215 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c30 c30 252 16777215 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c31 c31 254 5 3 Y 256 0 8
+def test t_many_col_types t_many_col_types c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+select a,b from t1;
+a b
+1 one
+0 two
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+select a,b from t1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1;
+a b
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+0 NULL
+8 eight
+81 8-1
+82 8-2
+9 nine
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+set @duplicate='duplicate ' ;
+set @1000=1000 ;
+set @5=5 ;
+select a,b from t1 where a < 5 ;
+a b
+1 one
+2 two
+3 three
+4 four
+0 NULL
+insert into t1 select a + @1000, concat(@duplicate,b) from t1
+where a < @5 ;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 ;
+a b
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+1000 NULL
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' insert into t1 select a + ?, concat(?,b) from t1
+where a < ? ' ;
+execute stmt1 using @1000, @duplicate, @5;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 ;
+a b
+1004 duplicate four
+1003 duplicate three
+1002 duplicate two
+1001 duplicate one
+1000 NULL
+delete from t1 where a >= 1000 ;
+set @float=1.00;
+set @five='five' ;
+drop table if exists t2;
+create table t2 like t1 ;
+insert into t2 (b,a)
+select @duplicate, sum(first.a) from t1 first, t1 second
+where first.a <> @5 and second.b = first.b
+and second.b <> @five
+group by second.b
+having sum(second.a) > @2
+union
+select b, a + @100 from t1
+where (a,b) in ( select sqrt(a+@1)+CAST(@float AS signed),b
+from t1);
+affected rows: 8
+info: Records: 8 Duplicates: 0 Warnings: 0
+select a,b from t2;
+a b
+81 duplicate
+82 duplicate
+8 duplicate
+4 duplicate
+9 duplicate
+7 duplicate
+3 duplicate
+103 three
+delete from t2 ;
+prepare stmt1 from ' insert into t2 (b,a)
+select ?, sum(first.a)
+ from t1 first, t1 second
+ where first.a <> ? and second.b = first.b and second.b <> ?
+ group by second.b
+ having sum(second.a) > ?
+union
+select b, a + ? from t1
+ where (a,b) in ( select sqrt(a+?)+CAST(? AS signed),b
+ from t1 ) ' ;
+execute stmt1 using @duplicate, @5, @five, @2, @100, @1, @float ;
+affected rows: 8
+info: Records: 8 Duplicates: 0 Warnings: 0
+select a,b from t2;
+a b
+81 duplicate
+82 duplicate
+8 duplicate
+4 duplicate
+9 duplicate
+7 duplicate
+3 duplicate
+103 three
+drop table t2;
+drop table t1, t_many_col_types;
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
new file mode 100644
index 00000000000..dfb147d0795
--- /dev/null
+++ b/mysql-test/r/ps_3innodb.result
@@ -0,0 +1,1269 @@
+use test;
+drop table if exists t1, t_many_col_types ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'InnoDB' ;
+create table t_many_col_types
+(
+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,
+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,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'InnoDB' ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+test_sequence
+------ simple select tests ------
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 ;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b) from t1
+group by 'a' ;
+group_concat(@arg00,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00) from t1
+group by 'a' ;
+group_concat(b,@arg00)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,?) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,?)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists new_tab ;
+create table new_tab (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into new_tab values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from new_tab where id1=? or value1=? ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+2 hh
+1 ii
+drop table new_tab ;
+drop table if exists new_tab ;
+create table new_tab(session_id char(9) not null) ;
+insert into new_tab values ('abc') ;
+prepare stmt1 from ' select * from new_tab
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table new_tab ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01);
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ? ';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t_many_col_types;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t_many_col_types.c2 - 0e-3) = t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t_many_col_types.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 21 7 Y 32768 4 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+2.0000 0 1 0
+18.0000 1 0 1
+18.0000 1 0 1
+execute stmt1 ;
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+2.0000 0 1 0
+18.0000 1 0 1
+18.0000 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 3 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 3 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t_many_col_types.c2-?)=t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t_many_col_types.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 23 2 Y 32768 31 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+2 0 1 0
+18 1 0 1
+18 1 0 1
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+2 0 1 0
+18 1 0 1
+18 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 3 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 3 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+drop table t2 ;
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' select * from t_many_col_types ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t_many_col_types t_many_col_types c1 c1 1 4 1 N 49155 0 63
+def test t_many_col_types t_many_col_types c2 c2 2 6 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c3 c3 9 9 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c4 c4 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c5 c5 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c6 c6 8 20 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c7 c7 4 12 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c8 c8 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c9 c9 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c10 c10 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c11 c11 0 9 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c12 c12 0 10 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c13 c13 10 10 10 Y 128 0 63
+def test t_many_col_types t_many_col_types c14 c14 12 19 19 Y 128 0 63
+def test t_many_col_types t_many_col_types c15 c15 7 19 19 N 1217 0 63
+def test t_many_col_types t_many_col_types c16 c16 11 8 8 Y 128 0 63
+def test t_many_col_types t_many_col_types c17 c17 13 4 4 Y 32864 0 63
+def test t_many_col_types t_many_col_types c18 c18 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c19 c19 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c20 c20 254 1 1 Y 0 0 8
+def test t_many_col_types t_many_col_types c21 c21 253 10 10 Y 0 0 8
+def test t_many_col_types t_many_col_types c22 c22 253 30 30 Y 0 0 8
+def test t_many_col_types t_many_col_types c23 c23 252 255 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c24 c24 252 255 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c25 c25 252 65535 4 Y 144 0 63
+def test t_many_col_types t_many_col_types c26 c26 252 65535 4 Y 16 0 8
+def test t_many_col_types t_many_col_types c27 c27 252 16777215 10 Y 144 0 63
+def test t_many_col_types t_many_col_types c28 c28 252 16777215 10 Y 16 0 8
+def test t_many_col_types t_many_col_types c29 c29 252 16777215 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c30 c30 252 16777215 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c31 c31 254 5 3 Y 256 0 8
+def test t_many_col_types t_many_col_types c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+select a,b from t1;
+a b
+0 two
+1 one
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+select a,b from t1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+8 eight
+9 nine
+81 8-1
+82 8-2
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+set @duplicate='duplicate ' ;
+set @1000=1000 ;
+set @5=5 ;
+select a,b from t1 where a < 5 ;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+insert into t1 select a + @1000, concat(@duplicate,b) from t1
+where a < @5 ;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' insert into t1 select a + ?, concat(?,b) from t1
+where a < ? ' ;
+execute stmt1 using @1000, @duplicate, @5;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+set @float=1.00;
+set @five='five' ;
+drop table if exists t2;
+create table t2 like t1 ;
+insert into t2 (b,a)
+select @duplicate, sum(first.a) from t1 first, t1 second
+where first.a <> @5 and second.b = first.b
+and second.b <> @five
+group by second.b
+having sum(second.a) > @2
+union
+select b, a + @100 from t1
+where (a,b) in ( select sqrt(a+@1)+CAST(@float AS signed),b
+from t1);
+affected rows: 8
+info: Records: 8 Duplicates: 0 Warnings: 0
+select a,b from t2;
+a b
+3 duplicate
+4 duplicate
+7 duplicate
+8 duplicate
+9 duplicate
+81 duplicate
+82 duplicate
+103 three
+delete from t2 ;
+prepare stmt1 from ' insert into t2 (b,a)
+select ?, sum(first.a)
+ from t1 first, t1 second
+ where first.a <> ? and second.b = first.b and second.b <> ?
+ group by second.b
+ having sum(second.a) > ?
+union
+select b, a + ? from t1
+ where (a,b) in ( select sqrt(a+?)+CAST(? AS signed),b
+ from t1 ) ' ;
+execute stmt1 using @duplicate, @5, @five, @2, @100, @1, @float ;
+affected rows: 8
+info: Records: 8 Duplicates: 0 Warnings: 0
+select a,b from t2;
+a b
+3 duplicate
+4 duplicate
+7 duplicate
+8 duplicate
+9 duplicate
+81 duplicate
+82 duplicate
+103 three
+drop table t2;
+drop table t1, t_many_col_types;
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
new file mode 100644
index 00000000000..112ef86a681
--- /dev/null
+++ b/mysql-test/r/ps_4heap.result
@@ -0,0 +1,1270 @@
+use test;
+drop table if exists t1, t_many_col_types ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'HEAP' ;
+drop table if exists t_many_col_types;
+create table t_many_col_types
+(
+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,
+c17 year, c18 bit, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 char(100), c24 char(100),
+c25 char(100), c26 char(100), c27 char(100), c28 char(100),
+c29 char(100), c30 char(100), c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'HEAP' ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+test_sequence
+------ simple select tests ------
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 ;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b) from t1
+group by 'a' ;
+group_concat(@arg00,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00) from t1
+group by 'a' ;
+group_concat(b,@arg00)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,?) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,?)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists new_tab ;
+create table new_tab (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into new_tab values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from new_tab where id1=? or value1=? ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+2 hh
+1 ii
+drop table new_tab ;
+drop table if exists new_tab ;
+create table new_tab(session_id char(9) not null) ;
+insert into new_tab values ('abc') ;
+prepare stmt1 from ' select * from new_tab
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table new_tab ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01);
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ? ';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t_many_col_types;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t_many_col_types.c2 - 0e-3) = t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t_many_col_types.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 21 7 Y 32768 4 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+execute stmt1 ;
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t_many_col_types.c2-?)=t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t_many_col_types.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 23 2 Y 32768 31 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+drop table t2 ;
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' select * from t_many_col_types ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t_many_col_types t_many_col_types c1 c1 1 4 1 N 49155 0 63
+def test t_many_col_types t_many_col_types c2 c2 2 6 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c3 c3 9 9 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c4 c4 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c5 c5 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c6 c6 8 20 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c7 c7 4 12 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c8 c8 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c9 c9 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c10 c10 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c11 c11 0 9 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c12 c12 0 10 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c13 c13 10 10 10 Y 128 0 63
+def test t_many_col_types t_many_col_types c14 c14 12 19 19 Y 128 0 63
+def test t_many_col_types t_many_col_types c15 c15 7 19 19 N 1217 0 63
+def test t_many_col_types t_many_col_types c16 c16 11 8 8 Y 128 0 63
+def test t_many_col_types t_many_col_types c17 c17 13 4 4 Y 32864 0 63
+def test t_many_col_types t_many_col_types c18 c18 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c19 c19 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c20 c20 254 1 1 Y 0 0 8
+def test t_many_col_types t_many_col_types c21 c21 253 10 10 Y 0 0 8
+def test t_many_col_types t_many_col_types c22 c22 253 30 30 Y 0 0 8
+def test t_many_col_types t_many_col_types c23 c23 253 100 8 Y 0 0 8
+def test t_many_col_types t_many_col_types c24 c24 253 100 8 Y 0 0 8
+def test t_many_col_types t_many_col_types c25 c25 253 100 4 Y 0 0 8
+def test t_many_col_types t_many_col_types c26 c26 253 100 4 Y 0 0 8
+def test t_many_col_types t_many_col_types c27 c27 253 100 10 Y 0 0 8
+def test t_many_col_types t_many_col_types c28 c28 253 100 10 Y 0 0 8
+def test t_many_col_types t_many_col_types c29 c29 253 100 8 Y 0 0 8
+def test t_many_col_types t_many_col_types c30 c30 253 100 8 Y 0 0 8
+def test t_many_col_types t_many_col_types c31 c31 254 5 3 Y 256 0 8
+def test t_many_col_types t_many_col_types c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+select a,b from t1;
+a b
+1 one
+0 two
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+select a,b from t1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1;
+a b
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+0 NULL
+8 eight
+81 8-1
+82 8-2
+9 nine
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 ;
+a b
+1100 x1000_1updated
+1000 x1000_3
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+set @duplicate='duplicate ' ;
+set @1000=1000 ;
+set @5=5 ;
+select a,b from t1 where a < 5 ;
+a b
+1 one
+2 two
+3 three
+4 four
+0 NULL
+insert into t1 select a + @1000, concat(@duplicate,b) from t1
+where a < @5 ;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 ;
+a b
+1002 duplicate two
+1001 duplicate one
+1003 duplicate three
+1004 duplicate four
+1000 NULL
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' insert into t1 select a + ?, concat(?,b) from t1
+where a < ? ' ;
+execute stmt1 using @1000, @duplicate, @5;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 ;
+a b
+1000 NULL
+1004 duplicate four
+1003 duplicate three
+1002 duplicate two
+1001 duplicate one
+delete from t1 where a >= 1000 ;
+set @float=1.00;
+set @five='five' ;
+drop table if exists t2;
+create table t2 like t1 ;
+insert into t2 (b,a)
+select @duplicate, sum(first.a) from t1 first, t1 second
+where first.a <> @5 and second.b = first.b
+and second.b <> @five
+group by second.b
+having sum(second.a) > @2
+union
+select b, a + @100 from t1
+where (a,b) in ( select sqrt(a+@1)+CAST(@float AS signed),b
+from t1);
+affected rows: 8
+info: Records: 8 Duplicates: 0 Warnings: 0
+select a,b from t2;
+a b
+81 duplicate
+82 duplicate
+8 duplicate
+4 duplicate
+9 duplicate
+7 duplicate
+3 duplicate
+103 three
+delete from t2 ;
+prepare stmt1 from ' insert into t2 (b,a)
+select ?, sum(first.a)
+ from t1 first, t1 second
+ where first.a <> ? and second.b = first.b and second.b <> ?
+ group by second.b
+ having sum(second.a) > ?
+union
+select b, a + ? from t1
+ where (a,b) in ( select sqrt(a+?)+CAST(? AS signed),b
+ from t1 ) ' ;
+execute stmt1 using @duplicate, @5, @five, @2, @100, @1, @float ;
+affected rows: 8
+info: Records: 8 Duplicates: 0 Warnings: 0
+select a,b from t2;
+a b
+81 duplicate
+82 duplicate
+8 duplicate
+4 duplicate
+9 duplicate
+7 duplicate
+3 duplicate
+103 three
+drop table t2;
+drop table t1, t_many_col_types;
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
new file mode 100644
index 00000000000..fab0b552b48
--- /dev/null
+++ b/mysql-test/r/ps_5merge.result
@@ -0,0 +1,2410 @@
+use test;
+drop table if exists t1, t1_1, t1_2,
+t_many_col_types, t_many_col_types_1, t_many_col_types_2;
+drop table if exists t1, t_many_col_types ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+create table t_many_col_types
+(
+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,
+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,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'MYISAM' ;
+rename table t1 to t1_1, t_many_col_types to t_many_col_types_1 ;
+drop table if exists t1, t_many_col_types ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+create table t_many_col_types
+(
+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,
+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,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'MYISAM' ;
+rename table t1 to t1_2, t_many_col_types to t_many_col_types_2 ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) ENGINE = MERGE UNION=(t1_1,t1_2)
+INSERT_METHOD=FIRST;
+create table t_many_col_types
+(
+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,
+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,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) ENGINE = MERGE UNION=(t_many_col_types_1,t_many_col_types_2)
+INSERT_METHOD=FIRST;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+test_sequence
+------ simple select tests ------
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 ;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b) from t1
+group by 'a' ;
+group_concat(@arg00,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00) from t1
+group by 'a' ;
+group_concat(b,@arg00)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,?) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,?)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists new_tab ;
+create table new_tab (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into new_tab values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from new_tab where id1=? or value1=? ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+2 hh
+1 ii
+drop table new_tab ;
+drop table if exists new_tab ;
+create table new_tab(session_id char(9) not null) ;
+insert into new_tab values ('abc') ;
+prepare stmt1 from ' select * from new_tab
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table new_tab ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01);
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+2 ABC 2
+2 ABC 3
+2 ABC 4
+3 ABC 1
+3 ABC 3
+4 ABC 1
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ? ';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+2 ABC 2
+2 ABC 3
+2 ABC 4
+3 ABC 1
+3 ABC 3
+4 ABC 1
+4 ABC 4
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t_many_col_types;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t_many_col_types.c2 - 0e-3) = t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t_many_col_types.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 21 7 Y 32768 4 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+execute stmt1 ;
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t_many_col_types.c2-?)=t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t_many_col_types.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 23 2 Y 32768 31 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+drop table t2 ;
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' select * from t_many_col_types ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t_many_col_types t_many_col_types c1 c1 1 4 1 N 49155 0 63
+def test t_many_col_types t_many_col_types c2 c2 2 6 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c3 c3 9 9 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c4 c4 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c5 c5 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c6 c6 8 20 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c7 c7 4 12 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c8 c8 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c9 c9 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c10 c10 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c11 c11 0 9 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c12 c12 0 10 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c13 c13 10 10 10 Y 128 0 63
+def test t_many_col_types t_many_col_types c14 c14 12 19 19 Y 128 0 63
+def test t_many_col_types t_many_col_types c15 c15 7 19 19 N 1217 0 63
+def test t_many_col_types t_many_col_types c16 c16 11 8 8 Y 128 0 63
+def test t_many_col_types t_many_col_types c17 c17 13 4 4 Y 32864 0 63
+def test t_many_col_types t_many_col_types c18 c18 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c19 c19 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c20 c20 254 1 1 Y 0 0 8
+def test t_many_col_types t_many_col_types c21 c21 253 10 10 Y 0 0 8
+def test t_many_col_types t_many_col_types c22 c22 253 30 30 Y 0 0 8
+def test t_many_col_types t_many_col_types c23 c23 252 255 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c24 c24 252 255 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c25 c25 252 65535 4 Y 144 0 63
+def test t_many_col_types t_many_col_types c26 c26 252 65535 4 Y 16 0 8
+def test t_many_col_types t_many_col_types c27 c27 252 16777215 10 Y 144 0 63
+def test t_many_col_types t_many_col_types c28 c28 252 16777215 10 Y 16 0 8
+def test t_many_col_types t_many_col_types c29 c29 252 16777215 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c30 c30 252 16777215 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c31 c31 254 5 3 Y 256 0 8
+def test t_many_col_types t_many_col_types c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+select a,b from t1;
+a b
+3 three
+0 two
+1 one
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1;
+a b
+3 three
+2 two
+1 one
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+select a,b from t1 ;
+a b
+3 three
+2 two
+1 one
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1;
+a b
+4 four
+3 three
+2 two
+1 one
+5 five
+7 sixmodified
+0 NULL
+8 eight
+81 8-1
+82 8-2
+9 nine
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+drop table t1, t_many_col_types ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) ENGINE = MERGE UNION=(t1_1,t1_2)
+INSERT_METHOD=LAST;
+create table t_many_col_types
+(
+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,
+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,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) ENGINE = MERGE UNION=(t_many_col_types_1,t_many_col_types_2)
+INSERT_METHOD=LAST;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+test_sequence
+------ simple select tests ------
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 ;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b) from t1
+group by 'a' ;
+group_concat(@arg00,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00) from t1
+group by 'a' ;
+group_concat(b,@arg00)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,?) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,?)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists new_tab ;
+create table new_tab (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into new_tab values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from new_tab where id1=? or value1=? ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+2 hh
+1 ii
+drop table new_tab ;
+drop table if exists new_tab ;
+create table new_tab(session_id char(9) not null) ;
+insert into new_tab values ('abc') ;
+prepare stmt1 from ' select * from new_tab
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table new_tab ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01);
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+2 ABC 2
+2 ABC 3
+2 ABC 4
+3 ABC 1
+3 ABC 3
+4 ABC 1
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ? ';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+2 ABC 2
+2 ABC 3
+2 ABC 4
+3 ABC 1
+3 ABC 3
+4 ABC 1
+4 ABC 4
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t_many_col_types;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t_many_col_types.c2 - 0e-3) = t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t_many_col_types.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 21 7 Y 32768 4 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+execute stmt1 ;
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t_many_col_types.c2-?)=t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t_many_col_types.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 23 2 Y 32768 31 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+drop table t2 ;
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' select * from t_many_col_types ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t_many_col_types t_many_col_types c1 c1 1 4 1 N 49155 0 63
+def test t_many_col_types t_many_col_types c2 c2 2 6 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c3 c3 9 9 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c4 c4 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c5 c5 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c6 c6 8 20 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c7 c7 4 12 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c8 c8 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c9 c9 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c10 c10 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c11 c11 0 9 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c12 c12 0 10 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c13 c13 10 10 10 Y 128 0 63
+def test t_many_col_types t_many_col_types c14 c14 12 19 19 Y 128 0 63
+def test t_many_col_types t_many_col_types c15 c15 7 19 19 N 1217 0 63
+def test t_many_col_types t_many_col_types c16 c16 11 8 8 Y 128 0 63
+def test t_many_col_types t_many_col_types c17 c17 13 4 4 Y 32864 0 63
+def test t_many_col_types t_many_col_types c18 c18 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c19 c19 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c20 c20 254 1 1 Y 0 0 8
+def test t_many_col_types t_many_col_types c21 c21 253 10 10 Y 0 0 8
+def test t_many_col_types t_many_col_types c22 c22 253 30 30 Y 0 0 8
+def test t_many_col_types t_many_col_types c23 c23 252 255 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c24 c24 252 255 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c25 c25 252 65535 4 Y 144 0 63
+def test t_many_col_types t_many_col_types c26 c26 252 65535 4 Y 16 0 8
+def test t_many_col_types t_many_col_types c27 c27 252 16777215 10 Y 144 0 63
+def test t_many_col_types t_many_col_types c28 c28 252 16777215 10 Y 16 0 8
+def test t_many_col_types t_many_col_types c29 c29 252 16777215 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c30 c30 252 16777215 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c31 c31 254 5 3 Y 256 0 8
+def test t_many_col_types t_many_col_types c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+select a,b from t1;
+a b
+3 three
+0 two
+1 one
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1;
+a b
+3 three
+2 two
+1 one
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+select a,b from t1 ;
+a b
+3 three
+2 two
+1 one
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1;
+a b
+4 four
+3 three
+2 two
+1 one
+5 five
+7 sixmodified
+0 NULL
+8 eight
+81 8-1
+82 8-2
+9 nine
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+drop table t1, t1_1, t1_2,
+t_many_col_types_1, t_many_col_types_2, t_many_col_types;
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
new file mode 100644
index 00000000000..ac0b38951c0
--- /dev/null
+++ b/mysql-test/r/ps_6bdb.result
@@ -0,0 +1,1269 @@
+use test;
+drop table if exists t1, t_many_col_types ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'BDB' ;
+create table t_many_col_types
+(
+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,
+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,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'BDB' ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+test_sequence
+------ simple select tests ------
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 ;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b) from t1
+group by 'a' ;
+group_concat(@arg00,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00) from t1
+group by 'a' ;
+group_concat(b,@arg00)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,?) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,?)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists new_tab ;
+create table new_tab (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into new_tab values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from new_tab where id1=? or value1=? ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+2 hh
+1 ii
+drop table new_tab ;
+drop table if exists new_tab ;
+create table new_tab(session_id char(9) not null) ;
+insert into new_tab values ('abc') ;
+prepare stmt1 from ' select * from new_tab
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table new_tab ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01);
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+2 ABC 2
+2 ABC 3
+2 ABC 4
+3 ABC 1
+3 ABC 3
+4 ABC 1
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ? ';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+2 ABC 2
+2 ABC 3
+2 ABC 4
+3 ABC 1
+3 ABC 3
+4 ABC 1
+4 ABC 4
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t_many_col_types;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t_many_col_types.c2 - 0e-3) = t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t_many_col_types.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 21 7 Y 32768 4 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+execute stmt1 ;
+scalar_s exists_s in_s in_row_s
+2.0000 0 1 0
+18.0000 1 0 1
+2.0000 0 1 0
+18.0000 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t_many_col_types.c2-?)=t2.c2
+ GROUP BY t_many_col_types.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t_many_col_types.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t_many_col_types,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def scalar_s 5 23 2 Y 32768 31 8
+def exists_s 8 1 1 N 32769 0 8
+def in_s 8 21 1 Y 32768 0 8
+def in_row_s 8 21 1 Y 32768 0 8
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+scalar_s exists_s in_s in_row_s
+2 0 1 0
+18 1 0 1
+2 0 1 0
+18 1 0 1
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 18 N 1 31 63
+def table 253 64 16 N 1 31 63
+def type 253 10 3 N 1 31 63
+def possible_keys 253 4096 0 Y 0 31 63
+def key 253 64 0 Y 0 31 63
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 63
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 44 N 1 31 63
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_many_col_types ALL NULL NULL NULL NULL 2
+1 PRIMARY <derived6> ALL NULL NULL NULL NULL 2 Using where
+6 DERIVED t2 ALL NULL NULL NULL NULL 2
+5 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+drop table t2 ;
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' select * from t_many_col_types ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t_many_col_types t_many_col_types c1 c1 1 4 1 N 49155 0 63
+def test t_many_col_types t_many_col_types c2 c2 2 6 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c3 c3 9 9 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c4 c4 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c5 c5 3 11 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c6 c6 8 20 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c7 c7 4 12 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c8 c8 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c9 c9 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c10 c10 5 22 1 Y 32768 31 63
+def test t_many_col_types t_many_col_types c11 c11 0 9 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c12 c12 0 10 6 Y 32768 4 63
+def test t_many_col_types t_many_col_types c13 c13 10 10 10 Y 128 0 63
+def test t_many_col_types t_many_col_types c14 c14 12 19 19 Y 128 0 63
+def test t_many_col_types t_many_col_types c15 c15 7 19 19 N 1217 0 63
+def test t_many_col_types t_many_col_types c16 c16 11 8 8 Y 128 0 63
+def test t_many_col_types t_many_col_types c17 c17 13 4 4 Y 32864 0 63
+def test t_many_col_types t_many_col_types c18 c18 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c19 c19 1 1 1 Y 32768 0 63
+def test t_many_col_types t_many_col_types c20 c20 254 1 1 Y 0 0 8
+def test t_many_col_types t_many_col_types c21 c21 253 10 10 Y 0 0 8
+def test t_many_col_types t_many_col_types c22 c22 253 30 30 Y 0 0 8
+def test t_many_col_types t_many_col_types c23 c23 252 255 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c24 c24 252 255 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c25 c25 252 65535 4 Y 144 0 63
+def test t_many_col_types t_many_col_types c26 c26 252 65535 4 Y 16 0 8
+def test t_many_col_types t_many_col_types c27 c27 252 16777215 10 Y 144 0 63
+def test t_many_col_types t_many_col_types c28 c28 252 16777215 10 Y 16 0 8
+def test t_many_col_types t_many_col_types c29 c29 252 16777215 8 Y 144 0 63
+def test t_many_col_types t_many_col_types c30 c30 252 16777215 8 Y 16 0 8
+def test t_many_col_types t_many_col_types c31 c31 254 5 3 Y 256 0 8
+def test t_many_col_types t_many_col_types c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+select a,b from t1;
+a b
+0 two
+1 one
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+select a,b from t1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t_many_col_types ;
+insert into t_many_col_types
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t_many_col_types
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+8 eight
+9 nine
+81 8-1
+82 8-2
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+set @duplicate='duplicate ' ;
+set @1000=1000 ;
+set @5=5 ;
+select a,b from t1 where a < 5 ;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+insert into t1 select a + @1000, concat(@duplicate,b) from t1
+where a < @5 ;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' insert into t1 select a + ?, concat(?,b) from t1
+where a < ? ' ;
+execute stmt1 using @1000, @duplicate, @5;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+set @float=1.00;
+set @five='five' ;
+drop table if exists t2;
+create table t2 like t1 ;
+insert into t2 (b,a)
+select @duplicate, sum(first.a) from t1 first, t1 second
+where first.a <> @5 and second.b = first.b
+and second.b <> @five
+group by second.b
+having sum(second.a) > @2
+union
+select b, a + @100 from t1
+where (a,b) in ( select sqrt(a+@1)+CAST(@float AS signed),b
+from t1);
+affected rows: 8
+info: Records: 8 Duplicates: 0 Warnings: 0
+select a,b from t2;
+a b
+3 duplicate
+4 duplicate
+7 duplicate
+8 duplicate
+9 duplicate
+81 duplicate
+82 duplicate
+103 three
+delete from t2 ;
+prepare stmt1 from ' insert into t2 (b,a)
+select ?, sum(first.a)
+ from t1 first, t1 second
+ where first.a <> ? and second.b = first.b and second.b <> ?
+ group by second.b
+ having sum(second.a) > ?
+union
+select b, a + ? from t1
+ where (a,b) in ( select sqrt(a+?)+CAST(? AS signed),b
+ from t1 ) ' ;
+execute stmt1 using @duplicate, @5, @five, @2, @100, @1, @float ;
+affected rows: 8
+info: Records: 8 Duplicates: 0 Warnings: 0
+select a,b from t2;
+a b
+3 duplicate
+4 duplicate
+7 duplicate
+8 duplicate
+9 duplicate
+81 duplicate
+82 duplicate
+103 three
+drop table t2;
+drop table t1, t_many_col_types;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 0baebc745cc..ceca8db317e 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -593,7 +593,7 @@ select * from t1;
a
set GLOBAL query_cache_size=1024;
Warnings:
-Warning 1282 Query cache failed to set size 1024, new query cache size is 0
+Warning 1282 Query cache failed to set size 1024; new query cache size is 0
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
@@ -601,7 +601,7 @@ select * from t1;
a
set GLOBAL query_cache_size=10240;
Warnings:
-Warning 1282 Query cache failed to set size 10240, new query cache size is 0
+Warning 1282 Query cache failed to set size 10240; new query cache size is 0
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
@@ -609,7 +609,7 @@ select * from t1;
a
set GLOBAL query_cache_size=20480;
Warnings:
-Warning 1282 Query cache failed to set size 20480, new query cache size is 0
+Warning 1282 Query cache failed to set size 20480; new query cache size is 0
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
@@ -617,7 +617,7 @@ select * from t1;
a
set GLOBAL query_cache_size=40960;
Warnings:
-Warning 1282 Query cache failed to set size 40960, new query cache size is 0
+Warning 1282 Query cache failed to set size 40960; new query cache size is 0
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index 244dcbd03d4..bdd87919fd9 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -244,7 +244,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range x x 5 NULL 2 Using where
explain select count(*) from t1 where x in (1);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index x x 5 NULL 9 Using where; Using index
+1 SIMPLE t1 ref x x 5 const 1 Using where; Using index
explain select count(*) from t1 where x in (1,2);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index x x 5 NULL 9 Using where; Using index
@@ -299,6 +299,27 @@ a b
15 1
47 1
DROP TABLE t1;
+CREATE TABLE t1 (
+id int( 11 ) unsigned NOT NULL AUTO_INCREMENT ,
+line int( 5 ) unsigned NOT NULL default '0',
+columnid int( 3 ) unsigned NOT NULL default '0',
+owner int( 3 ) unsigned NOT NULL default '0',
+ordinal int( 3 ) unsigned NOT NULL default '0',
+showid smallint( 6 ) unsigned NOT NULL default '1',
+tableid int( 1 ) unsigned NOT NULL default '1',
+content int( 5 ) unsigned NOT NULL default '188',
+PRIMARY KEY ( owner, id ) ,
+KEY menu( owner, showid, columnid ) ,
+KEY `COLUMN` ( owner, columnid, line ) ,
+KEY `LINES` ( owner, tableid, content, id ) ,
+KEY recount( owner, line )
+) ENGINE = MYISAM;
+INSERT into t1 (owner,id,columnid,line) values (11,15,15,1),(11,13,13,5);
+SELECT id, columnid, tableid, content, showid, line, ordinal FROM t1 WHERE owner=11 AND ((columnid IN ( 15, 13, 14 ) AND line IN ( 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 31 )) OR (columnid IN ( 13, 14 ) AND line IN ( 15 ))) LIMIT 0 , 30;
+id columnid tableid content showid line ordinal
+13 13 1 188 1 5 0
+15 15 1 188 1 1 0
+drop table t1;
create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
select id from t1 where id in (2,5,9) ;
diff --git a/mysql-test/r/rpl_charset.result b/mysql-test/r/rpl_charset.result
new file mode 100644
index 00000000000..8d42957c9d3
--- /dev/null
+++ b/mysql-test/r/rpl_charset.result
@@ -0,0 +1,201 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+drop database if exists test2;
+drop database if exists test3;
+create database test2 character set latin2;
+set @@character_set_server=latin5;
+create database test3;
+
+--- --master--
+show create database test2;
+Database Create Database
+test2 CREATE DATABASE `test2` /*!40100 DEFAULT CHARACTER SET latin2 */
+show create database test3;
+Database Create Database
+test3 CREATE DATABASE `test3` /*!40100 DEFAULT CHARACTER SET latin5 */
+
+--- --slave--
+show create database test2;
+Database Create Database
+test2 CREATE DATABASE `test2` /*!40100 DEFAULT CHARACTER SET latin2 */
+show create database test3;
+Database Create Database
+test3 CREATE DATABASE `test3` /*!40100 DEFAULT CHARACTER SET latin5 */
+set @@collation_server=armscii_bin;
+drop database test3;
+create database test3;
+
+--- --master--
+show create database test3;
+Database Create Database
+test3 CREATE DATABASE `test3` /*!40100 DEFAULT CHARACTER SET armscii8 COLLATE armscii_bin */
+
+--- --slave--
+show create database test3;
+Database Create Database
+test3 CREATE DATABASE `test3` /*!40100 DEFAULT CHARACTER SET armscii8 COLLATE armscii_bin */
+use test2;
+create table t1 (a int auto_increment primary key, b varchar(100));
+set character_set_client=cp850, collation_connection=latin2_croatian_ci;
+insert into t1 (b) values(@@character_set_server);
+insert into t1 (b) values(@@collation_server);
+insert into t1 (b) values(@@character_set_client);
+insert into t1 (b) values(@@character_set_connection);
+insert into t1 (b) values(@@collation_connection);
+
+--- --master--
+select * from t1 order by a;
+a b
+1 armscii8
+2 armscii_bin
+3 cp850
+4 latin2
+5 latin2_croatian_ci
+
+--- --slave--
+select * from test2.t1 order by a;
+a b
+1 armscii8
+2 armscii_bin
+3 cp850
+4 latin2
+5 latin2_croatian_ci
+set character_set_client=latin1, collation_connection=latin1_german1_ci;
+truncate table t1;
+insert into t1 (b) values(@@collation_connection);
+insert into t1 (b) values(LEAST("Müller","Muffler"));
+set collation_connection=latin1_german2_ci;
+insert into t1 (b) values(@@collation_connection);
+insert into t1 (b) values(LEAST("Müller","Muffler"));
+
+--- --master--
+select * from t1 order by a;
+a b
+1 latin1_german1_ci
+2 Muffler
+3 latin1_german2_ci
+4 Müller
+
+--- --slave--
+select * from test2.t1 order by a;
+a b
+1 latin1_german1_ci
+2 Muffler
+3 latin1_german2_ci
+4 Müller
+load data infile '../../std_data/words.dat' into table t1 (b);
+set @a= _cp850 'Müller' collate cp850_general_ci;
+truncate table t1;
+insert into t1 (b) values(collation(@a));
+
+--- --master--
+select * from t1 order by a;
+a b
+1 cp850_general_ci
+
+--- --slave--
+select * from test2.t1 order by a;
+a b
+1 cp850_general_ci
+drop database test2;
+drop database test3;
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.000001 79 Query 1 79 use `test`; drop database if exists test2
+master-bin.000001 143 Query 1 143 use `test`; drop database if exists test3
+master-bin.000001 207 Query 1 207 use `test`; create database test2 character set latin2
+master-bin.000001 284 Query 1 284 use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=30
+master-bin.000001 418 Query 1 418 use `test`; create database test3
+master-bin.000001 474 Query 1 474 use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=64
+master-bin.000001 608 Query 1 608 use `test`; drop database test3
+master-bin.000001 662 Query 1 662 use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=64
+master-bin.000001 796 Query 1 796 use `test`; create database test3
+master-bin.000001 852 Query 1 852 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 987 Query 1 987 use `test2`; create table t1 (a int auto_increment primary key, b varchar(100))
+master-bin.000001 1089 Query 1 1089 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 1225 Intvar 1 1225 INSERT_ID=1
+master-bin.000001 1253 Query 1 1253 use `test2`; insert into t1 (b) values(@@character_set_server)
+master-bin.000001 1338 Query 1 1338 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 1474 Intvar 1 1474 INSERT_ID=2
+master-bin.000001 1502 Query 1 1502 use `test2`; insert into t1 (b) values(@@collation_server)
+master-bin.000001 1583 Query 1 1583 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 1719 Intvar 1 1719 INSERT_ID=3
+master-bin.000001 1747 Query 1 1747 use `test2`; insert into t1 (b) values(@@character_set_client)
+master-bin.000001 1832 Query 1 1832 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 1968 Intvar 1 1968 INSERT_ID=4
+master-bin.000001 1996 Query 1 1996 use `test2`; insert into t1 (b) values(@@character_set_connection)
+master-bin.000001 2085 Query 1 2085 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 2221 Intvar 1 2221 INSERT_ID=5
+master-bin.000001 2249 Query 1 2249 use `test2`; insert into t1 (b) values(@@collation_connection)
+master-bin.000001 2334 Query 1 2334 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=5,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 2469 Query 1 2469 use `test2`; truncate table t1
+master-bin.000001 2522 Query 1 2522 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=5,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 2657 Intvar 1 2657 INSERT_ID=1
+master-bin.000001 2685 Query 1 2685 use `test2`; insert into t1 (b) values(@@collation_connection)
+master-bin.000001 2770 Query 1 2770 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=5,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 2905 Intvar 1 2905 INSERT_ID=2
+master-bin.000001 2933 Query 1 2933 use `test2`; insert into t1 (b) values(LEAST("Müller","Muffler"))
+master-bin.000001 3021 Query 1 3021 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 3157 Intvar 1 3157 INSERT_ID=3
+master-bin.000001 3185 Query 1 3185 use `test2`; insert into t1 (b) values(@@collation_connection)
+master-bin.000001 3270 Query 1 3270 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 3406 Intvar 1 3406 INSERT_ID=4
+master-bin.000001 3434 Query 1 3434 use `test2`; insert into t1 (b) values(LEAST("Müller","Muffler"))
+master-bin.000001 3522 Query 1 3522 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 3658 Intvar 1 3658 INSERT_ID=74
+master-bin.000001 3686 Create_file 1 3686 db=test2;table=t1;file_id=1;block_len=581
+master-bin.000001 4354 Query 1 4354 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 4490 Intvar 1 4490 INSERT_ID=5
+master-bin.000001 4518 Exec_load 1 4518 ;file_id=1
+master-bin.000001 4541 Query 1 4541 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 4677 Query 1 4677 use `test2`; truncate table t1
+master-bin.000001 4730 Query 1 4730 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 4866 Intvar 1 4866 INSERT_ID=1
+master-bin.000001 4894 User var 1 4894 @`a`=_cp850 0x4DFC6C6C6572 COLLATE cp850_general_ci
+master-bin.000001 4934 Query 1 4934 use `test2`; insert into t1 (b) values(collation(@a))
+master-bin.000001 5010 Query 1 5010 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 5146 Query 1 5146 use `test2`; drop database test2
+master-bin.000001 5201 Query 1 5201 SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
+master-bin.000001 5332 Query 1 5332 drop database test3
+set global character_set_server=latin2;
+ERROR HY000: Binary logging and replication forbid changing the global server character set or collation
+set global character_set_server=latin2;
+ERROR HY000: Binary logging and replication forbid changing the global server character set or collation
+set one_shot @@character_set_server=latin5;
+set @@max_join_size=1000;
+select @@character_set_server;
+@@character_set_server
+latin5
+select @@character_set_server;
+@@character_set_server
+latin1
+set @@character_set_server=latin5;
+select @@character_set_server;
+@@character_set_server
+latin5
+select @@character_set_server;
+@@character_set_server
+latin5
+set one_shot max_join_size=10;
+ERROR HY000: The SET ONE_SHOT syntax is reserved for purposes internal to the MySQL server
+set character_set_client=9999999;
+ERROR 42000: Unknown character set: '9999999'
+set collation_server=9999998;
+ERROR HY000: Unknown collation: '9999998'
+use test;
+CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255));
+SET CHARACTER_SET_CLIENT=koi8r,
+CHARACTER_SET_CONNECTION=cp1251,
+CHARACTER_SET_RESULTS=koi8r;
+INSERT INTO t1 (c1, c2) VALUES ('îÕ, ÚÁ ÒÙÂÁÌËÕ','îÕ, ÚÁ ÒÙÂÁÌËÕ');
+select hex(c1), hex(c2) from t1;
+hex(c1) hex(c2)
+CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3
+select hex(c1), hex(c2) from t1;
+hex(c1) hex(c2)
+CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3
+drop table t1;
diff --git a/mysql-test/r/rpl_delete_all.result b/mysql-test/r/rpl_delete_all.result
new file mode 100644
index 00000000000..97a535490dd
--- /dev/null
+++ b/mysql-test/r/rpl_delete_all.result
@@ -0,0 +1,31 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create database test1;
+drop database if exists test1;
+Warnings:
+Note 1008 Can't drop database 'test1'; database doesn't exist
+show tables from test1;
+ERROR HY000: Can't read dir of './test1/' (Errcode: X)
+create table t1 (a int);
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
+select * from t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+create table t1 (a int);
+insert into t1 values(1);
+delete from t1;
+select * from t1;
+a
+insert into t1 values(1);
+insert into t1 values(2);
+update t1 set a=2;
+select * from t1;
+a
+2
+2
+drop table t1;
diff --git a/mysql-test/r/rpl_free_items.result b/mysql-test/r/rpl_free_items.result
new file mode 100644
index 00000000000..91c1e2aa6e5
--- /dev/null
+++ b/mysql-test/r/rpl_free_items.result
@@ -0,0 +1,10 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create table t1 (a int);
+create table t2 (a int);
+drop table t1;
+drop table t2;
diff --git a/mysql-test/r/rpl_get_lock.result b/mysql-test/r/rpl_get_lock.result
index 2c57069e91a..26f33bfb42c 100644
--- a/mysql-test/r/rpl_get_lock.result
+++ b/mysql-test/r/rpl_get_lock.result
@@ -18,9 +18,9 @@ get_lock("lock",3)
select * from t1;
n
1
-select is_free_lock("lock"), is_used_lock("lock");
-is_free_lock("lock") is_used_lock("lock")
-0 6
+select is_free_lock("lock"), is_used_lock("lock") = connection_id();
+is_free_lock("lock") is_used_lock("lock") = connection_id()
+0 1
explain extended select is_free_lock("lock"), is_used_lock("lock");
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/rpl_ps.result b/mysql-test/r/rpl_ps.result
new file mode 100644
index 00000000000..c969575de76
--- /dev/null
+++ b/mysql-test/r/rpl_ps.result
@@ -0,0 +1,28 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+drop table if exists t1;
+create table t1(n char(30));
+prepare stmt1 from 'insert into t1 values (?)';
+set @var1= "from-master-1";
+execute stmt1 using @var1;
+set @var1= "from-master-2-'',";
+execute stmt1 using @var1;
+select * from t1;
+n
+from-master-1
+from-master-2-'',
+set @var2= 'insert into t1 values (concat("from-var-", ?))';
+prepare stmt2 from @var2;
+set @var1='from-master-3';
+execute stmt2 using @var1;
+select * from t1;
+n
+from-master-1
+from-master-2-'',
+from-var-from-master-3
+drop table t1;
+stop slave;
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index 01d39b2e44c..85071e13555 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -1,11 +1,11 @@
drop table if exists t1, t2, t3, t4;
drop table if exists t1, t2, t3, t4;
start slave;
-ERROR HY000: Could not initialize master info structure, more error messages can be found in the MySQL error log
+ERROR HY000: Could not initialize master info structure; more error messages can be found in the MySQL error log
start slave;
-ERROR HY000: Could not initialize master info structure, more error messages can be found in the MySQL error log
+ERROR HY000: Could not initialize master info structure; more error messages can be found in the MySQL error log
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
-ERROR HY000: Could not initialize master info structure, more error messages can be found in the MySQL error log
+ERROR HY000: Could not initialize master info structure; more error messages can be found in the MySQL error log
reset slave;
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
reset master;
diff --git a/mysql-test/r/rpl_server_id1.result b/mysql-test/r/rpl_server_id1.result
index b51022b0017..ed24c0ef35b 100644
--- a/mysql-test/r/rpl_server_id1.result
+++ b/mysql-test/r/rpl_server_id1.result
@@ -15,8 +15,5 @@ start slave;
insert into t1 values (1);
show status like "slave_running";
Variable_name Value
-Slave_running ON
-select * from t1;
-n
-1
+Slave_running OFF
drop table t1;
diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result
index 9826d4ff1c4..678b983104f 100644
--- a/mysql-test/r/rpl_temporary.result
+++ b/mysql-test/r/rpl_temporary.result
@@ -7,12 +7,12 @@ start slave;
reset master;
SET @save_select_limit=@@session.sql_select_limit;
SET @@session.sql_select_limit=10, @@session.pseudo_thread_id=100;
-ERROR HY000: Access denied. You need the SUPER privilege for this operation
+ERROR HY000: Access denied; you need the SUPER privilege for this operation
SELECT @@session.sql_select_limit = @save_select_limit;
@@session.sql_select_limit = @save_select_limit
1
SET @@session.sql_select_limit=10, @@session.sql_log_bin=0;
-ERROR HY000: Access denied. You need the SUPER privilege for this operation
+ERROR HY000: Access denied; you need the SUPER privilege for this operation
SELECT @@session.sql_select_limit = @save_select_limit;
@@session.sql_select_limit = @save_select_limit
1
diff --git a/mysql-test/r/rpl_timezone.result b/mysql-test/r/rpl_timezone.result
new file mode 100644
index 00000000000..c7be3324533
--- /dev/null
+++ b/mysql-test/r/rpl_timezone.result
@@ -0,0 +1,77 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create table t1 (t timestamp);
+create table t2 (t char(32));
+select @@time_zone;
+@@time_zone
+Europe/Moscow
+set time_zone='UTC';
+insert into t1 values ('20040101000000'), ('20040611093902');
+select * from t1;
+t
+2004-01-01 00:00:00
+2004-06-11 09:39:02
+select * from t1;
+t
+2004-01-01 03:00:00
+2004-06-11 13:39:02
+delete from t1;
+set time_zone='Europe/Moscow';
+insert into t1 values ('20040101000000'), ('20040611093902');
+select * from t1;
+t
+2004-01-01 00:00:00
+2004-06-11 09:39:02
+select * from t1;
+t
+2004-01-01 00:00:00
+2004-06-11 09:39:02
+show binlog events;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.000001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
+master-bin.000001 79 Query 1 79 use `test`; create table t1 (t timestamp)
+master-bin.000001 143 Query 1 143 use `test`; create table t2 (t char(32))
+master-bin.000001 206 Query 1 206 use `test`; SET ONE_SHOT TIME_ZONE='UTC'
+master-bin.000001 269 Query 1 269 use `test`; insert into t1 values ('20040101000000'), ('20040611093902')
+master-bin.000001 364 Query 1 364 use `test`; delete from t1
+master-bin.000001 413 Query 1 413 use `test`; insert into t1 values ('20040101000000'), ('20040611093902')
+set time_zone='MET';
+insert into t2 (select t from t1);
+select * from t1;
+t
+2003-12-31 22:00:00
+2004-06-11 07:39:02
+select * from t2;
+t
+2003-12-31 22:00:00
+2004-06-11 07:39:02
+delete from t2;
+set timestamp=1000072000;
+insert into t2 values (current_timestamp), (current_date), (current_time);
+set timestamp=1000072000;
+select current_timestamp, current_date, current_time;
+current_timestamp current_date current_time
+2001-09-10 01:46:40 2001-09-10 01:46:40
+select * from t2;
+t
+2001-09-09 23:46:40
+2001-09-09
+23:46:40
+delete from t2;
+insert into t2 values (from_unixtime(1000000000)),
+(unix_timestamp('2001-09-09 03:46:40'));
+select * from t2;
+t
+2001-09-09 03:46:40
+1000000000
+select * from t2;
+t
+2001-09-09 03:46:40
+1000000000
+set global time_zone='MET';
+ERROR HY000: Binary logging and replication forbid changing of the global server time zone
+drop table t1, t2;
diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result
index 45bedd0b176..ba8c0c1f131 100644
--- a/mysql-test/r/rpl_until.result
+++ b/mysql-test/r/rpl_until.result
@@ -57,15 +57,15 @@ show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 731 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 731 # Master master-bin.000001 710 No #
start slave until master_log_file='master-bin', master_log_pos=561;
-ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL
+ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12;
-ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL
+ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
start slave until master_log_file='master-bin.000001';
-ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL
+ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
start slave until relay_log_file='slave-relay-bin.000002';
-ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL
+ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561;
-ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL
+ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
start slave sql_thread;
start slave until master_log_file='master-bin.000001', master_log_pos=710;
Warnings:
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 6759702475d..cb251bb64ae 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -2071,7 +2071,14 @@ CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned defa
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);
-SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'NULL' AND b.sampletime < 'NULL' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
+SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
+gvid the_success the_fail the_size the_time
+Warnings:
+Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
+Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
+Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
+Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
+SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
gvid the_success the_fail the_size the_time
DROP TABLE t1,t2;
create table t1 ( A_Id bigint(20) NOT NULL default '0', A_UpdateBy char(10) NOT NULL default '', A_UpdateDate bigint(20) NOT NULL default '0', A_UpdateSerial int(11) NOT NULL default '0', other_types bigint(20) NOT NULL default '0', wss_type bigint(20) NOT NULL default '0');
diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result
index 23a39a242a1..470a3e8439f 100644
--- a/mysql-test/r/select_found.result
+++ b/mysql-test/r/select_found.result
@@ -226,3 +226,20 @@ WHERE ( r = 1 AND a IN ( 1, 2 ) AND ( u = 'w' OR u LIKE 'w/%' ) )
OR ( r = 1 AND a IN ( 3 ) AND ( u = 'w/U' OR u LIKE 'w/U/%' ) )
OR ( r = 1 AND a IN ( 1, 2, 3 ) AND ( u = 'w' ) );
drop table t1;
+CREATE TABLE t1 (a VARCHAR(16), UNIQUE(a));
+INSERT INTO t1 VALUES ('1'), ('2'), ('3');
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a = '2' LIMIT 0, 1;
+a
+2
+SELECT FOUND_ROWS();
+FOUND_ROWS()
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (0), (0), (1), (2);
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a = 0 GROUP BY a HAVING a > 10;
+a
+SELECT FOUND_ROWS();
+FOUND_ROWS()
+0
+DROP TABLE t1;
diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result
index 6bffdd85aa4..766ee8c0e14 100644
--- a/mysql-test/r/select_safe.result
+++ b/mysql-test/r/select_safe.result
@@ -30,7 +30,7 @@ ERROR HY000: You are using safe update mode and you tried to update a table with
delete from t1 where a+0=1;
ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5;
-ERROR 42000: The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
update t1 set b="a" limit 1;
update t1 set b="a" where b="b" limit 2;
delete from t1 where b="test" limit 1;
@@ -42,7 +42,7 @@ SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS;
2 0
insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a");
SELECT * from t1 order by a;
-ERROR 42000: The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
SET SQL_BIG_SELECTS=1;
SELECT * from t1 order by a;
a b
@@ -52,7 +52,7 @@ a b
5 a
SET MAX_JOIN_SIZE=2;
SELECT * from t1;
-ERROR 42000: The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
+ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
SET MAX_JOIN_SIZE=DEFAULT;
SELECT * from t1;
a b
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 3ea2082873d..27daed64816 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -43,7 +43,7 @@ wait_timeout 28800
show variables like "this_doesn't_exists%";
Variable_name Value
show table status from test like "this_doesn't_exists%";
-Name Engine Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
show databases;
Database
mysql
@@ -309,58 +309,58 @@ insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1,1),(2,2);
show table status;
-Name Engine Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 2 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 2 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 2 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 HEAP 9 Fixed 2 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP 9 Fixed 2 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP 9 Fixed 2 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
insert into t1 values (3),(4);
insert into t2 values (3),(4);
insert into t3 values (3,3),(4,4);
show table status;
-Name Engine Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 4 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 4 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 4 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 HEAP 9 Fixed 4 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP 9 Fixed 4 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP 9 Fixed 4 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
show table status;
-Name Engine Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 5 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 5 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 5 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 HEAP 9 Fixed 5 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP 9 Fixed 5 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP 9 Fixed 5 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1 where a=3;
delete from t2 where b=3;
delete from t3 where a=3;
show table status;
-Name Engine Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 4 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 4 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 4 9 # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 HEAP 9 Fixed 4 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP 9 Fixed 4 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP 9 Fixed 4 9 # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1;
delete from t2;
delete from t3;
show table status;
-Name Engine Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 0 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 0 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 0 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 HEAP 9 Fixed 0 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP 9 Fixed 0 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP 9 Fixed 0 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
show table status;
-Name Engine Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 1 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 1 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 1 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 HEAP 9 Fixed 1 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP 9 Fixed 1 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP 9 Fixed 1 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1 where a=5;
delete from t2 where b=5;
delete from t3 where a=5;
show table status;
-Name Engine Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 HEAP Fixed 0 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP Fixed 0 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP Fixed 0 9 # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 HEAP 9 Fixed 0 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 HEAP 9 Fixed 0 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 HEAP 9 Fixed 0 9 # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
drop table t1, t2, t3;
create database test_$1;
show create database test_$1;
@@ -378,21 +378,21 @@ show create database test_$1;
Database Create Database
test_$1 CREATE DATABASE `test_$1` /*!40100 DEFAULT CHARACTER SET latin1 */
drop table t1;
-ERROR 42000: Access denied for user: 'mysqltest_1'@'localhost' to database 'test_$1'
+ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'test_$1'
drop database test_$1;
-ERROR 42000: Access denied for user: 'mysqltest_1'@'localhost' to database 'test_$1'
+ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'test_$1'
select * from test_$1.t1;
-ERROR 42000: Access denied for user: 'mysqltest_2'@'localhost' to database 'test_$1'
+ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'test_$1'
show create database test_$1;
-ERROR 42000: Access denied for user: 'mysqltest_2'@'localhost' to database 'test_$1'
+ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'test_$1'
drop table test_$1.t1;
-ERROR 42000: Access denied for user: 'mysqltest_2'@'localhost' to database 'test_$1'
+ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'test_$1'
drop database test_$1;
-ERROR 42000: Access denied for user: 'mysqltest_2'@'localhost' to database 'test_$1'
+ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'test_$1'
select * from test_$1.t1;
-ERROR 42000: Access denied for user: 'mysqltest_3'@'localhost' to database 'test_$1'
+ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'test_$1'
show create database test_$1;
-ERROR 42000: Access denied for user: 'mysqltest_3'@'localhost' to database 'test_$1'
+ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'test_$1'
drop table test_$1.t1;
drop database test_$1;
delete from mysql.user
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index bc1e5af0a81..887466e4388 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -6,7 +6,7 @@ explain extended select (select 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1249 Select 2 was reduced during optimisation
+Note 1249 Select 2 was reduced during optimization
Note 1003 select 2 AS `(select 2)`
SELECT (SELECT 1) UNION SELECT (SELECT 2);
(SELECT 1)
@@ -18,8 +18,8 @@ id select_type table type possible_keys key key_len ref rows Extra
3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL
Warnings:
-Note 1249 Select 2 was reduced during optimisation
-Note 1249 Select 4 was reduced during optimisation
+Note 1249 Select 2 was reduced during optimization
+Note 1249 Select 4 was reduced during optimization
Note 1003 select 1 AS `(SELECT 1)` union select 2 AS `(SELECT 2)`
SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0))
@@ -31,7 +31,7 @@ id select_type table type possible_keys key key_len ref rows Extra
4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
Warnings:
-Note 1249 Select 2 was reduced during optimisation
+Note 1249 Select 2 was reduced during optimization
Note 1003 select (select 0 AS `0` union select 0 AS `0`) AS `(SELECT (SELECT 0 UNION SELECT 0))`
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
@@ -73,7 +73,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
1
1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
-ERROR HY000: Wrong usage of PROCEDURE and subquery
+ERROR HY000: Incorrect usage of PROCEDURE and subquery
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
ERROR HY000: Incorrect parameters to procedure 'ANALYSE'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
@@ -328,13 +328,13 @@ patient_uq clinic_uq
explain extended select * from t6 where exists (select * from t7 where uq = clinic_uq);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t6 ALL NULL NULL NULL NULL 4 Using where
-2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1
+2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1 Using index
Warnings:
Note 1276 Field or reference 'clinic_uq' of SELECT #2 was resolved in SELECT #1
-Note 1003 select test.t6.patient_uq AS `patient_uq`,test.t6.clinic_uq AS `clinic_uq` from test.t6 where exists(select test.t7.uq AS `uq`,test.t7.name AS `name` from test.t7 where (test.t7.uq = test.t6.clinic_uq))
+Note 1003 select test.t6.patient_uq AS `patient_uq`,test.t6.clinic_uq AS `clinic_uq` from test.t6 where exists(select 1 AS `Not_used` from test.t7 where (test.t7.uq = test.t6.clinic_uq))
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
-ERROR 23000: Column: 'a' in field list is ambiguous
-drop table if exists t1,t2,t3;
+ERROR 23000: Column 'a' in field list is ambiguous
+drop table t1,t2,t3;
CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0');
INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b');
CREATE TABLE t2 (a varchar(20),b int NOT NULL default '0');
@@ -720,7 +720,7 @@ EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ref id id 5 const 1 Using where; Using index
Warnings:
-Note 1249 Select 2 was reduced during optimisation
+Note 1249 Select 2 was reduced during optimization
Note 1003 select test.t2.id AS `id` from test.t2 where (test.t2.id = 1)
SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
id
@@ -732,8 +732,8 @@ EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ref id id 5 const 1 Using where; Using index
Warnings:
-Note 1249 Select 3 was reduced during optimisation
-Note 1249 Select 2 was reduced during optimisation
+Note 1249 Select 3 was reduced during optimization
+Note 1249 Select 2 was reduced during optimization
Note 1003 select test.t2.id AS `id` from test.t2 where (test.t2.id = (1 + 1))
EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
id select_type table type possible_keys key key_len ref rows Extra
@@ -867,7 +867,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
Warnings:
Note 1276 Field or reference 'a' of SELECT #2 was resolved in SELECT #1
-Note 1249 Select 2 was reduced during optimisation
+Note 1249 Select 2 was reduced during optimization
Note 1003 select (test.t1.a + 1) AS `(select a+1)` from test.t1
select (select a+1) from t1;
(select a+1)
@@ -984,7 +984,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
HANDLER t1 READ a=((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1))' at line 1
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
@@ -1083,24 +1083,24 @@ CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT 1)) a;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(1) NOT NULL default '0',
- `(SELECT 1)` bigint(1) NOT NULL default '0'
+ `a` bigint(20) NOT NULL default '0',
+ `(SELECT 1)` bigint(20) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a)) a;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(1) NOT NULL default '0',
- `(SELECT a)` bigint(1) NOT NULL default '0'
+ `a` bigint(20) NOT NULL default '0',
+ `(SELECT a)` bigint(20) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(1) NOT NULL default '0',
- `(SELECT a+0)` bigint(17) NOT NULL default '0'
+ `a` bigint(20) NOT NULL default '0',
+ `(SELECT a+0)` bigint(20) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a;
@@ -1110,7 +1110,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(17) NOT NULL default '0'
+ `a` bigint(20) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
@@ -1722,7 +1722,7 @@ create table t1(id int);
create table t2(id int);
create table t3(flag int);
select (select * from t3 where id not null) from t1, t2;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'null) from t1, t2' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null) from t1, t2' at line 1
drop table t1,t2,t3;
CREATE TABLE t1 (id INT);
CREATE TABLE t2 (id INT);
@@ -1825,3 +1825,77 @@ a
1
3
DROP TABLE t1;
+create table t1 (a int, b int);
+insert into t1 values (1,2),(3,4);
+select * from t1 up where exists (select * from t1 where t1.a=up.a);
+a b
+1 2
+3 4
+explain extended select * from t1 up where exists (select * from t1 where t1.a=up.a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY up ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
+Warnings:
+Note 1276 Field or reference 'up.a' of SELECT #2 was resolved in SELECT #1
+Note 1003 select test.up.a AS `a`,test.up.b AS `b` from test.t1 up where exists(select 1 AS `Not_used` from test.t1 where (test.t1.a = test.up.a))
+drop table t1;
+CREATE TABLE t1 (t1_a int);
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (t2_a int, t2_b int, PRIMARY KEY (t2_a, t2_b));
+INSERT INTO t2 VALUES (1, 1), (1, 2);
+SELECT * FROM t1, t2 table2 WHERE t1_a = 1 AND table2.t2_a = 1
+HAVING table2.t2_b = (SELECT MAX(t2_b) FROM t2 WHERE t2_a = table2.t2_a);
+t1_a t2_a t2_b
+1 1 2
+DROP TABLE t1, t2;
+CREATE TABLE t1 (id int(11) default NULL,name varchar(10) default NULL);
+INSERT INTO t1 VALUES (1,'Tim'),(2,'Rebecca'),(3,NULL);
+CREATE TABLE t2 (id int(11) default NULL, pet varchar(10) default NULL);
+INSERT INTO t2 VALUES (1,'Fido'),(2,'Spot'),(3,'Felix');
+SELECT a.*, b.* FROM (SELECT * FROM t1) AS a JOIN t2 as b on a.id=b.id;
+id name id pet
+1 Tim 1 Fido
+2 Rebecca 2 Spot
+3 NULL 3 Felix
+drop table t1,t2;
+CREATE TABLE t1 ( a int, b int );
+CREATE TABLE t2 ( c int, d int );
+INSERT INTO t1 VALUES (1,2), (2,3), (3,4);
+SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);
+abc b
+1 2
+2 3
+3 4
+INSERT INTO t2 SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);
+select * from t2;
+c d
+1 2
+2 3
+3 4
+CREATE TABLE t3 SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);
+select * from t3;
+abc b
+1 2
+2 3
+3 4
+prepare stmt1 from "INSERT INTO t2 SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);";
+execute stmt1;
+deallocate prepare stmt1;
+select * from t2;
+c d
+1 2
+2 3
+3 4
+1 2
+2 3
+3 4
+drop table t3;
+prepare stmt1 from "CREATE TABLE t3 SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);";
+execute stmt1;
+select * from t3;
+abc b
+1 2
+2 3
+3 4
+deallocate prepare stmt1;
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result
index 9c1816e295c..bbbc607b6f8 100644
--- a/mysql-test/r/subselect_innodb.result
+++ b/mysql-test/r/subselect_innodb.result
@@ -96,3 +96,13 @@ id value (select t1.value from t1 where t1.id=t2.id)
1 z a
2 x b
drop table t1,t2;
+create table t1 (a int, b int) engine=innodb;
+insert into t1 values (1,2), (1,3), (2,3), (2,4), (2,5), (3,4), (4,5), (4,100);
+create table t2 (a int) engine=innodb;
+insert into t2 values (1),(2),(3),(4);
+select a, sum(b) as b from t1 group by a having b > (select max(a) from t2);
+a b
+1 5
+2 12
+4 105
+drop table t1, t2;
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index 8376535593e..4b4377915c7 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -10,6 +10,11 @@ help_topic
host
proc
tables_priv
+time_zone
+time_zone_leap_second
+time_zone_name
+time_zone_transition
+time_zone_transition_type
user
show create table db;
Table Create Table
diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result
index 15f0d4121c7..10944c3706e 100644
--- a/mysql-test/r/timezone.result
+++ b/mysql-test/r/timezone.result
@@ -1,7 +1,7 @@
DROP TABLE IF EXISTS t1;
-show variables like "timezone";
+show variables like "system_time_zone";
Variable_name Value
-timezone MET
+system_time_zone MET
select @a:=FROM_UNIXTIME(1);
@a:=FROM_UNIXTIME(1)
1970-01-01 01:00:01
@@ -32,6 +32,13 @@ ts from_unixtime(ts)
1048989599 2003-03-30 03:59:59
1048989601 2003-03-30 04:00:01
DROP TABLE t1;
+CREATE TABLE t1 (ts timestamp);
+INSERT INTO t1 (ts) VALUES ('2003-03-30 01:59:59'),
+('2003-03-30 02:59:59'),
+('2003-03-30 03:00:00');
+Warnings:
+Warning 1299 Invalid TIMESTAMP value in column 'ts' at row 2
+DROP TABLE t1;
select unix_timestamp('1970-01-01 01:00:00'),
unix_timestamp('1970-01-01 01:00:01'),
unix_timestamp('2038-01-01 00:59:59'),
diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result
new file mode 100644
index 00000000000..5361ff4ffe6
--- /dev/null
+++ b/mysql-test/r/timezone2.result
@@ -0,0 +1,246 @@
+drop table if exists t1;
+create table t1 (ts timestamp);
+set time_zone='+00:00';
+select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
+unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp())
+0
+insert into t1 (ts) values ('2003-03-30 02:30:00');
+set time_zone='+10:30';
+select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
+unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp())
+-37800
+insert into t1 (ts) values ('2003-03-30 02:30:00');
+set time_zone='-10:00';
+select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
+unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp())
+36000
+insert into t1 (ts) values ('2003-03-30 02:30:00');
+select * from t1;
+ts
+2003-03-29 16:30:00
+2003-03-29 06:00:00
+2003-03-30 02:30:00
+drop table t1;
+select Name from mysql.time_zone_name where Name in
+('UTC','Universal','MET','Europe/Moscow','leap/Europe/Moscow');
+Name
+Europe/Moscow
+leap/Europe/Moscow
+MET
+Universal
+UTC
+create table t1 (i int, ts timestamp);
+set time_zone='MET';
+insert into t1 (i, ts) values
+(unix_timestamp('2003-03-01 00:00:00'),'2003-03-01 00:00:00');
+insert into t1 (i, ts) values
+(unix_timestamp('2003-03-30 01:59:59'),'2003-03-30 01:59:59'),
+(unix_timestamp('2003-03-30 02:30:00'),'2003-03-30 02:30:00'),
+(unix_timestamp('2003-03-30 03:00:00'),'2003-03-30 03:00:00');
+Warnings:
+Warning 1299 Invalid TIMESTAMP value in column 'ts' at row 2
+insert into t1 (i, ts) values
+(unix_timestamp('2003-05-01 00:00:00'),'2003-05-01 00:00:00');
+insert into t1 (i, ts) values
+(unix_timestamp('2003-10-26 01:00:00'),'2003-10-26 01:00:00'),
+(unix_timestamp('2003-10-26 02:00:00'),'2003-10-26 02:00:00'),
+(unix_timestamp('2003-10-26 02:59:59'),'2003-10-26 02:59:59'),
+(unix_timestamp('2003-10-26 04:00:00'),'2003-10-26 04:00:00'),
+(unix_timestamp('2003-10-26 02:59:59'),'2003-10-26 02:59:59');
+set time_zone='UTC';
+select * from t1;
+i ts
+1046473200 2003-02-28 23:00:00
+1048985999 2003-03-30 00:59:59
+1048986000 2003-03-30 01:00:00
+1048986000 2003-03-30 01:00:00
+1051740000 2003-04-30 22:00:00
+1067122800 2003-10-25 23:00:00
+1067126400 2003-10-26 00:00:00
+1067129999 2003-10-26 00:59:59
+1067137200 2003-10-26 03:00:00
+1067129999 2003-10-26 00:59:59
+delete from t1;
+set time_zone='Europe/Moscow';
+insert into t1 (i, ts) values
+(unix_timestamp('2004-01-01 00:00:00'),'2004-01-01 00:00:00'),
+(unix_timestamp('2004-03-28 02:30:00'),'2004-03-28 02:30:00'),
+(unix_timestamp('2004-08-01 00:00:00'),'2003-08-01 00:00:00'),
+(unix_timestamp('2004-10-31 02:30:00'),'2004-10-31 02:30:00');
+Warnings:
+Warning 1299 Invalid TIMESTAMP value in column 'ts' at row 2
+select * from t1;
+i ts
+1072904400 2004-01-01 00:00:00
+1080428400 2004-03-28 03:00:00
+1091304000 2003-08-01 00:00:00
+1099175400 2004-10-31 02:30:00
+delete from t1;
+set time_zone='leap/Europe/Moscow';
+insert into t1 (i, ts) values
+(unix_timestamp('2004-01-01 00:00:00'),'2004-01-01 00:00:00'),
+(unix_timestamp('2004-03-28 02:30:00'),'2004-03-28 02:30:00'),
+(unix_timestamp('2004-08-01 00:00:00'),'2003-08-01 00:00:00'),
+(unix_timestamp('2004-10-31 02:30:00'),'2004-10-31 02:30:00');
+Warnings:
+Warning 1299 Invalid TIMESTAMP value in column 'ts' at row 2
+select * from t1;
+i ts
+1072904422 2004-01-01 00:00:00
+1080428422 2004-03-28 03:00:00
+1091304022 2003-08-01 00:00:00
+1099175422 2004-10-31 02:30:00
+delete from t1;
+insert into t1 (i, ts) values
+(unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'),
+(unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00');
+select * from t1;
+i ts
+362793608 1981-07-01 03:59:59
+362793610 1981-07-01 04:00:00
+select from_unixtime(362793609);
+from_unixtime(362793609)
+1981-07-01 03:59:60
+drop table t1;
+create table t1 (ts timestamp);
+set time_zone='UTC';
+insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'),
+('1970-01-01 00:00:00'),('1970-01-01 00:00:01'),
+('2037-12-31 23:59:59'),('2038-01-01 00:00:00');
+Warnings:
+Warning 1264 Data truncated; out of range for column 'ts' at row 2
+Warning 1264 Data truncated; out of range for column 'ts' at row 3
+Warning 1264 Data truncated; out of range for column 'ts' at row 6
+select * from t1;
+ts
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+1970-01-01 00:00:01
+2037-12-31 23:59:59
+0000-00-00 00:00:00
+delete from t1;
+set time_zone='MET';
+insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'),
+('1970-01-01 01:00:00'),('1970-01-01 01:00:01'),
+('2038-01-01 00:59:59'),('2038-01-01 01:00:00');
+Warnings:
+Warning 1264 Data truncated; out of range for column 'ts' at row 2
+Warning 1264 Data truncated; out of range for column 'ts' at row 3
+Warning 1264 Data truncated; out of range for column 'ts' at row 6
+select * from t1;
+ts
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+1970-01-01 01:00:01
+2038-01-01 00:59:59
+0000-00-00 00:00:00
+delete from t1;
+set time_zone='+01:30';
+insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'),
+('1970-01-01 01:30:00'),('1970-01-01 01:30:01'),
+('2038-01-01 01:29:59'),('2038-01-01 01:30:00');
+Warnings:
+Warning 1264 Data truncated; out of range for column 'ts' at row 2
+Warning 1264 Data truncated; out of range for column 'ts' at row 3
+Warning 1264 Data truncated; out of range for column 'ts' at row 6
+select * from t1;
+ts
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+1970-01-01 01:30:01
+2038-01-01 01:29:59
+0000-00-00 00:00:00
+drop table t1;
+show variables like 'time_zone';
+Variable_name Value
+time_zone +01:30
+set time_zone = default;
+show variables like 'time_zone';
+Variable_name Value
+time_zone SYSTEM
+set time_zone= '0';
+ERROR HY000: Unknown or incorrect time zone: '0'
+set time_zone= '0:0';
+ERROR HY000: Unknown or incorrect time zone: '0:0'
+set time_zone= '-20:00';
+ERROR HY000: Unknown or incorrect time zone: '-20:00'
+set time_zone= '+20:00';
+ERROR HY000: Unknown or incorrect time zone: '+20:00'
+set time_zone= 'Some/Unknown/Time/Zone';
+ERROR HY000: Unknown or incorrect time zone: 'Some/Unknown/Time/Zone'
+select convert_tz(now(),'UTC', 'Universal') = now();
+convert_tz(now(),'UTC', 'Universal') = now()
+1
+select convert_tz(now(),'utc', 'UTC') = now();
+convert_tz(now(),'utc', 'UTC') = now()
+1
+select convert_tz('1917-11-07 12:00:00', 'MET', 'UTC');
+convert_tz('1917-11-07 12:00:00', 'MET', 'UTC')
+1917-11-07 12:00:00
+select convert_tz('1970-01-01 01:00:00', 'MET', 'UTC');
+convert_tz('1970-01-01 01:00:00', 'MET', 'UTC')
+1970-01-01 01:00:00
+select convert_tz('1970-01-01 01:00:01', 'MET', 'UTC');
+convert_tz('1970-01-01 01:00:01', 'MET', 'UTC')
+1970-01-01 00:00:01
+select convert_tz('2003-03-01 00:00:00', 'MET', 'UTC');
+convert_tz('2003-03-01 00:00:00', 'MET', 'UTC')
+2003-02-28 23:00:00
+select convert_tz('2003-03-30 01:59:59', 'MET', 'UTC');
+convert_tz('2003-03-30 01:59:59', 'MET', 'UTC')
+2003-03-30 00:59:59
+select convert_tz('2003-03-30 02:30:00', 'MET', 'UTC');
+convert_tz('2003-03-30 02:30:00', 'MET', 'UTC')
+2003-03-30 01:00:00
+select convert_tz('2003-03-30 03:00:00', 'MET', 'UTC');
+convert_tz('2003-03-30 03:00:00', 'MET', 'UTC')
+2003-03-30 01:00:00
+select convert_tz('2003-05-01 00:00:00', 'MET', 'UTC');
+convert_tz('2003-05-01 00:00:00', 'MET', 'UTC')
+2003-04-30 22:00:00
+select convert_tz('2003-10-26 01:00:00', 'MET', 'UTC');
+convert_tz('2003-10-26 01:00:00', 'MET', 'UTC')
+2003-10-25 23:00:00
+select convert_tz('2003-10-26 02:00:00', 'MET', 'UTC');
+convert_tz('2003-10-26 02:00:00', 'MET', 'UTC')
+2003-10-26 00:00:00
+select convert_tz('2003-10-26 02:59:59', 'MET', 'UTC');
+convert_tz('2003-10-26 02:59:59', 'MET', 'UTC')
+2003-10-26 00:59:59
+select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC');
+convert_tz('2003-10-26 04:00:00', 'MET', 'UTC')
+2003-10-26 03:00:00
+select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC');
+convert_tz('2038-01-01 00:59:59', 'MET', 'UTC')
+2037-12-31 23:59:59
+select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC');
+convert_tz('2038-01-01 01:00:00', 'MET', 'UTC')
+2038-01-01 01:00:00
+select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC');
+convert_tz('2103-01-01 04:00:00', 'MET', 'UTC')
+2103-01-01 04:00:00
+create table t1 (tz varchar(3));
+insert into t1 (tz) values ('MET'), ('UTC');
+select tz, convert_tz('2003-12-31 00:00:00',tz,'UTC'), convert_tz('2003-12-31 00:00:00','UTC',tz) from t1 order by tz;
+tz convert_tz('2003-12-31 00:00:00',tz,'UTC') convert_tz('2003-12-31 00:00:00','UTC',tz)
+MET 2003-12-30 23:00:00 2003-12-31 01:00:00
+UTC 2003-12-31 00:00:00 2003-12-31 00:00:00
+drop table t1;
+select convert_tz('2003-12-31 04:00:00', NULL, 'UTC');
+convert_tz('2003-12-31 04:00:00', NULL, 'UTC')
+NULL
+select convert_tz('2003-12-31 04:00:00', 'SomeNotExistingTimeZone', 'UTC');
+convert_tz('2003-12-31 04:00:00', 'SomeNotExistingTimeZone', 'UTC')
+NULL
+select convert_tz('2003-12-31 04:00:00', 'MET', 'SomeNotExistingTimeZone');
+convert_tz('2003-12-31 04:00:00', 'MET', 'SomeNotExistingTimeZone')
+NULL
+select convert_tz('2003-12-31 04:00:00', 'MET', NULL);
+convert_tz('2003-12-31 04:00:00', 'MET', NULL)
+NULL
+select convert_tz( NULL, 'MET', 'UTC');
+convert_tz( NULL, 'MET', 'UTC')
+NULL
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 6792f2f4c2c..580fc9a8d0b 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -27,7 +27,7 @@ t3 CREATE TABLE `t3` (
drop table t1,t2,t3
#;
CREATE TABLE t1 (a char(257) default "hello");
-ERROR 42000: Too big column length for column 'a' (max = 255). Use BLOB instead
+ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB instead
CREATE TABLE t2 (a blob default "hello");
ERROR 42000: BLOB/TEXT column 'a' can't have a default value
drop table if exists t1,t2;
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index cebd005c2c8..e77ef9f975b 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -73,3 +73,9 @@ SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ' , t2.
DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ' , t2.GMT)) DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ' , t2.GMT))
Wed, 06 March 2002 10:11:12 GMT-0800 Wed, 06 March 2002 10:11:12 GMT-0800
drop table t1,t2;
+CREATE TABLE t1 (f1 time default NULL, f2 time default NULL);
+INSERT INTO t1 (f1, f2) VALUES ('09:00', '12:00');
+SELECT DATE_FORMAT(f1, "%l.%i %p") , DATE_FORMAT(f2, "%l.%i %p") FROM t1;
+DATE_FORMAT(f1, "%l.%i %p") DATE_FORMAT(f2, "%l.%i %p")
+9.00 AM 12.00 PM
+DROP TABLE t1;
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index 66eb744e7ce..524bc9c50d4 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -1,12 +1,6 @@
drop table if exists t1;
create table t1 (t datetime);
-insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460);
-Warnings:
-Warning 1265 Data truncated for column 't' at row 13
-Warning 1265 Data truncated for column 't' at row 14
-Warning 1265 Data truncated for column 't' at row 15
-Warning 1265 Data truncated for column 't' at row 16
-Warning 1265 Data truncated for column 't' at row 17
+insert into t1 values (101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030100000000),(20030000000000);
select * from t1;
t
2000-01-01 00:00:00
@@ -21,11 +15,8 @@ t
1999-12-31 23:59:59
1000-01-01 00:00:00
9999-12-31 23:59:59
-0000-00-00 00:00:00
-0000-00-00 00:00:00
-0000-00-00 00:00:00
-0000-00-00 00:00:00
-0000-00-00 00:00:00
+2003-01-00 00:00:00
+2003-00-00 00:00:00
delete from t1 where t > 0;
optimize table t1;
Table Op Msg_type Msg_text
@@ -34,13 +25,7 @@ check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
delete from t1;
-insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460");
-Warnings:
-Warning 1264 Data truncated, out of range for column 't' at row 14
-Warning 1264 Data truncated, out of range for column 't' at row 15
-Warning 1264 Data truncated, out of range for column 't' at row 16
-Warning 1264 Data truncated, out of range for column 't' at row 17
-Warning 1264 Data truncated, out of range for column 't' at row 18
+insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030100000000"),("20030000000000");
select * from t1;
t
2000-01-01 00:00:00
@@ -56,11 +41,8 @@ t
1999-12-31 23:59:59
1000-01-01 00:00:00
9999-12-31 23:59:59
-0000-00-00 00:00:00
-0000-00-00 00:00:00
-0000-00-00 00:00:00
-0000-00-00 00:00:00
-0000-00-00 00:00:00
+2003-01-00 00:00:00
+2003-00-00 00:00:00
drop table t1;
CREATE TABLE t1 (a timestamp, b date, c time, d datetime);
insert into t1 (b,c,d) values(now(),curtime(),now());
@@ -114,3 +96,43 @@ insert into t1 values (now(), now());
select * from t1 where a is null or b is null;
a b
drop table t1;
+create table t1 (t datetime);
+insert into t1 values (20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460);
+Warnings:
+Warning 1265 Data truncated for column 't' at row 1
+Warning 1265 Data truncated for column 't' at row 2
+Warning 1265 Data truncated for column 't' at row 3
+Warning 1265 Data truncated for column 't' at row 4
+Warning 1265 Data truncated for column 't' at row 5
+select * from t1;
+t
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+delete from t1;
+insert into t1 values ("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460");
+Warnings:
+Warning 1264 Data truncated; out of range for column 't' at row 1
+Warning 1264 Data truncated; out of range for column 't' at row 2
+Warning 1264 Data truncated; out of range for column 't' at row 3
+Warning 1264 Data truncated; out of range for column 't' at row 4
+Warning 1264 Data truncated; out of range for column 't' at row 5
+select * from t1;
+t
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+delete from t1;
+insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer");
+Warnings:
+Warning 1264 Data truncated; out of range for column 't' at row 1
+Warning 1264 Data truncated; out of range for column 't' at row 2
+select * from t1;
+t
+0000-00-00 00:00:00
+2003-01-01 00:00:00
+drop table t1;
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index dc78369f583..a9dcabd121e 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -158,14 +158,14 @@ insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 1
Warning 1265 Data truncated for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
Warnings:
Warning 1265 Data truncated for column 'a' at row 3
@@ -201,29 +201,29 @@ drop table t1;
create table t1 (a decimal(10,2) unsigned);
insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 6
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 6
insert into t1 values ("-.1"),("+.1"),(".1");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 1
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 1
Warning 1265 Data truncated for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
Warnings:
Warning 1265 Data truncated for column 'a' at row 3
@@ -259,29 +259,29 @@ drop table t1;
create table t1 (a decimal(10,2) zerofill);
insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 6
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 6
insert into t1 values ("-.1"),("+.1"),(".1");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 1
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("-111111111.11"),("+1111111111.11"),("1111111111.11");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 1
Warning 1265 Data truncated for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
Warnings:
Warning 1265 Data truncated for column 'a' at row 3
@@ -321,13 +321,13 @@ insert into t1 values (00000000000001),(+0000000000001),(-0000000000001);
insert into t1 values (+111111111.11),(111111111.11),(-11111111.11);
insert into t1 values (-111111111.11),(+1111111111.11),(1111111111.11);
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values (1e+100),(1e-100),(-1e+100);
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 3
insert into t1 values (123.4e0),(123.4e+2),(123.4e-2),(123e1),(123e+0);
select * from t1;
a
@@ -361,8 +361,8 @@ drop table t1;
create table t1 (a decimal);
insert into t1 values (-99999999999999),(-1),('+1'),('01'),('+00000000000001'),('+12345678901'),(99999999999999);
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 7
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 7
select * from t1;
a
-9999999999
@@ -376,9 +376,9 @@ drop table t1;
create table t1 (a decimal unsigned);
insert into t1 values (-99999999999999),(-1),('+1'),('01'),('+00000000000001'),('+1234567890'),(99999999999999);
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 7
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 7
select * from t1;
a
0
@@ -392,9 +392,9 @@ drop table t1;
create table t1 (a decimal zerofill);
insert into t1 values (-99999999999999),(-1),('+1'),('01'),('+00000000000001'),('+1234567890'),(99999999999999);
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 7
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 7
select * from t1;
a
0000000000
@@ -408,9 +408,9 @@ drop table t1;
create table t1 (a decimal unsigned zerofill);
insert into t1 values (-99999999999999),(-1),('+1'),('01'),('+00000000000001'),('+1234567890'),(99999999999999);
Warnings:
-Warning 1264 Data truncated, out of range for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 7
+Warning 1264 Data truncated; out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 2
+Warning 1264 Data truncated; out of range for column 'a' at row 7
select * from t1;
a
0000000000
@@ -425,7 +425,7 @@ create table t1(a decimal(10,0));
insert into t1 values ("1e4294967295");
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 1
select * from t1;
a
99999999999
@@ -433,17 +433,24 @@ delete from t1;
insert into t1 values("1e4294967297");
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'a' at row 1
select * from t1;
a
99999999999
drop table t1;
CREATE TABLE t1 (a_dec DECIMAL(-1,0));
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '-1,0))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1,0))' at line 1
CREATE TABLE t1 (a_dec DECIMAL(-2,1));
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '-2,1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-2,1))' at line 1
CREATE TABLE t1 (a_dec DECIMAL(-1,1));
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '-1,1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1,1))' at line 1
+CREATE TABLE t1 (a_dec DECIMAL(0,11));
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a_dec` decimal(12,11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
create table t1(a decimal(7,3));
insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
select * from t1;
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index f044ced2342..30de1e62df7 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -15,8 +15,8 @@ f1 float NULL YES NULL select,insert,update,references
f2 double NULL YES NULL select,insert,update,references
insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150);
Warnings:
-Warning 1264 Data truncated, out of range for column 'f1' at row 7
-Warning 1264 Data truncated, out of range for column 'f1' at row 8
+Warning 1264 Data truncated; out of range for column 'f1' at row 7
+Warning 1264 Data truncated; out of range for column 'f1' at row 8
insert into t1 values(-10,-10),(1e-5,1e-5),(1e-10,1e-10),(1e-15,1e-15),(1e-20,1e-20),(1e-50,1e-50),(1e-150,1e-150);
select * from t1;
f1 f2
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index 8d80f342c1c..e803fde14a6 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -89,33 +89,33 @@ insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,N
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303101010','','','','3',3,3);
insert into t1 values (0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,NULL,19970807,080706,19970403090807,-1,-1,-1,'-1',-1,-1);
Warnings:
-Warning 1264 Data truncated, out of range for column 'utiny' at row 1
-Warning 1264 Data truncated, out of range for column 'ushort' at row 1
-Warning 1264 Data truncated, out of range for column 'umedium' at row 1
-Warning 1264 Data truncated, out of range for column 'ulong' at row 1
+Warning 1264 Data truncated; out of range for column 'utiny' at row 1
+Warning 1264 Data truncated; out of range for column 'ushort' at row 1
+Warning 1264 Data truncated; out of range for column 'umedium' at row 1
+Warning 1264 Data truncated; out of range for column 'ulong' at row 1
Warning 1265 Data truncated for column 'options' at row 1
Warning 1265 Data truncated for column 'flags' at row 1
insert into t1 values (0,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,NULL,0,0,0,-4294967295,-4294967295,-4294967295,'-4294967295',0,"one,two,tree");
Warnings:
Warning 1265 Data truncated for column 'string' at row 1
-Warning 1264 Data truncated, out of range for column 'tiny' at row 1
-Warning 1264 Data truncated, out of range for column 'short' at row 1
-Warning 1264 Data truncated, out of range for column 'medium' at row 1
-Warning 1264 Data truncated, out of range for column 'long_int' at row 1
-Warning 1264 Data truncated, out of range for column 'utiny' at row 1
-Warning 1264 Data truncated, out of range for column 'ushort' at row 1
-Warning 1264 Data truncated, out of range for column 'umedium' at row 1
-Warning 1264 Data truncated, out of range for column 'ulong' at row 1
+Warning 1264 Data truncated; out of range for column 'tiny' at row 1
+Warning 1264 Data truncated; out of range for column 'short' at row 1
+Warning 1264 Data truncated; out of range for column 'medium' at row 1
+Warning 1264 Data truncated; out of range for column 'long_int' at row 1
+Warning 1264 Data truncated; out of range for column 'utiny' at row 1
+Warning 1264 Data truncated; out of range for column 'ushort' at row 1
+Warning 1264 Data truncated; out of range for column 'umedium' at row 1
+Warning 1264 Data truncated; out of range for column 'ulong' at row 1
Warning 1265 Data truncated for column 'options' at row 1
insert into t1 values (0,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,NULL,0,0,0,4294967295,4294967295,4294967295,'4294967295',0,0);
Warnings:
-Warning 1264 Data truncated, out of range for column 'tiny' at row 1
-Warning 1264 Data truncated, out of range for column 'short' at row 1
-Warning 1264 Data truncated, out of range for column 'medium' at row 1
-Warning 1264 Data truncated, out of range for column 'long_int' at row 1
-Warning 1264 Data truncated, out of range for column 'utiny' at row 1
-Warning 1264 Data truncated, out of range for column 'ushort' at row 1
-Warning 1264 Data truncated, out of range for column 'umedium' at row 1
+Warning 1264 Data truncated; out of range for column 'tiny' at row 1
+Warning 1264 Data truncated; out of range for column 'short' at row 1
+Warning 1264 Data truncated; out of range for column 'medium' at row 1
+Warning 1264 Data truncated; out of range for column 'long_int' at row 1
+Warning 1264 Data truncated; out of range for column 'utiny' at row 1
+Warning 1264 Data truncated; out of range for column 'ushort' at row 1
+Warning 1264 Data truncated; out of range for column 'umedium' at row 1
Warning 1265 Data truncated for column 'options' at row 1
insert into t1 (tiny) values (1);
select auto,string,tiny,short,medium,long_int,longlong,real_float,real_double,utiny,ushort,umedium,ulong,ulonglong,mod(floor(time_stamp/1000000),1000000)-mod(curdate(),1000000),date_field,time_field,date_time,blob_col,tinyblob_col,mediumblob_col,longblob_col from t1;
diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result
index 68b56802120..025cf2a57f1 100644
--- a/mysql-test/r/type_time.result
+++ b/mysql-test/r/type_time.result
@@ -25,11 +25,11 @@ t
36:30:31
insert into t1 values("10.22.22"),(1234567),(123456789),(123456789.10),("10 22:22"),("12.45a");
Warnings:
-Note 1292 Truncated wrong time value: '10.22.22'
-Warning 1264 Data truncated, out of range for column 't' at row 2
-Warning 1264 Data truncated, out of range for column 't' at row 3
-Warning 1264 Data truncated, out of range for column 't' at row 4
-Note 1292 Truncated wrong time value: '12.45a'
+Warning 1265 Data truncated for column 't' at row 1
+Warning 1264 Data truncated; out of range for column 't' at row 2
+Warning 1264 Data truncated; out of range for column 't' at row 3
+Warning 1264 Data truncated; out of range for column 't' at row 4
+Warning 1265 Data truncated for column 't' at row 6
select * from t1;
t
10:22:33
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 976b3e72385..aa8c0903558 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -43,13 +43,7 @@ date_format(a,"%Y %y") year(a) year(now())
1970 70 1970 1970
drop table t1;
create table t1 (ix timestamp);
-insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000),(20030101010160),(20030101016001),(20030101240101),(20030132010101),(20031301010101);
-Warnings:
-Warning 1265 Data truncated for column 'ix' at row 10
-Warning 1265 Data truncated for column 'ix' at row 11
-Warning 1265 Data truncated for column 'ix' at row 12
-Warning 1265 Data truncated for column 'ix' at row 13
-Warning 1265 Data truncated for column 'ix' at row 14
+insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
select ix+0 from t1;
ix+0
19991101000000
@@ -61,24 +55,14 @@ ix+0
19990501000000
19991101000000
19990501000000
-0
-0
-0
-0
-0
delete from t1;
-insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101");
+insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000");
select ix+0 from t1;
ix+0
19991101000000
19990102030405
19990630232922
19990601000000
-0
-0
-0
-0
-0
drop table t1;
CREATE TABLE t1 (date date, date_time datetime, time_stamp timestamp);
INSERT INTO t1 VALUES ("1998-12-31","1998-12-31 23:59:59",19981231235959);
@@ -128,16 +112,66 @@ t2 t4 t6 t8 t10 t12 t14
0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00
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 1997-12-31 23:47:59
drop table t1;
+create table t1 (ix timestamp);
+insert into t1 values (0),(20030101010160),(20030101016001),(20030101240101),(20030132010101),(20031301010101),(20031200000000),(20030000000000);
+Warnings:
+Warning 1265 Data truncated for column 'ix' at row 2
+Warning 1265 Data truncated for column 'ix' at row 3
+Warning 1265 Data truncated for column 'ix' at row 4
+Warning 1265 Data truncated for column 'ix' at row 5
+Warning 1265 Data truncated for column 'ix' at row 6
+Warning 1265 Data truncated for column 'ix' at row 7
+Warning 1265 Data truncated for column 'ix' at row 8
+select ix+0 from t1;
+ix+0
+0
+0
+0
+0
+0
+0
+0
+0
+delete from t1;
+insert into t1 values ("00000000000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101"),("20031200000000"),("20030000000000");
+Warnings:
+Warning 1265 Data truncated for column 'ix' at row 2
+Warning 1265 Data truncated for column 'ix' at row 3
+Warning 1265 Data truncated for column 'ix' at row 4
+Warning 1265 Data truncated for column 'ix' at row 5
+Warning 1265 Data truncated for column 'ix' at row 6
+Warning 1265 Data truncated for column 'ix' at row 7
+Warning 1265 Data truncated for column 'ix' at row 8
+select ix+0 from t1;
+ix+0
+0
+0
+0
+0
+0
+0
+0
+0
+delete from t1;
+insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer");
+Warnings:
+Warning 1265 Data truncated for column 'ix' at row 1
+Warning 1265 Data truncated for column 'ix' at row 2
+select ix+0 from t1;
+ix+0
+0
+20030101000000
+drop table t1;
create table t1 (t1 timestamp, t2 timestamp default now());
-ERROR HY000: Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
create table t1 (t1 timestamp, t2 timestamp on update now());
-ERROR HY000: Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
create table t1 (t1 timestamp, t2 timestamp default now() on update now());
-ERROR HY000: Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
create table t1 (t1 timestamp default now(), t2 timestamp on update now());
-ERROR HY000: Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
create table t1 (t1 timestamp on update now(), t2 timestamp default now() on update now());
-ERROR HY000: Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
+ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
create table t1 (t1 timestamp default '2003-01-01 00:00:00', t2 datetime, t3 timestamp);
SET TIMESTAMP=1000000000;
insert into t1 values ();
diff --git a/mysql-test/r/type_uint.result b/mysql-test/r/type_uint.result
index f312e9b7f64..07eb47faa7c 100644
--- a/mysql-test/r/type_uint.result
+++ b/mysql-test/r/type_uint.result
@@ -4,7 +4,7 @@ create table t1 (this int unsigned);
insert into t1 values (1);
insert into t1 values (-1);
Warnings:
-Warning 1264 Data truncated, out of range for column 'this' at row 1
+Warning 1264 Data truncated; out of range for column 'this' at row 1
select * from t1;
this
1
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 0735ea4dc40..afee837b1a5 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -81,7 +81,7 @@ a b
2 b
1 a
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b;
-ERROR 42000: Table 't1' from one of SELECT's can not be used in global ORDER clause
+ERROR 42000: Table 't1' from one of the SELECTs cannot be used in global ORDER clause
explain extended (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
@@ -117,11 +117,11 @@ ERROR 21000: The used SELECT statements have a different number of columns
explain select a,b from t1 union select 1 limit 0;
ERROR 21000: The used SELECT statements have a different number of columns
select a,b from t1 into outfile 'skr' union select a,b from t2;
-ERROR HY000: Wrong usage of UNION and INTO
+ERROR HY000: Incorrect usage of UNION and INTO
select a,b from t1 order by a union select a,b from t2;
-ERROR HY000: Wrong usage of UNION and ORDER BY
+ERROR HY000: Incorrect usage of UNION and ORDER BY
insert into t3 select a from t1 order by a union select a from t2;
-ERROR HY000: Wrong usage of UNION and ORDER BY
+ERROR HY000: Incorrect usage of UNION and ORDER BY
create table t3 select a,b from t1 union select a from t2;
ERROR 21000: The used SELECT statements have a different number of columns
select a,b from t1 union select a from t2;
@@ -131,7 +131,7 @@ ERROR 21000: The used SELECT statements have a different number of columns
select a from t1 union select * from t2;
ERROR 21000: The used SELECT statements have a different number of columns
select * from t1 union select SQL_BUFFER_RESULT * from t2;
-ERROR 42000: Wrong usage/placement of 'SQL_BUFFER_RESULT'
+ERROR 42000: Incorrect usage/placement of 'SQL_BUFFER_RESULT'
create table t3 select a,b from t1 union all select a,b from t2;
insert into t3 select a,b from t1 union all select a,b from t2;
replace into t3 select a,b as c from t1 union all select a,b from t2;
@@ -341,7 +341,7 @@ select found_rows();
found_rows()
4
(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2;
a
1
@@ -424,7 +424,7 @@ a
3
3
(SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1;
-ERROR 42000: Wrong usage/placement of 'SQL_CALC_FOUND_ROWS'
+ERROR 42000: Incorrect usage/placement of 'SQL_CALC_FOUND_ROWS'
create temporary table t1 select a from t1 union select a from t2;
drop temporary table t1;
create table t1 select a from t1 union select a from t2;
@@ -546,7 +546,7 @@ aa
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` char(2) NOT NULL default ''
+ `a` char(20) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT 12 as a UNION select 12.2 as a;
@@ -557,7 +557,7 @@ a
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` double(4,1) NOT NULL default '0.0'
+ `a` double(53,1) NOT NULL default '0.0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t2 (it1 tinyint, it2 tinyint not null, i int not null, ib bigint, f float, d double, y year, da date, dt datetime, sc char(10), sv varchar(10), b blob, tx text);
@@ -647,7 +647,7 @@ f
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `f` binary(12) default NULL
+ `f` binary(24) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT y from t2 UNION select da from t2;
@@ -795,7 +795,7 @@ select * from t1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `1` bigint(1) NOT NULL default '0'
+ `1` bigint(20) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 select _latin1"test" union select _latin2"testt" ;
@@ -953,3 +953,38 @@ CREATE TABLE t2 (i int(11) default NULL,c char(1) default NULL,KEY i (i));
explain (select * from t1) union (select * from t2) order by not_existing_column;
ERROR 42S22: Unknown column 'not_existing_column' in 'order clause'
drop table t1, t2;
+CREATE TABLE t1 (uid int(1));
+INSERT INTO t1 SELECT 150;
+SELECT 'a' UNION SELECT uid FROM t1;
+a
+a
+150
+drop table t1;
+CREATE TABLE t1 ( ID1 int(10) unsigned NOT NULL DEFAULT '0' , ID2 datetime NOT NULL DEFAULT '0000-00-00 00:00:00' , DATA1 varchar(10) , DATA2 double(5,4) , DATA3 datetime , PRIMARY KEY (ID1,ID2));
+CREATE TABLE t2 ( ID int(3) unsigned NOT NULL DEFAULT '0' , DATA1 timestamp DEFAULT '0000-00-00 00:00:00' , PRIMARY KEY (ID));
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1);
+ID1 ID2 DATA1 DATA2 DATA3 ID DATA1
+drop table t1,t2;
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index a9351d2f1fb..2750478c1c5 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -162,3 +162,36 @@ charset(@a) collation(@a) coercibility(@a)
latin2 latin2_bin 0
select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST' collate latin2_general_ci;
ERROR HY000: Illegal mix of collations (latin2_bin,EXPLICIT) and (latin2_general_ci,EXPLICIT) for operation '='
+create table t1 (a varchar(50));
+reset master;
+SET TIMESTAMP=10000;
+SET @`a b`='hello';
+INSERT INTO t1 VALUES(@`a b`);
+set @var1= "';aaa";
+insert into t1 values (@var1);
+create table t2 (c char(30)) charset=ucs2;
+set @v=convert('abc' using ucs2);
+insert into t2 values (@v);
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.000001 79 User var 1 79 @`a b`=_latin1 0x68656C6C6F COLLATE latin1_swedish_ci
+master-bin.000001 120 Query 1 120 use `test`; INSERT INTO t1 VALUES(@`a b`)
+master-bin.000001 184 User var 1 184 @`var1`=_latin1 0x273B616161 COLLATE latin1_swedish_ci
+master-bin.000001 226 Query 1 226 use `test`; insert into t1 values (@var1)
+master-bin.000001 290 Query 1 290 use `test`; create table t2 (c char(30)) charset=ucs2
+master-bin.000001 366 User var 1 366 @`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci
+master-bin.000001 406 Query 1 406 use `test`; insert into t2 values (@v)
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+SET @`a b`:=_latin1 0x68656C6C6F COLLATE latin1_swedish_ci;
+use test;
+SET TIMESTAMP=10000;
+INSERT INTO t1 VALUES(@`a b`);
+SET @`var1`:=_latin1 0x273B616161 COLLATE latin1_swedish_ci;
+SET TIMESTAMP=10000;
+insert into t1 values (@var1);
+SET TIMESTAMP=10000;
+create table t2 (c char(30)) charset=ucs2;
+SET @`v`:=_ucs2 0x006100620063 COLLATE ucs2_general_ci;
+SET TIMESTAMP=10000;
+insert into t2 values (@v);
+drop table t1, t2;
diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result
index 26ce91286da..ab5779859ae 100644
--- a/mysql-test/r/varbinary.result
+++ b/mysql-test/r/varbinary.result
@@ -18,7 +18,7 @@ Warnings:
Note 1003 select test.t1.ID AS `ID`,test.t1.UNIQ AS `UNIQ` from test.t1 where (test.t1.UNIQ = 4084688022709641610)
drop table t1;
select x'hello';
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'x'hello'' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'x'hello'' at line 1
select 0xfg;
ERROR 42S22: Unknown column '0xfg' in 'field list'
create table t1 select 1 as x, 2 as xx;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index 31a0ada1267..461f398c2cc 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -239,7 +239,7 @@ ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF'
set unknown_variable=1;
ERROR HY000: Unknown system variable 'unknown_variable'
set max_join_size="hello";
-ERROR 42000: Wrong argument type to variable 'max_join_size'
+ERROR 42000: Incorrect argument type to variable 'max_join_size'
set storage_engine=UNKNOWN_TABLE_TYPE;
ERROR 42000: Unknown table engine 'UNKNOWN_TABLE_TYPE'
set storage_engine=INNODB, big_tables=2;
@@ -424,7 +424,7 @@ ERROR 42000: Variable 'ft_boolean_syntax' can't be set to the value of ''
set global myisam_max_sort_file_size=4294967296;
show global variables like 'myisam_max_sort_file_size';
Variable_name Value
-myisam_max_sort_file_size 4294967296
+myisam_max_sort_file_size MAX_FILE_SIZE
set global myisam_max_sort_file_size=default;
select @@global.max_user_connections,@@local.max_join_size;
@@global.max_user_connections @@session.max_join_size
@@ -451,12 +451,12 @@ select @a, @b;
@a @b
2 1
set @@global.global.key_buffer_size= 1;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size= 1' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size= 1' at line 1
set GLOBAL global.key_buffer_size= 1;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size= 1' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size= 1' at line 1
SELECT @@global.global.key_buffer_size;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
SELECT @@global.session.key_buffer_size;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
SELECT @@global.local.key_buffer_size;
-ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index 19d44ab6fea..d883feb7ce2 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -43,13 +43,13 @@ drop table t1;
create table t1(a tinyint, b int not null, c date, d char(5));
load data infile '../../std_data/warnings_loaddata.dat' into table t1 fields terminated by ',';
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'b' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'b' at row 2
Warning 1265 Data truncated for column 'd' at row 3
Warning 1265 Data truncated for column 'c' at row 4
Warning 1261 Row 5 doesn't contain data for all columns
Warning 1265 Data truncated for column 'b' at row 6
-Warning 1262 Row 7 was truncated; It contained more data than there were input columns
-Warning 1264 Data truncated, out of range for column 'a' at row 8
+Warning 1262 Row 7 was truncated; it contained more data than there were input columns
+Warning 1264 Data truncated; out of range for column 'a' at row 8
select @@warning_count;
@@warning_count
7
@@ -57,11 +57,11 @@ drop table t1;
create table t1(a tinyint NOT NULL, b tinyint unsigned, c char(5));
insert into t1 values(NULL,100,'mysql'),(10,-1,'mysql ab'),(500,256,'open source'),(20,NULL,'test');
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'a' at row 1
-Warning 1264 Data truncated, out of range for column 'b' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1264 Data truncated; out of range for column 'b' at row 2
Warning 1265 Data truncated for column 'c' at row 2
-Warning 1264 Data truncated, out of range for column 'a' at row 3
-Warning 1264 Data truncated, out of range for column 'b' at row 3
+Warning 1264 Data truncated; out of range for column 'a' at row 3
+Warning 1264 Data truncated; out of range for column 'b' at row 3
Warning 1265 Data truncated for column 'c' at row 3
alter table t1 modify c char(4);
Warnings:
@@ -70,7 +70,7 @@ Warning 1265 Data truncated for column 'c' at row 2
alter table t1 add d char(2);
update t1 set a=NULL where a=10;
Warnings:
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'a' at row 2
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 2
update t1 set c='mysql ab' where c='test';
Warnings:
Warning 1265 Data truncated for column 'c' at row 4
@@ -86,7 +86,7 @@ Warnings:
Warning 1265 Data truncated for column 'b' at row 1
Warning 1265 Data truncated for column 'b' at row 2
Warning 1265 Data truncated for column 'b' at row 3
-Warning 1263 Data truncated, NULL supplied to NOT NULL column 'a' at row 4
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 4
Warning 1265 Data truncated for column 'b' at row 4
insert into t2(b) values('mysqlab');
Warnings:
@@ -125,11 +125,11 @@ Warning 1266 Using storage engine MyISAM for table 't1'
drop table t1;
create table t1 (id int) type=heap;
Warnings:
-Warning 1287 'TYPE=storage_engine' is deprecated, use 'ENGINE=storage_engine' instead
+Warning 1287 'TYPE=storage_engine' is deprecated; use 'ENGINE=storage_engine' instead
alter table t1 type=myisam;
Warnings:
-Warning 1287 'TYPE=storage_engine' is deprecated, use 'ENGINE=storage_engine' instead
+Warning 1287 'TYPE=storage_engine' is deprecated; use 'ENGINE=storage_engine' instead
drop table t1;
set table_type=MYISAM;
Warnings:
-Warning 1287 'table_type' is deprecated, use 'storage_engine' instead
+Warning 1287 'table_type' is deprecated; use 'storage_engine' instead
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 32654bb0bc4..122dcaa6c49 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -304,3 +304,11 @@ SHOW CREATE TABLE t1;
--error 1091
ALTER TABLE t1 DROP PRIMARY KEY;
DROP TABLE t1;
+
+# BUG#3899
+create table t1 (a int, b int, key(a));
+insert into t1 values (1,1), (2,2);
+--error 1091
+alter table t1 drop key no_such_key;
+alter table t1 drop key a;
+drop table t1;
diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test
new file mode 100644
index 00000000000..5c2e73e5af7
--- /dev/null
+++ b/mysql-test/t/archive.test
@@ -0,0 +1,1300 @@
+#
+# Simple test for archive example
+# Taken fromm the select test
+#
+-- source include/have_archive.inc
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+CREATE TABLE t1 (
+ Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
+ Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
+) ENGINE=archive;
+
+INSERT INTO t1 VALUES (9410,9412);
+
+select period from t1;
+select * from t1;
+select t1.* from t1;
+
+#
+# Create test table
+#
+
+CREATE TABLE t2 (
+ auto int,
+ fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL,
+ companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL,
+ fld3 char(30) DEFAULT '' NOT NULL,
+ fld4 char(35) DEFAULT '' NOT NULL,
+ fld5 char(35) DEFAULT '' NOT NULL,
+ fld6 char(4) DEFAULT '' NOT NULL
+) ENGINE=archive;
+
+#
+# Populate table
+#
+
+--disable_query_log
+INSERT INTO t2 VALUES (1,000001,00,'Omaha','teethe','neat','');
+INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W');
+INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring','');
+INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
+INSERT INTO t2 VALUES (5,011501,37,'bewilderingly','wallet','balled','');
+INSERT INTO t2 VALUES (6,011701,37,'astound','parters','persist','W');
+INSERT INTO t2 VALUES (7,011702,37,'admonishing','eschew','attainments','');
+INSERT INTO t2 VALUES (8,011703,37,'sumac','quitter','fanatic','');
+INSERT INTO t2 VALUES (9,012001,37,'flanking','neat','measures','FAS');
+INSERT INTO t2 VALUES (10,012003,37,'combed','Steinberg','rightfulness','');
+INSERT INTO t2 VALUES (11,012004,37,'subjective','jarring','capably','');
+INSERT INTO t2 VALUES (12,012005,37,'scatterbrain','tinily','impulsive','');
+INSERT INTO t2 VALUES (13,012301,37,'Eulerian','balled','starlet','');
+INSERT INTO t2 VALUES (14,012302,36,'dubbed','persist','terminators','');
+INSERT INTO t2 VALUES (15,012303,37,'Kane','attainments','untying','');
+INSERT INTO t2 VALUES (16,012304,37,'overlay','fanatic','announces','FAS');
+INSERT INTO t2 VALUES (17,012305,37,'perturb','measures','featherweight','FAS');
+INSERT INTO t2 VALUES (18,012306,37,'goblins','rightfulness','pessimist','FAS');
+INSERT INTO t2 VALUES (19,012501,37,'annihilates','capably','daughter','');
+INSERT INTO t2 VALUES (20,012602,37,'Wotan','impulsive','decliner','FAS');
+INSERT INTO t2 VALUES (21,012603,37,'snatching','starlet','lawgiver','');
+INSERT INTO t2 VALUES (22,012604,37,'concludes','terminators','stated','');
+INSERT INTO t2 VALUES (23,012605,37,'laterally','untying','readable','');
+INSERT INTO t2 VALUES (24,012606,37,'yelped','announces','attrition','');
+INSERT INTO t2 VALUES (25,012701,37,'grazing','featherweight','cascade','FAS');
+INSERT INTO t2 VALUES (26,012702,37,'Baird','pessimist','motors','FAS');
+INSERT INTO t2 VALUES (27,012703,37,'celery','daughter','interrogate','');
+INSERT INTO t2 VALUES (28,012704,37,'misunderstander','decliner','pests','W');
+INSERT INTO t2 VALUES (29,013601,37,'handgun','lawgiver','stairway','');
+INSERT INTO t2 VALUES (30,013602,37,'foldout','stated','dopers','FAS');
+INSERT INTO t2 VALUES (31,013603,37,'mystic','readable','testicle','W');
+INSERT INTO t2 VALUES (32,013604,37,'succumbed','attrition','Parsifal','W');
+INSERT INTO t2 VALUES (33,013605,37,'Nabisco','cascade','leavings','');
+INSERT INTO t2 VALUES (34,013606,37,'fingerings','motors','postulation','W');
+INSERT INTO t2 VALUES (35,013607,37,'aging','interrogate','squeaking','');
+INSERT INTO t2 VALUES (36,013608,37,'afield','pests','contrasted','');
+INSERT INTO t2 VALUES (37,013609,37,'ammonium','stairway','leftover','');
+INSERT INTO t2 VALUES (38,013610,37,'boat','dopers','whiteners','');
+INSERT INTO t2 VALUES (39,013801,37,'intelligibility','testicle','erases','W');
+INSERT INTO t2 VALUES (40,013802,37,'Augustine','Parsifal','Punjab','W');
+INSERT INTO t2 VALUES (41,013803,37,'teethe','leavings','Merritt','');
+INSERT INTO t2 VALUES (42,013804,37,'dreaded','postulation','Quixotism','');
+INSERT INTO t2 VALUES (43,013901,37,'scholastics','squeaking','sweetish','FAS');
+INSERT INTO t2 VALUES (44,016001,37,'audiology','contrasted','dogging','FAS');
+INSERT INTO t2 VALUES (45,016201,37,'wallet','leftover','scornfully','FAS');
+INSERT INTO t2 VALUES (46,016202,37,'parters','whiteners','bellow','');
+INSERT INTO t2 VALUES (47,016301,37,'eschew','erases','bills','');
+INSERT INTO t2 VALUES (48,016302,37,'quitter','Punjab','cupboard','FAS');
+INSERT INTO t2 VALUES (49,016303,37,'neat','Merritt','sureties','FAS');
+INSERT INTO t2 VALUES (50,016304,37,'Steinberg','Quixotism','puddings','');
+INSERT INTO t2 VALUES (51,018001,37,'jarring','sweetish','tapestry','');
+INSERT INTO t2 VALUES (52,018002,37,'tinily','dogging','fetters','');
+INSERT INTO t2 VALUES (53,018003,37,'balled','scornfully','bivalves','');
+INSERT INTO t2 VALUES (54,018004,37,'persist','bellow','incurring','');
+INSERT INTO t2 VALUES (55,018005,37,'attainments','bills','Adolph','');
+INSERT INTO t2 VALUES (56,018007,37,'fanatic','cupboard','pithed','');
+INSERT INTO t2 VALUES (57,018008,37,'measures','sureties','emergency','');
+INSERT INTO t2 VALUES (58,018009,37,'rightfulness','puddings','Miles','');
+INSERT INTO t2 VALUES (59,018010,37,'capably','tapestry','trimmings','');
+INSERT INTO t2 VALUES (60,018012,37,'impulsive','fetters','tragedies','W');
+INSERT INTO t2 VALUES (61,018013,37,'starlet','bivalves','skulking','W');
+INSERT INTO t2 VALUES (62,018014,37,'terminators','incurring','flint','');
+INSERT INTO t2 VALUES (63,018015,37,'untying','Adolph','flopping','W');
+INSERT INTO t2 VALUES (64,018016,37,'announces','pithed','relaxing','FAS');
+INSERT INTO t2 VALUES (65,018017,37,'featherweight','emergency','offload','FAS');
+INSERT INTO t2 VALUES (66,018018,37,'pessimist','Miles','suites','W');
+INSERT INTO t2 VALUES (67,018019,37,'daughter','trimmings','lists','FAS');
+INSERT INTO t2 VALUES (68,018020,37,'decliner','tragedies','animized','FAS');
+INSERT INTO t2 VALUES (69,018021,37,'lawgiver','skulking','multilayer','W');
+INSERT INTO t2 VALUES (70,018022,37,'stated','flint','standardizes','FAS');
+INSERT INTO t2 VALUES (71,018023,37,'readable','flopping','Judas','');
+INSERT INTO t2 VALUES (72,018024,37,'attrition','relaxing','vacuuming','W');
+INSERT INTO t2 VALUES (73,018025,37,'cascade','offload','dentally','W');
+INSERT INTO t2 VALUES (74,018026,37,'motors','suites','humanness','W');
+INSERT INTO t2 VALUES (75,018027,37,'interrogate','lists','inch','W');
+INSERT INTO t2 VALUES (76,018028,37,'pests','animized','Weissmuller','W');
+INSERT INTO t2 VALUES (77,018029,37,'stairway','multilayer','irresponsibly','W');
+INSERT INTO t2 VALUES (78,018030,37,'dopers','standardizes','luckily','FAS');
+INSERT INTO t2 VALUES (79,018032,37,'testicle','Judas','culled','W');
+INSERT INTO t2 VALUES (80,018033,37,'Parsifal','vacuuming','medical','FAS');
+INSERT INTO t2 VALUES (81,018034,37,'leavings','dentally','bloodbath','FAS');
+INSERT INTO t2 VALUES (82,018035,37,'postulation','humanness','subschema','W');
+INSERT INTO t2 VALUES (83,018036,37,'squeaking','inch','animals','W');
+INSERT INTO t2 VALUES (84,018037,37,'contrasted','Weissmuller','Micronesia','');
+INSERT INTO t2 VALUES (85,018038,37,'leftover','irresponsibly','repetitions','');
+INSERT INTO t2 VALUES (86,018039,37,'whiteners','luckily','Antares','');
+INSERT INTO t2 VALUES (87,018040,37,'erases','culled','ventilate','W');
+INSERT INTO t2 VALUES (88,018041,37,'Punjab','medical','pityingly','');
+INSERT INTO t2 VALUES (89,018042,37,'Merritt','bloodbath','interdependent','');
+INSERT INTO t2 VALUES (90,018043,37,'Quixotism','subschema','Graves','FAS');
+INSERT INTO t2 VALUES (91,018044,37,'sweetish','animals','neonatal','');
+INSERT INTO t2 VALUES (92,018045,37,'dogging','Micronesia','scribbled','FAS');
+INSERT INTO t2 VALUES (93,018046,37,'scornfully','repetitions','chafe','W');
+INSERT INTO t2 VALUES (94,018048,37,'bellow','Antares','honoring','');
+INSERT INTO t2 VALUES (95,018049,37,'bills','ventilate','realtor','');
+INSERT INTO t2 VALUES (96,018050,37,'cupboard','pityingly','elite','');
+INSERT INTO t2 VALUES (97,018051,37,'sureties','interdependent','funereal','');
+INSERT INTO t2 VALUES (98,018052,37,'puddings','Graves','abrogating','');
+INSERT INTO t2 VALUES (99,018053,50,'tapestry','neonatal','sorters','');
+INSERT INTO t2 VALUES (100,018054,37,'fetters','scribbled','Conley','');
+INSERT INTO t2 VALUES (101,018055,37,'bivalves','chafe','lectured','');
+INSERT INTO t2 VALUES (102,018056,37,'incurring','honoring','Abraham','');
+INSERT INTO t2 VALUES (103,018057,37,'Adolph','realtor','Hawaii','W');
+INSERT INTO t2 VALUES (104,018058,37,'pithed','elite','cage','');
+INSERT INTO t2 VALUES (105,018059,36,'emergency','funereal','hushes','');
+INSERT INTO t2 VALUES (106,018060,37,'Miles','abrogating','Simla','');
+INSERT INTO t2 VALUES (107,018061,37,'trimmings','sorters','reporters','');
+INSERT INTO t2 VALUES (108,018101,37,'tragedies','Conley','Dutchman','FAS');
+INSERT INTO t2 VALUES (109,018102,37,'skulking','lectured','descendants','FAS');
+INSERT INTO t2 VALUES (110,018103,37,'flint','Abraham','groupings','FAS');
+INSERT INTO t2 VALUES (111,018104,37,'flopping','Hawaii','dissociate','');
+INSERT INTO t2 VALUES (112,018201,37,'relaxing','cage','coexist','W');
+INSERT INTO t2 VALUES (113,018202,37,'offload','hushes','Beebe','');
+INSERT INTO t2 VALUES (114,018402,37,'suites','Simla','Taoism','');
+INSERT INTO t2 VALUES (115,018403,37,'lists','reporters','Connally','');
+INSERT INTO t2 VALUES (116,018404,37,'animized','Dutchman','fetched','FAS');
+INSERT INTO t2 VALUES (117,018405,37,'multilayer','descendants','checkpoints','FAS');
+INSERT INTO t2 VALUES (118,018406,37,'standardizes','groupings','rusting','');
+INSERT INTO t2 VALUES (119,018409,37,'Judas','dissociate','galling','');
+INSERT INTO t2 VALUES (120,018601,37,'vacuuming','coexist','obliterates','');
+INSERT INTO t2 VALUES (121,018602,37,'dentally','Beebe','traitor','');
+INSERT INTO t2 VALUES (122,018603,37,'humanness','Taoism','resumes','FAS');
+INSERT INTO t2 VALUES (123,018801,37,'inch','Connally','analyzable','FAS');
+INSERT INTO t2 VALUES (124,018802,37,'Weissmuller','fetched','terminator','FAS');
+INSERT INTO t2 VALUES (125,018803,37,'irresponsibly','checkpoints','gritty','FAS');
+INSERT INTO t2 VALUES (126,018804,37,'luckily','rusting','firearm','W');
+INSERT INTO t2 VALUES (127,018805,37,'culled','galling','minima','');
+INSERT INTO t2 VALUES (128,018806,37,'medical','obliterates','Selfridge','');
+INSERT INTO t2 VALUES (129,018807,37,'bloodbath','traitor','disable','');
+INSERT INTO t2 VALUES (130,018808,37,'subschema','resumes','witchcraft','W');
+INSERT INTO t2 VALUES (131,018809,37,'animals','analyzable','betroth','W');
+INSERT INTO t2 VALUES (132,018810,37,'Micronesia','terminator','Manhattanize','');
+INSERT INTO t2 VALUES (133,018811,37,'repetitions','gritty','imprint','');
+INSERT INTO t2 VALUES (134,018812,37,'Antares','firearm','peeked','');
+INSERT INTO t2 VALUES (135,019101,37,'ventilate','minima','swelling','');
+INSERT INTO t2 VALUES (136,019102,37,'pityingly','Selfridge','interrelationships','W');
+INSERT INTO t2 VALUES (137,019103,37,'interdependent','disable','riser','');
+INSERT INTO t2 VALUES (138,019201,37,'Graves','witchcraft','Gandhian','W');
+INSERT INTO t2 VALUES (139,030501,37,'neonatal','betroth','peacock','A');
+INSERT INTO t2 VALUES (140,030502,50,'scribbled','Manhattanize','bee','A');
+INSERT INTO t2 VALUES (141,030503,37,'chafe','imprint','kanji','');
+INSERT INTO t2 VALUES (142,030504,37,'honoring','peeked','dental','');
+INSERT INTO t2 VALUES (143,031901,37,'realtor','swelling','scarf','FAS');
+INSERT INTO t2 VALUES (144,036001,37,'elite','interrelationships','chasm','A');
+INSERT INTO t2 VALUES (145,036002,37,'funereal','riser','insolence','A');
+INSERT INTO t2 VALUES (146,036004,37,'abrogating','Gandhian','syndicate','');
+INSERT INTO t2 VALUES (147,036005,37,'sorters','peacock','alike','');
+INSERT INTO t2 VALUES (148,038001,37,'Conley','bee','imperial','A');
+INSERT INTO t2 VALUES (149,038002,37,'lectured','kanji','convulsion','A');
+INSERT INTO t2 VALUES (150,038003,37,'Abraham','dental','railway','A');
+INSERT INTO t2 VALUES (151,038004,37,'Hawaii','scarf','validate','A');
+INSERT INTO t2 VALUES (152,038005,37,'cage','chasm','normalizes','A');
+INSERT INTO t2 VALUES (153,038006,37,'hushes','insolence','comprehensive','');
+INSERT INTO t2 VALUES (154,038007,37,'Simla','syndicate','chewing','');
+INSERT INTO t2 VALUES (155,038008,37,'reporters','alike','denizen','');
+INSERT INTO t2 VALUES (156,038009,37,'Dutchman','imperial','schemer','');
+INSERT INTO t2 VALUES (157,038010,37,'descendants','convulsion','chronicle','');
+INSERT INTO t2 VALUES (158,038011,37,'groupings','railway','Kline','');
+INSERT INTO t2 VALUES (159,038012,37,'dissociate','validate','Anatole','');
+INSERT INTO t2 VALUES (160,038013,37,'coexist','normalizes','partridges','');
+INSERT INTO t2 VALUES (161,038014,37,'Beebe','comprehensive','brunch','');
+INSERT INTO t2 VALUES (162,038015,37,'Taoism','chewing','recruited','');
+INSERT INTO t2 VALUES (163,038016,37,'Connally','denizen','dimensions','W');
+INSERT INTO t2 VALUES (164,038017,37,'fetched','schemer','Chicana','W');
+INSERT INTO t2 VALUES (165,038018,37,'checkpoints','chronicle','announced','');
+INSERT INTO t2 VALUES (166,038101,37,'rusting','Kline','praised','FAS');
+INSERT INTO t2 VALUES (167,038102,37,'galling','Anatole','employing','');
+INSERT INTO t2 VALUES (168,038103,37,'obliterates','partridges','linear','');
+INSERT INTO t2 VALUES (169,038104,37,'traitor','brunch','quagmire','');
+INSERT INTO t2 VALUES (170,038201,37,'resumes','recruited','western','A');
+INSERT INTO t2 VALUES (171,038202,37,'analyzable','dimensions','relishing','');
+INSERT INTO t2 VALUES (172,038203,37,'terminator','Chicana','serving','A');
+INSERT INTO t2 VALUES (173,038204,37,'gritty','announced','scheduling','');
+INSERT INTO t2 VALUES (174,038205,37,'firearm','praised','lore','');
+INSERT INTO t2 VALUES (175,038206,37,'minima','employing','eventful','');
+INSERT INTO t2 VALUES (176,038208,37,'Selfridge','linear','arteriole','A');
+INSERT INTO t2 VALUES (177,042801,37,'disable','quagmire','disentangle','');
+INSERT INTO t2 VALUES (178,042802,37,'witchcraft','western','cured','A');
+INSERT INTO t2 VALUES (179,046101,37,'betroth','relishing','Fenton','W');
+INSERT INTO t2 VALUES (180,048001,37,'Manhattanize','serving','avoidable','A');
+INSERT INTO t2 VALUES (181,048002,37,'imprint','scheduling','drains','A');
+INSERT INTO t2 VALUES (182,048003,37,'peeked','lore','detectably','FAS');
+INSERT INTO t2 VALUES (183,048004,37,'swelling','eventful','husky','');
+INSERT INTO t2 VALUES (184,048005,37,'interrelationships','arteriole','impelling','');
+INSERT INTO t2 VALUES (185,048006,37,'riser','disentangle','undoes','');
+INSERT INTO t2 VALUES (186,048007,37,'Gandhian','cured','evened','');
+INSERT INTO t2 VALUES (187,048008,37,'peacock','Fenton','squeezes','');
+INSERT INTO t2 VALUES (188,048101,37,'bee','avoidable','destroyer','FAS');
+INSERT INTO t2 VALUES (189,048102,37,'kanji','drains','rudeness','');
+INSERT INTO t2 VALUES (190,048201,37,'dental','detectably','beaner','FAS');
+INSERT INTO t2 VALUES (191,048202,37,'scarf','husky','boorish','');
+INSERT INTO t2 VALUES (192,048203,37,'chasm','impelling','Everhart','');
+INSERT INTO t2 VALUES (193,048204,37,'insolence','undoes','encompass','A');
+INSERT INTO t2 VALUES (194,048205,37,'syndicate','evened','mushrooms','');
+INSERT INTO t2 VALUES (195,048301,37,'alike','squeezes','Alison','A');
+INSERT INTO t2 VALUES (196,048302,37,'imperial','destroyer','externally','FAS');
+INSERT INTO t2 VALUES (197,048303,37,'convulsion','rudeness','pellagra','');
+INSERT INTO t2 VALUES (198,048304,37,'railway','beaner','cult','');
+INSERT INTO t2 VALUES (199,048305,37,'validate','boorish','creek','A');
+INSERT INTO t2 VALUES (200,048401,37,'normalizes','Everhart','Huffman','');
+INSERT INTO t2 VALUES (201,048402,37,'comprehensive','encompass','Majorca','FAS');
+INSERT INTO t2 VALUES (202,048403,37,'chewing','mushrooms','governing','A');
+INSERT INTO t2 VALUES (203,048404,37,'denizen','Alison','gadfly','FAS');
+INSERT INTO t2 VALUES (204,048405,37,'schemer','externally','reassigned','FAS');
+INSERT INTO t2 VALUES (205,048406,37,'chronicle','pellagra','intentness','W');
+INSERT INTO t2 VALUES (206,048407,37,'Kline','cult','craziness','');
+INSERT INTO t2 VALUES (207,048408,37,'Anatole','creek','psychic','');
+INSERT INTO t2 VALUES (208,048409,37,'partridges','Huffman','squabbled','');
+INSERT INTO t2 VALUES (209,048410,37,'brunch','Majorca','burlesque','');
+INSERT INTO t2 VALUES (210,048411,37,'recruited','governing','capped','');
+INSERT INTO t2 VALUES (211,048412,37,'dimensions','gadfly','extracted','A');
+INSERT INTO t2 VALUES (212,048413,37,'Chicana','reassigned','DiMaggio','');
+INSERT INTO t2 VALUES (213,048601,37,'announced','intentness','exclamation','FAS');
+INSERT INTO t2 VALUES (214,048602,37,'praised','craziness','subdirectory','');
+INSERT INTO t2 VALUES (215,048603,37,'employing','psychic','fangs','');
+INSERT INTO t2 VALUES (216,048604,37,'linear','squabbled','buyer','A');
+INSERT INTO t2 VALUES (217,048801,37,'quagmire','burlesque','pithing','A');
+INSERT INTO t2 VALUES (218,050901,37,'western','capped','transistorizing','A');
+INSERT INTO t2 VALUES (219,051201,37,'relishing','extracted','nonbiodegradable','');
+INSERT INTO t2 VALUES (220,056002,37,'serving','DiMaggio','dislocate','');
+INSERT INTO t2 VALUES (221,056003,37,'scheduling','exclamation','monochromatic','FAS');
+INSERT INTO t2 VALUES (222,056004,37,'lore','subdirectory','batting','');
+INSERT INTO t2 VALUES (223,056102,37,'eventful','fangs','postcondition','A');
+INSERT INTO t2 VALUES (224,056203,37,'arteriole','buyer','catalog','FAS');
+INSERT INTO t2 VALUES (225,056204,37,'disentangle','pithing','Remus','');
+INSERT INTO t2 VALUES (226,058003,37,'cured','transistorizing','devices','A');
+INSERT INTO t2 VALUES (227,058004,37,'Fenton','nonbiodegradable','bike','A');
+INSERT INTO t2 VALUES (228,058005,37,'avoidable','dislocate','qualify','');
+INSERT INTO t2 VALUES (229,058006,37,'drains','monochromatic','detained','');
+INSERT INTO t2 VALUES (230,058007,37,'detectably','batting','commended','');
+INSERT INTO t2 VALUES (231,058101,37,'husky','postcondition','civilize','');
+INSERT INTO t2 VALUES (232,058102,37,'impelling','catalog','Elmhurst','');
+INSERT INTO t2 VALUES (233,058103,37,'undoes','Remus','anesthetizing','');
+INSERT INTO t2 VALUES (234,058105,37,'evened','devices','deaf','');
+INSERT INTO t2 VALUES (235,058111,37,'squeezes','bike','Brigham','');
+INSERT INTO t2 VALUES (236,058112,37,'destroyer','qualify','title','');
+INSERT INTO t2 VALUES (237,058113,37,'rudeness','detained','coarse','');
+INSERT INTO t2 VALUES (238,058114,37,'beaner','commended','combinations','');
+INSERT INTO t2 VALUES (239,058115,37,'boorish','civilize','grayness','');
+INSERT INTO t2 VALUES (240,058116,37,'Everhart','Elmhurst','innumerable','FAS');
+INSERT INTO t2 VALUES (241,058117,37,'encompass','anesthetizing','Caroline','A');
+INSERT INTO t2 VALUES (242,058118,37,'mushrooms','deaf','fatty','FAS');
+INSERT INTO t2 VALUES (243,058119,37,'Alison','Brigham','eastbound','');
+INSERT INTO t2 VALUES (244,058120,37,'externally','title','inexperienced','');
+INSERT INTO t2 VALUES (245,058121,37,'pellagra','coarse','hoarder','A');
+INSERT INTO t2 VALUES (246,058122,37,'cult','combinations','scotch','W');
+INSERT INTO t2 VALUES (247,058123,37,'creek','grayness','passport','A');
+INSERT INTO t2 VALUES (248,058124,37,'Huffman','innumerable','strategic','FAS');
+INSERT INTO t2 VALUES (249,058125,37,'Majorca','Caroline','gated','');
+INSERT INTO t2 VALUES (250,058126,37,'governing','fatty','flog','');
+INSERT INTO t2 VALUES (251,058127,37,'gadfly','eastbound','Pipestone','');
+INSERT INTO t2 VALUES (252,058128,37,'reassigned','inexperienced','Dar','');
+INSERT INTO t2 VALUES (253,058201,37,'intentness','hoarder','Corcoran','');
+INSERT INTO t2 VALUES (254,058202,37,'craziness','scotch','flyers','A');
+INSERT INTO t2 VALUES (255,058303,37,'psychic','passport','competitions','W');
+INSERT INTO t2 VALUES (256,058304,37,'squabbled','strategic','suppliers','FAS');
+INSERT INTO t2 VALUES (257,058602,37,'burlesque','gated','skips','');
+INSERT INTO t2 VALUES (258,058603,37,'capped','flog','institutes','');
+INSERT INTO t2 VALUES (259,058604,37,'extracted','Pipestone','troop','A');
+INSERT INTO t2 VALUES (260,058605,37,'DiMaggio','Dar','connective','W');
+INSERT INTO t2 VALUES (261,058606,37,'exclamation','Corcoran','denies','');
+INSERT INTO t2 VALUES (262,058607,37,'subdirectory','flyers','polka','');
+INSERT INTO t2 VALUES (263,060401,36,'fangs','competitions','observations','FAS');
+INSERT INTO t2 VALUES (264,061701,36,'buyer','suppliers','askers','');
+INSERT INTO t2 VALUES (265,066201,36,'pithing','skips','homeless','FAS');
+INSERT INTO t2 VALUES (266,066501,36,'transistorizing','institutes','Anna','');
+INSERT INTO t2 VALUES (267,068001,36,'nonbiodegradable','troop','subdirectories','W');
+INSERT INTO t2 VALUES (268,068002,36,'dislocate','connective','decaying','FAS');
+INSERT INTO t2 VALUES (269,068005,36,'monochromatic','denies','outwitting','W');
+INSERT INTO t2 VALUES (270,068006,36,'batting','polka','Harpy','W');
+INSERT INTO t2 VALUES (271,068007,36,'postcondition','observations','crazed','');
+INSERT INTO t2 VALUES (272,068008,36,'catalog','askers','suffocate','');
+INSERT INTO t2 VALUES (273,068009,36,'Remus','homeless','provers','FAS');
+INSERT INTO t2 VALUES (274,068010,36,'devices','Anna','technically','');
+INSERT INTO t2 VALUES (275,068011,36,'bike','subdirectories','Franklinizations','');
+INSERT INTO t2 VALUES (276,068202,36,'qualify','decaying','considered','');
+INSERT INTO t2 VALUES (277,068302,36,'detained','outwitting','tinnily','');
+INSERT INTO t2 VALUES (278,068303,36,'commended','Harpy','uninterruptedly','');
+INSERT INTO t2 VALUES (279,068401,36,'civilize','crazed','whistled','A');
+INSERT INTO t2 VALUES (280,068501,36,'Elmhurst','suffocate','automate','');
+INSERT INTO t2 VALUES (281,068502,36,'anesthetizing','provers','gutting','W');
+INSERT INTO t2 VALUES (282,068503,36,'deaf','technically','surreptitious','');
+INSERT INTO t2 VALUES (283,068602,36,'Brigham','Franklinizations','Choctaw','');
+INSERT INTO t2 VALUES (284,068603,36,'title','considered','cooks','');
+INSERT INTO t2 VALUES (285,068701,36,'coarse','tinnily','millivolt','FAS');
+INSERT INTO t2 VALUES (286,068702,36,'combinations','uninterruptedly','counterpoise','');
+INSERT INTO t2 VALUES (287,068703,36,'grayness','whistled','Gothicism','');
+INSERT INTO t2 VALUES (288,076001,36,'innumerable','automate','feminine','');
+INSERT INTO t2 VALUES (289,076002,36,'Caroline','gutting','metaphysically','W');
+INSERT INTO t2 VALUES (290,076101,36,'fatty','surreptitious','sanding','A');
+INSERT INTO t2 VALUES (291,076102,36,'eastbound','Choctaw','contributorily','');
+INSERT INTO t2 VALUES (292,076103,36,'inexperienced','cooks','receivers','FAS');
+INSERT INTO t2 VALUES (293,076302,36,'hoarder','millivolt','adjourn','');
+INSERT INTO t2 VALUES (294,076303,36,'scotch','counterpoise','straggled','A');
+INSERT INTO t2 VALUES (295,076304,36,'passport','Gothicism','druggists','');
+INSERT INTO t2 VALUES (296,076305,36,'strategic','feminine','thanking','FAS');
+INSERT INTO t2 VALUES (297,076306,36,'gated','metaphysically','ostrich','');
+INSERT INTO t2 VALUES (298,076307,36,'flog','sanding','hopelessness','FAS');
+INSERT INTO t2 VALUES (299,076402,36,'Pipestone','contributorily','Eurydice','');
+INSERT INTO t2 VALUES (300,076501,36,'Dar','receivers','excitation','W');
+INSERT INTO t2 VALUES (301,076502,36,'Corcoran','adjourn','presumes','FAS');
+INSERT INTO t2 VALUES (302,076701,36,'flyers','straggled','imaginable','FAS');
+INSERT INTO t2 VALUES (303,078001,36,'competitions','druggists','concoct','W');
+INSERT INTO t2 VALUES (304,078002,36,'suppliers','thanking','peering','W');
+INSERT INTO t2 VALUES (305,078003,36,'skips','ostrich','Phelps','FAS');
+INSERT INTO t2 VALUES (306,078004,36,'institutes','hopelessness','ferociousness','FAS');
+INSERT INTO t2 VALUES (307,078005,36,'troop','Eurydice','sentences','');
+INSERT INTO t2 VALUES (308,078006,36,'connective','excitation','unlocks','');
+INSERT INTO t2 VALUES (309,078007,36,'denies','presumes','engrossing','W');
+INSERT INTO t2 VALUES (310,078008,36,'polka','imaginable','Ruth','');
+INSERT INTO t2 VALUES (311,078101,36,'observations','concoct','tying','');
+INSERT INTO t2 VALUES (312,078103,36,'askers','peering','exclaimers','');
+INSERT INTO t2 VALUES (313,078104,36,'homeless','Phelps','synergy','');
+INSERT INTO t2 VALUES (314,078105,36,'Anna','ferociousness','Huey','W');
+INSERT INTO t2 VALUES (315,082101,36,'subdirectories','sentences','merging','');
+INSERT INTO t2 VALUES (316,083401,36,'decaying','unlocks','judges','A');
+INSERT INTO t2 VALUES (317,084001,36,'outwitting','engrossing','Shylock','W');
+INSERT INTO t2 VALUES (318,084002,36,'Harpy','Ruth','Miltonism','');
+INSERT INTO t2 VALUES (319,086001,36,'crazed','tying','hen','W');
+INSERT INTO t2 VALUES (320,086102,36,'suffocate','exclaimers','honeybee','FAS');
+INSERT INTO t2 VALUES (321,086201,36,'provers','synergy','towers','');
+INSERT INTO t2 VALUES (322,088001,36,'technically','Huey','dilutes','W');
+INSERT INTO t2 VALUES (323,088002,36,'Franklinizations','merging','numerals','FAS');
+INSERT INTO t2 VALUES (324,088003,36,'considered','judges','democracy','FAS');
+INSERT INTO t2 VALUES (325,088004,36,'tinnily','Shylock','Ibero-','');
+INSERT INTO t2 VALUES (326,088101,36,'uninterruptedly','Miltonism','invalids','');
+INSERT INTO t2 VALUES (327,088102,36,'whistled','hen','behavior','');
+INSERT INTO t2 VALUES (328,088103,36,'automate','honeybee','accruing','');
+INSERT INTO t2 VALUES (329,088104,36,'gutting','towers','relics','A');
+INSERT INTO t2 VALUES (330,088105,36,'surreptitious','dilutes','rackets','');
+INSERT INTO t2 VALUES (331,088106,36,'Choctaw','numerals','Fischbein','W');
+INSERT INTO t2 VALUES (332,088201,36,'cooks','democracy','phony','W');
+INSERT INTO t2 VALUES (333,088203,36,'millivolt','Ibero-','cross','FAS');
+INSERT INTO t2 VALUES (334,088204,36,'counterpoise','invalids','cleanup','');
+INSERT INTO t2 VALUES (335,088302,37,'Gothicism','behavior','conspirator','');
+INSERT INTO t2 VALUES (336,088303,37,'feminine','accruing','label','FAS');
+INSERT INTO t2 VALUES (337,088305,37,'metaphysically','relics','university','');
+INSERT INTO t2 VALUES (338,088402,37,'sanding','rackets','cleansed','FAS');
+INSERT INTO t2 VALUES (339,088501,36,'contributorily','Fischbein','ballgown','');
+INSERT INTO t2 VALUES (340,088502,36,'receivers','phony','starlet','');
+INSERT INTO t2 VALUES (341,088503,36,'adjourn','cross','aqueous','');
+INSERT INTO t2 VALUES (342,098001,58,'straggled','cleanup','portrayal','A');
+INSERT INTO t2 VALUES (343,098002,58,'druggists','conspirator','despising','W');
+INSERT INTO t2 VALUES (344,098003,58,'thanking','label','distort','W');
+INSERT INTO t2 VALUES (345,098004,58,'ostrich','university','palmed','');
+INSERT INTO t2 VALUES (346,098005,58,'hopelessness','cleansed','faced','');
+INSERT INTO t2 VALUES (347,098006,58,'Eurydice','ballgown','silverware','');
+INSERT INTO t2 VALUES (348,141903,29,'excitation','starlet','assessor','');
+INSERT INTO t2 VALUES (349,098008,58,'presumes','aqueous','spiders','');
+INSERT INTO t2 VALUES (350,098009,58,'imaginable','portrayal','artificially','');
+INSERT INTO t2 VALUES (351,098010,58,'concoct','despising','reminiscence','');
+INSERT INTO t2 VALUES (352,098011,58,'peering','distort','Mexican','');
+INSERT INTO t2 VALUES (353,098012,58,'Phelps','palmed','obnoxious','');
+INSERT INTO t2 VALUES (354,098013,58,'ferociousness','faced','fragile','');
+INSERT INTO t2 VALUES (355,098014,58,'sentences','silverware','apprehensible','');
+INSERT INTO t2 VALUES (356,098015,58,'unlocks','assessor','births','');
+INSERT INTO t2 VALUES (357,098016,58,'engrossing','spiders','garages','');
+INSERT INTO t2 VALUES (358,098017,58,'Ruth','artificially','panty','');
+INSERT INTO t2 VALUES (359,098018,58,'tying','reminiscence','anteater','');
+INSERT INTO t2 VALUES (360,098019,58,'exclaimers','Mexican','displacement','A');
+INSERT INTO t2 VALUES (361,098020,58,'synergy','obnoxious','drovers','A');
+INSERT INTO t2 VALUES (362,098021,58,'Huey','fragile','patenting','A');
+INSERT INTO t2 VALUES (363,098022,58,'merging','apprehensible','far','A');
+INSERT INTO t2 VALUES (364,098023,58,'judges','births','shrieks','');
+INSERT INTO t2 VALUES (365,098024,58,'Shylock','garages','aligning','W');
+INSERT INTO t2 VALUES (366,098025,37,'Miltonism','panty','pragmatism','');
+INSERT INTO t2 VALUES (367,106001,36,'hen','anteater','fevers','W');
+INSERT INTO t2 VALUES (368,108001,36,'honeybee','displacement','reexamines','A');
+INSERT INTO t2 VALUES (369,108002,36,'towers','drovers','occupancies','');
+INSERT INTO t2 VALUES (370,108003,36,'dilutes','patenting','sweats','FAS');
+INSERT INTO t2 VALUES (371,108004,36,'numerals','far','modulators','');
+INSERT INTO t2 VALUES (372,108005,36,'democracy','shrieks','demand','W');
+INSERT INTO t2 VALUES (373,108007,36,'Ibero-','aligning','Madeira','');
+INSERT INTO t2 VALUES (374,108008,36,'invalids','pragmatism','Viennese','W');
+INSERT INTO t2 VALUES (375,108009,36,'behavior','fevers','chillier','W');
+INSERT INTO t2 VALUES (376,108010,36,'accruing','reexamines','wildcats','FAS');
+INSERT INTO t2 VALUES (377,108011,36,'relics','occupancies','gentle','');
+INSERT INTO t2 VALUES (378,108012,36,'rackets','sweats','Angles','W');
+INSERT INTO t2 VALUES (379,108101,36,'Fischbein','modulators','accuracies','');
+INSERT INTO t2 VALUES (380,108102,36,'phony','demand','toggle','');
+INSERT INTO t2 VALUES (381,108103,36,'cross','Madeira','Mendelssohn','W');
+INSERT INTO t2 VALUES (382,108111,50,'cleanup','Viennese','behaviorally','');
+INSERT INTO t2 VALUES (383,108105,36,'conspirator','chillier','Rochford','');
+INSERT INTO t2 VALUES (384,108106,36,'label','wildcats','mirror','W');
+INSERT INTO t2 VALUES (385,108107,36,'university','gentle','Modula','');
+INSERT INTO t2 VALUES (386,108108,50,'cleansed','Angles','clobbering','');
+INSERT INTO t2 VALUES (387,108109,36,'ballgown','accuracies','chronography','');
+INSERT INTO t2 VALUES (388,108110,36,'starlet','toggle','Eskimoizeds','');
+INSERT INTO t2 VALUES (389,108201,36,'aqueous','Mendelssohn','British','W');
+INSERT INTO t2 VALUES (390,108202,36,'portrayal','behaviorally','pitfalls','');
+INSERT INTO t2 VALUES (391,108203,36,'despising','Rochford','verify','W');
+INSERT INTO t2 VALUES (392,108204,36,'distort','mirror','scatter','FAS');
+INSERT INTO t2 VALUES (393,108205,36,'palmed','Modula','Aztecan','');
+INSERT INTO t2 VALUES (394,108301,36,'faced','clobbering','acuity','W');
+INSERT INTO t2 VALUES (395,108302,36,'silverware','chronography','sinking','W');
+INSERT INTO t2 VALUES (396,112101,36,'assessor','Eskimoizeds','beasts','FAS');
+INSERT INTO t2 VALUES (397,112102,36,'spiders','British','Witt','W');
+INSERT INTO t2 VALUES (398,113701,36,'artificially','pitfalls','physicists','FAS');
+INSERT INTO t2 VALUES (399,116001,36,'reminiscence','verify','folksong','A');
+INSERT INTO t2 VALUES (400,116201,36,'Mexican','scatter','strokes','FAS');
+INSERT INTO t2 VALUES (401,116301,36,'obnoxious','Aztecan','crowder','');
+INSERT INTO t2 VALUES (402,116302,36,'fragile','acuity','merry','');
+INSERT INTO t2 VALUES (403,116601,36,'apprehensible','sinking','cadenced','');
+INSERT INTO t2 VALUES (404,116602,36,'births','beasts','alimony','A');
+INSERT INTO t2 VALUES (405,116603,36,'garages','Witt','principled','A');
+INSERT INTO t2 VALUES (406,116701,36,'panty','physicists','golfing','');
+INSERT INTO t2 VALUES (407,116702,36,'anteater','folksong','undiscovered','');
+INSERT INTO t2 VALUES (408,118001,36,'displacement','strokes','irritates','');
+INSERT INTO t2 VALUES (409,118002,36,'drovers','crowder','patriots','A');
+INSERT INTO t2 VALUES (410,118003,36,'patenting','merry','rooms','FAS');
+INSERT INTO t2 VALUES (411,118004,36,'far','cadenced','towering','W');
+INSERT INTO t2 VALUES (412,118005,36,'shrieks','alimony','displease','');
+INSERT INTO t2 VALUES (413,118006,36,'aligning','principled','photosensitive','');
+INSERT INTO t2 VALUES (414,118007,36,'pragmatism','golfing','inking','');
+INSERT INTO t2 VALUES (415,118008,36,'fevers','undiscovered','gainers','');
+INSERT INTO t2 VALUES (416,118101,36,'reexamines','irritates','leaning','A');
+INSERT INTO t2 VALUES (417,118102,36,'occupancies','patriots','hydrant','A');
+INSERT INTO t2 VALUES (418,118103,36,'sweats','rooms','preserve','');
+INSERT INTO t2 VALUES (419,118202,36,'modulators','towering','blinded','A');
+INSERT INTO t2 VALUES (420,118203,36,'demand','displease','interactions','A');
+INSERT INTO t2 VALUES (421,118204,36,'Madeira','photosensitive','Barry','');
+INSERT INTO t2 VALUES (422,118302,36,'Viennese','inking','whiteness','A');
+INSERT INTO t2 VALUES (423,118304,36,'chillier','gainers','pastimes','W');
+INSERT INTO t2 VALUES (424,118305,36,'wildcats','leaning','Edenization','');
+INSERT INTO t2 VALUES (425,118306,36,'gentle','hydrant','Muscat','');
+INSERT INTO t2 VALUES (426,118307,36,'Angles','preserve','assassinated','');
+INSERT INTO t2 VALUES (427,123101,36,'accuracies','blinded','labeled','');
+INSERT INTO t2 VALUES (428,123102,36,'toggle','interactions','glacial','A');
+INSERT INTO t2 VALUES (429,123301,36,'Mendelssohn','Barry','implied','W');
+INSERT INTO t2 VALUES (430,126001,36,'behaviorally','whiteness','bibliographies','W');
+INSERT INTO t2 VALUES (431,126002,36,'Rochford','pastimes','Buchanan','');
+INSERT INTO t2 VALUES (432,126003,36,'mirror','Edenization','forgivably','FAS');
+INSERT INTO t2 VALUES (433,126101,36,'Modula','Muscat','innuendo','A');
+INSERT INTO t2 VALUES (434,126301,36,'clobbering','assassinated','den','FAS');
+INSERT INTO t2 VALUES (435,126302,36,'chronography','labeled','submarines','W');
+INSERT INTO t2 VALUES (436,126402,36,'Eskimoizeds','glacial','mouthful','A');
+INSERT INTO t2 VALUES (437,126601,36,'British','implied','expiring','');
+INSERT INTO t2 VALUES (438,126602,36,'pitfalls','bibliographies','unfulfilled','FAS');
+INSERT INTO t2 VALUES (439,126702,36,'verify','Buchanan','precession','');
+INSERT INTO t2 VALUES (440,128001,36,'scatter','forgivably','nullified','');
+INSERT INTO t2 VALUES (441,128002,36,'Aztecan','innuendo','affects','');
+INSERT INTO t2 VALUES (442,128003,36,'acuity','den','Cynthia','');
+INSERT INTO t2 VALUES (443,128004,36,'sinking','submarines','Chablis','A');
+INSERT INTO t2 VALUES (444,128005,36,'beasts','mouthful','betterments','FAS');
+INSERT INTO t2 VALUES (445,128007,36,'Witt','expiring','advertising','');
+INSERT INTO t2 VALUES (446,128008,36,'physicists','unfulfilled','rubies','A');
+INSERT INTO t2 VALUES (447,128009,36,'folksong','precession','southwest','FAS');
+INSERT INTO t2 VALUES (448,128010,36,'strokes','nullified','superstitious','A');
+INSERT INTO t2 VALUES (449,128011,36,'crowder','affects','tabernacle','W');
+INSERT INTO t2 VALUES (450,128012,36,'merry','Cynthia','silk','A');
+INSERT INTO t2 VALUES (451,128013,36,'cadenced','Chablis','handsomest','A');
+INSERT INTO t2 VALUES (452,128014,36,'alimony','betterments','Persian','A');
+INSERT INTO t2 VALUES (453,128015,36,'principled','advertising','analog','W');
+INSERT INTO t2 VALUES (454,128016,36,'golfing','rubies','complex','W');
+INSERT INTO t2 VALUES (455,128017,36,'undiscovered','southwest','Taoist','');
+INSERT INTO t2 VALUES (456,128018,36,'irritates','superstitious','suspend','');
+INSERT INTO t2 VALUES (457,128019,36,'patriots','tabernacle','relegated','');
+INSERT INTO t2 VALUES (458,128020,36,'rooms','silk','awesome','W');
+INSERT INTO t2 VALUES (459,128021,36,'towering','handsomest','Bruxelles','');
+INSERT INTO t2 VALUES (460,128022,36,'displease','Persian','imprecisely','A');
+INSERT INTO t2 VALUES (461,128023,36,'photosensitive','analog','televise','');
+INSERT INTO t2 VALUES (462,128101,36,'inking','complex','braking','');
+INSERT INTO t2 VALUES (463,128102,36,'gainers','Taoist','true','FAS');
+INSERT INTO t2 VALUES (464,128103,36,'leaning','suspend','disappointing','FAS');
+INSERT INTO t2 VALUES (465,128104,36,'hydrant','relegated','navally','W');
+INSERT INTO t2 VALUES (466,128106,36,'preserve','awesome','circus','');
+INSERT INTO t2 VALUES (467,128107,36,'blinded','Bruxelles','beetles','');
+INSERT INTO t2 VALUES (468,128108,36,'interactions','imprecisely','trumps','');
+INSERT INTO t2 VALUES (469,128202,36,'Barry','televise','fourscore','W');
+INSERT INTO t2 VALUES (470,128203,36,'whiteness','braking','Blackfoots','');
+INSERT INTO t2 VALUES (471,128301,36,'pastimes','true','Grady','');
+INSERT INTO t2 VALUES (472,128302,36,'Edenization','disappointing','quiets','FAS');
+INSERT INTO t2 VALUES (473,128303,36,'Muscat','navally','floundered','FAS');
+INSERT INTO t2 VALUES (474,128304,36,'assassinated','circus','profundity','W');
+INSERT INTO t2 VALUES (475,128305,36,'labeled','beetles','Garrisonian','W');
+INSERT INTO t2 VALUES (476,128307,36,'glacial','trumps','Strauss','');
+INSERT INTO t2 VALUES (477,128401,36,'implied','fourscore','cemented','FAS');
+INSERT INTO t2 VALUES (478,128502,36,'bibliographies','Blackfoots','contrition','A');
+INSERT INTO t2 VALUES (479,128503,36,'Buchanan','Grady','mutations','');
+INSERT INTO t2 VALUES (480,128504,36,'forgivably','quiets','exhibits','W');
+INSERT INTO t2 VALUES (481,128505,36,'innuendo','floundered','tits','');
+INSERT INTO t2 VALUES (482,128601,36,'den','profundity','mate','A');
+INSERT INTO t2 VALUES (483,128603,36,'submarines','Garrisonian','arches','');
+INSERT INTO t2 VALUES (484,128604,36,'mouthful','Strauss','Moll','');
+INSERT INTO t2 VALUES (485,128702,36,'expiring','cemented','ropers','');
+INSERT INTO t2 VALUES (486,128703,36,'unfulfilled','contrition','bombast','');
+INSERT INTO t2 VALUES (487,128704,36,'precession','mutations','difficultly','A');
+INSERT INTO t2 VALUES (488,138001,36,'nullified','exhibits','adsorption','');
+INSERT INTO t2 VALUES (489,138002,36,'affects','tits','definiteness','FAS');
+INSERT INTO t2 VALUES (490,138003,36,'Cynthia','mate','cultivation','A');
+INSERT INTO t2 VALUES (491,138004,36,'Chablis','arches','heals','A');
+INSERT INTO t2 VALUES (492,138005,36,'betterments','Moll','Heusen','W');
+INSERT INTO t2 VALUES (493,138006,36,'advertising','ropers','target','FAS');
+INSERT INTO t2 VALUES (494,138007,36,'rubies','bombast','cited','A');
+INSERT INTO t2 VALUES (495,138008,36,'southwest','difficultly','congresswoman','W');
+INSERT INTO t2 VALUES (496,138009,36,'superstitious','adsorption','Katherine','');
+INSERT INTO t2 VALUES (497,138102,36,'tabernacle','definiteness','titter','A');
+INSERT INTO t2 VALUES (498,138103,36,'silk','cultivation','aspire','A');
+INSERT INTO t2 VALUES (499,138104,36,'handsomest','heals','Mardis','');
+INSERT INTO t2 VALUES (500,138105,36,'Persian','Heusen','Nadia','W');
+INSERT INTO t2 VALUES (501,138201,36,'analog','target','estimating','FAS');
+INSERT INTO t2 VALUES (502,138302,36,'complex','cited','stuck','A');
+INSERT INTO t2 VALUES (503,138303,36,'Taoist','congresswoman','fifteenth','A');
+INSERT INTO t2 VALUES (504,138304,36,'suspend','Katherine','Colombo','');
+INSERT INTO t2 VALUES (505,138401,29,'relegated','titter','survey','A');
+INSERT INTO t2 VALUES (506,140102,29,'awesome','aspire','staffing','');
+INSERT INTO t2 VALUES (507,140103,29,'Bruxelles','Mardis','obtain','');
+INSERT INTO t2 VALUES (508,140104,29,'imprecisely','Nadia','loaded','');
+INSERT INTO t2 VALUES (509,140105,29,'televise','estimating','slaughtered','');
+INSERT INTO t2 VALUES (510,140201,29,'braking','stuck','lights','A');
+INSERT INTO t2 VALUES (511,140701,29,'true','fifteenth','circumference','');
+INSERT INTO t2 VALUES (512,141501,29,'disappointing','Colombo','dull','A');
+INSERT INTO t2 VALUES (513,141502,29,'navally','survey','weekly','A');
+INSERT INTO t2 VALUES (514,141901,29,'circus','staffing','wetness','');
+INSERT INTO t2 VALUES (515,141902,29,'beetles','obtain','visualized','');
+INSERT INTO t2 VALUES (516,142101,29,'trumps','loaded','Tannenbaum','');
+INSERT INTO t2 VALUES (517,142102,29,'fourscore','slaughtered','moribund','');
+INSERT INTO t2 VALUES (518,142103,29,'Blackfoots','lights','demultiplex','');
+INSERT INTO t2 VALUES (519,142701,29,'Grady','circumference','lockings','');
+INSERT INTO t2 VALUES (520,143001,29,'quiets','dull','thugs','FAS');
+INSERT INTO t2 VALUES (521,143501,29,'floundered','weekly','unnerves','');
+INSERT INTO t2 VALUES (522,143502,29,'profundity','wetness','abut','');
+INSERT INTO t2 VALUES (523,148001,29,'Garrisonian','visualized','Chippewa','A');
+INSERT INTO t2 VALUES (524,148002,29,'Strauss','Tannenbaum','stratifications','A');
+INSERT INTO t2 VALUES (525,148003,29,'cemented','moribund','signaled','');
+INSERT INTO t2 VALUES (526,148004,29,'contrition','demultiplex','Italianizes','A');
+INSERT INTO t2 VALUES (527,148005,29,'mutations','lockings','algorithmic','A');
+INSERT INTO t2 VALUES (528,148006,29,'exhibits','thugs','paranoid','FAS');
+INSERT INTO t2 VALUES (529,148007,29,'tits','unnerves','camping','A');
+INSERT INTO t2 VALUES (530,148009,29,'mate','abut','signifying','A');
+INSERT INTO t2 VALUES (531,148010,29,'arches','Chippewa','Patrice','W');
+INSERT INTO t2 VALUES (532,148011,29,'Moll','stratifications','search','A');
+INSERT INTO t2 VALUES (533,148012,29,'ropers','signaled','Angeles','A');
+INSERT INTO t2 VALUES (534,148013,29,'bombast','Italianizes','semblance','');
+INSERT INTO t2 VALUES (535,148023,36,'difficultly','algorithmic','taxed','');
+INSERT INTO t2 VALUES (536,148015,29,'adsorption','paranoid','Beatrice','');
+INSERT INTO t2 VALUES (537,148016,29,'definiteness','camping','retrace','');
+INSERT INTO t2 VALUES (538,148017,29,'cultivation','signifying','lockout','');
+INSERT INTO t2 VALUES (539,148018,29,'heals','Patrice','grammatic','');
+INSERT INTO t2 VALUES (540,148019,29,'Heusen','search','helmsman','');
+INSERT INTO t2 VALUES (541,148020,29,'target','Angeles','uniform','W');
+INSERT INTO t2 VALUES (542,148021,29,'cited','semblance','hamming','');
+INSERT INTO t2 VALUES (543,148022,29,'congresswoman','taxed','disobedience','');
+INSERT INTO t2 VALUES (544,148101,29,'Katherine','Beatrice','captivated','A');
+INSERT INTO t2 VALUES (545,148102,29,'titter','retrace','transferals','A');
+INSERT INTO t2 VALUES (546,148201,29,'aspire','lockout','cartographer','A');
+INSERT INTO t2 VALUES (547,148401,29,'Mardis','grammatic','aims','FAS');
+INSERT INTO t2 VALUES (548,148402,29,'Nadia','helmsman','Pakistani','');
+INSERT INTO t2 VALUES (549,148501,29,'estimating','uniform','burglarized','FAS');
+INSERT INTO t2 VALUES (550,148502,29,'stuck','hamming','saucepans','A');
+INSERT INTO t2 VALUES (551,148503,29,'fifteenth','disobedience','lacerating','A');
+INSERT INTO t2 VALUES (552,148504,29,'Colombo','captivated','corny','');
+INSERT INTO t2 VALUES (553,148601,29,'survey','transferals','megabytes','FAS');
+INSERT INTO t2 VALUES (554,148602,29,'staffing','cartographer','chancellor','');
+INSERT INTO t2 VALUES (555,150701,29,'obtain','aims','bulk','A');
+INSERT INTO t2 VALUES (556,152101,29,'loaded','Pakistani','commits','A');
+INSERT INTO t2 VALUES (557,152102,29,'slaughtered','burglarized','meson','W');
+INSERT INTO t2 VALUES (558,155202,36,'lights','saucepans','deputies','');
+INSERT INTO t2 VALUES (559,155203,29,'circumference','lacerating','northeaster','A');
+INSERT INTO t2 VALUES (560,155204,29,'dull','corny','dipole','');
+INSERT INTO t2 VALUES (561,155205,29,'weekly','megabytes','machining','0');
+INSERT INTO t2 VALUES (562,156001,29,'wetness','chancellor','therefore','');
+INSERT INTO t2 VALUES (563,156002,29,'visualized','bulk','Telefunken','');
+INSERT INTO t2 VALUES (564,156102,29,'Tannenbaum','commits','salvaging','');
+INSERT INTO t2 VALUES (565,156301,29,'moribund','meson','Corinthianizes','A');
+INSERT INTO t2 VALUES (566,156302,29,'demultiplex','deputies','restlessly','A');
+INSERT INTO t2 VALUES (567,156303,29,'lockings','northeaster','bromides','');
+INSERT INTO t2 VALUES (568,156304,29,'thugs','dipole','generalized','A');
+INSERT INTO t2 VALUES (569,156305,29,'unnerves','machining','mishaps','');
+INSERT INTO t2 VALUES (570,156306,29,'abut','therefore','quelling','');
+INSERT INTO t2 VALUES (571,156501,29,'Chippewa','Telefunken','spiritual','A');
+INSERT INTO t2 VALUES (572,158001,29,'stratifications','salvaging','beguiles','FAS');
+INSERT INTO t2 VALUES (573,158002,29,'signaled','Corinthianizes','Trobriand','FAS');
+INSERT INTO t2 VALUES (574,158101,29,'Italianizes','restlessly','fleeing','A');
+INSERT INTO t2 VALUES (575,158102,29,'algorithmic','bromides','Armour','A');
+INSERT INTO t2 VALUES (576,158103,29,'paranoid','generalized','chin','A');
+INSERT INTO t2 VALUES (577,158201,29,'camping','mishaps','provers','A');
+INSERT INTO t2 VALUES (578,158202,29,'signifying','quelling','aeronautic','A');
+INSERT INTO t2 VALUES (579,158203,29,'Patrice','spiritual','voltage','W');
+INSERT INTO t2 VALUES (580,158204,29,'search','beguiles','sash','');
+INSERT INTO t2 VALUES (581,158301,29,'Angeles','Trobriand','anaerobic','A');
+INSERT INTO t2 VALUES (582,158302,29,'semblance','fleeing','simultaneous','A');
+INSERT INTO t2 VALUES (583,158303,29,'taxed','Armour','accumulating','A');
+INSERT INTO t2 VALUES (584,158304,29,'Beatrice','chin','Medusan','A');
+INSERT INTO t2 VALUES (585,158305,29,'retrace','provers','shouted','A');
+INSERT INTO t2 VALUES (586,158306,29,'lockout','aeronautic','freakish','');
+INSERT INTO t2 VALUES (587,158501,29,'grammatic','voltage','index','FAS');
+INSERT INTO t2 VALUES (588,160301,29,'helmsman','sash','commercially','');
+INSERT INTO t2 VALUES (589,166101,50,'uniform','anaerobic','mistiness','A');
+INSERT INTO t2 VALUES (590,166102,50,'hamming','simultaneous','endpoint','');
+INSERT INTO t2 VALUES (591,168001,29,'disobedience','accumulating','straight','A');
+INSERT INTO t2 VALUES (592,168002,29,'captivated','Medusan','flurried','');
+INSERT INTO t2 VALUES (593,168003,29,'transferals','shouted','denotative','A');
+INSERT INTO t2 VALUES (594,168101,29,'cartographer','freakish','coming','FAS');
+INSERT INTO t2 VALUES (595,168102,29,'aims','index','commencements','FAS');
+INSERT INTO t2 VALUES (596,168103,29,'Pakistani','commercially','gentleman','');
+INSERT INTO t2 VALUES (597,168104,29,'burglarized','mistiness','gifted','');
+INSERT INTO t2 VALUES (598,168202,29,'saucepans','endpoint','Shanghais','');
+INSERT INTO t2 VALUES (599,168301,29,'lacerating','straight','sportswriting','A');
+INSERT INTO t2 VALUES (600,168502,29,'corny','flurried','sloping','A');
+INSERT INTO t2 VALUES (601,168503,29,'megabytes','denotative','navies','');
+INSERT INTO t2 VALUES (602,168601,29,'chancellor','coming','leaflet','A');
+INSERT INTO t2 VALUES (603,173001,40,'bulk','commencements','shooter','');
+INSERT INTO t2 VALUES (604,173701,40,'commits','gentleman','Joplin','FAS');
+INSERT INTO t2 VALUES (605,173702,40,'meson','gifted','babies','');
+INSERT INTO t2 VALUES (606,176001,40,'deputies','Shanghais','subdivision','FAS');
+INSERT INTO t2 VALUES (607,176101,40,'northeaster','sportswriting','burstiness','W');
+INSERT INTO t2 VALUES (608,176201,40,'dipole','sloping','belted','FAS');
+INSERT INTO t2 VALUES (609,176401,40,'machining','navies','assails','FAS');
+INSERT INTO t2 VALUES (610,176501,40,'therefore','leaflet','admiring','W');
+INSERT INTO t2 VALUES (611,176601,40,'Telefunken','shooter','swaying','0');
+INSERT INTO t2 VALUES (612,176602,40,'salvaging','Joplin','Goldstine','FAS');
+INSERT INTO t2 VALUES (613,176603,40,'Corinthianizes','babies','fitting','');
+INSERT INTO t2 VALUES (614,178001,40,'restlessly','subdivision','Norwalk','W');
+INSERT INTO t2 VALUES (615,178002,40,'bromides','burstiness','weakening','W');
+INSERT INTO t2 VALUES (616,178003,40,'generalized','belted','analogy','FAS');
+INSERT INTO t2 VALUES (617,178004,40,'mishaps','assails','deludes','');
+INSERT INTO t2 VALUES (618,178005,40,'quelling','admiring','cokes','');
+INSERT INTO t2 VALUES (619,178006,40,'spiritual','swaying','Clayton','');
+INSERT INTO t2 VALUES (620,178007,40,'beguiles','Goldstine','exhausts','');
+INSERT INTO t2 VALUES (621,178008,40,'Trobriand','fitting','causality','');
+INSERT INTO t2 VALUES (622,178101,40,'fleeing','Norwalk','sating','FAS');
+INSERT INTO t2 VALUES (623,178102,40,'Armour','weakening','icon','');
+INSERT INTO t2 VALUES (624,178103,40,'chin','analogy','throttles','');
+INSERT INTO t2 VALUES (625,178201,40,'provers','deludes','communicants','FAS');
+INSERT INTO t2 VALUES (626,178202,40,'aeronautic','cokes','dehydrate','FAS');
+INSERT INTO t2 VALUES (627,178301,40,'voltage','Clayton','priceless','FAS');
+INSERT INTO t2 VALUES (628,178302,40,'sash','exhausts','publicly','');
+INSERT INTO t2 VALUES (629,178401,40,'anaerobic','causality','incidentals','FAS');
+INSERT INTO t2 VALUES (630,178402,40,'simultaneous','sating','commonplace','');
+INSERT INTO t2 VALUES (631,178403,40,'accumulating','icon','mumbles','');
+INSERT INTO t2 VALUES (632,178404,40,'Medusan','throttles','furthermore','W');
+INSERT INTO t2 VALUES (633,178501,40,'shouted','communicants','cautioned','W');
+INSERT INTO t2 VALUES (634,186002,37,'freakish','dehydrate','parametrized','A');
+INSERT INTO t2 VALUES (635,186102,37,'index','priceless','registration','A');
+INSERT INTO t2 VALUES (636,186201,40,'commercially','publicly','sadly','FAS');
+INSERT INTO t2 VALUES (637,186202,40,'mistiness','incidentals','positioning','');
+INSERT INTO t2 VALUES (638,186203,40,'endpoint','commonplace','babysitting','');
+INSERT INTO t2 VALUES (639,186302,37,'straight','mumbles','eternal','A');
+INSERT INTO t2 VALUES (640,188007,37,'flurried','furthermore','hoarder','');
+INSERT INTO t2 VALUES (641,188008,37,'denotative','cautioned','congregates','');
+INSERT INTO t2 VALUES (642,188009,37,'coming','parametrized','rains','');
+INSERT INTO t2 VALUES (643,188010,37,'commencements','registration','workers','W');
+INSERT INTO t2 VALUES (644,188011,37,'gentleman','sadly','sags','A');
+INSERT INTO t2 VALUES (645,188012,37,'gifted','positioning','unplug','W');
+INSERT INTO t2 VALUES (646,188013,37,'Shanghais','babysitting','garage','A');
+INSERT INTO t2 VALUES (647,188014,37,'sportswriting','eternal','boulder','A');
+INSERT INTO t2 VALUES (648,188015,37,'sloping','hoarder','hollowly','A');
+INSERT INTO t2 VALUES (649,188016,37,'navies','congregates','specifics','');
+INSERT INTO t2 VALUES (650,188017,37,'leaflet','rains','Teresa','');
+INSERT INTO t2 VALUES (651,188102,37,'shooter','workers','Winsett','');
+INSERT INTO t2 VALUES (652,188103,37,'Joplin','sags','convenient','A');
+INSERT INTO t2 VALUES (653,188202,37,'babies','unplug','buckboards','FAS');
+INSERT INTO t2 VALUES (654,188301,40,'subdivision','garage','amenities','');
+INSERT INTO t2 VALUES (655,188302,40,'burstiness','boulder','resplendent','FAS');
+INSERT INTO t2 VALUES (656,188303,40,'belted','hollowly','priding','FAS');
+INSERT INTO t2 VALUES (657,188401,37,'assails','specifics','configurations','');
+INSERT INTO t2 VALUES (658,188402,37,'admiring','Teresa','untidiness','A');
+INSERT INTO t2 VALUES (659,188503,37,'swaying','Winsett','Brice','W');
+INSERT INTO t2 VALUES (660,188504,37,'Goldstine','convenient','sews','FAS');
+INSERT INTO t2 VALUES (661,188505,37,'fitting','buckboards','participated','');
+INSERT INTO t2 VALUES (662,190701,37,'Norwalk','amenities','Simon','FAS');
+INSERT INTO t2 VALUES (663,190703,50,'weakening','resplendent','certificates','');
+INSERT INTO t2 VALUES (664,191701,37,'analogy','priding','Fitzpatrick','');
+INSERT INTO t2 VALUES (665,191702,37,'deludes','configurations','Evanston','A');
+INSERT INTO t2 VALUES (666,191703,37,'cokes','untidiness','misted','');
+INSERT INTO t2 VALUES (667,196001,37,'Clayton','Brice','textures','A');
+INSERT INTO t2 VALUES (668,196002,37,'exhausts','sews','save','');
+INSERT INTO t2 VALUES (669,196003,37,'causality','participated','count','');
+INSERT INTO t2 VALUES (670,196101,37,'sating','Simon','rightful','A');
+INSERT INTO t2 VALUES (671,196103,37,'icon','certificates','chaperone','');
+INSERT INTO t2 VALUES (672,196104,37,'throttles','Fitzpatrick','Lizzy','A');
+INSERT INTO t2 VALUES (673,196201,37,'communicants','Evanston','clenched','A');
+INSERT INTO t2 VALUES (674,196202,37,'dehydrate','misted','effortlessly','');
+INSERT INTO t2 VALUES (675,196203,37,'priceless','textures','accessed','');
+INSERT INTO t2 VALUES (676,198001,37,'publicly','save','beaters','A');
+INSERT INTO t2 VALUES (677,198003,37,'incidentals','count','Hornblower','FAS');
+INSERT INTO t2 VALUES (678,198004,37,'commonplace','rightful','vests','A');
+INSERT INTO t2 VALUES (679,198005,37,'mumbles','chaperone','indulgences','FAS');
+INSERT INTO t2 VALUES (680,198006,37,'furthermore','Lizzy','infallibly','A');
+INSERT INTO t2 VALUES (681,198007,37,'cautioned','clenched','unwilling','FAS');
+INSERT INTO t2 VALUES (682,198008,37,'parametrized','effortlessly','excrete','FAS');
+INSERT INTO t2 VALUES (683,198009,37,'registration','accessed','spools','A');
+INSERT INTO t2 VALUES (684,198010,37,'sadly','beaters','crunches','FAS');
+INSERT INTO t2 VALUES (685,198011,37,'positioning','Hornblower','overestimating','FAS');
+INSERT INTO t2 VALUES (686,198012,37,'babysitting','vests','ineffective','');
+INSERT INTO t2 VALUES (687,198013,37,'eternal','indulgences','humiliation','A');
+INSERT INTO t2 VALUES (688,198014,37,'hoarder','infallibly','sophomore','');
+INSERT INTO t2 VALUES (689,198015,37,'congregates','unwilling','star','');
+INSERT INTO t2 VALUES (690,198017,37,'rains','excrete','rifles','');
+INSERT INTO t2 VALUES (691,198018,37,'workers','spools','dialysis','');
+INSERT INTO t2 VALUES (692,198019,37,'sags','crunches','arriving','');
+INSERT INTO t2 VALUES (693,198020,37,'unplug','overestimating','indulge','');
+INSERT INTO t2 VALUES (694,198021,37,'garage','ineffective','clockers','');
+INSERT INTO t2 VALUES (695,198022,37,'boulder','humiliation','languages','');
+INSERT INTO t2 VALUES (696,198023,50,'hollowly','sophomore','Antarctica','A');
+INSERT INTO t2 VALUES (697,198024,37,'specifics','star','percentage','');
+INSERT INTO t2 VALUES (698,198101,37,'Teresa','rifles','ceiling','A');
+INSERT INTO t2 VALUES (699,198103,37,'Winsett','dialysis','specification','');
+INSERT INTO t2 VALUES (700,198105,37,'convenient','arriving','regimented','A');
+INSERT INTO t2 VALUES (701,198106,37,'buckboards','indulge','ciphers','');
+INSERT INTO t2 VALUES (702,198201,37,'amenities','clockers','pictures','A');
+INSERT INTO t2 VALUES (703,198204,37,'resplendent','languages','serpents','A');
+INSERT INTO t2 VALUES (704,198301,53,'priding','Antarctica','allot','A');
+INSERT INTO t2 VALUES (705,198302,53,'configurations','percentage','realized','A');
+INSERT INTO t2 VALUES (706,198303,53,'untidiness','ceiling','mayoral','A');
+INSERT INTO t2 VALUES (707,198304,53,'Brice','specification','opaquely','A');
+INSERT INTO t2 VALUES (708,198401,37,'sews','regimented','hostess','FAS');
+INSERT INTO t2 VALUES (709,198402,37,'participated','ciphers','fiftieth','');
+INSERT INTO t2 VALUES (710,198403,37,'Simon','pictures','incorrectly','');
+INSERT INTO t2 VALUES (711,202101,37,'certificates','serpents','decomposition','FAS');
+INSERT INTO t2 VALUES (712,202301,37,'Fitzpatrick','allot','stranglings','');
+INSERT INTO t2 VALUES (713,202302,37,'Evanston','realized','mixture','FAS');
+INSERT INTO t2 VALUES (714,202303,37,'misted','mayoral','electroencephalography','FAS');
+INSERT INTO t2 VALUES (715,202304,37,'textures','opaquely','similarities','FAS');
+INSERT INTO t2 VALUES (716,202305,37,'save','hostess','charges','W');
+INSERT INTO t2 VALUES (717,202601,37,'count','fiftieth','freest','FAS');
+INSERT INTO t2 VALUES (718,202602,37,'rightful','incorrectly','Greenberg','FAS');
+INSERT INTO t2 VALUES (719,202605,37,'chaperone','decomposition','tinting','');
+INSERT INTO t2 VALUES (720,202606,37,'Lizzy','stranglings','expelled','W');
+INSERT INTO t2 VALUES (721,202607,37,'clenched','mixture','warm','');
+INSERT INTO t2 VALUES (722,202901,37,'effortlessly','electroencephalography','smoothed','');
+INSERT INTO t2 VALUES (723,202902,37,'accessed','similarities','deductions','FAS');
+INSERT INTO t2 VALUES (724,202903,37,'beaters','charges','Romano','W');
+INSERT INTO t2 VALUES (725,202904,37,'Hornblower','freest','bitterroot','');
+INSERT INTO t2 VALUES (726,202907,37,'vests','Greenberg','corset','');
+INSERT INTO t2 VALUES (727,202908,37,'indulgences','tinting','securing','');
+INSERT INTO t2 VALUES (728,203101,37,'infallibly','expelled','environing','FAS');
+INSERT INTO t2 VALUES (729,203103,37,'unwilling','warm','cute','');
+INSERT INTO t2 VALUES (730,203104,37,'excrete','smoothed','Crays','');
+INSERT INTO t2 VALUES (731,203105,37,'spools','deductions','heiress','FAS');
+INSERT INTO t2 VALUES (732,203401,37,'crunches','Romano','inform','FAS');
+INSERT INTO t2 VALUES (733,203402,37,'overestimating','bitterroot','avenge','');
+INSERT INTO t2 VALUES (734,203404,37,'ineffective','corset','universals','');
+INSERT INTO t2 VALUES (735,203901,37,'humiliation','securing','Kinsey','W');
+INSERT INTO t2 VALUES (736,203902,37,'sophomore','environing','ravines','FAS');
+INSERT INTO t2 VALUES (737,203903,37,'star','cute','bestseller','');
+INSERT INTO t2 VALUES (738,203906,37,'rifles','Crays','equilibrium','');
+INSERT INTO t2 VALUES (739,203907,37,'dialysis','heiress','extents','0');
+INSERT INTO t2 VALUES (740,203908,37,'arriving','inform','relatively','');
+INSERT INTO t2 VALUES (741,203909,37,'indulge','avenge','pressure','FAS');
+INSERT INTO t2 VALUES (742,206101,37,'clockers','universals','critiques','FAS');
+INSERT INTO t2 VALUES (743,206201,37,'languages','Kinsey','befouled','');
+INSERT INTO t2 VALUES (744,206202,37,'Antarctica','ravines','rightfully','FAS');
+INSERT INTO t2 VALUES (745,206203,37,'percentage','bestseller','mechanizing','FAS');
+INSERT INTO t2 VALUES (746,206206,37,'ceiling','equilibrium','Latinizes','');
+INSERT INTO t2 VALUES (747,206207,37,'specification','extents','timesharing','');
+INSERT INTO t2 VALUES (748,206208,37,'regimented','relatively','Aden','');
+INSERT INTO t2 VALUES (749,208001,37,'ciphers','pressure','embassies','');
+INSERT INTO t2 VALUES (750,208002,37,'pictures','critiques','males','FAS');
+INSERT INTO t2 VALUES (751,208003,37,'serpents','befouled','shapelessly','FAS');
+INSERT INTO t2 VALUES (752,208004,37,'allot','rightfully','genres','FAS');
+INSERT INTO t2 VALUES (753,208008,37,'realized','mechanizing','mastering','');
+INSERT INTO t2 VALUES (754,208009,37,'mayoral','Latinizes','Newtonian','');
+INSERT INTO t2 VALUES (755,208010,37,'opaquely','timesharing','finishers','FAS');
+INSERT INTO t2 VALUES (756,208011,37,'hostess','Aden','abates','');
+INSERT INTO t2 VALUES (757,208101,37,'fiftieth','embassies','teem','');
+INSERT INTO t2 VALUES (758,208102,37,'incorrectly','males','kiting','FAS');
+INSERT INTO t2 VALUES (759,208103,37,'decomposition','shapelessly','stodgy','FAS');
+INSERT INTO t2 VALUES (760,208104,37,'stranglings','genres','scalps','FAS');
+INSERT INTO t2 VALUES (761,208105,37,'mixture','mastering','feed','FAS');
+INSERT INTO t2 VALUES (762,208110,37,'electroencephalography','Newtonian','guitars','');
+INSERT INTO t2 VALUES (763,208111,37,'similarities','finishers','airships','');
+INSERT INTO t2 VALUES (764,208112,37,'charges','abates','store','');
+INSERT INTO t2 VALUES (765,208113,37,'freest','teem','denounces','');
+INSERT INTO t2 VALUES (766,208201,37,'Greenberg','kiting','Pyle','FAS');
+INSERT INTO t2 VALUES (767,208203,37,'tinting','stodgy','Saxony','');
+INSERT INTO t2 VALUES (768,208301,37,'expelled','scalps','serializations','FAS');
+INSERT INTO t2 VALUES (769,208302,37,'warm','feed','Peruvian','FAS');
+INSERT INTO t2 VALUES (770,208305,37,'smoothed','guitars','taxonomically','FAS');
+INSERT INTO t2 VALUES (771,208401,37,'deductions','airships','kingdom','A');
+INSERT INTO t2 VALUES (772,208402,37,'Romano','store','stint','A');
+INSERT INTO t2 VALUES (773,208403,37,'bitterroot','denounces','Sault','A');
+INSERT INTO t2 VALUES (774,208404,37,'corset','Pyle','faithful','');
+INSERT INTO t2 VALUES (775,208501,37,'securing','Saxony','Ganymede','FAS');
+INSERT INTO t2 VALUES (776,208502,37,'environing','serializations','tidiness','FAS');
+INSERT INTO t2 VALUES (777,208503,37,'cute','Peruvian','gainful','FAS');
+INSERT INTO t2 VALUES (778,208504,37,'Crays','taxonomically','contrary','FAS');
+INSERT INTO t2 VALUES (779,208505,37,'heiress','kingdom','Tipperary','FAS');
+INSERT INTO t2 VALUES (780,210101,37,'inform','stint','tropics','W');
+INSERT INTO t2 VALUES (781,210102,37,'avenge','Sault','theorizers','');
+INSERT INTO t2 VALUES (782,210103,37,'universals','faithful','renew','0');
+INSERT INTO t2 VALUES (783,210104,37,'Kinsey','Ganymede','already','');
+INSERT INTO t2 VALUES (784,210105,37,'ravines','tidiness','terminal','');
+INSERT INTO t2 VALUES (785,210106,37,'bestseller','gainful','Hegelian','');
+INSERT INTO t2 VALUES (786,210107,37,'equilibrium','contrary','hypothesizer','');
+INSERT INTO t2 VALUES (787,210401,37,'extents','Tipperary','warningly','FAS');
+INSERT INTO t2 VALUES (788,213201,37,'relatively','tropics','journalizing','FAS');
+INSERT INTO t2 VALUES (789,213203,37,'pressure','theorizers','nested','');
+INSERT INTO t2 VALUES (790,213204,37,'critiques','renew','Lars','');
+INSERT INTO t2 VALUES (791,213205,37,'befouled','already','saplings','');
+INSERT INTO t2 VALUES (792,213206,37,'rightfully','terminal','foothill','');
+INSERT INTO t2 VALUES (793,213207,37,'mechanizing','Hegelian','labeled','');
+INSERT INTO t2 VALUES (794,216101,37,'Latinizes','hypothesizer','imperiously','FAS');
+INSERT INTO t2 VALUES (795,216103,37,'timesharing','warningly','reporters','FAS');
+INSERT INTO t2 VALUES (796,218001,37,'Aden','journalizing','furnishings','FAS');
+INSERT INTO t2 VALUES (797,218002,37,'embassies','nested','precipitable','FAS');
+INSERT INTO t2 VALUES (798,218003,37,'males','Lars','discounts','FAS');
+INSERT INTO t2 VALUES (799,218004,37,'shapelessly','saplings','excises','FAS');
+INSERT INTO t2 VALUES (800,143503,50,'genres','foothill','Stalin','');
+INSERT INTO t2 VALUES (801,218006,37,'mastering','labeled','despot','FAS');
+INSERT INTO t2 VALUES (802,218007,37,'Newtonian','imperiously','ripeness','FAS');
+INSERT INTO t2 VALUES (803,218008,37,'finishers','reporters','Arabia','');
+INSERT INTO t2 VALUES (804,218009,37,'abates','furnishings','unruly','');
+INSERT INTO t2 VALUES (805,218010,37,'teem','precipitable','mournfulness','');
+INSERT INTO t2 VALUES (806,218011,37,'kiting','discounts','boom','FAS');
+INSERT INTO t2 VALUES (807,218020,37,'stodgy','excises','slaughter','A');
+INSERT INTO t2 VALUES (808,218021,50,'scalps','Stalin','Sabine','');
+INSERT INTO t2 VALUES (809,218022,37,'feed','despot','handy','FAS');
+INSERT INTO t2 VALUES (810,218023,37,'guitars','ripeness','rural','');
+INSERT INTO t2 VALUES (811,218024,37,'airships','Arabia','organizer','');
+INSERT INTO t2 VALUES (812,218101,37,'store','unruly','shipyard','FAS');
+INSERT INTO t2 VALUES (813,218102,37,'denounces','mournfulness','civics','FAS');
+INSERT INTO t2 VALUES (814,218103,37,'Pyle','boom','inaccuracy','FAS');
+INSERT INTO t2 VALUES (815,218201,37,'Saxony','slaughter','rules','FAS');
+INSERT INTO t2 VALUES (816,218202,37,'serializations','Sabine','juveniles','FAS');
+INSERT INTO t2 VALUES (817,218203,37,'Peruvian','handy','comprised','W');
+INSERT INTO t2 VALUES (818,218204,37,'taxonomically','rural','investigations','');
+INSERT INTO t2 VALUES (819,218205,37,'kingdom','organizer','stabilizes','A');
+INSERT INTO t2 VALUES (820,218301,37,'stint','shipyard','seminaries','FAS');
+INSERT INTO t2 VALUES (821,218302,37,'Sault','civics','Hunter','A');
+INSERT INTO t2 VALUES (822,218401,37,'faithful','inaccuracy','sporty','FAS');
+INSERT INTO t2 VALUES (823,218402,37,'Ganymede','rules','test','FAS');
+INSERT INTO t2 VALUES (824,218403,37,'tidiness','juveniles','weasels','');
+INSERT INTO t2 VALUES (825,218404,37,'gainful','comprised','CERN','');
+INSERT INTO t2 VALUES (826,218407,37,'contrary','investigations','tempering','');
+INSERT INTO t2 VALUES (827,218408,37,'Tipperary','stabilizes','afore','FAS');
+INSERT INTO t2 VALUES (828,218409,37,'tropics','seminaries','Galatean','');
+INSERT INTO t2 VALUES (829,218410,37,'theorizers','Hunter','techniques','W');
+INSERT INTO t2 VALUES (830,226001,37,'renew','sporty','error','');
+INSERT INTO t2 VALUES (831,226002,37,'already','test','veranda','');
+INSERT INTO t2 VALUES (832,226003,37,'terminal','weasels','severely','');
+INSERT INTO t2 VALUES (833,226004,37,'Hegelian','CERN','Cassites','FAS');
+INSERT INTO t2 VALUES (834,226005,37,'hypothesizer','tempering','forthcoming','');
+INSERT INTO t2 VALUES (835,226006,37,'warningly','afore','guides','');
+INSERT INTO t2 VALUES (836,226007,37,'journalizing','Galatean','vanish','FAS');
+INSERT INTO t2 VALUES (837,226008,37,'nested','techniques','lied','A');
+INSERT INTO t2 VALUES (838,226203,37,'Lars','error','sawtooth','FAS');
+INSERT INTO t2 VALUES (839,226204,37,'saplings','veranda','fated','FAS');
+INSERT INTO t2 VALUES (840,226205,37,'foothill','severely','gradually','');
+INSERT INTO t2 VALUES (841,226206,37,'labeled','Cassites','widens','');
+INSERT INTO t2 VALUES (842,226207,37,'imperiously','forthcoming','preclude','');
+INSERT INTO t2 VALUES (843,226208,37,'reporters','guides','Jobrel','');
+INSERT INTO t2 VALUES (844,226209,37,'furnishings','vanish','hooker','');
+INSERT INTO t2 VALUES (845,226210,37,'precipitable','lied','rainstorm','');
+INSERT INTO t2 VALUES (846,226211,37,'discounts','sawtooth','disconnects','');
+INSERT INTO t2 VALUES (847,228001,37,'excises','fated','cruelty','');
+INSERT INTO t2 VALUES (848,228004,37,'Stalin','gradually','exponentials','A');
+INSERT INTO t2 VALUES (849,228005,37,'despot','widens','affective','A');
+INSERT INTO t2 VALUES (850,228006,37,'ripeness','preclude','arteries','');
+INSERT INTO t2 VALUES (851,228007,37,'Arabia','Jobrel','Crosby','FAS');
+INSERT INTO t2 VALUES (852,228008,37,'unruly','hooker','acquaint','');
+INSERT INTO t2 VALUES (853,228009,37,'mournfulness','rainstorm','evenhandedly','');
+INSERT INTO t2 VALUES (854,228101,37,'boom','disconnects','percentage','');
+INSERT INTO t2 VALUES (855,228108,37,'slaughter','cruelty','disobedience','');
+INSERT INTO t2 VALUES (856,228109,37,'Sabine','exponentials','humility','');
+INSERT INTO t2 VALUES (857,228110,37,'handy','affective','gleaning','A');
+INSERT INTO t2 VALUES (858,228111,37,'rural','arteries','petted','A');
+INSERT INTO t2 VALUES (859,228112,37,'organizer','Crosby','bloater','A');
+INSERT INTO t2 VALUES (860,228113,37,'shipyard','acquaint','minion','A');
+INSERT INTO t2 VALUES (861,228114,37,'civics','evenhandedly','marginal','A');
+INSERT INTO t2 VALUES (862,228115,37,'inaccuracy','percentage','apiary','A');
+INSERT INTO t2 VALUES (863,228116,37,'rules','disobedience','measures','');
+INSERT INTO t2 VALUES (864,228117,37,'juveniles','humility','precaution','');
+INSERT INTO t2 VALUES (865,228118,37,'comprised','gleaning','repelled','');
+INSERT INTO t2 VALUES (866,228119,37,'investigations','petted','primary','FAS');
+INSERT INTO t2 VALUES (867,228120,37,'stabilizes','bloater','coverings','');
+INSERT INTO t2 VALUES (868,228121,37,'seminaries','minion','Artemia','A');
+INSERT INTO t2 VALUES (869,228122,37,'Hunter','marginal','navigate','');
+INSERT INTO t2 VALUES (870,228201,37,'sporty','apiary','spatial','');
+INSERT INTO t2 VALUES (871,228206,37,'test','measures','Gurkha','');
+INSERT INTO t2 VALUES (872,228207,37,'weasels','precaution','meanwhile','A');
+INSERT INTO t2 VALUES (873,228208,37,'CERN','repelled','Melinda','A');
+INSERT INTO t2 VALUES (874,228209,37,'tempering','primary','Butterfield','');
+INSERT INTO t2 VALUES (875,228210,37,'afore','coverings','Aldrich','A');
+INSERT INTO t2 VALUES (876,228211,37,'Galatean','Artemia','previewing','A');
+INSERT INTO t2 VALUES (877,228212,37,'techniques','navigate','glut','A');
+INSERT INTO t2 VALUES (878,228213,37,'error','spatial','unaffected','');
+INSERT INTO t2 VALUES (879,228214,37,'veranda','Gurkha','inmate','');
+INSERT INTO t2 VALUES (880,228301,37,'severely','meanwhile','mineral','');
+INSERT INTO t2 VALUES (881,228305,37,'Cassites','Melinda','impending','A');
+INSERT INTO t2 VALUES (882,228306,37,'forthcoming','Butterfield','meditation','A');
+INSERT INTO t2 VALUES (883,228307,37,'guides','Aldrich','ideas','');
+INSERT INTO t2 VALUES (884,228308,37,'vanish','previewing','miniaturizes','W');
+INSERT INTO t2 VALUES (885,228309,37,'lied','glut','lewdly','');
+INSERT INTO t2 VALUES (886,228310,37,'sawtooth','unaffected','title','');
+INSERT INTO t2 VALUES (887,228311,37,'fated','inmate','youthfulness','');
+INSERT INTO t2 VALUES (888,228312,37,'gradually','mineral','creak','FAS');
+INSERT INTO t2 VALUES (889,228313,37,'widens','impending','Chippewa','');
+INSERT INTO t2 VALUES (890,228314,37,'preclude','meditation','clamored','');
+INSERT INTO t2 VALUES (891,228401,65,'Jobrel','ideas','freezes','');
+INSERT INTO t2 VALUES (892,228402,65,'hooker','miniaturizes','forgivably','FAS');
+INSERT INTO t2 VALUES (893,228403,65,'rainstorm','lewdly','reduce','FAS');
+INSERT INTO t2 VALUES (894,228404,65,'disconnects','title','McGovern','W');
+INSERT INTO t2 VALUES (895,228405,65,'cruelty','youthfulness','Nazis','W');
+INSERT INTO t2 VALUES (896,228406,65,'exponentials','creak','epistle','W');
+INSERT INTO t2 VALUES (897,228407,65,'affective','Chippewa','socializes','W');
+INSERT INTO t2 VALUES (898,228408,65,'arteries','clamored','conceptions','');
+INSERT INTO t2 VALUES (899,228409,65,'Crosby','freezes','Kevin','');
+INSERT INTO t2 VALUES (900,228410,65,'acquaint','forgivably','uncovering','');
+INSERT INTO t2 VALUES (901,230301,37,'evenhandedly','reduce','chews','FAS');
+INSERT INTO t2 VALUES (902,230302,37,'percentage','McGovern','appendixes','FAS');
+INSERT INTO t2 VALUES (903,230303,37,'disobedience','Nazis','raining','');
+INSERT INTO t2 VALUES (904,018062,37,'humility','epistle','infest','');
+INSERT INTO t2 VALUES (905,230501,37,'gleaning','socializes','compartment','');
+INSERT INTO t2 VALUES (906,230502,37,'petted','conceptions','minting','');
+INSERT INTO t2 VALUES (907,230503,37,'bloater','Kevin','ducks','');
+INSERT INTO t2 VALUES (908,230504,37,'minion','uncovering','roped','A');
+INSERT INTO t2 VALUES (909,230505,37,'marginal','chews','waltz','');
+INSERT INTO t2 VALUES (910,230506,37,'apiary','appendixes','Lillian','');
+INSERT INTO t2 VALUES (911,230507,37,'measures','raining','repressions','A');
+INSERT INTO t2 VALUES (912,230508,37,'precaution','infest','chillingly','');
+INSERT INTO t2 VALUES (913,230509,37,'repelled','compartment','noncritical','');
+INSERT INTO t2 VALUES (914,230901,37,'primary','minting','lithograph','');
+INSERT INTO t2 VALUES (915,230902,37,'coverings','ducks','spongers','');
+INSERT INTO t2 VALUES (916,230903,37,'Artemia','roped','parenthood','');
+INSERT INTO t2 VALUES (917,230904,37,'navigate','waltz','posed','');
+INSERT INTO t2 VALUES (918,230905,37,'spatial','Lillian','instruments','');
+INSERT INTO t2 VALUES (919,230906,37,'Gurkha','repressions','filial','');
+INSERT INTO t2 VALUES (920,230907,37,'meanwhile','chillingly','fixedly','');
+INSERT INTO t2 VALUES (921,230908,37,'Melinda','noncritical','relives','');
+INSERT INTO t2 VALUES (922,230909,37,'Butterfield','lithograph','Pandora','');
+INSERT INTO t2 VALUES (923,230910,37,'Aldrich','spongers','watering','A');
+INSERT INTO t2 VALUES (924,230911,37,'previewing','parenthood','ungrateful','');
+INSERT INTO t2 VALUES (925,230912,37,'glut','posed','secures','');
+INSERT INTO t2 VALUES (926,230913,37,'unaffected','instruments','chastisers','');
+INSERT INTO t2 VALUES (927,230914,37,'inmate','filial','icon','');
+INSERT INTO t2 VALUES (928,231304,37,'mineral','fixedly','reuniting','A');
+INSERT INTO t2 VALUES (929,231305,37,'impending','relives','imagining','A');
+INSERT INTO t2 VALUES (930,231306,37,'meditation','Pandora','abiding','A');
+INSERT INTO t2 VALUES (931,231307,37,'ideas','watering','omnisciently','');
+INSERT INTO t2 VALUES (932,231308,37,'miniaturizes','ungrateful','Britannic','');
+INSERT INTO t2 VALUES (933,231309,37,'lewdly','secures','scholastics','A');
+INSERT INTO t2 VALUES (934,231310,37,'title','chastisers','mechanics','A');
+INSERT INTO t2 VALUES (935,231311,37,'youthfulness','icon','humidly','A');
+INSERT INTO t2 VALUES (936,231312,37,'creak','reuniting','masterpiece','');
+INSERT INTO t2 VALUES (937,231313,37,'Chippewa','imagining','however','');
+INSERT INTO t2 VALUES (938,231314,37,'clamored','abiding','Mendelian','');
+INSERT INTO t2 VALUES (939,231315,37,'freezes','omnisciently','jarred','');
+INSERT INTO t2 VALUES (940,232102,37,'forgivably','Britannic','scolds','');
+INSERT INTO t2 VALUES (941,232103,37,'reduce','scholastics','infatuate','');
+INSERT INTO t2 VALUES (942,232104,37,'McGovern','mechanics','willed','A');
+INSERT INTO t2 VALUES (943,232105,37,'Nazis','humidly','joyfully','');
+INSERT INTO t2 VALUES (944,232106,37,'epistle','masterpiece','Microsoft','');
+INSERT INTO t2 VALUES (945,232107,37,'socializes','however','fibrosities','');
+INSERT INTO t2 VALUES (946,232108,37,'conceptions','Mendelian','Baltimorean','');
+INSERT INTO t2 VALUES (947,232601,37,'Kevin','jarred','equestrian','');
+INSERT INTO t2 VALUES (948,232602,37,'uncovering','scolds','Goodrich','');
+INSERT INTO t2 VALUES (949,232603,37,'chews','infatuate','apish','A');
+INSERT INTO t2 VALUES (950,232605,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5950,1232605,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5951,1232606,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5952,1232607,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5953,1232608,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5954,1232609,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (951,232606,37,'raining','joyfully','Tropez','');
+INSERT INTO t2 VALUES (952,232607,37,'infest','Microsoft','nouns','');
+INSERT INTO t2 VALUES (953,232608,37,'compartment','fibrosities','distracting','');
+INSERT INTO t2 VALUES (954,232609,37,'minting','Baltimorean','mutton','');
+INSERT INTO t2 VALUES (955,236104,37,'ducks','equestrian','bridgeable','A');
+INSERT INTO t2 VALUES (956,236105,37,'roped','Goodrich','stickers','A');
+INSERT INTO t2 VALUES (957,236106,37,'waltz','apish','transcontinental','A');
+INSERT INTO t2 VALUES (958,236107,37,'Lillian','Adlerian','amateurish','');
+INSERT INTO t2 VALUES (959,236108,37,'repressions','Tropez','Gandhian','');
+INSERT INTO t2 VALUES (960,236109,37,'chillingly','nouns','stratified','');
+INSERT INTO t2 VALUES (961,236110,37,'noncritical','distracting','chamberlains','');
+INSERT INTO t2 VALUES (962,236111,37,'lithograph','mutton','creditably','');
+INSERT INTO t2 VALUES (963,236112,37,'spongers','bridgeable','philosophic','');
+INSERT INTO t2 VALUES (964,236113,37,'parenthood','stickers','ores','');
+INSERT INTO t2 VALUES (965,238005,37,'posed','transcontinental','Carleton','');
+INSERT INTO t2 VALUES (966,238006,37,'instruments','amateurish','tape','A');
+INSERT INTO t2 VALUES (967,238007,37,'filial','Gandhian','afloat','A');
+INSERT INTO t2 VALUES (968,238008,37,'fixedly','stratified','goodness','A');
+INSERT INTO t2 VALUES (969,238009,37,'relives','chamberlains','welcoming','');
+INSERT INTO t2 VALUES (970,238010,37,'Pandora','creditably','Pinsky','FAS');
+INSERT INTO t2 VALUES (971,238011,37,'watering','philosophic','halting','');
+INSERT INTO t2 VALUES (972,238012,37,'ungrateful','ores','bibliography','');
+INSERT INTO t2 VALUES (973,238013,37,'secures','Carleton','decoding','');
+INSERT INTO t2 VALUES (974,240401,41,'chastisers','tape','variance','A');
+INSERT INTO t2 VALUES (975,240402,41,'icon','afloat','allowed','A');
+INSERT INTO t2 VALUES (976,240901,41,'reuniting','goodness','dire','A');
+INSERT INTO t2 VALUES (977,240902,41,'imagining','welcoming','dub','A');
+INSERT INTO t2 VALUES (978,241801,41,'abiding','Pinsky','poisoning','');
+INSERT INTO t2 VALUES (979,242101,41,'omnisciently','halting','Iraqis','A');
+INSERT INTO t2 VALUES (980,242102,41,'Britannic','bibliography','heaving','');
+INSERT INTO t2 VALUES (981,242201,41,'scholastics','decoding','population','A');
+INSERT INTO t2 VALUES (982,242202,41,'mechanics','variance','bomb','A');
+INSERT INTO t2 VALUES (983,242501,41,'humidly','allowed','Majorca','A');
+INSERT INTO t2 VALUES (984,242502,41,'masterpiece','dire','Gershwins','');
+INSERT INTO t2 VALUES (985,246201,41,'however','dub','explorers','');
+INSERT INTO t2 VALUES (986,246202,41,'Mendelian','poisoning','libretto','A');
+INSERT INTO t2 VALUES (987,246203,41,'jarred','Iraqis','occurred','');
+INSERT INTO t2 VALUES (988,246204,41,'scolds','heaving','Lagos','');
+INSERT INTO t2 VALUES (989,246205,41,'infatuate','population','rats','');
+INSERT INTO t2 VALUES (990,246301,41,'willed','bomb','bankruptcies','A');
+INSERT INTO t2 VALUES (991,246302,41,'joyfully','Majorca','crying','');
+INSERT INTO t2 VALUES (992,248001,41,'Microsoft','Gershwins','unexpected','');
+INSERT INTO t2 VALUES (993,248002,41,'fibrosities','explorers','accessed','A');
+INSERT INTO t2 VALUES (994,248003,41,'Baltimorean','libretto','colorful','A');
+INSERT INTO t2 VALUES (995,248004,41,'equestrian','occurred','versatility','A');
+INSERT INTO t2 VALUES (996,248005,41,'Goodrich','Lagos','cosy','');
+INSERT INTO t2 VALUES (997,248006,41,'apish','rats','Darius','A');
+INSERT INTO t2 VALUES (998,248007,41,'Adlerian','bankruptcies','mastering','A');
+INSERT INTO t2 VALUES (999,248008,41,'Tropez','crying','Asiaticizations','A');
+INSERT INTO t2 VALUES (1000,248009,41,'nouns','unexpected','offerers','A');
+INSERT INTO t2 VALUES (1001,248010,41,'distracting','accessed','uncles','A');
+INSERT INTO t2 VALUES (1002,248011,41,'mutton','colorful','sleepwalk','');
+INSERT INTO t2 VALUES (1003,248012,41,'bridgeable','versatility','Ernestine','');
+INSERT INTO t2 VALUES (1004,248013,41,'stickers','cosy','checksumming','');
+INSERT INTO t2 VALUES (1005,248014,41,'transcontinental','Darius','stopped','');
+INSERT INTO t2 VALUES (1006,248015,41,'amateurish','mastering','sicker','');
+INSERT INTO t2 VALUES (1007,248016,41,'Gandhian','Asiaticizations','Italianization','');
+INSERT INTO t2 VALUES (1008,248017,41,'stratified','offerers','alphabetic','');
+INSERT INTO t2 VALUES (1009,248018,41,'chamberlains','uncles','pharmaceutic','');
+INSERT INTO t2 VALUES (1010,248019,41,'creditably','sleepwalk','creator','');
+INSERT INTO t2 VALUES (1011,248020,41,'philosophic','Ernestine','chess','');
+INSERT INTO t2 VALUES (1012,248021,41,'ores','checksumming','charcoal','');
+INSERT INTO t2 VALUES (1013,248101,41,'Carleton','stopped','Epiphany','A');
+INSERT INTO t2 VALUES (1014,248102,41,'tape','sicker','bulldozes','A');
+INSERT INTO t2 VALUES (1015,248201,41,'afloat','Italianization','Pygmalion','A');
+INSERT INTO t2 VALUES (1016,248202,41,'goodness','alphabetic','caressing','A');
+INSERT INTO t2 VALUES (1017,248203,41,'welcoming','pharmaceutic','Palestine','A');
+INSERT INTO t2 VALUES (1018,248204,41,'Pinsky','creator','regimented','A');
+INSERT INTO t2 VALUES (1019,248205,41,'halting','chess','scars','A');
+INSERT INTO t2 VALUES (1020,248206,41,'bibliography','charcoal','realest','A');
+INSERT INTO t2 VALUES (1021,248207,41,'decoding','Epiphany','diffusing','A');
+INSERT INTO t2 VALUES (1022,248208,41,'variance','bulldozes','clubroom','A');
+INSERT INTO t2 VALUES (1023,248209,41,'allowed','Pygmalion','Blythe','A');
+INSERT INTO t2 VALUES (1024,248210,41,'dire','caressing','ahead','');
+INSERT INTO t2 VALUES (1025,248211,50,'dub','Palestine','reviver','');
+INSERT INTO t2 VALUES (1026,250501,34,'poisoning','regimented','retransmitting','A');
+INSERT INTO t2 VALUES (1027,250502,34,'Iraqis','scars','landslide','');
+INSERT INTO t2 VALUES (1028,250503,34,'heaving','realest','Eiffel','');
+INSERT INTO t2 VALUES (1029,250504,34,'population','diffusing','absentee','');
+INSERT INTO t2 VALUES (1030,250505,34,'bomb','clubroom','aye','');
+INSERT INTO t2 VALUES (1031,250601,34,'Majorca','Blythe','forked','A');
+INSERT INTO t2 VALUES (1032,250602,34,'Gershwins','ahead','Peruvianizes','');
+INSERT INTO t2 VALUES (1033,250603,34,'explorers','reviver','clerked','');
+INSERT INTO t2 VALUES (1034,250604,34,'libretto','retransmitting','tutor','');
+INSERT INTO t2 VALUES (1035,250605,34,'occurred','landslide','boulevard','');
+INSERT INTO t2 VALUES (1036,251001,34,'Lagos','Eiffel','shuttered','');
+INSERT INTO t2 VALUES (1037,251002,34,'rats','absentee','quotes','A');
+INSERT INTO t2 VALUES (1038,251003,34,'bankruptcies','aye','Caltech','');
+INSERT INTO t2 VALUES (1039,251004,34,'crying','forked','Mossberg','');
+INSERT INTO t2 VALUES (1040,251005,34,'unexpected','Peruvianizes','kept','');
+INSERT INTO t2 VALUES (1041,251301,34,'accessed','clerked','roundly','');
+INSERT INTO t2 VALUES (1042,251302,34,'colorful','tutor','features','A');
+INSERT INTO t2 VALUES (1043,251303,34,'versatility','boulevard','imaginable','A');
+INSERT INTO t2 VALUES (1044,251304,34,'cosy','shuttered','controller','');
+INSERT INTO t2 VALUES (1045,251305,34,'Darius','quotes','racial','');
+INSERT INTO t2 VALUES (1046,251401,34,'mastering','Caltech','uprisings','A');
+INSERT INTO t2 VALUES (1047,251402,34,'Asiaticizations','Mossberg','narrowed','A');
+INSERT INTO t2 VALUES (1048,251403,34,'offerers','kept','cannot','A');
+INSERT INTO t2 VALUES (1049,251404,34,'uncles','roundly','vest','');
+INSERT INTO t2 VALUES (1050,251405,34,'sleepwalk','features','famine','');
+INSERT INTO t2 VALUES (1051,251406,34,'Ernestine','imaginable','sugars','');
+INSERT INTO t2 VALUES (1052,251801,34,'checksumming','controller','exterminated','A');
+INSERT INTO t2 VALUES (1053,251802,34,'stopped','racial','belays','');
+INSERT INTO t2 VALUES (1054,252101,34,'sicker','uprisings','Hodges','A');
+INSERT INTO t2 VALUES (1055,252102,34,'Italianization','narrowed','translatable','');
+INSERT INTO t2 VALUES (1056,252301,34,'alphabetic','cannot','duality','A');
+INSERT INTO t2 VALUES (1057,252302,34,'pharmaceutic','vest','recording','A');
+INSERT INTO t2 VALUES (1058,252303,34,'creator','famine','rouses','A');
+INSERT INTO t2 VALUES (1059,252304,34,'chess','sugars','poison','');
+INSERT INTO t2 VALUES (1060,252305,34,'charcoal','exterminated','attitude','');
+INSERT INTO t2 VALUES (1061,252306,34,'Epiphany','belays','dusted','');
+INSERT INTO t2 VALUES (1062,252307,34,'bulldozes','Hodges','encompasses','');
+INSERT INTO t2 VALUES (1063,252308,34,'Pygmalion','translatable','presentation','');
+INSERT INTO t2 VALUES (1064,252309,34,'caressing','duality','Kantian','');
+INSERT INTO t2 VALUES (1065,256001,34,'Palestine','recording','imprecision','A');
+INSERT INTO t2 VALUES (1066,256002,34,'regimented','rouses','saving','');
+INSERT INTO t2 VALUES (1067,256003,34,'scars','poison','maternal','');
+INSERT INTO t2 VALUES (1068,256004,34,'realest','attitude','hewed','');
+INSERT INTO t2 VALUES (1069,256005,34,'diffusing','dusted','kerosene','');
+INSERT INTO t2 VALUES (1070,258001,34,'clubroom','encompasses','Cubans','');
+INSERT INTO t2 VALUES (1071,258002,34,'Blythe','presentation','photographers','');
+INSERT INTO t2 VALUES (1072,258003,34,'ahead','Kantian','nymph','A');
+INSERT INTO t2 VALUES (1073,258004,34,'reviver','imprecision','bedlam','A');
+INSERT INTO t2 VALUES (1074,258005,34,'retransmitting','saving','north','A');
+INSERT INTO t2 VALUES (1075,258006,34,'landslide','maternal','Schoenberg','A');
+INSERT INTO t2 VALUES (1076,258007,34,'Eiffel','hewed','botany','A');
+INSERT INTO t2 VALUES (1077,258008,34,'absentee','kerosene','curs','');
+INSERT INTO t2 VALUES (1078,258009,34,'aye','Cubans','solidification','');
+INSERT INTO t2 VALUES (1079,258010,34,'forked','photographers','inheritresses','');
+INSERT INTO t2 VALUES (1080,258011,34,'Peruvianizes','nymph','stiller','');
+INSERT INTO t2 VALUES (1081,258101,68,'clerked','bedlam','t1','A');
+INSERT INTO t2 VALUES (1082,258102,68,'tutor','north','suite','A');
+INSERT INTO t2 VALUES (1083,258103,34,'boulevard','Schoenberg','ransomer','');
+INSERT INTO t2 VALUES (1084,258104,68,'shuttered','botany','Willy','');
+INSERT INTO t2 VALUES (1085,258105,68,'quotes','curs','Rena','A');
+INSERT INTO t2 VALUES (1086,258106,68,'Caltech','solidification','Seattle','A');
+INSERT INTO t2 VALUES (1087,258107,68,'Mossberg','inheritresses','relaxes','A');
+INSERT INTO t2 VALUES (1088,258108,68,'kept','stiller','exclaim','');
+INSERT INTO t2 VALUES (1089,258109,68,'roundly','t1','implicated','A');
+INSERT INTO t2 VALUES (1090,258110,68,'features','suite','distinguish','');
+INSERT INTO t2 VALUES (1091,258111,68,'imaginable','ransomer','assayed','');
+INSERT INTO t2 VALUES (1092,258112,68,'controller','Willy','homeowner','');
+INSERT INTO t2 VALUES (1093,258113,68,'racial','Rena','and','');
+INSERT INTO t2 VALUES (1094,258201,34,'uprisings','Seattle','stealth','');
+INSERT INTO t2 VALUES (1095,258202,34,'narrowed','relaxes','coinciding','A');
+INSERT INTO t2 VALUES (1096,258203,34,'cannot','exclaim','founder','A');
+INSERT INTO t2 VALUES (1097,258204,34,'vest','implicated','environing','');
+INSERT INTO t2 VALUES (1098,258205,34,'famine','distinguish','jewelry','');
+INSERT INTO t2 VALUES (1099,258301,34,'sugars','assayed','lemons','A');
+INSERT INTO t2 VALUES (1100,258401,34,'exterminated','homeowner','brokenness','A');
+INSERT INTO t2 VALUES (1101,258402,34,'belays','and','bedpost','A');
+INSERT INTO t2 VALUES (1102,258403,34,'Hodges','stealth','assurers','A');
+INSERT INTO t2 VALUES (1103,258404,34,'translatable','coinciding','annoyers','');
+INSERT INTO t2 VALUES (1104,258405,34,'duality','founder','affixed','');
+INSERT INTO t2 VALUES (1105,258406,34,'recording','environing','warbling','');
+INSERT INTO t2 VALUES (1106,258407,34,'rouses','jewelry','seriously','');
+INSERT INTO t2 VALUES (1107,228123,37,'poison','lemons','boasted','');
+INSERT INTO t2 VALUES (1108,250606,34,'attitude','brokenness','Chantilly','');
+INSERT INTO t2 VALUES (1109,208405,37,'dusted','bedpost','Iranizes','');
+INSERT INTO t2 VALUES (1110,212101,37,'encompasses','assurers','violinist','');
+INSERT INTO t2 VALUES (1111,218206,37,'presentation','annoyers','extramarital','');
+INSERT INTO t2 VALUES (1112,150401,37,'Kantian','affixed','spates','');
+INSERT INTO t2 VALUES (1113,248212,41,'imprecision','warbling','cloakroom','');
+INSERT INTO t2 VALUES (1114,128026,00,'saving','seriously','gazer','');
+INSERT INTO t2 VALUES (1115,128024,00,'maternal','boasted','hand','');
+INSERT INTO t2 VALUES (1116,128027,00,'hewed','Chantilly','tucked','');
+INSERT INTO t2 VALUES (1117,128025,00,'kerosene','Iranizes','gems','');
+INSERT INTO t2 VALUES (1118,128109,00,'Cubans','violinist','clinker','');
+INSERT INTO t2 VALUES (1119,128705,00,'photographers','extramarital','refiner','');
+INSERT INTO t2 VALUES (1120,126303,00,'nymph','spates','callus','');
+INSERT INTO t2 VALUES (1121,128308,00,'bedlam','cloakroom','leopards','');
+INSERT INTO t2 VALUES (1122,128204,00,'north','gazer','comfortingly','');
+INSERT INTO t2 VALUES (1123,128205,00,'Schoenberg','hand','generically','');
+INSERT INTO t2 VALUES (1124,128206,00,'botany','tucked','getters','');
+INSERT INTO t2 VALUES (1125,128207,00,'curs','gems','sexually','');
+INSERT INTO t2 VALUES (1126,118205,00,'solidification','clinker','spear','');
+INSERT INTO t2 VALUES (1127,116801,00,'inheritresses','refiner','serums','');
+INSERT INTO t2 VALUES (1128,116803,00,'stiller','callus','Italianization','');
+INSERT INTO t2 VALUES (1129,116804,00,'t1','leopards','attendants','');
+INSERT INTO t2 VALUES (1130,116802,00,'suite','comfortingly','spies','');
+INSERT INTO t2 VALUES (1131,128605,00,'ransomer','generically','Anthony','');
+INSERT INTO t2 VALUES (1132,118308,00,'Willy','getters','planar','');
+INSERT INTO t2 VALUES (1133,113702,00,'Rena','sexually','cupped','');
+INSERT INTO t2 VALUES (1134,113703,00,'Seattle','spear','cleanser','');
+INSERT INTO t2 VALUES (1135,112103,00,'relaxes','serums','commuters','');
+INSERT INTO t2 VALUES (1136,118009,00,'exclaim','Italianization','honeysuckle','');
+INSERT INTO t2 VALUES (5136,1118009,00,'exclaim','Italianization','honeysuckle','');
+INSERT INTO t2 VALUES (1137,138011,00,'implicated','attendants','orphanage','');
+INSERT INTO t2 VALUES (1138,138010,00,'distinguish','spies','skies','');
+INSERT INTO t2 VALUES (1139,138012,00,'assayed','Anthony','crushers','');
+INSERT INTO t2 VALUES (1140,068304,00,'homeowner','planar','Puritan','');
+INSERT INTO t2 VALUES (1141,078009,00,'and','cupped','squeezer','');
+INSERT INTO t2 VALUES (1142,108013,00,'stealth','cleanser','bruises','');
+INSERT INTO t2 VALUES (1143,084004,00,'coinciding','commuters','bonfire','');
+INSERT INTO t2 VALUES (1144,083402,00,'founder','honeysuckle','Colombo','');
+INSERT INTO t2 VALUES (1145,084003,00,'environing','orphanage','nondecreasing','');
+INSERT INTO t2 VALUES (1146,088504,00,'jewelry','skies','innocents','');
+INSERT INTO t2 VALUES (1147,088005,00,'lemons','crushers','masked','');
+INSERT INTO t2 VALUES (1148,088007,00,'brokenness','Puritan','file','');
+INSERT INTO t2 VALUES (1149,088006,00,'bedpost','squeezer','brush','');
+INSERT INTO t2 VALUES (1150,148025,00,'assurers','bruises','mutilate','');
+INSERT INTO t2 VALUES (1151,148024,00,'annoyers','bonfire','mommy','');
+INSERT INTO t2 VALUES (1152,138305,00,'affixed','Colombo','bulkheads','');
+INSERT INTO t2 VALUES (1153,138306,00,'warbling','nondecreasing','undeclared','');
+INSERT INTO t2 VALUES (1154,152701,00,'seriously','innocents','displacements','');
+INSERT INTO t2 VALUES (1155,148505,00,'boasted','masked','nieces','');
+INSERT INTO t2 VALUES (1156,158003,00,'Chantilly','file','coeducation','');
+INSERT INTO t2 VALUES (1157,156201,00,'Iranizes','brush','brassy','');
+INSERT INTO t2 VALUES (1158,156202,00,'violinist','mutilate','authenticator','');
+INSERT INTO t2 VALUES (1159,158307,00,'extramarital','mommy','Washoe','');
+INSERT INTO t2 VALUES (1160,158402,00,'spates','bulkheads','penny','');
+INSERT INTO t2 VALUES (1161,158401,00,'cloakroom','undeclared','Flagler','');
+INSERT INTO t2 VALUES (1162,068013,00,'gazer','displacements','stoned','');
+INSERT INTO t2 VALUES (1163,068012,00,'hand','nieces','cranes','');
+INSERT INTO t2 VALUES (1164,068203,00,'tucked','coeducation','masterful','');
+INSERT INTO t2 VALUES (1165,088205,00,'gems','brassy','biracial','');
+INSERT INTO t2 VALUES (1166,068704,00,'clinker','authenticator','steamships','');
+INSERT INTO t2 VALUES (1167,068604,00,'refiner','Washoe','windmills','');
+INSERT INTO t2 VALUES (1168,158502,00,'callus','penny','exploit','');
+INSERT INTO t2 VALUES (1169,123103,00,'leopards','Flagler','riverfront','');
+INSERT INTO t2 VALUES (1170,148026,00,'comfortingly','stoned','sisterly','');
+INSERT INTO t2 VALUES (1171,123302,00,'generically','cranes','sharpshoot','');
+INSERT INTO t2 VALUES (1172,076503,00,'getters','masterful','mittens','');
+INSERT INTO t2 VALUES (1173,126304,00,'sexually','biracial','interdependency','');
+INSERT INTO t2 VALUES (1174,068306,00,'spear','steamships','policy','');
+INSERT INTO t2 VALUES (1175,143504,00,'serums','windmills','unleashing','');
+INSERT INTO t2 VALUES (1176,160201,00,'Italianization','exploit','pretenders','');
+INSERT INTO t2 VALUES (1177,148028,00,'attendants','riverfront','overstatements','');
+INSERT INTO t2 VALUES (1178,148027,00,'spies','sisterly','birthed','');
+INSERT INTO t2 VALUES (1179,143505,00,'Anthony','sharpshoot','opportunism','');
+INSERT INTO t2 VALUES (1180,108014,00,'planar','mittens','showroom','');
+INSERT INTO t2 VALUES (1181,076104,00,'cupped','interdependency','compromisingly','');
+INSERT INTO t2 VALUES (1182,078106,00,'cleanser','policy','Medicare','');
+INSERT INTO t2 VALUES (1183,126102,00,'commuters','unleashing','corresponds','');
+INSERT INTO t2 VALUES (1184,128029,00,'honeysuckle','pretenders','hardware','');
+INSERT INTO t2 VALUES (1185,128028,00,'orphanage','overstatements','implant','');
+INSERT INTO t2 VALUES (1186,018410,00,'skies','birthed','Alicia','');
+INSERT INTO t2 VALUES (1187,128110,00,'crushers','opportunism','requesting','');
+INSERT INTO t2 VALUES (1188,148506,00,'Puritan','showroom','produced','');
+INSERT INTO t2 VALUES (1189,123303,00,'squeezer','compromisingly','criticizes','');
+INSERT INTO t2 VALUES (1190,123304,00,'bruises','Medicare','backer','');
+INSERT INTO t2 VALUES (1191,068504,00,'bonfire','corresponds','positively','');
+INSERT INTO t2 VALUES (1192,068305,00,'Colombo','hardware','colicky','');
+INSERT INTO t2 VALUES (1193,000000,00,'nondecreasing','implant','thrillingly','');
+--enable_query_log
+
+#
+# Search with a key
+#
+
+select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%";
+select fld3 from t2 where fld3 like "%cultivation" ;
+
+#
+# Search with a key using sorting and limit the same time
+#
+
+select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3;
+select fld3,companynr from t2 where companynr = 58 order by fld3;
+
+select fld3 from t2 order by fld3 desc limit 10;
+select fld3 from t2 order by fld3 desc limit 5;
+select fld3 from t2 order by fld3 desc limit 5,5;
+
+#
+# Search with a key having a constant with each unique key.
+# The table is read directly with read-next on fld3
+#
+
+select t2.fld3 from t2 where fld3 = 'honeysuckle';
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_';
+select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_';
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%';
+select t2.fld3 from t2 where fld3 LIKE 'h%le';
+
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_';
+select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%';
+
+#
+# Test sorting with a used key (there is no need for sorting)
+#
+
+select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
+select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3;
+
+#
+# Search with a key with LIKE constant
+# If the like starts with a certain letter key will be used.
+#
+
+select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%';
+select fld3 from t2 where fld3 like "L%" and fld3 = "ok";
+select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly");
+select fld1,fld3 from t2 where fld1 like "25050%";
+select fld1,fld3 from t2 where fld1 like "25050_";
+
+#
+# Test for insert after select
+#
+INSERT INTO t2 VALUES (1,000001,00,'Omaha','teethe','neat','');
+INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W');
+INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring','');
+INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
+SELECT * FROM t2;
+drop table t1, t2;
diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test
index 99a75889431..73588a91aac 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -3,6 +3,7 @@
#
--disable_warnings
drop table if exists t1;
+drop table if exists t2;
--enable_warnings
SET SQL_WARNINGS=1;
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index 6823dd23b73..7ee7d18439d 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -822,3 +822,78 @@ alter table t1 modify a char(10) binary;
explain select a from t1;
select a from t1;
drop table t1;
+
+#
+# bug#2686 - index_merge select on BerkeleyDB table with varchar PK causes mysqld to crash
+#
+
+create table t1(
+ pk1 text not null, pk2 text not null, pk3 char(4),
+ key1 int, key2 int,
+ primary key(pk1(4), pk2(4), pk3), key(key1), key(key2)
+) engine=bdb;
+insert into t1 values (concat('aaa-', repeat('A', 4000)),
+ concat('eee-', repeat('e', 4000)), 'a++a', 1, 1);
+insert into t1 values (concat('bbb-', repeat('B', 4000)),
+ concat('ggg-', repeat('G', 4000)), 'b++b', 1, 1);
+select substring(pk1, 1, 4), substring(pk1, 4001),
+ substring(pk2, 1, 4), substring(pk2, 4001), pk3, key1, key2
+ from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+#
+# bug#2688 - Wrong index_merge query results for BDB table with variable length primary key
+#
+
+create table t1 (
+ pk1 varchar(8) not null default '',
+ pk2 varchar(4) not null default '',
+ key1 int(11) default null,
+ key2 int(11) default null,
+ primary key (pk1,pk2),
+ key key1 (key1),
+ key key2 (key2)) engine=bdb;
+insert into t1 values ('','empt',2,2), ('a','a--a',2,2),
+ ('bb','b--b',2,2), ('ccc','c--c',2,2), ('dddd','d--d',2,2);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+
+#
+# Bug #4000: problem with active cursor.
+#
+
+set autocommit=0;
+create table t1(b varchar(30)) engine=bdb;
+insert into t1 values ('one');
+commit;
+select b FROM t1 outer_table where
+exists (select 'two' from t1 where 'two' = outer_table.b);
+drop table t1;
+set autocommit=1;
+
+#
+# Bug #4089: subselect and open cursor.
+#
+
+create table t1(a int primary key, b varchar(30)) engine=bdb;
+insert into t1 values (1,'one'), (2,'two'), (3,'three'), (4,'four');
+create table t2 like t1;
+insert t2 select * from t1;
+select a from t1 where a in (select a from t2);
+delete from t2;
+insert into t2 (a, b)
+ select a, b from t1 where (a, b) in (select a, b from t1);
+select * from t2;
+drop table t1, t2;
+
+#
+# Bug #4304: TRUNCATE <table of type BDB> , wrong result
+#
+
+create table t1 (a int, b varchar(30), primary key(a)) engine = bdb;
+insert into t1 values (1,'one');
+commit;
+truncate t1;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/ctype_uca.test b/mysql-test/t/ctype_uca.test
new file mode 100644
index 00000000000..6ff1407247f
--- /dev/null
+++ b/mysql-test/t/ctype_uca.test
@@ -0,0 +1,181 @@
+-- source include/have_ucs2.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+#
+# Test Unicode collations.
+#
+
+set names utf8;
+create table t1 (c1 char(10) character set utf8 collate utf8_bin);
+
+#
+# Basic Latin
+#
+insert into t1 values ('A'),('a');
+insert into t1 values ('B'),('b');
+insert into t1 values ('C'),('c');
+insert into t1 values ('D'),('d');
+insert into t1 values ('E'),('e');
+insert into t1 values ('F'),('f');
+insert into t1 values ('G'),('g');
+insert into t1 values ('H'),('h');
+insert into t1 values ('I'),('i');
+insert into t1 values ('J'),('j');
+insert into t1 values ('K'),('k');
+insert into t1 values ('L'),('l');
+insert into t1 values ('M'),('m');
+insert into t1 values ('N'),('n');
+insert into t1 values ('O'),('o');
+insert into t1 values ('P'),('p');
+insert into t1 values ('Q'),('q');
+insert into t1 values ('R'),('r');
+insert into t1 values ('S'),('s');
+insert into t1 values ('T'),('t');
+insert into t1 values ('U'),('u');
+insert into t1 values ('V'),('v');
+insert into t1 values ('W'),('w');
+insert into t1 values ('X'),('x');
+insert into t1 values ('Y'),('y');
+insert into t1 values ('Z'),('z');
+
+#
+# Latin1 suppliment
+#
+insert into t1 values (_ucs2 0x00e0),(_ucs2 0x00c0);
+insert into t1 values (_ucs2 0x00e1),(_ucs2 0x00c1);
+insert into t1 values (_ucs2 0x00e2),(_ucs2 0x00c2);
+insert into t1 values (_ucs2 0x00e3),(_ucs2 0x00c3);
+insert into t1 values (_ucs2 0x00e4),(_ucs2 0x00c4);
+insert into t1 values (_ucs2 0x00e5),(_ucs2 0x00c5);
+insert into t1 values (_ucs2 0x00e6),(_ucs2 0x00c6);
+insert into t1 values (_ucs2 0x00e7),(_ucs2 0x00c7);
+insert into t1 values (_ucs2 0x00e8),(_ucs2 0x00c8);
+insert into t1 values (_ucs2 0x00e9),(_ucs2 0x00c9);
+insert into t1 values (_ucs2 0x00ea),(_ucs2 0x00ca);
+insert into t1 values (_ucs2 0x00eb),(_ucs2 0x00cb);
+insert into t1 values (_ucs2 0x00ec),(_ucs2 0x00cc);
+insert into t1 values (_ucs2 0x00ed),(_ucs2 0x00cd);
+insert into t1 values (_ucs2 0x00ee),(_ucs2 0x00ce);
+insert into t1 values (_ucs2 0x00ef),(_ucs2 0x00cf);
+
+insert into t1 values (_ucs2 0x00f0),(_ucs2 0x00d0);
+insert into t1 values (_ucs2 0x00f1),(_ucs2 0x00d1);
+insert into t1 values (_ucs2 0x00f2),(_ucs2 0x00d2);
+insert into t1 values (_ucs2 0x00f3),(_ucs2 0x00d3);
+insert into t1 values (_ucs2 0x00f4),(_ucs2 0x00d4);
+insert into t1 values (_ucs2 0x00f5),(_ucs2 0x00d5);
+insert into t1 values (_ucs2 0x00f6),(_ucs2 0x00d6);
+insert into t1 values (_ucs2 0x00f7),(_ucs2 0x00d7);
+insert into t1 values (_ucs2 0x00f8),(_ucs2 0x00d8);
+insert into t1 values (_ucs2 0x00f9),(_ucs2 0x00d9);
+insert into t1 values (_ucs2 0x00fa),(_ucs2 0x00da);
+insert into t1 values (_ucs2 0x00fb),(_ucs2 0x00db);
+insert into t1 values (_ucs2 0x00fc),(_ucs2 0x00dc);
+insert into t1 values (_ucs2 0x00fd),(_ucs2 0x00dd);
+insert into t1 values (_ucs2 0x00fe),(_ucs2 0x00de);
+insert into t1 values (_ucs2 0x00ff),(_ucs2 0x00df);
+
+#
+# Latin extended-A, 0100-017F
+#
+insert into t1 values (_ucs2 0x0100),(_ucs2 0x0101),(_ucs2 0x0102),(_ucs2 0x0103);
+insert into t1 values (_ucs2 0x0104),(_ucs2 0x0105),(_ucs2 0x0106),(_ucs2 0x0107);
+insert into t1 values (_ucs2 0x0108),(_ucs2 0x0109),(_ucs2 0x010a),(_ucs2 0x010b);
+insert into t1 values (_ucs2 0x010c),(_ucs2 0x010d),(_ucs2 0x010e),(_ucs2 0x010f);
+insert into t1 values (_ucs2 0x0110),(_ucs2 0x0111),(_ucs2 0x0112),(_ucs2 0x0113);
+insert into t1 values (_ucs2 0x0114),(_ucs2 0x0115),(_ucs2 0x0116),(_ucs2 0x0117);
+insert into t1 values (_ucs2 0x0118),(_ucs2 0x0119),(_ucs2 0x011a),(_ucs2 0x011b);
+insert into t1 values (_ucs2 0x011c),(_ucs2 0x011d),(_ucs2 0x011e),(_ucs2 0x011f);
+insert into t1 values (_ucs2 0x0120),(_ucs2 0x0121),(_ucs2 0x0122),(_ucs2 0x0123);
+insert into t1 values (_ucs2 0x0124),(_ucs2 0x0125),(_ucs2 0x0126),(_ucs2 0x0127);
+insert into t1 values (_ucs2 0x0128),(_ucs2 0x0129),(_ucs2 0x012a),(_ucs2 0x012b);
+insert into t1 values (_ucs2 0x012c),(_ucs2 0x012d),(_ucs2 0x012e),(_ucs2 0x012f);
+insert into t1 values (_ucs2 0x0130),(_ucs2 0x0131),(_ucs2 0x0132),(_ucs2 0x0133);
+insert into t1 values (_ucs2 0x0134),(_ucs2 0x0135),(_ucs2 0x0136),(_ucs2 0x0137);
+insert into t1 values (_ucs2 0x0138),(_ucs2 0x0139),(_ucs2 0x013a),(_ucs2 0x013b);
+insert into t1 values (_ucs2 0x013c),(_ucs2 0x013d),(_ucs2 0x013e),(_ucs2 0x013f);
+insert into t1 values (_ucs2 0x0140),(_ucs2 0x0141),(_ucs2 0x0142),(_ucs2 0x0143);
+insert into t1 values (_ucs2 0x0144),(_ucs2 0x0145),(_ucs2 0x0146),(_ucs2 0x0147);
+insert into t1 values (_ucs2 0x0148),(_ucs2 0x0149),(_ucs2 0x014a),(_ucs2 0x014b);
+insert into t1 values (_ucs2 0x014c),(_ucs2 0x014d),(_ucs2 0x014e),(_ucs2 0x014f);
+insert into t1 values (_ucs2 0x0150),(_ucs2 0x0151),(_ucs2 0x0152),(_ucs2 0x0153);
+insert into t1 values (_ucs2 0x0154),(_ucs2 0x0155),(_ucs2 0x0156),(_ucs2 0x0157);
+insert into t1 values (_ucs2 0x0158),(_ucs2 0x0159),(_ucs2 0x015a),(_ucs2 0x015b);
+insert into t1 values (_ucs2 0x015c),(_ucs2 0x015d),(_ucs2 0x015e),(_ucs2 0x015f);
+insert into t1 values (_ucs2 0x0160),(_ucs2 0x0161),(_ucs2 0x0162),(_ucs2 0x0163);
+insert into t1 values (_ucs2 0x0164),(_ucs2 0x0165),(_ucs2 0x0166),(_ucs2 0x0167);
+insert into t1 values (_ucs2 0x0168),(_ucs2 0x0169),(_ucs2 0x016a),(_ucs2 0x016b);
+insert into t1 values (_ucs2 0x016c),(_ucs2 0x016d),(_ucs2 0x016e),(_ucs2 0x016f);
+insert into t1 values (_ucs2 0x0170),(_ucs2 0x0171),(_ucs2 0x0172),(_ucs2 0x0173);
+insert into t1 values (_ucs2 0x0174),(_ucs2 0x0175),(_ucs2 0x0176),(_ucs2 0x0177);
+insert into t1 values (_ucs2 0x0178),(_ucs2 0x0179),(_ucs2 0x017a),(_ucs2 0x017b);
+insert into t1 values (_ucs2 0x017c),(_ucs2 0x017d),(_ucs2 0x017e),(_ucs2 0x017f);
+
+#
+# Latin extended-B, 0180-024F
+#
+insert into t1 values (_ucs2 0x0180),(_ucs2 0x0181),(_ucs2 0x0182),(_ucs2 0x0183);
+insert into t1 values (_ucs2 0x0184),(_ucs2 0x0185),(_ucs2 0x0186),(_ucs2 0x0187);
+insert into t1 values (_ucs2 0x0188),(_ucs2 0x0189),(_ucs2 0x018a),(_ucs2 0x018b);
+insert into t1 values (_ucs2 0x018c),(_ucs2 0x018d),(_ucs2 0x018e),(_ucs2 0x018f);
+insert into t1 values (_ucs2 0x0190),(_ucs2 0x0191),(_ucs2 0x0192),(_ucs2 0x0193);
+insert into t1 values (_ucs2 0x0194),(_ucs2 0x0195),(_ucs2 0x0196),(_ucs2 0x0197);
+insert into t1 values (_ucs2 0x0198),(_ucs2 0x0199),(_ucs2 0x019a),(_ucs2 0x019b);
+insert into t1 values (_ucs2 0x019c),(_ucs2 0x019d),(_ucs2 0x019e),(_ucs2 0x019f);
+insert into t1 values (_ucs2 0x01a0),(_ucs2 0x01a1),(_ucs2 0x01a2),(_ucs2 0x01a3);
+insert into t1 values (_ucs2 0x01a4),(_ucs2 0x01a5),(_ucs2 0x01a6),(_ucs2 0x01a7);
+insert into t1 values (_ucs2 0x01a8),(_ucs2 0x01a9),(_ucs2 0x01aa),(_ucs2 0x01ab);
+insert into t1 values (_ucs2 0x01ac),(_ucs2 0x01ad),(_ucs2 0x01ae),(_ucs2 0x01af);
+insert into t1 values (_ucs2 0x01b0),(_ucs2 0x01b1),(_ucs2 0x01b2),(_ucs2 0x01b3);
+insert into t1 values (_ucs2 0x01b4),(_ucs2 0x01b5),(_ucs2 0x01b6),(_ucs2 0x01b7);
+insert into t1 values (_ucs2 0x01b8),(_ucs2 0x01b9),(_ucs2 0x01ba),(_ucs2 0x01bb);
+insert into t1 values (_ucs2 0x01bc),(_ucs2 0x01bd),(_ucs2 0x01be),(_ucs2 0x01bf);
+insert into t1 values (_ucs2 0x01c0),(_ucs2 0x01c1),(_ucs2 0x01c2),(_ucs2 0x01c3);
+insert into t1 values (_ucs2 0x01c4),(_ucs2 0x01c5),(_ucs2 0x01c6),(_ucs2 0x01c7);
+insert into t1 values (_ucs2 0x01c8),(_ucs2 0x01c9),(_ucs2 0x01ca),(_ucs2 0x01cb);
+insert into t1 values (_ucs2 0x01cc),(_ucs2 0x01cd),(_ucs2 0x01ce),(_ucs2 0x01cf);
+insert into t1 values (_ucs2 0x01d0),(_ucs2 0x01d1),(_ucs2 0x01d2),(_ucs2 0x01d3);
+insert into t1 values (_ucs2 0x01d4),(_ucs2 0x01d5),(_ucs2 0x01d6),(_ucs2 0x01d7);
+insert into t1 values (_ucs2 0x01d8),(_ucs2 0x01d9),(_ucs2 0x01da),(_ucs2 0x01db);
+insert into t1 values (_ucs2 0x01dc),(_ucs2 0x01dd),(_ucs2 0x01de),(_ucs2 0x01df);
+insert into t1 values (_ucs2 0x01e0),(_ucs2 0x01e1),(_ucs2 0x01e2),(_ucs2 0x01e3);
+insert into t1 values (_ucs2 0x01e4),(_ucs2 0x01e5),(_ucs2 0x01e6),(_ucs2 0x01e7);
+insert into t1 values (_ucs2 0x01e8),(_ucs2 0x01e9),(_ucs2 0x01ea),(_ucs2 0x01eb);
+insert into t1 values (_ucs2 0x01ec),(_ucs2 0x01ed),(_ucs2 0x01ee),(_ucs2 0x01ef);
+insert into t1 values (_ucs2 0x01f0),(_ucs2 0x01f1),(_ucs2 0x01f2),(_ucs2 0x01f3);
+insert into t1 values (_ucs2 0x01f4),(_ucs2 0x01f5),(_ucs2 0x01f6),(_ucs2 0x01f7);
+insert into t1 values (_ucs2 0x01f8),(_ucs2 0x01f9),(_ucs2 0x01fa),(_ucs2 0x01fb);
+insert into t1 values (_ucs2 0x01fc),(_ucs2 0x01fd),(_ucs2 0x01fe),(_ucs2 0x01ff);
+
+
+insert into t1 values ('AA'),('Aa'),('aa'),('aA');
+insert into t1 values ('CH'),('Ch'),('ch'),('cH');
+insert into t1 values ('DZ'),('Dz'),('dz'),('dZ');
+insert into t1 values ('IJ'),('Ij'),('ij'),('iJ');
+insert into t1 values ('LJ'),('Lj'),('lj'),('lJ');
+insert into t1 values ('LL'),('Ll'),('ll'),('lL');
+insert into t1 values ('NJ'),('Nj'),('nj'),('nJ');
+insert into t1 values ('OE'),('Oe'),('oe'),('oE');
+insert into t1 values ('SS'),('Ss'),('ss'),('sS');
+insert into t1 values ('RR'),('Rr'),('rr'),('rR');
+
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_unicode_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_icelandic_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_latvian_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_romanian_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_slovenian_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_polish_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_estonian_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_spanish_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_swedish_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_turkish_ci;
+
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_czech_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_danish_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_lithuanian_ci;
+--select group_concat(c1 order by c1) from t1 group by c1 collate utf8_slovak_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_spanish2_ci;
+
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index 5b1a5923ad4..b8574fb7623 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -47,6 +47,16 @@ LPAD(_ucs2 X'0420',10,_ucs2 X'0421') l,
RPAD(_ucs2 X'0420',10,_ucs2 X'0421') r;
SHOW CREATE TABLE t1;
DROP TABLE t1;
+
+
+#
+# BUG3946
+#
+
+create table t2(f1 Char(30));
+insert into t2 values ("103000"), ("22720000"), ("3401200"), ("78000");
+select lpad(f1, 12, "-o-/") from t2;
+drop table t2;
######################################################
#
# Test of like
diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test
index 6281f2a4249..e5405d9f1bd 100644
--- a/mysql-test/t/ctype_ujis.test
+++ b/mysql-test/t/ctype_ujis.test
@@ -73,3 +73,13 @@ create index idx_c1 on t1(c1);
select c1 as 'using index' from t1 where c1 like cast(concat(0xA4A2, '%') as char character set ujis);
select c1 as 'no index' from t1 where c1 like cast(concat('%',0xA4A2, '%') as char character set ujis);
drop table t1;
+
+
+# Bug 2077
+CREATE TABLE t1 (
+ a char(1) NOT NULL default '',
+ b enum('¤¢','¤¤') default NULL
+) CHARACTER SET ujis;
+SHOW CREATE TABLE t1;
+SHOW COLUMNS FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 4e68efeffc3..6a504a8533a 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -141,3 +141,19 @@ select * from t1 where a = 'b';
select * from t1 where a = 'b' and a = 'b';
select * from t1 where a = 'b' and a != 'b';
drop table t1;
+
+#
+# Bug #3928 regexp [[:>:]] and UTF-8
+#
+set names utf8;
+
+# This should return TRUE
+select 'ваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+select 'ваÑÑ ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+select ' ваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+select ' ваÑÑ ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+
+# This should return FALSE
+select 'ваÑÑz' rlike '[[:<:]]ваÑÑ[[:>:]]';
+select 'zваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]';
+select 'zваÑÑz' rlike '[[:<:]]ваÑÑ[[:>:]]';
diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test
index e370b545eff..56c8ce77627 100644
--- a/mysql-test/t/delete.test
+++ b/mysql-test/t/delete.test
@@ -98,3 +98,14 @@ select * from t11;
delete ignore from t11 where t11.b <> (select b from t2 where t11.a < t2.a);
select * from t11;
drop table t11, t12, t2;
+
+#
+# Bug #4198: deletion and KEYREAD
+#
+
+create table t1 (a int, b int, unique key (a), key (b));
+insert into t1 values (3, 3), (7, 7);
+delete t1 from t1 where a = 3;
+check table t1;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/flush_table.test b/mysql-test/t/flush_table.test
index 4ddcd53d5c8..8bee94cf21f 100644
--- a/mysql-test/t/flush_table.test
+++ b/mysql-test/t/flush_table.test
@@ -4,10 +4,55 @@
# Test of flush table
#
-#drop table if exists t1;
-#create table t1 (a int not null auto_increment primary key);
-#insert into t1 values(0);
-#lock table t1 read;
-#flush table t1;
-#check table t1;
-#drop table t1;
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+create table t1 (a int not null auto_increment primary key);
+insert into t1 values(0);
+lock table t1 read;
+flush table t1;
+check table t1;
+drop table t1;
+
+#
+# In the following test FLUSH TABLES produces a deadlock
+# (hang forever) if the fix for bug#3565 is missing.
+#
+create table t1(table_id char(20) primary key);
+create table t2(table_id char(20) primary key);
+insert into t1 values ('test.t1');
+insert into t1 values ('');
+insert into t2 values ('test.t2');
+insert into t2 values ('');
+handler t1 open as a1;
+handler t1 open as a2;
+handler t2 open;
+handler a1 read first limit 9;
+handler a2 read first limit 9;
+handler t2 read first limit 9;
+flush tables;
+--error 1109;
+handler a1 read first limit 9;
+--error 1109;
+handler a2 read first limit 9;
+--error 1109;
+handler t2 read first limit 9;
+#
+handler t1 open as a1;
+handler t1 open as a2;
+handler t2 open;
+handler a1 read first limit 9;
+handler a2 read first limit 9;
+handler t2 read first limit 9;
+flush table t1;
+--error 1109;
+handler a1 read first limit 9;
+--error 1109;
+handler a2 read first limit 9;
+handler t2 read first limit 9;
+flush table t2;
+--error 1109;
+handler t2 close;
+drop table t1;
+drop table t2;
+
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index ac88125965a..66df5b1cb92 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -69,10 +69,10 @@ select * from t1 where MATCH a,b AGAINST ('+(support collections) +foobar*' IN B
select * from t1 where MATCH a,b AGAINST ('+(+(support collections)) +foobar*' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE);
-# bug#2708 crash
+# bug#2708, bug#3870 crash
select * from t1 where MATCH a,b AGAINST('"space model' IN BOOLEAN MODE);
-
+
# boolean w/o index:
select * from t1 where MATCH a AGAINST ("search" IN BOOLEAN MODE);
@@ -279,3 +279,12 @@ SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück');
SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrueck');
DROP TABLE t1;
+#
+# bug#3964
+#
+
+CREATE TABLE t1 (s varchar(255), FULLTEXT (s)) DEFAULT CHARSET=utf8;
+insert into t1 (s) values ('pära para para'),('para para para');
+select * from t1 where match(s) against('para' in boolean mode);
+select * from t1 where match(s) against('par*' in boolean mode);
+DROP TABLE t1;
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index aede2220466..62343fa2af8 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -61,7 +61,7 @@ select grp,group_concat(c order by c) from t1 group by grp;
# Test warnings
-set group_concat_max_len = 5;
+set group_concat_max_len = 4;
select grp,group_concat(c) from t1 group by grp;
show warnings;
set group_concat_max_len = 1024;
@@ -83,7 +83,7 @@ insert into t1 values (4,'www.host.com'), (5,'www.google.com'),(5,'www.help.com'
insert into t2 values (1,4), (5,4), (5,5);
# Make this order independent
--replace_result www.help.com X www.host.com X www.google.com X
-select REQ_ID, Group_Concat(URL) as URL from t1, t2 where
+select REQ_ID, Group_Concat(URL) as URL from t1, t2 where
t2.URL_ID = t1.URL_ID group by REQ_ID;
# check min/max function
--replace_result www.help.com X www.host.com X www.google.com X
@@ -132,7 +132,7 @@ drop table t1, t2;
CREATE TABLE t1 (id1 tinyint(4) NOT NULL, id2 tinyint(4) NOT NULL);
INSERT INTO t1 VALUES (1, 1),(1, 2),(1, 3),(1, 4),(1, 5),(2, 1),(2, 2),(2, 3);
-CREATE TABLE t2 (id1 tinyint(4) NOT NULL);
+CREATE TABLE t2 (id1 tinyint(4) NOT NULL);
INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 AND t1.id1=1 GROUP BY t1.id1;
SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
@@ -163,7 +163,7 @@ drop table t1;
# Test with subqueries (Bug #3319)
#
-create table t1 (a int, c int);
+create table t1 (a int, c int);
insert into t1 values (1, 2), (2, 3), (2, 4), (3, 5);
create table t2 (a int, c int);
insert into t2 values (1, 5), (2, 4), (3, 3), (3,3);
@@ -189,3 +189,15 @@ INSERT INTO t1 VALUES (1), (2);
INSERT INTO t2 VALUES (1), (2);
SELECT GROUP_CONCAT(t1.a*t2.a ORDER BY t2.a) FROM t1, t2 GROUP BY t1.a;
DROP TABLE t1, t2;
+
+#
+# Bug #4035: group_concat() and HAVING
+#
+
+CREATE TABLE t1 (a char(4));
+INSERT INTO t1 VALUES ('John'), ('Anna'), ('Bill');
+SELECT GROUP_CONCAT(a SEPARATOR '||') AS names FROM t1
+ HAVING names LIKE '%An%';
+SELECT GROUP_CONCAT(a SEPARATOR '###') AS names FROM t1
+ HAVING LEFT(names, 1) ='J';
+DROP TABLE t1;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 7966a2262f4..74f4c1bad44 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -396,3 +396,25 @@ create table t1 (a int);
select variance(2) from t1;
select stddev(2) from t1;
drop table t1;
+
+
+#
+# cleunup() of optimized away count(*) and max/min
+#
+create table t1 (a int);
+insert into t1 values (1),(2);
+prepare stmt1 from 'SELECT COUNT(*) FROM t1';
+execute stmt1;
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+drop table t1;
+
+create table t1 (a int, primary key(a));
+insert into t1 values (1),(2);
+prepare stmt1 from 'SELECT max(a) FROM t1';
+execute stmt1;
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+drop table t1;
diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test
index 36c3a38d2fe..7048d188604 100644
--- a/mysql-test/t/func_if.test
+++ b/mysql-test/t/func_if.test
@@ -47,3 +47,12 @@ create table t1 (x int, y int);
insert into t1 values (0,6),(10,16),(20,26),(30,10),(40,46),(50,56);
select min(if(y -x > 5,y,NULL)), max(if(y - x > 5,y,NULL)) from t1;
drop table t1;
+
+#
+# BUG#3987
+#
+create table t1 (a int);
+insert t1 values (1),(2);
+select if(1>2,a,avg(a)) from t1;
+drop table t1;
+
diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test
index 91f55af48cc..ad83202afa0 100644
--- a/mysql-test/t/func_like.test
+++ b/mysql-test/t/func_like.test
@@ -25,14 +25,23 @@ select * from t1 where a like "%abc\d%";
drop table t1;
+create table t1 (a varchar(10), key(a));
+
#
# Bug #2231
#
-
-create table t1 (a varchar(10), key(a));
insert into t1 values ('a'), ('a\\b');
select * from t1 where a like 'a\\%' escape '#';
select * from t1 where a like 'a\\%' escape '#' and a like 'a\\\\b';
+
+#
+# Bug #4200: Prepared statement parameter as argument to ESCAPE
+#
+prepare stmt1 from 'select * from t1 where a like \'a\\%\' escape ?';
+set @esc='#';
+execute stmt1 using @esc;
+deallocate prepare stmt1;
+
drop table t1;
#
diff --git a/mysql-test/t/func_regexp.test b/mysql-test/t/func_regexp.test
index edfa9afcfa6..1a771d466fa 100644
--- a/mysql-test/t/func_regexp.test
+++ b/mysql-test/t/func_regexp.test
@@ -60,3 +60,16 @@ select _koi8r 0xF7 regexp _koi8r '[[:alpha:]]';
select _latin1'a' regexp _latin1'A' collate latin1_general_ci;
select _latin1'a' regexp _latin1'A' collate latin1_bin;
+
+#
+# regexp cleanup()
+#
+create table t1 (a varchar(40));
+insert into t1 values ('C1'),('C2'),('R1'),('C3'),('R2'),('R3');
+prepare stmt1 from 'select a from t1 where a rlike ? order by a';
+set @a="^C.*";
+execute stmt1 using @a;
+set @a="^R.*";
+execute stmt1 using @a;
+deallocate prepare stmt1;
+drop table t1;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index c138b848491..cc8d8a88437 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -304,6 +304,7 @@ select collation(soundex(_latin2'ab')), coercibility(soundex(_latin2'ab'));
select collation(substring(_latin2'ab',1)), coercibility(substring(_latin2'ab',1));
select collation(insert(_latin2'abcd',2,3,_latin2'ef')), coercibility(insert(_latin2'abcd',2,3,_latin2'ef'));
select collation(replace(_latin2'abcd',_latin2'b',_latin2'B')), coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B'));
+select collation(encode('abcd','ab')), coercibility(encode('abcd','ab'));
create table t1
select
@@ -336,7 +337,8 @@ select
soundex(_latin2'ab'),
substring(_latin2'ab',1),
insert(_latin2'abcd',2,3,_latin2'ef'),
- replace(_latin2'abcd',_latin2'b',_latin2'B')
+ replace(_latin2'abcd',_latin2'b',_latin2'B'),
+ encode('abcd','ab')
;
show create table t1;
drop table t1;
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 69306f69f40..0ca3d86818e 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -255,7 +255,6 @@ select date_add(date,INTERVAL "1 1" YEAR_MONTH) from t1;
select date_add(date,INTERVAL "1:1:1" HOUR_SECOND) from t1;
select date_add(date,INTERVAL "1 1:1" DAY_MINUTE) from t1;
select date_add(date,INTERVAL "1 1:1:1" DAY_SECOND) from t1;
-
select date_add(date,INTERVAL "1" WEEK) from t1;
select date_add(date,INTERVAL "1" QUARTER) from t1;
select timestampadd(MINUTE, 1, date) from t1;
@@ -280,7 +279,6 @@ select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1,
timestampdiff(SQL_TSI_DAY, '1996-02-01', '1996-03-01') as a3,
timestampdiff(SQL_TSI_DAY, '2000-02-01', '2000-03-01') as a4;
-# The following is not as one would expect...
select date_add(time,INTERVAL 1 SECOND) from t1;
drop table t1;
diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test
index 8e91e5891b8..817249b7e4c 100644
--- a/mysql-test/t/gis-rtree.test
+++ b/mysql-test/t/gis-rtree.test
@@ -1,3 +1,5 @@
+-- source include/have_geometry.inc
+
#
# test of rtree (using with spatial data)
#
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index ea460d5f7b0..590007caba1 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -1,3 +1,5 @@
+-- source include/have_geometry.inc
+
#
# Spatial objects
#
diff --git a/mysql-test/t/innodb_cache.test b/mysql-test/t/innodb_cache.test
index 8568fce7d97..101dde37f89 100644
--- a/mysql-test/t/innodb_cache.test
+++ b/mysql-test/t/innodb_cache.test
@@ -52,10 +52,31 @@ show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
commit;
show status like "Qcache_queries_in_cache";
+drop table t3,t2,t1;
-drop table if exists t1;
CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) ENGINE=InnoDB;
select count(*) from t1;
insert into t1 (id) values (0);
select count(*) from t1;
drop table t1;
+
+#
+# one statement roll back inside transation
+#
+set GLOBAL query_cache_size=1355776;
+CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY a (a)) ENGINE=innodb;
+CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY b (b)) ENGINE=innodb;
+CREATE TABLE t3 ( id int(10) NOT NULL auto_increment, t1_id int(10) NOT NULL default '0', t2_id int(10) NOT NULL default '0', state int(11) default NULL, PRIMARY KEY (id), UNIQUE KEY t1_id (t1_id,t2_id), KEY t2_id (t2_id,t1_id), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`t2_id`) REFERENCES `t2` (`id`)) ENGINE=innodb;
+INSERT INTO t1 VALUES (1,'me');
+INSERT INTO t2 VALUES (1,'you');
+INSERT INTO t3 VALUES (2,1,1,2);
+delete from t3 where t1_id = 1 and t2_id = 1;
+select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc;
+begin;
+insert into t3 VALUES ( NULL, 1, 1, 2 );
+-- error 1062
+insert into t3 VALUES ( NULL, 1, 1, 2 );
+commit;
+select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc;
+drop table t3,t2,t1;
+
diff --git a/mysql-test/t/lowercase_table2.test b/mysql-test/t/lowercase_table2.test
index 5c479391916..a4eaeac4ef4 100644
--- a/mysql-test/t/lowercase_table2.test
+++ b/mysql-test/t/lowercase_table2.test
@@ -89,3 +89,14 @@ SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHER
SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
drop table T1;
+
+#
+# Test name conversion with ALTER TABLE / CREATE INDEX (Bug #3109)
+#
+
+create table T1 (A int);
+alter table T1 add index (A);
+show tables like 'T1%';
+alter table t1 add index (A);
+show tables like 't1%';
+drop table t1;
diff --git a/mysql-test/t/lowercase_table3.test b/mysql-test/t/lowercase_table3.test
index 1753772ecc3..a394cde7237 100644
--- a/mysql-test/t/lowercase_table3.test
+++ b/mysql-test/t/lowercase_table3.test
@@ -9,7 +9,7 @@
disable_query_log;
show variables like "lower_case_%";
--require r/true.require
-select @@version_compile_os NOT IN ("NT","WIN2000","Win95/Win98","XP") as "TRUE";
+select convert(@@version_compile_os using latin1) NOT IN ("NT","WIN2000","Win95/Win98","XP") as "TRUE";
enable_query_log;
--disable_warnings
@@ -31,7 +31,7 @@ flush tables;
# storing things in lower case.
#
-CREATE TABLE t1 (a int) type=INNODB;
+CREATE TABLE t1 (a int) ENGINE=INNODB;
--error 1016
SELECT * from T1;
drop table t1;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 1f61e200613..cf55c26fb69 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -190,6 +190,14 @@ select * from t5 order by a,b;
select * from t6 order by a,b;
insert into t1 values (99,NULL);
select * from t4 where a+0 > 90;
+# bug#4008 - cannot determine a unique key that caused "dupl. key error"
+--error 1062
+insert t5 values (1,1);
+--error 1062
+insert t6 values (2,1);
+insert t5 values (1,1) on duplicate key update b=b+10;
+insert t6 values (2,1) on duplicate key update b=b+20;
+select * from t5 where a < 3;
drop table t6, t5, t4, t3, t2, t1;
CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) ENGINE=MyISAM;
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 68d8af87e45..a3b733c3c03 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -404,6 +404,7 @@ update t1, t2 set t1.b=1 where t1.a=t2.a;
update t1, t2 set t1.b=(select t3.b from t3 where t1.a=t3.a) where t1.a=t2.a;
connection root;
revoke all privileges on mysqltest.t1 from mysqltest_1@localhost;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1';
drop database mysqltest;
diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
index d15dac8c0bc..a8bbe60d58e 100644
--- a/mysql-test/t/mysqlbinlog.test
+++ b/mysql-test/t/mysqlbinlog.test
@@ -1,11 +1,12 @@
# We are using .opt file since we need small binlog size
---disable_warnings
-drop table if exists t1,t2;
---enable_warnings
# we need this for getting fixed timestamps inside of this test
set timestamp=1000000000;
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
create table t1 (word varchar(20));
create table t2 (id int auto_increment not null primary key);
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index bcfe81dc95f..89b3739f955 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -73,11 +73,12 @@ DROP TABLE t1;
#
# Bug #1994
+# Bug #4261
#
CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r;
-INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5');
---exec $MYSQL_DUMP --skip-comments test t1
+INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL);
+--exec $MYSQL_DUMP --skip-comments --skip-extended-insert test t1
DROP TABLE t1;
#
diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test
new file mode 100644
index 00000000000..f95aa82b7cc
--- /dev/null
+++ b/mysql-test/t/ndb_alter_table.test
@@ -0,0 +1,41 @@
+-- source include/have_ndb.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+#
+# Basic test to show that the ALTER TABLE
+# is working
+#
+CREATE TABLE t1 (
+ a INT NOT NULL,
+ b INT NOT NULL
+) ENGINE=ndbcluster;
+
+INSERT INTO t1 VALUES (9410,9412);
+
+ALTER TABLE t1 ADD COLUMN c int not null;
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+#
+# More advanced test
+#
+create table t1 (
+col1 int not null auto_increment primary key,
+col2 varchar(30) not null,
+col3 varchar (20) not null,
+col4 varchar(4) not null,
+col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null,
+col6 int not null, to_be_deleted int);
+insert into t1 values (2,4,3,5,"PENDING",1,7);
+alter table t1
+add column col4_5 varchar(20) not null after col4,
+add column col7 varchar(30) not null after col5,
+add column col8 datetime not null, drop column to_be_deleted,
+change column col2 fourth varchar(30) not null after col3,
+modify column col6 int not null first;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test
new file mode 100644
index 00000000000..d04599f223e
--- /dev/null
+++ b/mysql-test/t/ndb_autodiscover.test
@@ -0,0 +1,267 @@
+-- source include/have_ndb.inc
+
+--disable_warnings
+drop table if exists t1,t2,t3,t4,t5,t6,t9;
+--enable_warnings
+
+################################################
+# Test that a table that does not exist as a
+# frm file on disk can be "discovered" from a
+# connected NDB Cluster
+#
+
+flush status;
+
+#
+# Test discover + SELECT
+#
+
+create table t1(
+ id int not null primary key,
+ name char(20)
+) engine=ndb;
+
+insert into t1 values(1, "Autodiscover");
+flush tables;
+system rm var/master-data/test/t1.frm ;
+select * from t1;
+show status like 'handler_discover%';
+
+#
+# Test discover + INSERT
+#
+
+flush tables;
+system rm var/master-data/test/t1.frm ;
+insert into t1 values (2, "Auto 2");
+show status like 'handler_discover%';
+insert into t1 values (3, "Discover 3");
+show status like 'handler_discover%';
+flush tables;
+system rm var/master-data/test/t1.frm ;
+select * from t1 order by id;
+show status like 'handler_discover%';
+
+#
+# Test discover + UPDATE
+#
+
+flush tables;
+system rm var/master-data/test/t1.frm ;
+update t1 set name="Autodiscover" where id = 2;
+show status like 'handler_discover%';
+select * from t1 order by name;
+show status like 'handler_discover%';
+
+#
+# Test discover + DELETE
+#
+
+flush tables;
+system rm var/master-data/test/t1.frm ;
+delete from t1 where id = 3;
+select * from t1 order by id;
+show status like 'handler_discover%';
+
+drop table t1;
+
+
+
+######################################################
+# Test that a table that is outdated on disk
+# can be "discovered" from a connected NDB Cluster
+#
+
+flush status;
+
+create table t2(
+ id int not null primary key,
+ name char(22)
+) engine=ndb;
+insert into t2 values (1, "Discoverer");
+select * from t2;
+show status like 'handler_discover%';
+flush tables;
+
+# Modify the frm file on disk
+system echo "blaj" >> var/master-data/test/t2.frm ;
+select * from t2;
+
+show status like 'handler_discover%';
+
+drop table t2;
+
+
+##################################################
+# Test that a table that already exists in NDB
+# is only discovered if CREATE TABLE IF NOT EXISTS
+# is used
+#
+
+flush status;
+
+create table t3(
+ id int not null primary key,
+ name char(255)
+) engine=ndb;
+insert into t3 values (1, "Explorer");
+select * from t3;
+show status like 'handler_discover%';
+flush tables;
+
+# Remove the frm file from disk
+system rm var/master-data/test/t3.frm ;
+
+--error 1050
+create table t3(
+ id int not null primary key,
+ name char(20), a int, b float, c char(24)
+) engine=ndb;
+
+# The table shall not have been discovered since
+# IF NOT EXISTS wasn't specified
+
+show status like 'handler_discover%';
+SHOW TABLES FROM test;
+
+# now it should be discovered
+create table IF NOT EXISTS t3(
+ id int not null primary key,
+ id2 int not null,
+ name char(20)
+) engine=ndb;
+
+# NOTE! the table called t3 have now been updated to
+# use the same frm as in NDB, thus it's not certain that
+# the table schema is the same as was stated in the
+# CREATE TABLE statement above
+
+show status like 'handler_discover%';
+
+SHOW CREATE TABLE t3;
+
+select * from t3;
+show status like 'handler_discover%';
+
+drop table t3;
+
+#######################################################
+# Test that a table that already exists as frm file
+# but not in NDB can be deleted from disk.
+#
+
+# Manual test
+#flush status;
+#
+#create table t4(
+# id int not null primary key,
+# name char(27)
+#) engine=ndb;
+#insert into t4 values (1, "Automatic");
+#select * from t4;
+#
+# Remove the table from NDB
+#system drop_tab -c "$NDB_CONNECTSTRING2" -d test t4 > /dev/null ;
+#system drop_tab -c "host=localhost:2200;nodeid=5" -d test t4 > /dev/null ;
+#
+#--error 1296
+#select * from t4;
+#
+#flush table t4;
+#--error 1016
+#select * from t4;
+#
+#show status like 'handler_discover%';
+#drop table t4;
+#flush tables;
+#show tables;
+#--error 1146
+#select * from t4;
+
+
+#########################################################
+# Test that a table that has been changed in NDB
+# since it's been opened will be refreshed and discovered
+# again
+#
+
+flush status;
+
+show status like 'handler_discover%';
+
+create table t5(
+ id int not null primary key,
+ name char(200)
+) engine=ndb;
+insert into t5 values (1, "Magnus");
+select * from t5;
+
+ALTER TABLE t5 ADD COLUMN adress char(255) FIRST;
+
+select * from t5;
+
+insert into t5 values
+ ("Adress for record 2", 2, "Carl-Gustav"),
+ ("Adress for record 3", 3, "Karl-Emil");
+update t5 set name="Bertil" where id = 2;
+select * from t5 order by id;
+
+show status like 'handler_discover%';
+
+drop table t5;
+
+
+################################################################
+# Test that a table that has been changed with ALTER TABLE
+# can be used from the same thread
+#
+
+flush status;
+
+show status like 'handler_discover%';
+
+create table t6(
+ id int not null primary key,
+ name char(20)
+) engine=ndb;
+insert into t6 values (1, "Magnus");
+select * from t6;
+
+ALTER TABLE t6 ADD COLUMN adress char(255) FIRST;
+
+select * from t6;
+insert into t6 values
+ ("Adress for record 2", 2, "Carl-Gustav"),
+ ("Adress for record 3", 3, "Karl-Emil");
+update t6 set name="Bertil" where id = 2;
+select * from t6 order by id;
+
+show status like 'handler_discover%';
+
+drop table t6;
+
+######################################################
+# Simple test to show use of discover on startup
+# Note! This should always be the last step in this
+# file, the table t9 will be used and dropped
+# by ndb_autodiscover2
+#
+
+CREATE TABLE t9 (
+ a int NOT NULL PRIMARY KEY,
+ b int
+) engine=ndb;
+
+insert t9 values(1, 2), (2,3), (3, 4), (4, 5);
+
+#Don't drop the table, instead remove the frm file
+system rm var/master-data/test/t9.frm ;
+
+# Now leave test case, when ndb_autodiscover2 will run, this
+# MySQL Server will have been restarted because it has a
+# ndb_autodiscover2-master.opt file. And thus the table should
+# have been discovered by the "discover on startup" function.
+
+#TODO
+#SLECT * FROM t1, t2, t4;
+#handler discover 3;
diff --git a/mysql-test/t/ndb_autodiscover2-master.opt b/mysql-test/t/ndb_autodiscover2-master.opt
new file mode 100644
index 00000000000..e0d075c3fbd
--- /dev/null
+++ b/mysql-test/t/ndb_autodiscover2-master.opt
@@ -0,0 +1 @@
+--skip-external-locking
diff --git a/mysql-test/t/ndb_autodiscover2.test b/mysql-test/t/ndb_autodiscover2.test
new file mode 100644
index 00000000000..297795d909e
--- /dev/null
+++ b/mysql-test/t/ndb_autodiscover2.test
@@ -0,0 +1,13 @@
+-- source include/have_ndb.inc
+
+#
+# Simple test to show use of discover on startup
+# The previous step has simply removed the frm file
+# from disk, but left the table in NDB
+#
+select * from t9 order by a;
+
+# handler_discover should be zero
+show status like 'handler_discover%';
+
+drop table t9;
diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test
index d03abc34633..271357ed561 100644
--- a/mysql-test/t/ndb_basic.test
+++ b/mysql-test/t/ndb_basic.test
@@ -1,7 +1,7 @@
-- source include/have_ndb.inc
--disable_warnings
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7;
--enable_warnings
#
@@ -23,6 +23,7 @@ SELECT pk1 FROM t1;
SELECT * FROM t1;
SELECT t1.* FROM t1;
+# Update on record by primary key
UPDATE t1 SET attr1=1 WHERE pk1=9410;
SELECT * FROM t1;
@@ -35,13 +36,23 @@ SELECT * FROM t1;
DELETE FROM t1;
SELECT * FROM t1;
-# Delete the record by specifying pk
-INSERT INTO t1 VALUES (9410,9412);
+# Insert more records and update them all at once
+INSERT INTO t1 VALUES (9410,9412), (9411, 9413), (9408, 8765),
+(7,8), (8,9), (9,10), (10,11), (11,12), (12,13), (13,14);
+UPDATE t1 SET attr1 = 9999;
+SELECT * FROM t1 ORDER BY pk1;
+
+UPDATE t1 SET attr1 = 9998 WHERE pk1 < 1000;
+SELECT * FROM t1 ORDER BY pk1;
+
+UPDATE t1 SET attr1 = 9997 WHERE attr1 = 9999;
+SELECT * FROM t1 ORDER BY pk1;
+
+# Delete one record by specifying pk
DELETE FROM t1 WHERE pk1 = 9410;
-SELECT * FROM t1;
+SELECT * FROM t1 ORDER BY pk1;
-# Insert three records and delete the
-INSERT INTO t1 VALUES (9410,9412), (9411, 9413), (9408, 8765);
+# Delete all from table
DELETE FROM t1;
SELECT * FROM t1;
@@ -96,3 +107,211 @@ CREATE TABLE t1 (
INSERT INTO t1 values(1, 9999);
DROP TABLE t1;
+
+
+#
+# A more extensive test with a lot more records
+#
+
+CREATE TABLE t2 (
+ a bigint unsigned NOT NULL PRIMARY KEY,
+ b int unsigned not null,
+ c int unsigned
+) engine=ndbcluster;
+
+CREATE TABLE t3 (
+ a bigint unsigned NOT NULL,
+ b bigint unsigned not null,
+ c bigint unsigned,
+ PRIMARY KEY(a)
+) engine=ndbcluster;
+
+CREATE TABLE t4 (
+ a bigint unsigned NOT NULL,
+ b bigint unsigned not null,
+ c bigint unsigned NOT NULL,
+ d int unsigned,
+ PRIMARY KEY(a, b, c)
+) engine=ndbcluster;
+
+
+#
+# insert more records into tables
+#
+let $1=1000;
+disable_query_log;
+while ($1)
+{
+ eval insert into t2 values($1, $1+9, 5);
+ eval insert into t3 values($1, $1+9, 5);
+ eval insert into t4 values($1, $1+9, 5, $1+26000);
+ dec $1;
+}
+enable_query_log;
+
+
+#
+# delete every other record in the tables
+#
+let $1=1000;
+disable_query_log;
+while ($1)
+{
+ eval delete from t2 where a=$1;
+ eval delete from t3 where a=$1;
+ eval delete from t4 where a=$1 and b=$1+9 and c=5;
+ dec $1;
+ dec $1;
+}
+enable_query_log;
+
+
+select * from t2 where a = 7 order by b;
+select * from t2 where a = 7 order by a;
+select * from t2 where a = 7 order by 2;
+select * from t2 where a = 7 order by c;
+
+select * from t2 where a = 7 and b = 16 order by b;
+select * from t2 where a = 7 and b = 16 order by a;
+select * from t2 where a = 7 and b = 17 order by a;
+select * from t2 where a = 7 and b != 16 order by b;
+
+select * from t2 where a = 7 and b = 16 and c = 5 order by b;
+select * from t2 where a = 7 and b = 16 and c = 5 order by a;
+select * from t2 where a = 7 and b = 16 and c = 6 order by a;
+select * from t2 where a = 7 and b != 16 and c = 5 order by b;
+
+select * from t3 where a = 7 order by b;
+select * from t3 where a = 7 order by a;
+select * from t3 where a = 7 order by 2;
+select * from t3 where a = 7 order by c;
+
+select * from t3 where a = 7 and b = 16 order by b;
+select * from t3 where a = 7 and b = 16 order by a;
+select * from t3 where a = 7 and b = 17 order by a;
+select * from t3 where a = 7 and b != 16 order by b;
+
+select * from t4 where a = 7 order by b;
+select * from t4 where a = 7 order by a;
+select * from t4 where a = 7 order by 2;
+select * from t4 where a = 7 order by c;
+
+select * from t4 where a = 7 and b = 16 order by b;
+select * from t4 where a = 7 and b = 16 order by a;
+select * from t4 where a = 7 and b = 17 order by a;
+select * from t4 where a = 7 and b != 16 order by b;
+
+#
+# update records
+#
+let $1=1000;
+disable_query_log;
+while ($1)
+{
+ eval update t2 set c=$1 where a=$1;
+ eval update t3 set c=7 where a=$1 and b=$1+9 and c=5;
+ eval update t4 set d=$1+21987 where a=$1 and b=$1+9 and c=5;
+ dec $1;
+ dec $1;
+}
+enable_query_log;
+
+delete from t2;
+delete from t3;
+delete from t4;
+
+drop table t2;
+drop table t3;
+drop table t4;
+
+#
+# Test delete and update from table with 3 keys
+#
+
+CREATE TABLE t5 (
+ a bigint unsigned NOT NULL,
+ b bigint unsigned not null,
+ c bigint unsigned NOT NULL,
+ d int unsigned,
+ PRIMARY KEY(a, b, c)
+) engine=ndbcluster;
+
+insert into t5 values(10, 19, 5, 26010);
+
+delete from t5 where a=10 and b=19 and c=5;
+
+select * from t5;
+
+insert into t5 values(10, 19, 5, 26010);
+
+update t5 set d=21997 where a=10 and b=19 and c=5;
+
+select * from t5;
+
+delete from t5;
+
+drop table t5;
+
+#
+# Test using table with a char(255) column first in table
+#
+
+CREATE TABLE t6 (
+ adress char(255),
+ a int NOT NULL PRIMARY KEY,
+ b int
+) engine = NDB;
+
+insert into t6 values
+ ("Nice road 3456", 1, 23),
+ ("Street Road 78", 3, 92),
+ ("Road street 89C", 5, 71),
+ (NULL, 7, NULL);
+select * from t6 order by a;
+select a, b from t6 order by a;
+
+update t6 set adress="End of road 09" where a=3;
+update t6 set b=181, adress="Street 76" where a=7;
+select * from t6 order by a;
+select * from t6 where a=1;
+delete from t6 where a=1;
+select * from t6 order by a;
+delete from t6 where b=71;
+select * from t6 order by a;
+
+drop table t6;
+
+#
+# Test using table with a char(255) column first in table and a
+# primary key consisting of two columns
+#
+
+CREATE TABLE t7 (
+ adress char(255),
+ a int NOT NULL,
+ b int,
+ c int NOT NULL,
+ PRIMARY KEY(a, c)
+) engine = NDB;
+
+insert into t7 values
+ ("Highway 3456", 1, 23, 2),
+ ("Street Road 78", 3, 92, 3),
+ ("Main street 89C", 5, 71, 4),
+ (NULL, 8, NULL, 12);
+select * from t7 order by a;
+select a, b from t7 order by a;
+
+update t7 set adress="End of road 09" where a=3;
+update t7 set adress="Gatuvägen 90C" where a=5 and c=4;
+update t7 set adress="No adress" where adress is NULL;
+select * from t7 order by a;
+select * from t7 where a=1 and c=2;
+delete from t7 where a=1;
+delete from t7 where a=3 and c=3;
+delete from t7 where a=5 and c=4;
+select * from t7;
+delete from t7 where b=23;
+select * from t7;
+
+drop table t7;
diff --git a/mysql-test/t/ndb_index.test b/mysql-test/t/ndb_index.test
new file mode 100644
index 00000000000..d3977dc3ea4
--- /dev/null
+++ b/mysql-test/t/ndb_index.test
@@ -0,0 +1,129 @@
+-- source include/have_ndb.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+CREATE TABLE t1 (
+ PORT varchar(16) NOT NULL,
+ ACCESSNODE varchar(16) NOT NULL,
+ POP varchar(48) NOT NULL,
+ ACCESSTYPE int unsigned NOT NULL,
+ CUSTOMER_ID varchar(20) NOT NULL,
+ PROVIDER varchar(16),
+ TEXPIRE int unsigned,
+ NUM_IP int unsigned,
+ LEASED_NUM_IP int unsigned,
+ LOCKED_IP int unsigned,
+ STATIC_DNS int unsigned,
+ SUSPENDED_SERVICE int unsigned,
+ SUSPENDED_REASON int unsigned,
+ BGP_COMMUNITY int unsigned,
+ INDEX CUSTOMER_ID_INDEX(CUSTOMER_ID),
+ INDEX FQPN_INDEX(POP,ACCESSNODE,PORT),
+ PRIMARY KEY(POP,ACCESSNODE,PORT,ACCESSTYPE)
+) engine=ndbcluster;
+
+INSERT INTO t1 VALUES ('port67', 'node78', 'pop98', 1, 'kllopmn', 'pr_43', 121212, 1, 2, 3, 8, NULL, NULL, NULL);
+INSERT INTO t1 VALUES ('port67', 'node78', 'pop99', 2, 'klkighh', 'pr_44', 121213, 3, 3, 6, 7, NULL, NULL, NULL);
+INSERT INTO t1 VALUES ('port79', 'node79', 'pop79', 2, 'kpongfaa', 'pr_44', 981213, 2, 4, 10, 11, 2, 99, 1278);
+
+
+# Test select using port
+select port, accessnode, pop, accesstype from t1 where port='port67' order by accesstype;
+select port, accessnode, pop, accesstype from t1 where port='foo';
+
+# Test select using accessnode
+select port, accessnode, pop, accesstype from t1 where accessnode='node78' order by accesstype;
+select port, accessnode, pop, accesstype from t1 where accessnode='foo';
+
+# Test select using pop
+select port, accessnode, pop, accesstype from t1 where pop='pop98';
+select port, accessnode, pop, accesstype from t1 where pop='pop98';
+select port, accessnode, pop, accesstype from t1 where pop='pop98';
+select port, accessnode, pop, accesstype from t1 where pop='pop98' order by accesstype;
+# The following two querys will not return any rows since
+# the index used for access is case sensitive
+# They are thus disabled for now
+#select port, accessnode, pop, accesstype from t1 where pop='POP98';
+#select port, accessnode, pop, accesstype from t1 where pop='POP98' order by accesstype;
+select port, accessnode, pop, accesstype from t1 where pop='foo';
+
+# Test select using accesstype
+select port, accessnode, pop, accesstype from t1 where accesstype=1;
+select port, accessnode, pop, accesstype from t1 where accesstype=2 order by port;
+select port, accessnode, pop, accesstype from t1 where accesstype=98 order by port;
+
+# Test select using customer_id
+# NOTE! customer_id has a INDEX (ordered index in NDB), it's case sensitive!
+select port, accessnode, pop, accesstype from t1 where customer_id='kllopmn';
+select port, accessnode, pop, accesstype from t1 where customer_id='KLLOPMN';
+select port, accessnode, pop, accesstype from t1 where customer_id='kLLoPMn';
+select port, accessnode, pop, accesstype from t1 where customer_id='foo';
+
+# Test select using provider
+select port, accessnode, pop, accesstype from t1 where provider='pr_43';
+select port, accessnode, pop, accesstype from t1 where provider='foo';
+
+# Test select using texpire
+select port, accessnode from t1 where texpire=121212;
+select port, accessnode from t1 where texpire=2323;
+
+# Test select using num_ip
+select port, accessnode, pop, accesstype from t1 where num_ip=1;
+select port, accessnode, pop, accesstype from t1 where num_ip=89;
+
+# Test select using leased_num_ip
+select port, accessnode, pop, accesstype from t1 where leased_num_ip=2;
+select port, accessnode, pop, accesstype from t1 where leased_num_ip=89;
+
+# Test select using locked_ip
+select port, accessnode, pop, accesstype from t1 where locked_ip=3;
+select port, accessnode, pop, accesstype from t1 where locked_ip=89;
+
+# Test select using static_dns
+select port, accessnode, pop, accesstype from t1 where static_dns=8;
+select port, accessnode, pop, accesstype from t1 where static_dns=89;
+
+# Test select using suspended_service
+select port, accessnode, pop, accesstype from t1 where suspended_service=8;
+select port, accessnode, pop, accesstype from t1 where suspended_service=89;
+
+# Test select using suspended_reason
+select port, accessnode, pop, accesstype from t1 where suspended_reason=NULL;
+select port, accessnode, pop, accesstype from t1 where suspended_reason=89;
+select port, accessnode, pop, accesstype from t1 where suspended_reason=0;
+
+# Test select using bgp_community
+select port, accessnode, pop, accesstype from t1 where bgp_community=NULL;
+select port, accessnode, pop, accesstype from t1 where bgp_community=89;
+select port, accessnode, pop, accesstype from t1 where bgp_community=0;
+
+# Test select using full primary key
+select port, accessnode, pop, accesstype from t1 where port='port67' and accessnode='node78' and pop='pop98' and accesstype=1;
+select port, accessnode, pop, accesstype from t1 where port='port67' and accesstype=1 and accessnode='node78' and pop='pop98';
+select port, accessnode, pop, accesstype from t1 where pop='pop98' and port='port67' and accesstype=1 and accessnode='node78';
+select port, accessnode from t1 where port='foo' and accessnode='foo' and pop='foo' and accesstype=99;
+
+# Test select using partial primary key
+select port, accessnode, pop, accesstype from t1 where port='port67' and pop='pop98' and accesstype=1;
+select port, accessnode, pop, accesstype from t1 where accesstype=1 and accessnode='node78' and pop='pop98';
+select port, accessnode, pop, accesstype from t1 where port='port67' and accesstype=1 and accessnode='node78';
+select port, accessnode from t1 where port='foo' and accessnode='foo' and pop='foo';
+
+# Test select using CUSTOMER_ID_INDEX
+select port, accessnode, pop, accesstype from t1 where customer_id='kllopmn';
+select port, accessnode, pop, accesstype from t1 where customer_id='kllopmn' and accesstype=1;
+select port, accessnode, pop, accesstype from t1 where customer_id='kllopmn' and accesstype=2;
+select port, accessnode, pop, accesstype from t1 where accesstype=2 and customer_id='kllopmn';
+
+# Test select using FQPN_INDEX
+select port, accessnode, pop, accesstype from t1 where pop='pop98' and accessnode='node78' and port='port67';
+#select port, accessnode, pop, accesstype from t1 where pop='pop98' and accessnode='node78' and port='port67' order by accesstype;
+#select port, accessnode, pop, accesstype from t1 where accessnode='node78' and port='port67' and pop='pop98' order by accesstype;
+#select port, accessnode, pop, accesstype from t1 where port='port67' and pop='pop98' and accessnode='node78' order by accesstype;
+select port, accessnode, pop, accesstype from t1 where pop='pop98' and accessnode='node78' and port='port67' and customer_id='kllopmn';
+select port, accessnode, pop, accesstype from t1 where pop='pop98' and accessnode='node78' and port='port67' and customer_id='foo';
+
+
+drop table t1;
diff --git a/mysql-test/t/ndb_index_ordered.test b/mysql-test/t/ndb_index_ordered.test
new file mode 100644
index 00000000000..79686fce0e1
--- /dev/null
+++ b/mysql-test/t/ndb_index_ordered.test
@@ -0,0 +1,112 @@
+-- source include/have_ndb.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Simple test to show use of ordered indexes
+#
+
+CREATE TABLE t1 (
+ a int unsigned NOT NULL PRIMARY KEY,
+ b int unsigned not null,
+ c int unsigned,
+ KEY(b)
+) engine=ndbcluster;
+
+insert t1 values(1, 2, 3), (2,3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
+select * from t1 order by b;
+select * from t1 where b >= 4 order by b;
+select * from t1 where b = 4 order by b;
+select * from t1 where b > 4 order by b;
+select * from t1 where b < 4 order by b;
+select * from t1 where b <= 4 order by b;
+
+#
+# Here we should add some "explain select" to verify that the ordered index is
+# used for these queries.
+#
+
+#
+# Update using ordered index scan
+#
+
+update t1 set c = 3 where b = 3;
+select * from t1 order by a;
+update t1 set c = 10 where b >= 6;
+select * from t1 order by a;
+update t1 set c = 11 where b < 5;
+select * from t1 order by a;
+update t1 set c = 12 where b > 0;
+select * from t1 order by a;
+update t1 set c = 13 where b <= 3;
+select * from t1 order by a;
+
+
+#
+# Delete using ordered index scan
+#
+
+drop table t1;
+
+CREATE TABLE t1 (
+ a int unsigned NOT NULL PRIMARY KEY,
+ b int unsigned not null,
+ c int unsigned,
+ KEY(b)
+) engine=ndbcluster;
+
+insert t1 values(1, 2, 13), (2,3, 13), (3, 4, 12), (4, 5, 12), (5,6, 12), (6,7, 12);
+
+delete from t1 where b = 3;
+select * from t1 order by a;
+delete from t1 where b >= 6;
+select * from t1 order by a;
+delete from t1 where b < 4;
+select * from t1 order by a;
+delete from t1 where b > 5;
+select * from t1 order by a;
+delete from t1 where b <= 4;
+select * from t1 order by a;
+
+drop table t1;
+
+
+#
+#multi part key
+#
+CREATE TABLE t1 (
+ a int unsigned NOT NULL PRIMARY KEY,
+ b int unsigned not null,
+ c int unsigned not null
+) engine = ndb;
+
+create index a1 on t1 (b, c);
+
+insert into t1 values (1, 2, 13);
+insert into t1 values (2,3, 13);
+insert into t1 values (3, 4, 12);
+insert into t1 values (4, 5, 12);
+insert into t1 values (5,6, 12);
+insert into t1 values (6,7, 12);
+insert into t1 values (7, 2, 1);
+insert into t1 values (8,3, 6);
+insert into t1 values (9, 4, 12);
+insert into t1 values (14, 5, 4);
+insert into t1 values (15,5,5);
+insert into t1 values (16,5, 6);
+insert into t1 values (17,4,4);
+insert into t1 values (18,1, 7);
+
+
+
+select * from t1 order by a;
+select * from t1 where b<=5 order by a;
+select * from t1 where b<=5 and c=0;
+insert into t1 values (19,4, 0);
+select * from t1 where b<=5 and c=0;
+select * from t1 where b=4 and c<=5;
+select * from t1 where b<=4 and c<=5 order by a;
+select * from t1 where b<=5 and c=0 or b<=5 and c=2;
+drop table t1;
diff --git a/mysql-test/t/ndb_index_unique.test b/mysql-test/t/ndb_index_unique.test
new file mode 100644
index 00000000000..7cfc9a77452
--- /dev/null
+++ b/mysql-test/t/ndb_index_unique.test
@@ -0,0 +1,175 @@
+-- source include/have_ndb.inc
+
+--disable_warnings
+drop table if exists t1, t2, t3, t4, t5, t6, t7;
+--enable_warnings
+
+#
+# Simple test to show use of UNIQUE indexes
+#
+
+CREATE TABLE t1 (
+ a int unsigned NOT NULL PRIMARY KEY,
+ b int unsigned not null,
+ c int unsigned,
+ UNIQUE(b)
+) engine=ndbcluster;
+
+insert t1 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
+select * from t1 order by b;
+select * from t1 where b = 4 order by b;
+insert into t1 values(7,8,3);
+select * from t1 where b = 4 order by a;
+
+drop table t1;
+
+
+#
+# Show use of UNIQUE USING HASH indexes
+#
+
+CREATE TABLE t2 (
+ a int unsigned NOT NULL PRIMARY KEY,
+ b int unsigned not null,
+ c int unsigned not null,
+ UNIQUE USING HASH (b, c)
+) engine=ndbcluster;
+
+insert t2 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
+select * from t2 where a = 3;
+select * from t2 where b = 4;
+select * from t2 where c = 6;
+insert into t2 values(7,8,3);
+select * from t2 where b = 4 order by a;
+
+drop table t2;
+
+#
+# Show use of PRIMARY KEY USING HASH indexes
+#
+
+CREATE TABLE t3 (
+ a int unsigned NOT NULL,
+ b int unsigned not null,
+ c int unsigned,
+ PRIMARY KEY USING HASH (a, b)
+) engine=ndbcluster;
+
+insert t3 values(1, 2, 3), (2, 3, 5), (3, 4, 6), (4, 5, 8), (5,6, 2), (6,7, 2);
+select * from t3 where a = 3;
+select * from t3 where b = 4;
+select * from t3 where c = 6;
+insert into t3 values(7,8,3);
+select * from t3 where b = 4 order by a;
+
+drop table t3;
+
+#
+# More complex tables
+#
+
+CREATE TABLE t1 (
+ cid smallint(5) unsigned NOT NULL default '0',
+ cv varchar(250) NOT NULL default '',
+ PRIMARY KEY (cid),
+ UNIQUE KEY cv (cv)
+) engine=ndbcluster;
+INSERT INTO t1 VALUES (8,'dummy');
+CREATE TABLE t2 (
+ cid bigint(20) unsigned NOT NULL auto_increment,
+ cap varchar(255) NOT NULL default '',
+ PRIMARY KEY (cid)
+) engine=ndbcluster;
+CREATE TABLE t3 (
+ gid bigint(20) unsigned NOT NULL auto_increment,
+ gn varchar(255) NOT NULL default '',
+ must tinyint(4) default NULL,
+ PRIMARY KEY (gid)
+) engine=ndbcluster;
+INSERT INTO t3 VALUES (1,'V1',NULL);
+CREATE TABLE t4 (
+ uid bigint(20) unsigned NOT NULL default '0',
+ gid bigint(20) unsigned NOT NULL,
+ rid bigint(20) unsigned NOT NULL default '-1',
+ cid bigint(20) unsigned NOT NULL default '-1',
+ UNIQUE KEY m (uid,gid,rid,cid)
+) engine=ndbcluster;
+INSERT INTO t4 VALUES (1,1,2,4);
+INSERT INTO t4 VALUES (1,1,2,3);
+INSERT INTO t4 VALUES (1,1,5,7);
+INSERT INTO t4 VALUES (1,1,10,8);
+CREATE TABLE t5 (
+ rid bigint(20) unsigned NOT NULL auto_increment,
+ rl varchar(255) NOT NULL default '',
+ PRIMARY KEY (rid)
+) engine=ndbcluster;
+CREATE TABLE t6 (
+ uid bigint(20) unsigned NOT NULL auto_increment,
+ un varchar(250) NOT NULL default '',
+ uc smallint(5) unsigned NOT NULL default '0',
+ PRIMARY KEY (uid),
+ UNIQUE KEY nc (un,uc)
+) engine=ndbcluster;
+INSERT INTO t6 VALUES (1,'test',8);
+INSERT INTO t6 VALUES (2,'test2',9);
+INSERT INTO t6 VALUES (3,'tre',3);
+CREATE TABLE t7 (
+ mid bigint(20) unsigned NOT NULL PRIMARY KEY,
+ uid bigint(20) unsigned NOT NULL default '0',
+ gid bigint(20) unsigned NOT NULL,
+ rid bigint(20) unsigned NOT NULL default '-1',
+ cid bigint(20) unsigned NOT NULL default '-1',
+ UNIQUE KEY m (uid,gid,rid,cid)
+) engine=ndbcluster;
+INSERT INTO t7 VALUES(1, 1, 1, 1, 1);
+INSERT INTO t7 VALUES(2, 2, 1, 1, 1);
+INSERT INTO t7 VALUES(3, 3, 1, 1, 1);
+INSERT INTO t7 VALUES(4, 4, 1, 1, 1);
+INSERT INTO t7 VALUES(5, 5, 1, 1, 1);
+INSERT INTO t7 VALUES(6, 1, 1, 1, 6);
+INSERT INTO t7 VALUES(7, 2, 1, 1, 7);
+INSERT INTO t7 VALUES(8, 3, 1, 1, 8);
+INSERT INTO t7 VALUES(9, 4, 1, 1, 9);
+INSERT INTO t7 VALUES(10, 5, 1, 1, 10);
+
+select * from t1 where cv = 'dummy';
+select * from t1 where cv = 'test';
+select * from t4 where uid = 1 and gid=1 and rid=2 and cid=4;
+select * from t4 where uid = 1 and gid=1 and rid=1 and cid=4;
+select * from t4 where uid = 1 order by cid;
+select * from t4 where rid = 2 order by cid;
+select * from t6 where un='test' and uc=8;
+select * from t6 where un='test' and uc=7;
+select * from t6 where un='test';
+select * from t7 where mid = 8;
+select * from t7 where uid = 8;
+select * from t7 where uid = 1 order by mid;
+select * from t7 where uid = 4 order by mid;
+select * from t7 where gid = 4;
+select * from t7 where gid = 1 order by mid;
+select * from t7 where cid = 4;
+select * from t7 where cid = 8;
+
+#
+# insert more records into t4
+#
+let $1=100;
+disable_query_log;
+while ($1)
+{
+ eval insert into t4 values(1, $1, 5, 12);
+ eval insert into t4 values($1, 3, 9, 11);
+ dec $1;
+}
+enable_query_log;
+
+select * from t4 where uid = 1 and gid=1 and rid=2 and cid=4;
+select * from t4 where uid = 1 and gid=1 and rid=1 and cid=4;
+select * from t4 where uid = 1 order by gid,cid;
+select * from t4 where uid = 1 order by gid,cid;
+select * from t4 where rid = 2 order by cid;
+
+
+drop table t1,t2,t3,t4,t5,t6,t7;
+
+
diff --git a/mysql-test/t/ndb_insert.test b/mysql-test/t/ndb_insert.test
new file mode 100644
index 00000000000..c55a925dca2
--- /dev/null
+++ b/mysql-test/t/ndb_insert.test
@@ -0,0 +1,433 @@
+-- source include/have_ndb.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+#
+# Basic test of INSERT in NDB
+#
+
+#
+# Create a normal table with primary key
+#
+CREATE TABLE t1 (
+ pk1 INT NOT NULL PRIMARY KEY,
+ b INT NOT NULL,
+ c INT NOT NULL
+) ENGINE=ndbcluster;
+
+INSERT INTO t1 VALUES (0, 0, 0);
+SELECT * FROM t1;
+
+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),
+(11,11,11),(12,12,12),(13,13,13),(14,14,14),(15,15,15),
+(16,16,16),(17,17,17),(18,18,18),(19,19,19),(20,20,20),
+(21,21,21),(22,22,22),(23,23,23),(24,24,24),(25,25,25),
+(26,26,26),(27,27,27),(28,28,28),(29,29,29),(30,30,30),
+(31,31,31),(32,32,32),(33,33,33),(34,34,34),(35,35,35),
+(36,36,36),(37,37,37),(38,38,38),(39,39,39),(40,40,40),
+(41,41,41),(42,42,42),(43,43,43),(44,44,44),(45,45,45),
+(46,46,46),(47,47,47),(48,48,48),(49,49,49),(50,50,50),
+(51,51,51),(52,52,52),(53,53,53),(54,54,54),(55,55,55),
+(56,56,56),(57,57,57),(58,58,58),(59,59,59),(60,60,60),
+(61,61,61),(62,62,62),(63,63,63),(64,64,64),(65,65,65),
+(66,66,66),(67,67,67),(68,68,68),(69,69,69),(70,70,70),
+(71,71,71),(72,72,72),(73,73,73),(74,74,74),(75,75,75),
+(76,76,76),(77,77,77),(78,78,78),(79,79,79),(80,80,80),
+(81,81,81),(82,82,82),(83,83,83),(84,84,84),(85,85,85),
+(86,86,86),(87,87,87),(88,88,88),(89,89,89),(90,90,90),
+(91,91,91),(92,92,92),(93,93,93),(94,94,94),(95,95,95),
+(96,96,96),(97,97,97),(98,98,98),(99,99,99),(100,100,100),
+(101,101,101),(102,102,102),(103,103,103),(104,104,104),(105,105,105),
+(106,106,106),(107,107,107),(108,108,108),(109,109,109),(110,110,110),
+(111,111,111),(112,112,112),(113,113,113),(114,114,114),(115,115,115),
+(116,116,116),(117,117,117),(118,118,118),(119,119,119),(120,120,120),
+(121,121,121),(122,122,122),(123,123,123),(124,124,124),(125,125,125),
+(126,126,126),(127,127,127),(128,128,128),(129,129,129),(130,130,130),
+(131,131,131),(132,132,132),(133,133,133),(134,134,134),(135,135,135),
+(136,136,136),(137,137,137),(138,138,138),(139,139,139),(140,140,140),
+(141,141,141),(142,142,142),(143,143,143),(144,144,144),(145,145,145),
+(146,146,146),(147,147,147),(148,148,148),(149,149,149),(150,150,150),
+(151,151,151),(152,152,152),(153,153,153),(154,154,154),(155,155,155),
+(156,156,156),(157,157,157),(158,158,158),(159,159,159),(160,160,160),
+(161,161,161),(162,162,162),(163,163,163),(164,164,164),(165,165,165),
+(166,166,166),(167,167,167),(168,168,168),(169,169,169),(170,170,170),
+(171,171,171),(172,172,172),(173,173,173),(174,174,174),(175,175,175),
+(176,176,176),(177,177,177),(178,178,178),(179,179,179),(180,180,180),
+(181,181,181),(182,182,182),(183,183,183),(184,184,184),(185,185,185),
+(186,186,186),(187,187,187),(188,188,188),(189,189,189),(190,190,190),
+(191,191,191),(192,192,192),(193,193,193),(194,194,194),(195,195,195),
+(196,196,196),(197,197,197),(198,198,198),(199,199,199),(200,200,200),
+(201,201,201),(202,202,202),(203,203,203),(204,204,204),(205,205,205),
+(206,206,206),(207,207,207),(208,208,208),(209,209,209),(210,210,210),
+(211,211,211),(212,212,212),(213,213,213),(214,214,214),(215,215,215),
+(216,216,216),(217,217,217),(218,218,218),(219,219,219),(220,220,220),
+(221,221,221),(222,222,222),(223,223,223),(224,224,224),(225,225,225),
+(226,226,226),(227,227,227),(228,228,228),(229,229,229),(230,230,230),
+(231,231,231),(232,232,232),(233,233,233),(234,234,234),(235,235,235),
+(236,236,236),(237,237,237),(238,238,238),(239,239,239),(240,240,240),
+(241,241,241),(242,242,242),(243,243,243),(244,244,244),(245,245,245),
+(246,246,246),(247,247,247),(248,248,248),(249,249,249),(250,250,250),
+(251,251,251),(252,252,252),(253,253,253),(254,254,254),(255,255,255),
+(256,256,256),(257,257,257),(258,258,258),(259,259,259),(260,260,260),
+(261,261,261),(262,262,262),(263,263,263),(264,264,264),(265,265,265),
+(266,266,266),(267,267,267),(268,268,268),(269,269,269),(270,270,270),
+(271,271,271),(272,272,272),(273,273,273),(274,274,274),(275,275,275),
+(276,276,276),(277,277,277),(278,278,278),(279,279,279),(280,280,280),
+(281,281,281),(282,282,282),(283,283,283),(284,284,284),(285,285,285),
+(286,286,286),(287,287,287),(288,288,288),(289,289,289),(290,290,290),
+(291,291,291),(292,292,292),(293,293,293),(294,294,294),(295,295,295),
+(296,296,296),(297,297,297),(298,298,298),(299,299,299),(300,300,300),
+(301,301,301),(302,302,302),(303,303,303),(304,304,304),(305,305,305),
+(306,306,306),(307,307,307),(308,308,308),(309,309,309),(310,310,310),
+(311,311,311),(312,312,312),(313,313,313),(314,314,314),(315,315,315),
+(316,316,316),(317,317,317),(318,318,318),(319,319,319),(320,320,320),
+(321,321,321),(322,322,322),(323,323,323),(324,324,324),(325,325,325),
+(326,326,326),(327,327,327),(328,328,328),(329,329,329),(330,330,330),
+(331,331,331),(332,332,332),(333,333,333),(334,334,334),(335,335,335),
+(336,336,336),(337,337,337),(338,338,338),(339,339,339),(340,340,340),
+(341,341,341),(342,342,342),(343,343,343),(344,344,344),(345,345,345),
+(346,346,346),(347,347,347),(348,348,348),(349,349,349),(350,350,350),
+(351,351,351),(352,352,352),(353,353,353),(354,354,354),(355,355,355),
+(356,356,356),(357,357,357),(358,358,358),(359,359,359),(360,360,360),
+(361,361,361),(362,362,362),(363,363,363),(364,364,364),(365,365,365),
+(366,366,366),(367,367,367),(368,368,368),(369,369,369),(370,370,370),
+(371,371,371),(372,372,372),(373,373,373),(374,374,374),(375,375,375),
+(376,376,376),(377,377,377),(378,378,378),(379,379,379),(380,380,380),
+(381,381,381),(382,382,382),(383,383,383),(384,384,384),(385,385,385),
+(386,386,386),(387,387,387),(388,388,388),(389,389,389),(390,390,390),
+(391,391,391),(392,392,392),(393,393,393),(394,394,394),(395,395,395),
+(396,396,396),(397,397,397),(398,398,398),(399,399,399),(400,400,400),
+(401,401,401),(402,402,402),(403,403,403),(404,404,404),(405,405,405),
+(406,406,406),(407,407,407),(408,408,408),(409,409,409),(410,410,410),
+(411,411,411),(412,412,412),(413,413,413),(414,414,414),(415,415,415),
+(416,416,416),(417,417,417),(418,418,418),(419,419,419),(420,420,420),
+(421,421,421),(422,422,422),(423,423,423),(424,424,424),(425,425,425),
+(426,426,426),(427,427,427),(428,428,428),(429,429,429),(430,430,430),
+(431,431,431),(432,432,432),(433,433,433),(434,434,434),(435,435,435),
+(436,436,436),(437,437,437),(438,438,438),(439,439,439),(440,440,440),
+(441,441,441),(442,442,442),(443,443,443),(444,444,444),(445,445,445),
+(446,446,446),(447,447,447),(448,448,448),(449,449,449),(450,450,450),
+(451,451,451),(452,452,452),(453,453,453),(454,454,454),(455,455,455),
+(456,456,456),(457,457,457),(458,458,458),(459,459,459),(460,460,460),
+(461,461,461),(462,462,462),(463,463,463),(464,464,464),(465,465,465),
+(466,466,466),(467,467,467),(468,468,468),(469,469,469),(470,470,470),
+(471,471,471),(472,472,472),(473,473,473),(474,474,474),(475,475,475),
+(476,476,476),(477,477,477),(478,478,478),(479,479,479),(480,480,480),
+(481,481,481),(482,482,482),(483,483,483),(484,484,484),(485,485,485),
+(486,486,486),(487,487,487),(488,488,488),(489,489,489),(490,490,490),
+(491,491,491),(492,492,492),(493,493,493),(494,494,494),(495,495,495),
+(496,496,496),(497,497,497),(498,498,498),(499,499,499),(500, 500, 500);
+
+SELECT COUNT(*) FROM t1;
+
+INSERT INTO t1 VALUES
+(501,501,501),(502,502,502),(503,503,503),(504,504,504),(505,505,505),
+(506,506,506),(507,507,507),(508,508,508),(509,509,509),(510,510,510),
+(511,511,511),(512,512,512),(513,513,513),(514,514,514),(515,515,515),
+(516,516,516),(517,517,517),(518,518,518),(519,519,519),(520,520,520),
+(521,521,521),(522,522,522),(523,523,523),(524,524,524),(525,525,525),
+(526,526,526),(527,527,527),(528,528,528),(529,529,529),(530,530,530),
+(531,531,531),(532,532,532),(533,533,533),(534,534,534),(535,535,535),
+(536,536,536),(537,537,537),(538,538,538),(539,539,539),(540,540,540),
+(541,541,541),(542,542,542),(543,543,543),(544,544,544),(545,545,545),
+(546,546,546),(547,547,547),(548,548,548),(549,549,549),(550,550,550),
+(551,551,551),(552,552,552),(553,553,553),(554,554,554),(555,555,555),
+(556,556,556),(557,557,557),(558,558,558),(559,559,559),(560,560,560),
+(561,561,561),(562,562,562),(563,563,563),(564,564,564),(565,565,565),
+(566,566,566),(567,567,567),(568,568,568),(569,569,569),(570,570,570),
+(571,571,571),(572,572,572),(573,573,573),(574,574,574),(575,575,575),
+(576,576,576),(577,577,577),(578,578,578),(579,579,579),(580,580,580),
+(581,581,581),(582,582,582),(583,583,583),(584,584,584),(585,585,585),
+(586,586,586),(587,587,587),(588,588,588),(589,589,589),(590,590,590),
+(591,591,591),(592,592,592),(593,593,593),(594,594,594),(595,595,595),
+(596,596,596),(597,597,597),(598,598,598),(599,599,599),(600,600,600),
+(601,601,601),(602,602,602),(603,603,603),(604,604,604),(605,605,605),
+(606,606,606),(607,607,607),(608,608,608),(609,609,609),(610,610,610),
+(611,611,611),(612,612,612),(613,613,613),(614,614,614),(615,615,615),
+(616,616,616),(617,617,617),(618,618,618),(619,619,619),(620,620,620),
+(621,621,621),(622,622,622),(623,623,623),(624,624,624),(625,625,625),
+(626,626,626),(627,627,627),(628,628,628),(629,629,629),(630,630,630),
+(631,631,631),(632,632,632),(633,633,633),(634,634,634),(635,635,635),
+(636,636,636),(637,637,637),(638,638,638),(639,639,639),(640,640,640),
+(641,641,641),(642,642,642),(643,643,643),(644,644,644),(645,645,645),
+(646,646,646),(647,647,647),(648,648,648),(649,649,649),(650,650,650),
+(651,651,651),(652,652,652),(653,653,653),(654,654,654),(655,655,655),
+(656,656,656),(657,657,657),(658,658,658),(659,659,659),(660,660,660),
+(661,661,661),(662,662,662),(663,663,663),(664,664,664),(665,665,665),
+(666,666,666),(667,667,667),(668,668,668),(669,669,669),(670,670,670),
+(671,671,671),(672,672,672),(673,673,673),(674,674,674),(675,675,675),
+(676,676,676),(677,677,677),(678,678,678),(679,679,679),(680,680,680),
+(681,681,681),(682,682,682),(683,683,683),(684,684,684),(685,685,685),
+(686,686,686),(687,687,687),(688,688,688),(689,689,689),(690,690,690),
+(691,691,691),(692,692,692),(693,693,693),(694,694,694),(695,695,695),
+(696,696,696),(697,697,697),(698,698,698),(699,699,699),(700,700,700),
+(701,701,701),(702,702,702),(703,703,703),(704,704,704),(705,705,705),
+(706,706,706),(707,707,707),(708,708,708),(709,709,709),(710,710,710),
+(711,711,711),(712,712,712),(713,713,713),(714,714,714),(715,715,715),
+(716,716,716),(717,717,717),(718,718,718),(719,719,719),(720,720,720),
+(721,721,721),(722,722,722),(723,723,723),(724,724,724),(725,725,725),
+(726,726,726),(727,727,727),(728,728,728),(729,729,729),(730,730,730),
+(731,731,731),(732,732,732),(733,733,733),(734,734,734),(735,735,735),
+(736,736,736),(737,737,737),(738,738,738),(739,739,739),(740,740,740),
+(741,741,741),(742,742,742),(743,743,743),(744,744,744),(745,745,745),
+(746,746,746),(747,747,747),(748,748,748),(749,749,749),(750,750,750),
+(751,751,751),(752,752,752),(753,753,753),(754,754,754),(755,755,755),
+(756,756,756),(757,757,757),(758,758,758),(759,759,759),(760,760,760),
+(761,761,761),(762,762,762),(763,763,763),(764,764,764),(765,765,765),
+(766,766,766),(767,767,767),(768,768,768),(769,769,769),(770,770,770),
+(771,771,771),(772,772,772),(773,773,773),(774,774,774),(775,775,775),
+(776,776,776),(777,777,777),(778,778,778),(779,779,779),(780,780,780),
+(781,781,781),(782,782,782),(783,783,783),(784,784,784),(785,785,785),
+(786,786,786),(787,787,787),(788,788,788),(789,789,789),(790,790,790),
+(791,791,791),(792,792,792),(793,793,793),(794,794,794),(795,795,795),
+(796,796,796),(797,797,797),(798,798,798),(799,799,799),(800,800,800),
+(801,801,801),(802,802,802),(803,803,803),(804,804,804),(805,805,805),
+(806,806,806),(807,807,807),(808,808,808),(809,809,809),(810,810,810),
+(811,811,811),(812,812,812),(813,813,813),(814,814,814),(815,815,815),
+(816,816,816),(817,817,817),(818,818,818),(819,819,819),(820,820,820),
+(821,821,821),(822,822,822),(823,823,823),(824,824,824),(825,825,825),
+(826,826,826),(827,827,827),(828,828,828),(829,829,829),(830,830,830),
+(831,831,831),(832,832,832),(833,833,833),(834,834,834),(835,835,835),
+(836,836,836),(837,837,837),(838,838,838),(839,839,839),(840,840,840),
+(841,841,841),(842,842,842),(843,843,843),(844,844,844),(845,845,845),
+(846,846,846),(847,847,847),(848,848,848),(849,849,849),(850,850,850),
+(851,851,851),(852,852,852),(853,853,853),(854,854,854),(855,855,855),
+(856,856,856),(857,857,857),(858,858,858),(859,859,859),(860,860,860),
+(861,861,861),(862,862,862),(863,863,863),(864,864,864),(865,865,865),
+(866,866,866),(867,867,867),(868,868,868),(869,869,869),(870,870,870),
+(871,871,871),(872,872,872),(873,873,873),(874,874,874),(875,875,875),
+(876,876,876),(877,877,877),(878,878,878),(879,879,879),(880,880,880),
+(881,881,881),(882,882,882),(883,883,883),(884,884,884),(885,885,885),
+(886,886,886),(887,887,887),(888,888,888),(889,889,889),(890,890,890),
+(891,891,891),(892,892,892),(893,893,893),(894,894,894),(895,895,895),
+(896,896,896),(897,897,897),(898,898,898),(899,899,899),(900,900,900),
+(901,901,901),(902,902,902),(903,903,903),(904,904,904),(905,905,905),
+(906,906,906),(907,907,907),(908,908,908),(909,909,909),(910,910,910),
+(911,911,911),(912,912,912),(913,913,913),(914,914,914),(915,915,915),
+(916,916,916),(917,917,917),(918,918,918),(919,919,919),(920,920,920),
+(921,921,921),(922,922,922),(923,923,923),(924,924,924),(925,925,925),
+(926,926,926),(927,927,927),(928,928,928),(929,929,929),(930,930,930),
+(931,931,931),(932,932,932),(933,933,933),(934,934,934),(935,935,935),
+(936,936,936),(937,937,937),(938,938,938),(939,939,939),(940,940,940),
+(941,941,941),(942,942,942),(943,943,943),(944,944,944),(945,945,945),
+(946,946,946),(947,947,947),(948,948,948),(949,949,949),(950,950,950),
+(951,951,951),(952,952,952),(953,953,953),(954,954,954),(955,955,955),
+(956,956,956),(957,957,957),(958,958,958),(959,959,959),(960,960,960),
+(961,961,961),(962,962,962),(963,963,963),(964,964,964),(965,965,965),
+(966,966,966),(967,967,967),(968,968,968),(969,969,969),(970,970,970),
+(971,971,971),(972,972,972),(973,973,973),(974,974,974),(975,975,975),
+(976,976,976),(977,977,977),(978,978,978),(979,979,979),(980,980,980),
+(981,981,981),(982,982,982),(983,983,983),(984,984,984),(985,985,985),
+(986,986,986),(987,987,987),(988,988,988),(989,989,989),(990,990,990),
+(991,991,991),(992,992,992),(993,993,993),(994,994,994),(995,995,995),
+(996,996,996),(997,997,997),(998,998,998),(999,999,999),(1000,1000,1000),
+(1001,1001,1001),(1002,1002,1002),(1003,1003,1003),(1004,1004,1004),(1005,1005,1005),
+(1006,1006,1006),(1007,1007,1007),(1008,1008,1008),(1009,1009,1009),(1010,1010,1010),
+(1011,1011,1011),(1012,1012,1012),(1013,1013,1013),(1014,1014,1014),(1015,1015,1015),
+(1016,1016,1016),(1017,1017,1017),(1018,1018,1018),(1019,1019,1019),(1020,1020,1020),
+(1021,1021,1021),(1022,1022,1022),(1023,1023,1023),(1024,1024,1024),(1025,1025,1025),
+(1026,1026,1026),(1027,1027,1027),(1028,1028,1028),(1029,1029,1029),(1030,1030,1030),
+(1031,1031,1031),(1032,1032,1032),(1033,1033,1033),(1034,1034,1034),(1035,1035,1035),
+(1036,1036,1036),(1037,1037,1037),(1038,1038,1038),(1039,1039,1039),(1040,1040,1040),
+(1041,1041,1041),(1042,1042,1042),(1043,1043,1043),(1044,1044,1044),(1045,1045,1045),
+(1046,1046,1046),(1047,1047,1047),(1048,1048,1048),(1049,1049,1049),(1050,1050,1050),
+(1051,1051,1051),(1052,1052,1052),(1053,1053,1053),(1054,1054,1054),(1055,1055,1055),
+(1056,1056,1056),(1057,1057,1057),(1058,1058,1058),(1059,1059,1059),(1060,1060,1060),
+(1061,1061,1061),(1062,1062,1062),(1063,1063,1063),(1064,1064,1064),(1065,1065,1065),
+(1066,1066,1066),(1067,1067,1067),(1068,1068,1068),(1069,1069,1069),(1070,1070,1070),
+(1071,1071,1071),(1072,1072,1072),(1073,1073,1073),(1074,1074,1074),(1075,1075,1075),
+(1076,1076,1076),(1077,1077,1077),(1078,1078,1078),(1079,1079,1079),(1080,1080,1080),
+(1081,1081,1081),(1082,1082,1082),(1083,1083,1083),(1084,1084,1084),(1085,1085,1085),
+(1086,1086,1086),(1087,1087,1087),(1088,1088,1088),(1089,1089,1089),(1090,1090,1090),
+(1091,1091,1091),(1092,1092,1092),(1093,1093,1093),(1094,1094,1094),(1095,1095,1095),
+(1096,1096,1096),(1097,1097,1097),(1098,1098,1098),(1099,1099,1099),(1100,1100,1100),
+(1101,1101,1101),(1102,1102,1102),(1103,1103,1103),(1104,1104,1104),(1105,1105,1105),
+(1106,1106,1106),(1107,1107,1107),(1108,1108,1108),(1109,1109,1109),(1110,1110,1110),
+(1111,1111,1111),(1112,1112,1112),(1113,1113,1113),(1114,1114,1114),(1115,1115,1115),
+(1116,1116,1116),(1117,1117,1117),(1118,1118,1118),(1119,1119,1119),(1120,1120,1120),
+(1121,1121,1121),(1122,1122,1122),(1123,1123,1123),(1124,1124,1124),(1125,1125,1125),
+(1126,1126,1126),(1127,1127,1127),(1128,1128,1128),(1129,1129,1129),(1130,1130,1130),
+(1131,1131,1131),(1132,1132,1132),(1133,1133,1133),(1134,1134,1134),(1135,1135,1135),
+(1136,1136,1136),(1137,1137,1137),(1138,1138,1138),(1139,1139,1139),(1140,1140,1140),
+(1141,1141,1141),(1142,1142,1142),(1143,1143,1143),(1144,1144,1144),(1145,1145,1145),
+(1146,1146,1146),(1147,1147,1147),(1148,1148,1148),(1149,1149,1149),(1150,1150,1150),
+(1151,1151,1151),(1152,1152,1152),(1153,1153,1153),(1154,1154,1154),(1155,1155,1155),
+(1156,1156,1156),(1157,1157,1157),(1158,1158,1158),(1159,1159,1159),(1160,1160,1160),
+(1161,1161,1161),(1162,1162,1162),(1163,1163,1163),(1164,1164,1164),(1165,1165,1165),
+(1166,1166,1166),(1167,1167,1167),(1168,1168,1168),(1169,1169,1169),(1170,1170,1170),
+(1171,1171,1171),(1172,1172,1172),(1173,1173,1173),(1174,1174,1174),(1175,1175,1175),
+(1176,1176,1176),(1177,1177,1177),(1178,1178,1178),(1179,1179,1179),(1180,1180,1180),
+(1181,1181,1181),(1182,1182,1182),(1183,1183,1183),(1184,1184,1184),(1185,1185,1185),
+(1186,1186,1186),(1187,1187,1187),(1188,1188,1188),(1189,1189,1189),(1190,1190,1190),
+(1191,1191,1191),(1192,1192,1192),(1193,1193,1193),(1194,1194,1194),(1195,1195,1195),
+(1196,1196,1196),(1197,1197,1197),(1198,1198,1198),(1199,1199,1199),(1200,1200,1200),
+(1201,1201,1201),(1202,1202,1202),(1203,1203,1203),(1204,1204,1204),(1205,1205,1205),
+(1206,1206,1206),(1207,1207,1207),(1208,1208,1208),(1209,1209,1209),(1210,1210,1210),
+(1211,1211,1211),(1212,1212,1212),(1213,1213,1213),(1214,1214,1214),(1215,1215,1215),
+(1216,1216,1216),(1217,1217,1217),(1218,1218,1218),(1219,1219,1219),(1220,1220,1220),
+(1221,1221,1221),(1222,1222,1222),(1223,1223,1223),(1224,1224,1224),(1225,1225,1225),
+(1226,1226,1226),(1227,1227,1227),(1228,1228,1228),(1229,1229,1229),(1230,1230,1230),
+(1231,1231,1231),(1232,1232,1232),(1233,1233,1233),(1234,1234,1234),(1235,1235,1235),
+(1236,1236,1236),(1237,1237,1237),(1238,1238,1238),(1239,1239,1239),(1240,1240,1240),
+(1241,1241,1241),(1242,1242,1242),(1243,1243,1243),(1244,1244,1244),(1245,1245,1245),
+(1246,1246,1246),(1247,1247,1247),(1248,1248,1248),(1249,1249,1249),(1250,1250,1250),
+(1251,1251,1251),(1252,1252,1252),(1253,1253,1253),(1254,1254,1254),(1255,1255,1255),
+(1256,1256,1256),(1257,1257,1257),(1258,1258,1258),(1259,1259,1259),(1260,1260,1260),
+(1261,1261,1261),(1262,1262,1262),(1263,1263,1263),(1264,1264,1264),(1265,1265,1265),
+(1266,1266,1266),(1267,1267,1267),(1268,1268,1268),(1269,1269,1269),(1270,1270,1270),
+(1271,1271,1271),(1272,1272,1272),(1273,1273,1273),(1274,1274,1274),(1275,1275,1275),
+(1276,1276,1276),(1277,1277,1277),(1278,1278,1278),(1279,1279,1279),(1280,1280,1280),
+(1281,1281,1281),(1282,1282,1282),(1283,1283,1283),(1284,1284,1284),(1285,1285,1285),
+(1286,1286,1286),(1287,1287,1287),(1288,1288,1288),(1289,1289,1289),(1290,1290,1290),
+(1291,1291,1291),(1292,1292,1292),(1293,1293,1293),(1294,1294,1294),(1295,1295,1295),
+(1296,1296,1296),(1297,1297,1297),(1298,1298,1298),(1299,1299,1299),(1300,1300,1300),
+(1301,1301,1301),(1302,1302,1302),(1303,1303,1303),(1304,1304,1304),(1305,1305,1305),
+(1306,1306,1306),(1307,1307,1307),(1308,1308,1308),(1309,1309,1309),(1310,1310,1310),
+(1311,1311,1311),(1312,1312,1312),(1313,1313,1313),(1314,1314,1314),(1315,1315,1315),
+(1316,1316,1316),(1317,1317,1317),(1318,1318,1318),(1319,1319,1319),(1320,1320,1320),
+(1321,1321,1321),(1322,1322,1322),(1323,1323,1323),(1324,1324,1324),(1325,1325,1325),
+(1326,1326,1326),(1327,1327,1327),(1328,1328,1328),(1329,1329,1329),(1330,1330,1330),
+(1331,1331,1331),(1332,1332,1332),(1333,1333,1333),(1334,1334,1334),(1335,1335,1335),
+(1336,1336,1336),(1337,1337,1337),(1338,1338,1338),(1339,1339,1339),(1340,1340,1340),
+(1341,1341,1341),(1342,1342,1342),(1343,1343,1343),(1344,1344,1344),(1345,1345,1345),
+(1346,1346,1346),(1347,1347,1347),(1348,1348,1348),(1349,1349,1349),(1350,1350,1350),
+(1351,1351,1351),(1352,1352,1352),(1353,1353,1353),(1354,1354,1354),(1355,1355,1355),
+(1356,1356,1356),(1357,1357,1357),(1358,1358,1358),(1359,1359,1359),(1360,1360,1360),
+(1361,1361,1361),(1362,1362,1362),(1363,1363,1363),(1364,1364,1364),(1365,1365,1365),
+(1366,1366,1366),(1367,1367,1367),(1368,1368,1368),(1369,1369,1369),(1370,1370,1370),
+(1371,1371,1371),(1372,1372,1372),(1373,1373,1373),(1374,1374,1374),(1375,1375,1375),
+(1376,1376,1376),(1377,1377,1377),(1378,1378,1378),(1379,1379,1379),(1380,1380,1380),
+(1381,1381,1381),(1382,1382,1382),(1383,1383,1383),(1384,1384,1384),(1385,1385,1385),
+(1386,1386,1386),(1387,1387,1387),(1388,1388,1388),(1389,1389,1389),(1390,1390,1390),
+(1391,1391,1391),(1392,1392,1392),(1393,1393,1393),(1394,1394,1394),(1395,1395,1395),
+(1396,1396,1396),(1397,1397,1397),(1398,1398,1398),(1399,1399,1399),(1400,1400,1400),
+(1401,1401,1401),(1402,1402,1402),(1403,1403,1403),(1404,1404,1404),(1405,1405,1405),
+(1406,1406,1406),(1407,1407,1407),(1408,1408,1408),(1409,1409,1409),(1410,1410,1410),
+(1411,1411,1411),(1412,1412,1412),(1413,1413,1413),(1414,1414,1414),(1415,1415,1415),
+(1416,1416,1416),(1417,1417,1417),(1418,1418,1418),(1419,1419,1419),(1420,1420,1420),
+(1421,1421,1421),(1422,1422,1422),(1423,1423,1423),(1424,1424,1424),(1425,1425,1425),
+(1426,1426,1426),(1427,1427,1427),(1428,1428,1428),(1429,1429,1429),(1430,1430,1430),
+(1431,1431,1431),(1432,1432,1432),(1433,1433,1433),(1434,1434,1434),(1435,1435,1435),
+(1436,1436,1436),(1437,1437,1437),(1438,1438,1438),(1439,1439,1439),(1440,1440,1440),
+(1441,1441,1441),(1442,1442,1442),(1443,1443,1443),(1444,1444,1444),(1445,1445,1445),
+(1446,1446,1446),(1447,1447,1447),(1448,1448,1448),(1449,1449,1449),(1450,1450,1450),
+(1451,1451,1451),(1452,1452,1452),(1453,1453,1453),(1454,1454,1454),(1455,1455,1455),
+(1456,1456,1456),(1457,1457,1457),(1458,1458,1458),(1459,1459,1459),(1460,1460,1460),
+(1461,1461,1461),(1462,1462,1462),(1463,1463,1463),(1464,1464,1464),(1465,1465,1465),
+(1466,1466,1466),(1467,1467,1467),(1468,1468,1468),(1469,1469,1469),(1470,1470,1470),
+(1471,1471,1471),(1472,1472,1472),(1473,1473,1473),(1474,1474,1474),(1475,1475,1475),
+(1476,1476,1476),(1477,1477,1477),(1478,1478,1478),(1479,1479,1479),(1480,1480,1480),
+(1481,1481,1481),(1482,1482,1482),(1483,1483,1483),(1484,1484,1484),(1485,1485,1485),
+(1486,1486,1486),(1487,1487,1487),(1488,1488,1488),(1489,1489,1489),(1490,1490,1490),
+(1491,1491,1491),(1492,1492,1492),(1493,1493,1493),(1494,1494,1494),(1495,1495,1495),
+(1496,1496,1496),(1497,1497,1497),(1498,1498,1498),(1499,1499,1499),(1500,1500,1500),
+(1501,1501,1501),(1502,1502,1502),(1503,1503,1503),(1504,1504,1504),(1505,1505,1505),
+(1506,1506,1506),(1507,1507,1507),(1508,1508,1508),(1509,1509,1509),(1510,1510,1510),
+(1511,1511,1511),(1512,1512,1512),(1513,1513,1513),(1514,1514,1514),(1515,1515,1515),
+(1516,1516,1516),(1517,1517,1517),(1518,1518,1518),(1519,1519,1519),(1520,1520,1520),
+(1521,1521,1521),(1522,1522,1522),(1523,1523,1523),(1524,1524,1524),(1525,1525,1525),
+(1526,1526,1526),(1527,1527,1527),(1528,1528,1528),(1529,1529,1529),(1530,1530,1530),
+(1531,1531,1531),(1532,1532,1532),(1533,1533,1533),(1534,1534,1534),(1535,1535,1535),
+(1536,1536,1536),(1537,1537,1537),(1538,1538,1538),(1539,1539,1539),(1540,1540,1540),
+(1541,1541,1541),(1542,1542,1542),(1543,1543,1543),(1544,1544,1544),(1545,1545,1545),
+(1546,1546,1546),(1547,1547,1547),(1548,1548,1548),(1549,1549,1549),(1550,1550,1550),
+(1551,1551,1551),(1552,1552,1552),(1553,1553,1553),(1554,1554,1554),(1555,1555,1555),
+(1556,1556,1556),(1557,1557,1557),(1558,1558,1558),(1559,1559,1559),(1560,1560,1560),
+(1561,1561,1561),(1562,1562,1562),(1563,1563,1563),(1564,1564,1564),(1565,1565,1565),
+(1566,1566,1566),(1567,1567,1567),(1568,1568,1568),(1569,1569,1569),(1570,1570,1570),
+(1571,1571,1571),(1572,1572,1572),(1573,1573,1573),(1574,1574,1574),(1575,1575,1575),
+(1576,1576,1576),(1577,1577,1577),(1578,1578,1578),(1579,1579,1579),(1580,1580,1580),
+(1581,1581,1581),(1582,1582,1582),(1583,1583,1583),(1584,1584,1584),(1585,1585,1585),
+(1586,1586,1586),(1587,1587,1587),(1588,1588,1588),(1589,1589,1589),(1590,1590,1590),
+(1591,1591,1591),(1592,1592,1592),(1593,1593,1593),(1594,1594,1594),(1595,1595,1595),
+(1596,1596,1596),(1597,1597,1597),(1598,1598,1598),(1599,1599,1599),(1600,1600,1600),
+(1601,1601,1601),(1602,1602,1602),(1603,1603,1603),(1604,1604,1604),(1605,1605,1605),
+(1606,1606,1606),(1607,1607,1607),(1608,1608,1608),(1609,1609,1609),(1610,1610,1610),
+(1611,1611,1611),(1612,1612,1612),(1613,1613,1613),(1614,1614,1614),(1615,1615,1615),
+(1616,1616,1616),(1617,1617,1617),(1618,1618,1618),(1619,1619,1619),(1620,1620,1620),
+(1621,1621,1621),(1622,1622,1622),(1623,1623,1623),(1624,1624,1624),(1625,1625,1625),
+(1626,1626,1626),(1627,1627,1627),(1628,1628,1628),(1629,1629,1629),(1630,1630,1630),
+(1631,1631,1631),(1632,1632,1632),(1633,1633,1633),(1634,1634,1634),(1635,1635,1635),
+(1636,1636,1636),(1637,1637,1637),(1638,1638,1638),(1639,1639,1639),(1640,1640,1640),
+(1641,1641,1641),(1642,1642,1642),(1643,1643,1643),(1644,1644,1644),(1645,1645,1645),
+(1646,1646,1646),(1647,1647,1647),(1648,1648,1648),(1649,1649,1649),(1650,1650,1650),
+(1651,1651,1651),(1652,1652,1652),(1653,1653,1653),(1654,1654,1654),(1655,1655,1655),
+(1656,1656,1656),(1657,1657,1657),(1658,1658,1658),(1659,1659,1659),(1660,1660,1660),
+(1661,1661,1661),(1662,1662,1662),(1663,1663,1663),(1664,1664,1664),(1665,1665,1665),
+(1666,1666,1666),(1667,1667,1667),(1668,1668,1668),(1669,1669,1669),(1670,1670,1670),
+(1671,1671,1671),(1672,1672,1672),(1673,1673,1673),(1674,1674,1674),(1675,1675,1675),
+(1676,1676,1676),(1677,1677,1677),(1678,1678,1678),(1679,1679,1679),(1680,1680,1680),
+(1681,1681,1681),(1682,1682,1682),(1683,1683,1683),(1684,1684,1684),(1685,1685,1685),
+(1686,1686,1686),(1687,1687,1687),(1688,1688,1688),(1689,1689,1689),(1690,1690,1690),
+(1691,1691,1691),(1692,1692,1692),(1693,1693,1693),(1694,1694,1694),(1695,1695,1695),
+(1696,1696,1696),(1697,1697,1697),(1698,1698,1698),(1699,1699,1699),(1700,1700,1700),
+(1701,1701,1701),(1702,1702,1702),(1703,1703,1703),(1704,1704,1704),(1705,1705,1705),
+(1706,1706,1706),(1707,1707,1707),(1708,1708,1708),(1709,1709,1709),(1710,1710,1710),
+(1711,1711,1711),(1712,1712,1712),(1713,1713,1713),(1714,1714,1714),(1715,1715,1715),
+(1716,1716,1716),(1717,1717,1717),(1718,1718,1718),(1719,1719,1719),(1720,1720,1720),
+(1721,1721,1721),(1722,1722,1722),(1723,1723,1723),(1724,1724,1724),(1725,1725,1725),
+(1726,1726,1726),(1727,1727,1727),(1728,1728,1728),(1729,1729,1729),(1730,1730,1730),
+(1731,1731,1731),(1732,1732,1732),(1733,1733,1733),(1734,1734,1734),(1735,1735,1735),
+(1736,1736,1736),(1737,1737,1737),(1738,1738,1738),(1739,1739,1739),(1740,1740,1740),
+(1741,1741,1741),(1742,1742,1742),(1743,1743,1743),(1744,1744,1744),(1745,1745,1745),
+(1746,1746,1746),(1747,1747,1747),(1748,1748,1748),(1749,1749,1749),(1750,1750,1750),
+(1751,1751,1751),(1752,1752,1752),(1753,1753,1753),(1754,1754,1754),(1755,1755,1755),
+(1756,1756,1756),(1757,1757,1757),(1758,1758,1758),(1759,1759,1759),(1760,1760,1760),
+(1761,1761,1761),(1762,1762,1762),(1763,1763,1763),(1764,1764,1764),(1765,1765,1765),
+(1766,1766,1766),(1767,1767,1767),(1768,1768,1768),(1769,1769,1769),(1770,1770,1770),
+(1771,1771,1771),(1772,1772,1772),(1773,1773,1773),(1774,1774,1774),(1775,1775,1775),
+(1776,1776,1776),(1777,1777,1777),(1778,1778,1778),(1779,1779,1779),(1780,1780,1780),
+(1781,1781,1781),(1782,1782,1782),(1783,1783,1783),(1784,1784,1784),(1785,1785,1785),
+(1786,1786,1786),(1787,1787,1787),(1788,1788,1788),(1789,1789,1789),(1790,1790,1790),
+(1791,1791,1791),(1792,1792,1792),(1793,1793,1793),(1794,1794,1794),(1795,1795,1795),
+(1796,1796,1796),(1797,1797,1797),(1798,1798,1798),(1799,1799,1799),(1800,1800,1800),
+(1801,1801,1801),(1802,1802,1802),(1803,1803,1803),(1804,1804,1804),(1805,1805,1805),
+(1806,1806,1806),(1807,1807,1807),(1808,1808,1808),(1809,1809,1809),(1810,1810,1810),
+(1811,1811,1811),(1812,1812,1812),(1813,1813,1813),(1814,1814,1814),(1815,1815,1815),
+(1816,1816,1816),(1817,1817,1817),(1818,1818,1818),(1819,1819,1819),(1820,1820,1820),
+(1821,1821,1821),(1822,1822,1822),(1823,1823,1823),(1824,1824,1824),(1825,1825,1825),
+(1826,1826,1826),(1827,1827,1827),(1828,1828,1828),(1829,1829,1829),(1830,1830,1830),
+(1831,1831,1831),(1832,1832,1832),(1833,1833,1833),(1834,1834,1834),(1835,1835,1835),
+(1836,1836,1836),(1837,1837,1837),(1838,1838,1838),(1839,1839,1839),(1840,1840,1840),
+(1841,1841,1841),(1842,1842,1842),(1843,1843,1843),(1844,1844,1844),(1845,1845,1845),
+(1846,1846,1846),(1847,1847,1847),(1848,1848,1848),(1849,1849,1849),(1850,1850,1850),
+(1851,1851,1851),(1852,1852,1852),(1853,1853,1853),(1854,1854,1854),(1855,1855,1855),
+(1856,1856,1856),(1857,1857,1857),(1858,1858,1858),(1859,1859,1859),(1860,1860,1860),
+(1861,1861,1861),(1862,1862,1862),(1863,1863,1863),(1864,1864,1864),(1865,1865,1865),
+(1866,1866,1866),(1867,1867,1867),(1868,1868,1868),(1869,1869,1869),(1870,1870,1870),
+(1871,1871,1871),(1872,1872,1872),(1873,1873,1873),(1874,1874,1874),(1875,1875,1875),
+(1876,1876,1876),(1877,1877,1877),(1878,1878,1878),(1879,1879,1879),(1880,1880,1880),
+(1881,1881,1881),(1882,1882,1882),(1883,1883,1883),(1884,1884,1884),(1885,1885,1885),
+(1886,1886,1886),(1887,1887,1887),(1888,1888,1888),(1889,1889,1889),(1890,1890,1890),
+(1891,1891,1891),(1892,1892,1892),(1893,1893,1893),(1894,1894,1894),(1895,1895,1895),
+(1896,1896,1896),(1897,1897,1897),(1898,1898,1898),(1899,1899,1899),(1900,1900,1900),
+(1901,1901,1901),(1902,1902,1902),(1903,1903,1903),(1904,1904,1904),(1905,1905,1905),
+(1906,1906,1906),(1907,1907,1907),(1908,1908,1908),(1909,1909,1909),(1910,1910,1910),
+(1911,1911,1911),(1912,1912,1912),(1913,1913,1913),(1914,1914,1914),(1915,1915,1915),
+(1916,1916,1916),(1917,1917,1917),(1918,1918,1918),(1919,1919,1919),(1920,1920,1920),
+(1921,1921,1921),(1922,1922,1922),(1923,1923,1923),(1924,1924,1924),(1925,1925,1925),
+(1926,1926,1926),(1927,1927,1927),(1928,1928,1928),(1929,1929,1929),(1930,1930,1930),
+(1931,1931,1931),(1932,1932,1932),(1933,1933,1933),(1934,1934,1934),(1935,1935,1935),
+(1936,1936,1936),(1937,1937,1937),(1938,1938,1938),(1939,1939,1939),(1940,1940,1940),
+(1941,1941,1941),(1942,1942,1942),(1943,1943,1943),(1944,1944,1944),(1945,1945,1945),
+(1946,1946,1946),(1947,1947,1947),(1948,1948,1948),(1949,1949,1949),(1950,1950,1950),
+(1951,1951,1951),(1952,1952,1952),(1953,1953,1953),(1954,1954,1954),(1955,1955,1955),
+(1956,1956,1956),(1957,1957,1957),(1958,1958,1958),(1959,1959,1959),(1960,1960,1960),
+(1961,1961,1961),(1962,1962,1962),(1963,1963,1963),(1964,1964,1964),(1965,1965,1965),
+(1966,1966,1966),(1967,1967,1967),(1968,1968,1968),(1969,1969,1969),(1970,1970,1970),
+(1971,1971,1971),(1972,1972,1972),(1973,1973,1973),(1974,1974,1974),(1975,1975,1975),
+(1976,1976,1976),(1977,1977,1977),(1978,1978,1978),(1979,1979,1979),(1980,1980,1980),
+(1981,1981,1981),(1982,1982,1982),(1983,1983,1983),(1984,1984,1984),(1985,1985,1985),
+(1986,1986,1986),(1987,1987,1987),(1988,1988,1988),(1989,1989,1989),(1990,1990,1990),
+(1991,1991,1991),(1992,1992,1992),(1993,1993,1993),(1994,1994,1994),(1995,1995,1995),
+(1996,1996,1996),(1997,1997,1997),(1998,1998,1998),(1999,1999,1999);
+
+SELECT COUNT(*) FROM t1;
+
+
+
+DROP TABLE t1;
diff --git a/mysql-test/t/ndb_minmax.test b/mysql-test/t/ndb_minmax.test
new file mode 100644
index 00000000000..3be193ce602
--- /dev/null
+++ b/mysql-test/t/ndb_minmax.test
@@ -0,0 +1,66 @@
+-- source include/have_ndb.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+CREATE TABLE t1 (
+ a int PRIMARY KEY
+) engine = ndb;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (6);
+
+select MAX(a) from t1;
+select MAX(a) from t1;
+select MAX(a) from t1;
+select MAX(a) from t1;
+select MIN(a) from t1;
+select MIN(a) from t1;
+select MIN(a) from t1;
+select * from t1 order by a;
+select MIN(a) from t1;
+select MAX(a) from t1;
+select MAX(a) from t1;
+select * from t1 order by a;
+drop table t1;
+
+
+CREATE TABLE t2 (
+ a int PRIMARY KEY,
+ b int not null,
+ c int not null,
+ KEY(b),
+ UNIQUE(c)
+) engine = ndb;
+
+INSERT INTO t2 VALUES (1, 5, 1);
+INSERT INTO t2 VALUES (2, 2, 7);
+INSERT INTO t2 VALUES (3, 3, 3);
+INSERT INTO t2 VALUES (4, 4, 4);
+INSERT INTO t2 VALUES (5, 5, 5);
+INSERT INTO t2 VALUES (6, 6, 6);
+INSERT INTO t2 VALUES (7, 2, 10);
+INSERT INTO t2 VALUES (8, 10, 2);
+
+
+select MAX(a) from t2;
+select MAX(b) from t2;
+select MAX(c) from t2;
+select MIN(a) from t2;
+select MIN(b) from t2;
+select MIN(c) from t2;
+select * from t2 order by a;
+select MIN(b) from t2;
+select MAX(a) from t2;
+select MAX(c) from t2;
+select * from t2 order by a;
+drop table t2;
+
+
+
+
diff --git a/mysql-test/t/ndb_replace.test b/mysql-test/t/ndb_replace.test
new file mode 100644
index 00000000000..8ba332fc7af
--- /dev/null
+++ b/mysql-test/t/ndb_replace.test
@@ -0,0 +1,27 @@
+-- source include/have_ndb.inc
+
+#
+# Test of REPLACE with NDB
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+CREATE TABLE t1 (
+ gesuchnr int(11) DEFAULT '0' NOT NULL,
+ benutzer_id int(11) DEFAULT '0' NOT NULL,
+ PRIMARY KEY (gesuchnr,benutzer_id)
+) engine=ndbcluster;
+
+replace into t1 (gesuchnr,benutzer_id) values (2,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+insert into t1 (gesuchnr, benutzer_id) value (3,2);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+--error 1022
+insert into t1 (gesuchnr,benutzer_id) values (1,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+select * from t1 order by gesuchnr;
+drop table t1;
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
new file mode 100644
index 00000000000..35f9b193fe4
--- /dev/null
+++ b/mysql-test/t/ps.test
@@ -0,0 +1,208 @@
+#
+# SQL Syntax for Prepared Statements test
+#
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+create table t1
+(
+ a int primary key,
+ b char(10)
+);
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+
+# basic functionality
+set @a=2;
+prepare stmt1 from 'select * from t1 where a <= ?';
+execute stmt1 using @a;
+set @a=3;
+execute stmt1 using @a;
+
+# non-existant statement
+--error 1243
+deallocate prepare no_such_statement;
+
+--error 1210
+execute stmt1;
+
+# Nesting ps commands is not allowed:
+--error 1064
+prepare stmt2 from 'prepare nested_stmt from "select 1"';
+
+--error 1064
+prepare stmt2 from 'execute stmt1';
+
+--error 1064
+prepare stmt2 from 'deallocate prepare z';
+
+# PS insert
+prepare stmt3 from 'insert into t1 values (?,?)';
+set @arg1=5, @arg2='five';
+execute stmt3 using @arg1, @arg2;
+select * from t1 where a>3;
+
+# PS update
+prepare stmt4 from 'update t1 set a=? where b=?';
+set @arg1=55, @arg2='five';
+execute stmt4 using @arg1, @arg2;
+select * from t1 where a>3;
+
+# PS create/delete
+prepare stmt4 from 'create table t2 (a int)';
+execute stmt4;
+prepare stmt4 from 'drop table t2';
+execute stmt4;
+
+# Do something that will cause error
+--error 1051
+execute stmt4;
+
+# placeholders in result field names.
+prepare stmt5 from 'select ? + a from t1';
+set @a=1;
+execute stmt5 using @a;
+
+execute stmt5 using @no_such_var;
+
+set @nullvar=1;
+set @nullvar=NULL;
+execute stmt5 using @nullvar;
+
+set @nullvar2=NULL;
+execute stmt5 using @nullvar2;
+
+# Check that multiple SQL statements are disabled inside PREPARE
+--error 1064
+prepare stmt6 from 'select 1; select2';
+
+--error 1064
+prepare stmt6 from 'insert into t1 values (5,"five"); select2';
+
+# This shouldn't parse
+--error 1064
+explain prepare stmt6 from 'insert into t1 values (5,"five"); select2';
+
+create table t2
+(
+ a int
+);
+
+insert into t2 values (0);
+
+# parameter is NULL
+set @arg00=NULL ;
+prepare stmt1 from 'select 1 FROM t2 where a=?' ;
+execute stmt1 using @arg00 ;
+
+# prepare using variables:
+--error 1064
+prepare stmt1 from @nosuchvar;
+
+set @ivar= 1234;
+--error 1064
+prepare stmt1 from @ivar;
+
+set @fvar= 123.4567;
+--error 1064
+prepare stmt1 from @fvar;
+
+set @str1 = 'select ?';
+set @str2 = convert(@str1 using ucs2);
+prepare stmt1 from @str2;
+execute stmt1 using @ivar;
+drop table t1,t2;
+
+#
+# Bug #4105: Server crash on attempt to prepare a statement with character
+# set introducer
+#
+PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?";
+set @var='A';
+EXECUTE stmt1 USING @var;
+DEALLOCATE PREPARE stmt1;
+
+#
+# BUG#3486: FOUND_ROWS() fails inside stored procedure [and prepared statement]
+#
+create table t1 (id int);
+prepare stmt1 from "select FOUND_ROWS()";
+select SQL_CALC_FOUND_ROWS * from t1;
+# Expect 0
+execute stmt1;
+insert into t1 values (1);
+select SQL_CALC_FOUND_ROWS * from t1;
+# Expect 1
+execute stmt1;
+# Expect 0
+execute stmt1;
+deallocate prepare stmt1;
+drop table t1;
+
+#
+# prepared EXPLAIN
+#
+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,
+ 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,
+ c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+ c32 set('monday', 'tuesday', 'wednesday')
+) engine = MYISAM ;
+create table t2 like t1;
+
+set @stmt= ' explain SELECT (SELECT SUM(c1 + c12 + 0.0) FROM t2 where (t1.c2 - 0e-3) = t2.c2 GROUP BY t1.c15 LIMIT 1) as scalar_s, exists (select 1.0e+0 from t2 where t2.c3 * 9.0000000000 = t1.c4) as exists_s, c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s, (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s FROM t1, (select c25 x, c32 y from t2) tt WHERE x * 1 = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+explain SELECT (SELECT SUM(c1 + c12 + 0.0) FROM t2 where (t1.c2 - 0e-3) = t2.c2 GROUP BY t1.c15 LIMIT 1) as scalar_s, exists (select 1.0e+0 from t2 where t2.c3 * 9.0000000000 = t1.c4) as exists_s, c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s, (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s FROM t1, (select c25 x, c32 y from t2) tt WHERE x * 1 = c25;
+deallocate prepare stmt1;
+drop tables t1,t2;
+
+#
+# parameters from variables (for field creation)
+#
+set @arg00=1;
+prepare stmt1 from ' create table t1 (m int) as select 1 as m ' ;
+execute stmt1 ;
+select m from t1;
+drop table t1;
+prepare stmt1 from ' create table t1 (m int) as select ? as m ' ;
+execute stmt1 using @arg00;
+select m from t1;
+deallocate prepare stmt1;
+drop table t1;
+
+#
+# eq() for parameters
+#
+create table t1 (id int(10) unsigned NOT NULL default '0',
+ name varchar(64) NOT NULL default '',
+ PRIMARY KEY (id), UNIQUE KEY `name` (`name`));
+insert into t1 values (1,'1'),(2,'2'),(3,'3'),(4,'4'),(5,'5'),(6,'6'),(7,'7');
+prepare stmt1 from 'select name from t1 where id=? or id=?';
+set @id1=1,@id2=6;
+execute stmt1 using @id1, @id2;
+select name from t1 where id=1 or id=6;
+deallocate prepare stmt1;
+drop table t1;
+
+#
+# SHOW TABLE STATUS test
+#
+create table t1 ( a int primary key, b varchar(30)) engine = MYISAM ;
+prepare stmt1 from ' show table status from test like ''t1%'' ';
+--replace_column 12 # 13 # 14 #
+execute stmt1;
+--replace_column 12 # 13 # 14 #
+show table status from test like 't1%' ;
+deallocate prepare stmt1 ;
+drop table t1;
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
new file mode 100644
index 00000000000..b7686bbd26a
--- /dev/null
+++ b/mysql-test/t/ps_1general.test
@@ -0,0 +1,739 @@
+###################### ps_general.test #######################
+# #
+# basic and miscellaneous tests for prepared statements #
+# #
+##############################################################
+
+
+# Please do not
+# - modify (INSERT/UPDATE/DELETE) the content of the tables
+# t1 and t_many_col_types. Such tests should be done in
+# include/ps_modify.inc
+# - insert test cases where the results depend on the
+# table type. Such tests should be done in the files
+# include/ps_query.inc, include/ps_modify ...
+#
+
+use test;
+--disable_query_log
+select '------ basic tests ------' as test_sequence ;
+--enable_query_log
+
+let $type= 'MYISAM' ;
+# create the tables (t1 and t_many_col_types) used in many tests
+--source include/ps_create.inc
+# insert data into these tables
+--source include/ps_renew.inc
+
+
+##### The basic functions ####
+
+# 1. PREPARE stmt_name FROM <preparable statement>;
+# <preparable statement> ::=
+# 'literal_stmt' |
+# @variable_ref_stmt.
+# The statement may contain question marks as placeholders for parameters.
+#
+# Bind a statement name to a string containing a SQL statement and
+# send it to the server. The server will parse the statement and
+# reply with "Query Ok" or an error message.
+#
+PREPARE stmt FROM ' select * from t1 where a = ? ' ;
+
+# 2. EXECUTE stmt_name [USING @var [, @var ]];
+# Current values of supplied variables are used as parameters.
+#
+# Send the server the order to execute the statement and supply values
+# for the input parameters needed.
+# If no error occurs the server reply will be identical to the reply for
+# the query used in PREPARE with question marks replaced with values of
+# the input variables.
+#
+SET @var= 2 ;
+EXECUTE stmt USING @var ;
+# The non prepared statement with the same server reply would be:
+select * from t1 where a = @var ;
+
+# 3. DEALLOCATE PREPARE stmt_name;
+#
+# Send the server the order to drop the parse informations.
+# The server will reply with "Query Ok" or an error message.
+DEALLOCATE PREPARE stmt ;
+
+## prepare
+# prepare without parameter
+prepare stmt1 from ' select 1 as my_col ' ;
+# prepare with parameter
+prepare stmt1 from ' select ? as my_col ' ;
+# prepare must fail (incomplete statements/wrong syntax)
+--error 1064
+prepare ;
+--error 1064
+prepare stmt1 ;
+--error 1064
+prepare stmt1 from ;
+--error 1064
+prepare_garbage stmt1 from ' select 1 ' ;
+--error 1064
+prepare stmt1 from_garbage ' select 1 ' ;
+--error 1064
+prepare stmt1 from ' select_garbage 1 ' ;
+--error 1064
+prepare from ' select 1 ' ;
+--error 1064
+prepare stmt1 ' select 1 ' ;
+--error 1064
+prepare ? from ' select ? as my_col ' ;
+# statement in variable
+set @arg00='select 1 as my_col';
+prepare stmt1 from @arg00;
+# prepare must fail (query variable is empty)
+set @arg00='';
+--error 1065
+prepare stmt1 from @arg00;
+set @arg00=NULL;
+# prepare must fail (query variable is NULL)
+--error 1064
+prepare stmt1 from @arg01;
+
+prepare stmt1 from ' select * from t1 where a <= 2 ' ;
+# prepare must fail (column does not exist)
+--error 1054
+prepare stmt1 from ' select * from t1 where x <= 2 ' ;
+--disable_warnings
+drop table if exists not_exist ;
+--enable_warnings
+# prepare must fail (table does not exist)
+--error 1146
+prepare stmt1 from ' select * from not_exist where a <= 2 ' ;
+
+# case derived from client_test.c: test_prepare_syntax()
+# prepare must fail (incomplete statement)
+--error 1064
+prepare stmt1 from ' insert into t1 values(? ' ;
+--error 1064
+prepare stmt1 from ' select a, b from t1
+ where a=? and where ' ;
+
+## execute
+# execute must fail (statement never_prepared never prepared)
+--error 1243
+execute never_prepared ;
+# execute must fail (prepare stmt1 just failed,
+# but there was a successful prepare of stmt1 before)
+prepare stmt1 from ' select * from t1 where a <= 2 ' ;
+--error 1146
+prepare stmt1 from ' select * from not_exist where a <= 2 ' ;
+--error 1243
+execute stmt1 ;
+
+# drop the table between prepare and execute
+create table to_be_dropped
+(
+ a int primary key,
+ b char(30),
+ c int
+);
+insert into to_be_dropped( a, b, c) values( 1, 'original table', 1);
+prepare stmt2 from ' select * from to_be_dropped ' ;
+execute stmt2 ;
+drop table to_be_dropped ;
+# execute must fail (table was dropped after prepare)
+--error 1146
+execute stmt2 ;
+# cases derived from client_test.c: test_select_prepare()
+# 1. drop + create table (same column names/types/order)
+# between prepare and execute
+create table to_be_dropped
+(
+ a int primary key,
+ b char(30),
+ c int
+);
+insert into to_be_dropped( a, b, c) values( 9, 'recreated table', 9);
+execute stmt2 ;
+drop table to_be_dropped ;
+# 2. drop + create table (same column names/types but different order)
+# between prepare and execute
+create table to_be_dropped
+(
+ a int primary key,
+ c int,
+ b char(30)
+);
+insert into to_be_dropped( a, b, c) values( 9, 'recreated table', 9);
+execute stmt2 ;
+drop table to_be_dropped ;
+# 3. drop + create table (same column names/types/order+extra column)
+# between prepare and execute
+create table to_be_dropped
+(
+ a int primary key,
+ b char(30),
+ c int,
+ d timestamp default current_timestamp
+);
+insert into to_be_dropped( a, b, c) values( 9, 'recreated table', 9);
+execute stmt2 ;
+drop table to_be_dropped ;
+# 4. drop + create table (same column names/types, different order +
+# additional column) between prepare and execute
+create table to_be_dropped
+(
+ a int primary key,
+ d timestamp default current_timestamp,
+ b char(30),
+ c int
+);
+insert into to_be_dropped( a, b, c) values( 9, 'recreated table', 9);
+execute stmt2 ;
+drop table to_be_dropped ;
+# 5. drop + create table (same column names/order, different types)
+# between prepare and execute
+create table to_be_dropped
+(
+ a timestamp default '2004-02-29 18:01:59',
+ b char(30),
+ c int
+);
+insert into to_be_dropped( b, c) values( 'recreated table', 9);
+execute stmt2 ;
+drop table to_be_dropped ;
+# 6. drop + create table (same column types/order, different names)
+# between prepare and execute
+create table to_be_dropped
+(
+ f1 int primary key,
+ f2 char(30),
+ f3 int
+);
+insert into to_be_dropped( f1, f2, f3) values( 9, 'recreated table', 9);
+--error 1054
+execute stmt2 ;
+drop table to_be_dropped ;
+
+# execute without parameter
+prepare stmt1 from ' select * from t1 where a <= 2 ' ;
+execute stmt1 ;
+# execute with parameter
+set @arg00=1 ;
+set @arg01='two' ;
+prepare stmt1 from ' select * from t1 where a <= ? ' ;
+execute stmt1 using @arg00;
+# execute must fail (too small number of parameters)
+--error 1210
+execute stmt1 ;
+# execute must fail (too big number of parameters)
+--error 1210
+execute stmt1 using @arg00, @arg01;
+# execute must fail (parameter is not set)
+execute stmt1 using @not_set;
+
+## deallocate
+# deallocate must fail (never_prepared was never prepared)
+--error 1243
+deallocate prepare never_prepared ;
+# deallocate must fail (prepare stmt1 just failed,
+# but there was a successful prepare before)
+prepare stmt1 from ' select * from t1 where a <= 2 ' ;
+--error 1146
+prepare stmt1 from ' select * from not_exist where a <= 2 ' ;
+--error 1243
+deallocate prepare stmt1;
+create table to_be_dropped
+(
+ a int primary key,
+ b char(10)
+);
+prepare stmt2 from ' select a,b from to_be_dropped where a <= 2 ' ;
+drop table to_be_dropped ;
+# deallocate prepared statement where the table was dropped after prepare
+deallocate prepare stmt2;
+
+## parallel use of more than one prepared statement handlers
+# switch between different queries
+prepare stmt1 from ' select a from t1 where a <= 2 ' ;
+prepare stmt2 from ' select b from t1 where a <= 2 ' ;
+execute stmt2 ;
+execute stmt1 ;
+# switch between statement handlers of the same query
+prepare stmt1 from ' select a from t1 where a <= 2 ' ;
+prepare stmt2 from ' select a from t1 where a <= 2 ' ;
+execute stmt2 ;
+execute stmt1 ;
+deallocate prepare stmt1 ;
+# Will the deallocate of stmt1 with the same query affect stmt2 ?
+execute stmt2 ;
+
+--disable_query_log
+select '------ show and misc tests ------' as test_sequence ;
+--enable_query_log
+
+--disable_warnings
+drop table if exists t2;
+--enable_warnings
+create table t2
+(
+ a int primary key, b char(10)
+);
+
+###### SHOW COMMANDS
+prepare stmt4 from ' show databases ';
+execute stmt4;
+prepare stmt4 from ' show tables from test like ''t2%'' ';
+execute stmt4;
+prepare stmt4 from ' show columns from t2 from test like ''a%'' ';
+execute stmt4;
+create index t2_idx on t2(b);
+prepare stmt4 from ' show index from t2 from test ';
+execute stmt4;
+prepare stmt4 from ' show table status from test like ''t2%'' ';
+# egalize date and time values
+--replace_column 12 # 13 # 14 #
+# Bug#4288 : prepared statement 'show table status ..', wrong output on execute
+execute stmt4;
+# try the same with the big table
+prepare stmt4 from ' show table status from test like ''t_many_col_types%'' ';
+# egalize date and time values
+--replace_column 12 # 13 # 14 #
+# Bug#4288
+execute stmt4;
+prepare stmt4 from ' show status like ''Threads_running'' ';
+execute stmt4;
+prepare stmt4 from ' show variables like ''sql_mode'' ';
+execute stmt4;
+prepare stmt4 from ' show engine bdb logs ';
+# The output depends on the history (actions of the bdb engine).
+# That is the reason why, we switch the output here off.
+# (The real output will be tested in ps_6bdb.test)
+# --replace_result $MYSQL_TEST_DIR TEST_DIR
+--disable_result_log
+execute stmt4;
+--enable_result_log
+prepare stmt4 from ' show full processlist ';
+--replace_column 1 number
+execute stmt4;
+prepare stmt4 from ' show grants for user ';
+--error 1295
+prepare stmt4 from ' show create table t2 ';
+--error 1295
+prepare stmt4 from ' show master status ';
+--error 1295
+prepare stmt4 from ' show master logs ';
+--error 1295
+prepare stmt4 from ' show slave status ';
+--error 1295
+prepare stmt4 from ' show warnings limit 20 ';
+--error 1295
+prepare stmt4 from ' show errors limit 20 ';
+prepare stmt4 from ' show storage engines ';
+--replace_column 2 YES/NO
+execute stmt4;
+
+###### MISC STUFF
+## get a warning and an error
+# cases derived from client_test.c: test_warnings(), test_errors()
+--disable_warnings
+drop table if exists tx;
+--enable_warnings
+prepare stmt1 from ' drop table if exists tx ' ;
+execute stmt1 ;
+prepare stmt1 from ' drop table tx ' ;
+--error 1051
+execute stmt1 ;
+
+## nonsense like prepare of prepare,execute or deallocate
+--error 1064
+prepare stmt1 from ' prepare stmt2 from '' select 1 '' ' ;
+--error 1064
+prepare stmt1 from ' execute stmt2 ' ;
+--error 1064
+prepare stmt1 from ' deallocate prepare never_prepared ' ;
+
+## switch the database connection
+--error 1295
+prepare stmt4 from ' use test ' ;
+
+## create/drop database
+--error 1295
+prepare stmt3 from ' create database drop_me ';
+create database drop_me ;
+--error 1295
+prepare stmt3 from ' drop database drop_me ';
+drop database drop_me ;
+
+## grant/revoke + drop user
+--error 1295
+prepare stmt3 from ' grant all on test.t1 to drop_user@localhost
+identified by ''looser'' ';
+grant all on test.t1 to drop_user@localhost
+identified by 'looser' ;
+--error 1295
+prepare stmt3 from ' revoke all privileges on test.t1 from
+drop_user@localhost ';
+revoke all privileges on test.t1 from drop_user@localhost ;
+--error 1295
+prepare stmt3 from ' drop user drop_user@localhost ';
+drop user drop_user@localhost;
+--error 1141
+
+#### table related commands
+## describe
+prepare stmt3 from ' describe t2 ';
+execute stmt3;
+drop table t2 ;
+--error 1146
+execute stmt3;
+## lock/unlock
+--error 1295
+prepare stmt3 from ' lock tables t1 read ' ;
+--error 1295
+prepare stmt3 from ' unlock tables ' ;
+## Load/Unload table contents
+--error 1295
+prepare stmt1 from ' load data infile ''data.txt''
+into table t1 fields terminated by ''\t'' ';
+prepare stmt1 from ' select * into outfile ''data.txt'' from t1 ';
+execute stmt1 ;
+##
+--error 1295
+prepare stmt1 from ' optimize table t1 ' ;
+--error 1295
+prepare stmt1 from ' analyze table t1 ' ;
+--error 1295
+prepare stmt1 from ' checksum table t1 ' ;
+--error 1295
+prepare stmt1 from ' repair table t1 ' ;
+--error 1295
+prepare stmt1 from ' restore table t1 from ''data.txt'' ' ;
+## handler
+--error 1295
+prepare stmt1 from ' handler t1 open ';
+
+
+## commit/rollback
+--error 1295
+prepare stmt3 from ' commit ' ;
+--error 1295
+prepare stmt3 from ' rollback ' ;
+
+
+## switch the sql_mode
+prepare stmt4 from ' SET sql_mode=ansi ';
+execute stmt4;
+# check if the sql_mode is now ansi
+select 'a' || 'b' ;
+prepare stmt4 from ' SET sql_mode="" ';
+execute stmt4;
+# check if the sql_mode is not ansi
+select 'a' || 'b' ;
+# Will a switch of the sqlmode affect the execution of already prepared
+# statements ?
+prepare stmt5 from ' select ''a'' || ''b'' ' ;
+execute stmt5;
+SET sql_mode=ansi;
+execute stmt5;
+SET sql_mode="";
+
+--error 1295
+prepare stmt1 from ' flush local privileges ' ;
+--error 1295
+prepare stmt1 from ' reset query cache ' ;
+--error 1295
+prepare stmt1 from ' KILL 0 ';
+
+## simple explain
+# cases derived from client_test.c: test_explain_bug()
+prepare stmt1 from ' explain select a from t1 order by b ';
+--enable_metadata
+execute stmt1;
+--disable_metadata
+SET @arg00=1 ;
+prepare stmt1 from ' explain select a from t1 where a > ? order by b ';
+--enable_metadata
+execute stmt1 using @arg00;
+--disable_metadata
+
+--disable_query_log
+select '------ create/drop/alter/rename tests ------' as test_sequence ;
+--enable_query_log
+
+--disable_warnings
+drop table if exists t2, t3;
+--enable_warnings
+
+prepare stmt_drop from ' drop table if exists t2 ' ;
+--disable_warnings
+execute stmt_drop;
+--enable_warnings
+
+prepare stmt_create from ' create table t2 (
+ a int primary key, b char(10)) ';
+execute stmt_create;
+prepare stmt3 from ' create table t3 like t2 ';
+execute stmt3;
+drop table t3;
+
+set @arg00=1;
+prepare stmt3 from ' create table t3 (m int) select ? as m ' ;
+# Bug#4280 server hangs, prepared "create table .. as select ? .."
+execute stmt3 using @arg00;
+select m from t3;
+drop table t3;
+
+--error 1295
+prepare stmt3 from ' create index t2_idx on t2(b) ';
+--error 1295
+prepare stmt3 from ' drop index t2_idx on t2 ' ;
+--error 1295
+prepare stmt3 from ' alter table t2 drop primary key ';
+--disable_warnings
+drop table if exists new_t2;
+--enable_warnings
+prepare stmt3 from ' rename table t2 to new_t2 ';
+execute stmt3;
+--error 1050
+execute stmt3;
+rename table new_t2 to t2;
+drop table t2;
+
+--disable_query_log
+select '------ big statement tests ------' as test_sequence ;
+--enable_query_log
+# Attention: The limits used are NOT derived from the manual
+# or other sources.
+
+## many lines ( 50 )
+select 'ABC' as my_const_col from t1 where
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 ;
+prepare stmt1 from ' select ''ABC'' as my_const_col FROM t1 WHERE
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 AND
+1 = 1 ' ;
+execute stmt1 ;
+execute stmt1 ;
+
+## many characters ( about 1400 )
+
+select 'ABC' as my_const_col FROM t1 WHERE
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' AND
+'1234567890123456789012345678901234567890123456789012345678901234567890'
+= '1234567890123456789012345678901234567890123456789012345678901234567890' ;
+prepare stmt1 from ' select ''ABC'' as my_const_col FROM t1 WHERE
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' AND
+''1234567890123456789012345678901234567890123456789012345678901234567890''
+= ''1234567890123456789012345678901234567890123456789012345678901234567890'' ';
+execute stmt1 ;
+execute stmt1 ;
+
+
+## many parameters ( 50 )
+set @arg00= 1;
+set @arg01= 1;
+set @arg02= 1;
+set @arg03= 1;
+set @arg04= 1;
+set @arg05= 1;
+set @arg06= 1;
+set @arg07= 1;
+set @arg10= 1;
+set @arg11= 1;
+set @arg12= 1;
+set @arg13= 1;
+set @arg14= 1;
+set @arg15= 1;
+set @arg16= 1;
+set @arg17= 1;
+set @arg20= 1;
+set @arg21= 1;
+set @arg22= 1;
+set @arg23= 1;
+set @arg24= 1;
+set @arg25= 1;
+set @arg26= 1;
+set @arg27= 1;
+set @arg30= 1;
+set @arg31= 1;
+set @arg32= 1;
+set @arg33= 1;
+set @arg34= 1;
+set @arg35= 1;
+set @arg36= 1;
+set @arg37= 1;
+set @arg40= 1;
+set @arg41= 1;
+set @arg42= 1;
+set @arg43= 1;
+set @arg44= 1;
+set @arg45= 1;
+set @arg46= 1;
+set @arg47= 1;
+set @arg50= 1;
+set @arg51= 1;
+set @arg52= 1;
+set @arg53= 1;
+set @arg54= 1;
+set @arg55= 1;
+set @arg56= 1;
+set @arg57= 1;
+set @arg60= 1;
+set @arg61= 1;
+
+select 'ABC' as my_const_col FROM t1 WHERE
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and @arg00=@arg00 and
+@arg00=@arg00 ;
+prepare stmt1 from ' select ''ABC'' as my_const_col FROM t1 WHERE
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? and ? = ? and ? = ? and ? = ? and
+ ? = ? ' ;
+execute stmt1 using
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00;
+execute stmt1 using
+@arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07,
+@arg10, @arg11, @arg12, @arg13, @arg14, @arg15, @arg16, @arg17,
+@arg20, @arg21, @arg22, @arg23, @arg24, @arg25, @arg26, @arg27,
+@arg30, @arg31, @arg32, @arg33, @arg34, @arg35, @arg36, @arg37,
+@arg40, @arg41, @arg42, @arg43, @arg44, @arg45, @arg46, @arg47,
+@arg50, @arg51, @arg52, @arg53, @arg54, @arg55, @arg56, @arg57,
+@arg60, @arg61 ;
+
+drop table t1 ;
diff --git a/mysql-test/t/ps_2myisam.test b/mysql-test/t/ps_2myisam.test
new file mode 100644
index 00000000000..3bb8b01cf87
--- /dev/null
+++ b/mysql-test/t/ps_2myisam.test
@@ -0,0 +1,17 @@
+###############################################
+# #
+# Prepared Statements test on MYISAM tables #
+# #
+###############################################
+
+use test;
+
+let $type= 'MYISAM' ;
+-- source include/ps_create.inc
+-- source include/ps_renew.inc
+
+-- source include/ps_query.inc
+-- source include/ps_modify.inc
+-- source include/ps_modify1.inc
+
+drop table t1, t_many_col_types;
diff --git a/mysql-test/t/ps_3innodb.test b/mysql-test/t/ps_3innodb.test
new file mode 100644
index 00000000000..71acf3b76f1
--- /dev/null
+++ b/mysql-test/t/ps_3innodb.test
@@ -0,0 +1,17 @@
+###############################################
+# #
+# Prepared Statements test on InnoDB tables #
+# #
+###############################################
+
+use test;
+
+let $type= 'InnoDB' ;
+-- source include/ps_create.inc
+-- source include/ps_renew.inc
+
+-- source include/ps_query.inc
+-- source include/ps_modify.inc
+-- source include/ps_modify1.inc
+
+drop table t1, t_many_col_types;
diff --git a/mysql-test/t/ps_4heap.test b/mysql-test/t/ps_4heap.test
new file mode 100644
index 00000000000..8aa715b095e
--- /dev/null
+++ b/mysql-test/t/ps_4heap.test
@@ -0,0 +1,43 @@
+###############################################
+# #
+# Prepared Statements test on HEAP tables #
+# #
+###############################################
+
+use test;
+
+let $type= 'HEAP' ;
+--disable_warnings
+drop table if exists t1, t_many_col_types ;
+--enable_warnings
+eval create table t1
+(
+ a int, b varchar(30),
+ primary key(a)
+) engine = $type ;
+
+--disable_warnings
+drop table if exists t_many_col_types;
+--enable_warnings
+# The used table type doesn't support BLOB/TEXT columns (error 1163)
+# So we use char(100) instead.
+eval create table t_many_col_types
+(
+ 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,
+ c17 year, c18 bit, c19 bool, c20 char,
+ c21 char(10), c22 varchar(30), c23 char(100), c24 char(100),
+ c25 char(100), c26 char(100), c27 char(100), c28 char(100),
+ c29 char(100), c30 char(100), c31 enum('one', 'two', 'three'),
+ c32 set('monday', 'tuesday', 'wednesday'),
+ primary key(c1)
+) engine = $type ;
+-- source include/ps_renew.inc
+
+-- source include/ps_query.inc
+-- source include/ps_modify.inc
+-- source include/ps_modify1.inc
+
+drop table t1, t_many_col_types;
diff --git a/mysql-test/t/ps_5merge.test b/mysql-test/t/ps_5merge.test
new file mode 100644
index 00000000000..ee4beea78c4
--- /dev/null
+++ b/mysql-test/t/ps_5merge.test
@@ -0,0 +1,78 @@
+###############################################
+# #
+# Prepared Statements test on MERGE tables #
+# #
+###############################################
+
+use test;
+
+--disable_warnings
+drop table if exists t1, t1_1, t1_2,
+ t_many_col_types, t_many_col_types_1, t_many_col_types_2;
+--enable_warnings
+let $type= 'MYISAM' ;
+-- source include/ps_create.inc
+rename table t1 to t1_1, t_many_col_types to t_many_col_types_1 ;
+-- source include/ps_create.inc
+rename table t1 to t1_2, t_many_col_types to t_many_col_types_2 ;
+
+create table t1
+(
+ a int, b varchar(30),
+ primary key(a)
+) ENGINE = MERGE UNION=(t1_1,t1_2)
+INSERT_METHOD=FIRST;
+create table t_many_col_types
+(
+ 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,
+ 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,
+ c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+ c32 set('monday', 'tuesday', 'wednesday'),
+ primary key(c1)
+) ENGINE = MERGE UNION=(t_many_col_types_1,t_many_col_types_2)
+INSERT_METHOD=FIRST;
+-- source include/ps_renew.inc
+
+-- source include/ps_query.inc
+-- source include/ps_modify.inc
+# no test of ps_modify1, because insert .. select
+# is not allowed on MERGE tables
+# -- source include/ps_modify1.inc
+
+# Lets's try the same tests with INSERT_METHOD=LAST
+drop table t1, t_many_col_types ;
+create table t1
+(
+ a int, b varchar(30),
+ primary key(a)
+) ENGINE = MERGE UNION=(t1_1,t1_2)
+INSERT_METHOD=LAST;
+create table t_many_col_types
+(
+ 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,
+ 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,
+ c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+ c32 set('monday', 'tuesday', 'wednesday'),
+ primary key(c1)
+) ENGINE = MERGE UNION=(t_many_col_types_1,t_many_col_types_2)
+INSERT_METHOD=LAST;
+-- source include/ps_renew.inc
+
+-- source include/ps_query.inc
+-- source include/ps_modify.inc
+# no test of ps_modify1, because insert .. select
+# is not allowed on MERGE tables
+# -- source include/ps_modify1.inc
+
+drop table t1, t1_1, t1_2,
+ t_many_col_types_1, t_many_col_types_2, t_many_col_types;
diff --git a/mysql-test/t/ps_6bdb.test b/mysql-test/t/ps_6bdb.test
new file mode 100644
index 00000000000..dde6a05268e
--- /dev/null
+++ b/mysql-test/t/ps_6bdb.test
@@ -0,0 +1,18 @@
+###############################################
+# #
+# Prepared Statements test on BDB tables #
+# #
+###############################################
+
+use test;
+
+-- source include/have_bdb.inc
+let $type= 'BDB' ;
+-- source include/ps_create.inc
+-- source include/ps_renew.inc
+
+-- source include/ps_query.inc
+-- source include/ps_modify.inc
+-- source include/ps_modify1.inc
+
+drop table t1, t_many_col_types;
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index 4665cd02ed8..471af8e4a5b 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -255,7 +255,34 @@ WHERE
);
DROP TABLE t1;
+#
+# Test of problem with IN on many different keyparts. (Bug #4157)
+#
+
+CREATE TABLE t1 (
+id int( 11 ) unsigned NOT NULL AUTO_INCREMENT ,
+line int( 5 ) unsigned NOT NULL default '0',
+columnid int( 3 ) unsigned NOT NULL default '0',
+owner int( 3 ) unsigned NOT NULL default '0',
+ordinal int( 3 ) unsigned NOT NULL default '0',
+showid smallint( 6 ) unsigned NOT NULL default '1',
+tableid int( 1 ) unsigned NOT NULL default '1',
+content int( 5 ) unsigned NOT NULL default '188',
+PRIMARY KEY ( owner, id ) ,
+KEY menu( owner, showid, columnid ) ,
+KEY `COLUMN` ( owner, columnid, line ) ,
+KEY `LINES` ( owner, tableid, content, id ) ,
+KEY recount( owner, line )
+) ENGINE = MYISAM;
+
+INSERT into t1 (owner,id,columnid,line) values (11,15,15,1),(11,13,13,5);
+
+SELECT id, columnid, tableid, content, showid, line, ordinal FROM t1 WHERE owner=11 AND ((columnid IN ( 15, 13, 14 ) AND line IN ( 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 31 )) OR (columnid IN ( 13, 14 ) AND line IN ( 15 ))) LIMIT 0 , 30;
+drop table t1;
+
+#
# test for a bug with in() and unique key
+#
create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test
index 00c14c43ff3..60262fdf59c 100644
--- a/mysql-test/t/rpl000015.test
+++ b/mysql-test/t/rpl000015.test
@@ -12,7 +12,7 @@ show slave status;
change master to master_host='127.0.0.1';
# The following needs to be cleaned up when change master is fixed
---replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT
+--replace_result $MASTER_MYPORT MASTER_PORT $MYSQL_TCP_PORT MASTER_PORT
--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
--replace_result $MASTER_MYPORT MASTER_PORT
diff --git a/mysql-test/t/rpl_charset.test b/mysql-test/t/rpl_charset.test
new file mode 100644
index 00000000000..c13b57a3108
--- /dev/null
+++ b/mysql-test/t/rpl_charset.test
@@ -0,0 +1,153 @@
+# Replication of character sets.
+# This test will fail if the server/client does not support enough charsets.
+
+# Remember that there currently exists
+# Bug #2326: Charset of table is determined by charset of db only if "USE db;"
+
+source include/master-slave.inc;
+--disable_warnings
+drop database if exists test2;
+drop database if exists test3;
+--enable_warnings
+
+create database test2 character set latin2;
+set @@character_set_server=latin5;
+create database test3;
+--disable_query_log
+select "--- --master--" as "";
+--enable_query_log
+show create database test2;
+show create database test3;
+sync_slave_with_master;
+--disable_query_log
+select "--- --slave--" as "";
+--enable_query_log
+show create database test2;
+show create database test3;
+
+connection master;
+set @@collation_server=armscii_bin;
+drop database test3;
+create database test3;
+--disable_query_log
+select "--- --master--" as "";
+--enable_query_log
+show create database test3;
+sync_slave_with_master;
+--disable_query_log
+select "--- --slave--" as "";
+--enable_query_log
+show create database test3;
+
+connection master;
+use test2;
+create table t1 (a int auto_increment primary key, b varchar(100));
+set character_set_client=cp850, collation_connection=latin2_croatian_ci;
+insert into t1 (b) values(@@character_set_server);
+insert into t1 (b) values(@@collation_server);
+# character_set_database and collation_database are not tested as they
+# are not replicated (Bar said that this variable may be removed shortly).
+insert into t1 (b) values(@@character_set_client);
+# collation_client does not exist
+insert into t1 (b) values(@@character_set_connection);
+insert into t1 (b) values(@@collation_connection);
+--disable_query_log
+select "--- --master--" as "";
+--enable_query_log
+select * from t1 order by a;
+sync_slave_with_master;
+--disable_query_log
+select "--- --slave--" as "";
+--enable_query_log
+select * from test2.t1 order by a;
+
+connection master;
+set character_set_client=latin1, collation_connection=latin1_german1_ci;
+truncate table t1;
+insert into t1 (b) values(@@collation_connection);
+insert into t1 (b) values(LEAST("Müller","Muffler"));
+set collation_connection=latin1_german2_ci;
+insert into t1 (b) values(@@collation_connection);
+insert into t1 (b) values(LEAST("Müller","Muffler"));
+--disable_query_log
+select "--- --master--" as "";
+--enable_query_log
+select * from t1 order by a;
+sync_slave_with_master;
+--disable_query_log
+select "--- --slave--" as "";
+--enable_query_log
+select * from test2.t1 order by a;
+
+# See if SET ONE_SHOT gets into binlog when LOAD DATA
+connection master;
+load data infile '../../std_data/words.dat' into table t1 (b);
+
+# See if user var is prefixed with collation in binlog and replicated well.
+# Note: replication of user variables is broken as far as derivation is
+# concerned. That's because when we store a user variable in the binlog,
+# we lose its derivation. So later on the slave, it's impossible to
+# know if the collation was explicit or not, so we use DERIVATION_NONE,
+# which provokes error messages (like 'Illegal mix of collation') when
+# we replay the master's INSERT/etc statements.
+set @a= _cp850 'Müller' collate cp850_general_ci;
+truncate table t1;
+insert into t1 (b) values(collation(@a));
+--disable_query_log
+select "--- --master--" as "";
+--enable_query_log
+select * from t1 order by a;
+sync_slave_with_master;
+--disable_query_log
+select "--- --slave--" as "";
+--enable_query_log
+select * from test2.t1 order by a;
+
+connection master;
+drop database test2;
+drop database test3;
+show binlog events from 79;
+sync_slave_with_master;
+
+# Check that we can't change global.collation_server
+
+error 1105;
+set global character_set_server=latin2;
+connection master;
+error 1105;
+set global character_set_server=latin2;
+
+# Check that SET ONE_SHOT is really one shot
+
+set one_shot @@character_set_server=latin5;
+set @@max_join_size=1000;
+select @@character_set_server;
+select @@character_set_server;
+set @@character_set_server=latin5;
+select @@character_set_server;
+select @@character_set_server;
+
+# ONE_SHOT on not charset/collation stuff is not allowed
+error 1105;
+set one_shot max_join_size=10;
+
+# Test of wrong character set numbers;
+error 1115;
+set character_set_client=9999999;
+error 1273;
+set collation_server=9999998;
+
+# This one was contributed by Sergey Petrunia (BUG#3943)
+
+use test;
+CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255));
+SET CHARACTER_SET_CLIENT=koi8r,
+ CHARACTER_SET_CONNECTION=cp1251,
+ CHARACTER_SET_RESULTS=koi8r;
+INSERT INTO t1 (c1, c2) VALUES ('îÕ, ÚÁ ÒÙÂÁÌËÕ','îÕ, ÚÁ ÒÙÂÁÌËÕ');
+select hex(c1), hex(c2) from t1;
+sync_slave_with_master;
+select hex(c1), hex(c2) from t1;
+connection master;
+drop table t1;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_delete_all.test b/mysql-test/t/rpl_delete_all.test
new file mode 100644
index 00000000000..6ca98b34caf
--- /dev/null
+++ b/mysql-test/t/rpl_delete_all.test
@@ -0,0 +1,41 @@
+source include/master-slave.inc;
+
+connection slave;
+create database test1;
+connection master;
+drop database if exists test1;
+sync_slave_with_master;
+# can't read dir
+--replace_result "Errcode: 1" "Errcode: X" "Errcode: 2" "Errcode: X"
+--error 12
+show tables from test1;
+
+connection slave;
+create table t1 (a int);
+connection master;
+drop table if exists t1;
+sync_slave_with_master;
+# table does not exist
+--error 1146
+select * from t1;
+
+connection master;
+create table t1 (a int);
+sync_slave_with_master;
+insert into t1 values(1);
+connection master;
+delete from t1;
+sync_slave_with_master;
+select * from t1;
+
+insert into t1 values(1);
+connection master;
+insert into t1 values(2);
+update t1 set a=2;
+sync_slave_with_master;
+select * from t1;
+
+# cleanup
+connection master;
+drop table t1;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_free_items-slave.opt b/mysql-test/t/rpl_free_items-slave.opt
new file mode 100644
index 00000000000..b828d03fafb
--- /dev/null
+++ b/mysql-test/t/rpl_free_items-slave.opt
@@ -0,0 +1 @@
+--replicate-wild-ignore-table=test.%
diff --git a/mysql-test/t/rpl_free_items.test b/mysql-test/t/rpl_free_items.test
new file mode 100644
index 00000000000..3228ffd9cde
--- /dev/null
+++ b/mysql-test/t/rpl_free_items.test
@@ -0,0 +1,20 @@
+source include/master-slave.inc;
+create table t1 (a int);
+create table t2 (a int);
+disable_query_log;
+SET @query="INSERT INTO t2 SELECT * FROM t1 WHERE a REGEXP \"0\"";
+let $1 = 2000;
+while ($1)
+{
+ eval SET @query=concat(@query, " OR a REGEXP '$1'");
+ dec $1;
+}
+let $1=`select @query`;
+eval $1;
+enable_query_log;
+# I have seen the slave crash either now or at shutdown
+sync_slave_with_master;
+connection master;
+drop table t1;
+drop table t2;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_get_lock.test b/mysql-test/t/rpl_get_lock.test
index c3b033fb03a..5e58753e59a 100644
--- a/mysql-test/t/rpl_get_lock.test
+++ b/mysql-test/t/rpl_get_lock.test
@@ -22,7 +22,7 @@ connection slave;
sync_with_master;
select get_lock("lock",3);
select * from t1;
-select is_free_lock("lock"), is_used_lock("lock");
+select is_free_lock("lock"), is_used_lock("lock") = connection_id();
explain extended select is_free_lock("lock"), is_used_lock("lock");
# Check lock functions
select is_free_lock("lock2");
diff --git a/mysql-test/t/rpl_ps.test b/mysql-test/t/rpl_ps.test
new file mode 100644
index 00000000000..79f48381a4f
--- /dev/null
+++ b/mysql-test/t/rpl_ps.test
@@ -0,0 +1,43 @@
+#
+# Test of replicating user variables
+#
+source include/master-slave.inc;
+
+#save_master_pos;
+#connection slave;
+#sync_with_master;
+#reset master;
+#connection master;
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1(n char(30));
+
+prepare stmt1 from 'insert into t1 values (?)';
+set @var1= "from-master-1";
+execute stmt1 using @var1;
+set @var1= "from-master-2-'',";
+execute stmt1 using @var1;
+select * from t1;
+
+set @var2= 'insert into t1 values (concat("from-var-", ?))';
+prepare stmt2 from @var2;
+set @var1='from-master-3';
+execute stmt2 using @var1;
+
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from t1;
+
+connection master;
+
+drop table t1;
+
+save_master_pos;
+connection slave;
+sync_with_master;
+stop slave;
+
diff --git a/mysql-test/t/rpl_relayspace-slave.opt b/mysql-test/t/rpl_relayspace-slave.opt
index 05cb01731d2..06d96aa3b9a 100644
--- a/mysql-test/t/rpl_relayspace-slave.opt
+++ b/mysql-test/t/rpl_relayspace-slave.opt
@@ -1 +1 @@
- -O relay_log_space_limit=10 \ No newline at end of file
+--relay_log_space_limit=10
diff --git a/mysql-test/t/rpl_server_id1.test b/mysql-test/t/rpl_server_id1.test
index aefcb81c930..4d504325294 100644
--- a/mysql-test/t/rpl_server_id1.test
+++ b/mysql-test/t/rpl_server_id1.test
@@ -1,5 +1,8 @@
-# This test checks that a slave does not execute queries originating
-# from itself, by default.
+# This test checks that the slave I/O thread refuses to start if slave
+# and master have the same server id (because this is a useless setup,
+# and otherwise SHOW SLAVE STATUS shows progress but all queries are
+# ignored, which has caught our customers), unless
+# --replicate-same-server-id.
source include/master-slave.inc;
connection slave;
@@ -18,5 +21,4 @@ insert into t1 values (1);
# (when slave is its own master without --replicate-same-server-id)
sleep 2; # enough time for the event to be replicated (it should not)
show status like "slave_running";
-select * from t1;
drop table t1;
diff --git a/mysql-test/t/rpl_timezone-master.opt b/mysql-test/t/rpl_timezone-master.opt
new file mode 100644
index 00000000000..8e43bfbbb7e
--- /dev/null
+++ b/mysql-test/t/rpl_timezone-master.opt
@@ -0,0 +1 @@
+--default-time-zone=Europe/Moscow
diff --git a/mysql-test/t/rpl_timezone-slave.opt b/mysql-test/t/rpl_timezone-slave.opt
new file mode 100644
index 00000000000..8e43bfbbb7e
--- /dev/null
+++ b/mysql-test/t/rpl_timezone-slave.opt
@@ -0,0 +1 @@
+--default-time-zone=Europe/Moscow
diff --git a/mysql-test/t/rpl_timezone.test b/mysql-test/t/rpl_timezone.test
new file mode 100644
index 00000000000..8dff90a84cf
--- /dev/null
+++ b/mysql-test/t/rpl_timezone.test
@@ -0,0 +1,84 @@
+# Test of replication of time zones.
+source include/master-slave.inc;
+
+# Some preparations
+let $VERSION=`select version()`;
+create table t1 (t timestamp);
+create table t2 (t char(32));
+
+#
+# Let us check how well replication works when we are saving datetime
+# value in TIMESTAMP field.
+#
+connection master;
+select @@time_zone;
+set time_zone='UTC';
+insert into t1 values ('20040101000000'), ('20040611093902');
+select * from t1;
+# On slave we still in 'Europe/Moscow' so we should see equivalent but
+# textually different values.
+sync_slave_with_master;
+select * from t1;
+
+# Let us check also that setting of time_zone back to default also works
+# well
+connection master;
+delete from t1;
+set time_zone='Europe/Moscow';
+insert into t1 values ('20040101000000'), ('20040611093902');
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+connection master;
+# We should not see SET ONE_SHOT time_zone before second insert
+--replace_result $VERSION VERSION
+show binlog events;
+
+#
+# Now let us check how well we replicate statments reading TIMESTAMP fields
+# (We should see the same data on master and on slave but it should differ
+# from originally inserted)
+#
+set time_zone='MET';
+insert into t2 (select t from t1);
+select * from t1;
+sync_slave_with_master;
+select * from t2;
+
+#
+# Now let us check how well we replicate various CURRENT_* functions
+#
+connection master;
+delete from t2;
+set timestamp=1000072000;
+insert into t2 values (current_timestamp), (current_date), (current_time);
+sync_slave_with_master;
+# Values in ouput of these to queries should differ because we are in
+# in 'MET' on master and in 'Europe/Moscow on slave...
+set timestamp=1000072000;
+select current_timestamp, current_date, current_time;
+select * from t2;
+
+#
+# At last let us check replication of FROM_UNIXTIME/UNIX_TIMESTAMP functions.
+#
+connection master;
+delete from t2;
+insert into t2 values (from_unixtime(1000000000)),
+ (unix_timestamp('2001-09-09 03:46:40'));
+select * from t2;
+sync_slave_with_master;
+# We should get same result on slave as on master
+select * from t2;
+
+#
+# Let us check that we are not allowing to set global time_zone with
+# replication
+#
+connection master;
+--error 1105
+set global time_zone='MET';
+
+# Clean up
+drop table t1, t2;
+sync_slave_with_master;
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 0a3de178456..57827f3cc7f 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -1771,7 +1771,9 @@ CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned defa
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);
-SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'NULL' AND b.sampletime < 'NULL' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
+SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
+# Testing the same select with NULL's instead of invalid datetime values
+SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
DROP TABLE t1,t2;
#
diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test
index e63e894c1cf..c20b6e9ab6c 100644
--- a/mysql-test/t/select_found.test
+++ b/mysql-test/t/select_found.test
@@ -137,3 +137,22 @@ WHERE ( r = 1 AND a IN ( 1, 2 ) AND ( u = 'w' OR u LIKE 'w/%' ) )
OR ( r = 1 AND a IN ( 1, 2, 3 ) AND ( u = 'w' ) );
drop table t1;
+#
+# Bug #3738: we have a ref key
+#
+
+CREATE TABLE t1 (a VARCHAR(16), UNIQUE(a));
+INSERT INTO t1 VALUES ('1'), ('2'), ('3');
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a = '2' LIMIT 0, 1;
+SELECT FOUND_ROWS();
+DROP TABLE t1;
+
+#
+# Bug #3845: group by, having and empty result
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (0), (0), (1), (2);
+SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a = 0 GROUP BY a HAVING a > 10;
+SELECT FOUND_ROWS();
+DROP TABLE t1;
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index deb95af9168..3ff2605cff4 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -222,37 +222,37 @@ CREATE TABLE t3 (
insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1,1),(2,2);
---replace_column 6 # 7 # 8 #
+--replace_column 7 # 8 # 9 #
show table status;
insert into t1 values (3),(4);
insert into t2 values (3),(4);
insert into t3 values (3,3),(4,4);
---replace_column 6 # 7 # 8 #
+--replace_column 7 # 8 # 9 #
show table status;
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
---replace_column 6 # 7 # 8 #
+--replace_column 7 # 8 # 9 #
show table status;
delete from t1 where a=3;
delete from t2 where b=3;
delete from t3 where a=3;
---replace_column 6 # 7 # 8 #
+--replace_column 7 # 8 # 9 #
show table status;
delete from t1;
delete from t2;
delete from t3;
---replace_column 6 # 7 # 8 #
+--replace_column 7 # 8 # 9 #
show table status;
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
---replace_column 6 # 7 # 8 #
+--replace_column 7 # 8 # 9 #
show table status;
delete from t1 where a=5;
delete from t2 where b=5;
delete from t3 where a=5;
---replace_column 6 # 7 # 8 #
+--replace_column 7 # 8 # 9 #
show table status;
drop table t1, t2, t3;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 7807f139a93..3a729b37d99 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -135,7 +135,7 @@ explain extended select * from t6 where exists (select * from t7 where uq = clin
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
# different tipes & group functions
-drop table if exists t1,t2,t3;
+drop table t1,t2,t3;
CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0');
INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b');
@@ -1163,3 +1163,57 @@ SELECT a FROM t1 WHERE a >= ALL ( SELECT a FROM t1 WHERE b = 2 );
SELECT a FROM t1 WHERE a <= ALL ( SELECT a FROM t1 WHERE b = 2 );
SELECT a FROM t1 WHERE a <> ALL ( SELECT a FROM t1 WHERE b = 2 );
DROP TABLE t1;
+
+#
+# SELECT(EXISTS * ...)optimisation
+#
+create table t1 (a int, b int);
+insert into t1 values (1,2),(3,4);
+select * from t1 up where exists (select * from t1 where t1.a=up.a);
+explain extended select * from t1 up where exists (select * from t1 where t1.a=up.a);
+drop table t1;
+
+#
+# Bug #4102: subselect in HAVING
+#
+
+CREATE TABLE t1 (t1_a int);
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (t2_a int, t2_b int, PRIMARY KEY (t2_a, t2_b));
+INSERT INTO t2 VALUES (1, 1), (1, 2);
+SELECT * FROM t1, t2 table2 WHERE t1_a = 1 AND table2.t2_a = 1
+ HAVING table2.t2_b = (SELECT MAX(t2_b) FROM t2 WHERE t2_a = table2.t2_a);
+DROP TABLE t1, t2;
+
+#
+# Test problem with NULL and derived tables (Bug #4097)
+#
+
+CREATE TABLE t1 (id int(11) default NULL,name varchar(10) default NULL);
+INSERT INTO t1 VALUES (1,'Tim'),(2,'Rebecca'),(3,NULL);
+CREATE TABLE t2 (id int(11) default NULL, pet varchar(10) default NULL);
+INSERT INTO t2 VALUES (1,'Fido'),(2,'Spot'),(3,'Felix');
+SELECT a.*, b.* FROM (SELECT * FROM t1) AS a JOIN t2 as b on a.id=b.id;
+drop table t1,t2;
+
+#
+# outer fields resolving in INSERT/REPLACE and CRETE with SELECT
+#
+CREATE TABLE t1 ( a int, b int );
+CREATE TABLE t2 ( c int, d int );
+INSERT INTO t1 VALUES (1,2), (2,3), (3,4);
+SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);
+INSERT INTO t2 SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);
+select * from t2;
+CREATE TABLE t3 SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);
+select * from t3;
+prepare stmt1 from "INSERT INTO t2 SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);";
+execute stmt1;
+deallocate prepare stmt1;
+select * from t2;
+drop table t3;
+prepare stmt1 from "CREATE TABLE t3 SELECT a AS abc, b FROM t1 WHERE b = (SELECT MIN(b) FROM t1 WHERE a=abc);";
+execute stmt1;
+select * from t3;
+deallocate prepare stmt1;
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test
index 47642832158..8c13171d221 100644
--- a/mysql-test/t/subselect_innodb.test
+++ b/mysql-test/t/subselect_innodb.test
@@ -101,3 +101,13 @@ insert into t2 values (1,'z'),(2,'x');
select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2;
select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2;
drop table t1,t2;
+
+#
+# unlocking tables with subqueries in HAVING
+#
+create table t1 (a int, b int) engine=innodb;
+insert into t1 values (1,2), (1,3), (2,3), (2,4), (2,5), (3,4), (4,5), (4,100);
+create table t2 (a int) engine=innodb;
+insert into t2 values (1),(2),(3),(4);
+select a, sum(b) as b from t1 group by a having b > (select max(a) from t2);
+drop table t1, t2;
diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test
index 6f3979bf66e..a81772c74e4 100644
--- a/mysql-test/t/system_mysql_db_fix.test
+++ b/mysql-test/t/system_mysql_db_fix.test
@@ -74,5 +74,10 @@ DROP TABLE user;
DROP TABLE func;
DROP TABLE tables_priv;
DROP TABLE columns_priv;
+DROP TABLE help_category;
+DROP TABLE help_keyword;
+DROP TABLE help_relation;
+DROP TABLE help_topic;
-- enable_query_log
+
diff --git a/mysql-test/t/system_mysql_db_refs.test b/mysql-test/t/system_mysql_db_refs.test
index 62d6f3de944..4c6557ba5c7 100644
--- a/mysql-test/t/system_mysql_db_refs.test
+++ b/mysql-test/t/system_mysql_db_refs.test
@@ -99,3 +99,4 @@ drop table test_func;
drop table test_host;
drop table test_user;
drop table test_db;
+
diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test
index 194602f376c..ffc2e3a3ebf 100644
--- a/mysql-test/t/timezone.test
+++ b/mysql-test/t/timezone.test
@@ -1,5 +1,6 @@
#
-# Test of timezone handling. This script must be run with TZ=MET
+# Test of SYSTEM time zone handling ( for my_system_gmt_sec()).
+# This script must be run with TZ=MET
-- require r/have_met_timezone.require
disable_query_log;
@@ -13,7 +14,7 @@ DROP TABLE IF EXISTS t1;
# The following is because of daylight saving time
--replace_result MEST MET
-show variables like "timezone";
+show variables like "system_time_zone";
#
# Test unix timestamp
@@ -40,6 +41,16 @@ INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
SELECT ts,from_unixtime(ts) FROM t1;
DROP TABLE t1;
+
+#
+# Test of warning for spring time-gap values for system time zone
+#
+CREATE TABLE t1 (ts timestamp);
+INSERT INTO t1 (ts) VALUES ('2003-03-30 01:59:59'),
+ ('2003-03-30 02:59:59'),
+ ('2003-03-30 03:00:00');
+DROP TABLE t1;
+
#
# Test for fix for Bug#2523
#
diff --git a/mysql-test/t/timezone2.test b/mysql-test/t/timezone2.test
new file mode 100644
index 00000000000..49579421570
--- /dev/null
+++ b/mysql-test/t/timezone2.test
@@ -0,0 +1,189 @@
+# This script tests our own time zone support functions
+
+# Preparing playground
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+
+#
+# Let us first check +HH:MM style timezones
+#
+create table t1 (ts timestamp);
+
+set time_zone='+00:00';
+select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
+insert into t1 (ts) values ('2003-03-30 02:30:00');
+
+set time_zone='+10:30';
+select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
+insert into t1 (ts) values ('2003-03-30 02:30:00');
+
+set time_zone='-10:00';
+select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
+insert into t1 (ts) values ('2003-03-30 02:30:00');
+
+# Here we will get different results
+select * from t1;
+
+drop table t1;
+
+
+#
+# Let us try DB specified time zones
+#
+select Name from mysql.time_zone_name where Name in
+ ('UTC','Universal','MET','Europe/Moscow','leap/Europe/Moscow');
+
+create table t1 (i int, ts timestamp);
+
+set time_zone='MET';
+
+# We check common date time value and non existent or ambiguios values
+# Normal value without DST
+insert into t1 (i, ts) values
+ (unix_timestamp('2003-03-01 00:00:00'),'2003-03-01 00:00:00');
+# Values around and in spring time-gap
+insert into t1 (i, ts) values
+ (unix_timestamp('2003-03-30 01:59:59'),'2003-03-30 01:59:59'),
+ (unix_timestamp('2003-03-30 02:30:00'),'2003-03-30 02:30:00'),
+ (unix_timestamp('2003-03-30 03:00:00'),'2003-03-30 03:00:00');
+# Normal value with DST
+insert into t1 (i, ts) values
+ (unix_timestamp('2003-05-01 00:00:00'),'2003-05-01 00:00:00');
+# Ambiguos values (also check for determenism)
+insert into t1 (i, ts) values
+ (unix_timestamp('2003-10-26 01:00:00'),'2003-10-26 01:00:00'),
+ (unix_timestamp('2003-10-26 02:00:00'),'2003-10-26 02:00:00'),
+ (unix_timestamp('2003-10-26 02:59:59'),'2003-10-26 02:59:59'),
+ (unix_timestamp('2003-10-26 04:00:00'),'2003-10-26 04:00:00'),
+ (unix_timestamp('2003-10-26 02:59:59'),'2003-10-26 02:59:59');
+
+set time_zone='UTC';
+
+select * from t1;
+
+delete from t1;
+
+# Simple check for 'Europe/Moscow' time zone just for showing that it works
+set time_zone='Europe/Moscow';
+insert into t1 (i, ts) values
+ (unix_timestamp('2004-01-01 00:00:00'),'2004-01-01 00:00:00'),
+ (unix_timestamp('2004-03-28 02:30:00'),'2004-03-28 02:30:00'),
+ (unix_timestamp('2004-08-01 00:00:00'),'2003-08-01 00:00:00'),
+ (unix_timestamp('2004-10-31 02:30:00'),'2004-10-31 02:30:00');
+select * from t1;
+delete from t1;
+
+
+#
+# Check for time zone with leap seconds
+# Values in ts column must be the same but values in i column should
+# differ from corresponding values for Europe/Moscow a bit.
+#
+set time_zone='leap/Europe/Moscow';
+insert into t1 (i, ts) values
+ (unix_timestamp('2004-01-01 00:00:00'),'2004-01-01 00:00:00'),
+ (unix_timestamp('2004-03-28 02:30:00'),'2004-03-28 02:30:00'),
+ (unix_timestamp('2004-08-01 00:00:00'),'2003-08-01 00:00:00'),
+ (unix_timestamp('2004-10-31 02:30:00'),'2004-10-31 02:30:00');
+select * from t1;
+delete from t1;
+# Let us test leap jump
+insert into t1 (i, ts) values
+ (unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'),
+ (unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00');
+select * from t1;
+# Additional 60ieth second!
+select from_unixtime(362793609);
+
+drop table t1;
+
+
+#
+# Let us test range for TIMESTAMP
+#
+create table t1 (ts timestamp);
+set time_zone='UTC';
+insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'),
+ ('1970-01-01 00:00:00'),('1970-01-01 00:00:01'),
+ ('2037-12-31 23:59:59'),('2038-01-01 00:00:00');
+select * from t1;
+delete from t1;
+# MET time zone has range shifted by one hour
+set time_zone='MET';
+insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'),
+ ('1970-01-01 01:00:00'),('1970-01-01 01:00:01'),
+ ('2038-01-01 00:59:59'),('2038-01-01 01:00:00');
+select * from t1;
+delete from t1;
+# same for +01:30 time zone
+set time_zone='+01:30';
+insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'),
+ ('1970-01-01 01:30:00'),('1970-01-01 01:30:01'),
+ ('2038-01-01 01:29:59'),('2038-01-01 01:30:00');
+select * from t1;
+
+drop table t1;
+
+
+#
+# Test of show variables
+#
+show variables like 'time_zone';
+set time_zone = default;
+show variables like 'time_zone';
+
+
+#
+# Let us try some invalid time zone specifications
+#
+--error 1298
+set time_zone= '0';
+--error 1298
+set time_zone= '0:0';
+--error 1298
+set time_zone= '-20:00';
+--error 1298
+set time_zone= '+20:00';
+--error 1298
+set time_zone= 'Some/Unknown/Time/Zone';
+
+
+# Let us check that aliases for time zones work and they are
+# case-insensitive
+select convert_tz(now(),'UTC', 'Universal') = now();
+select convert_tz(now(),'utc', 'UTC') = now();
+
+
+#
+# Let us test CONVERT_TZ function (may be func_time.test is better place).
+#
+select convert_tz('1917-11-07 12:00:00', 'MET', 'UTC');
+select convert_tz('1970-01-01 01:00:00', 'MET', 'UTC');
+select convert_tz('1970-01-01 01:00:01', 'MET', 'UTC');
+select convert_tz('2003-03-01 00:00:00', 'MET', 'UTC');
+select convert_tz('2003-03-30 01:59:59', 'MET', 'UTC');
+select convert_tz('2003-03-30 02:30:00', 'MET', 'UTC');
+select convert_tz('2003-03-30 03:00:00', 'MET', 'UTC');
+select convert_tz('2003-05-01 00:00:00', 'MET', 'UTC');
+select convert_tz('2003-10-26 01:00:00', 'MET', 'UTC');
+select convert_tz('2003-10-26 02:00:00', 'MET', 'UTC');
+select convert_tz('2003-10-26 02:59:59', 'MET', 'UTC');
+select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC');
+select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC');
+select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC');
+select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC');
+
+# Let us test variable time zone argument
+create table t1 (tz varchar(3));
+insert into t1 (tz) values ('MET'), ('UTC');
+select tz, convert_tz('2003-12-31 00:00:00',tz,'UTC'), convert_tz('2003-12-31 00:00:00','UTC',tz) from t1 order by tz;
+drop table t1;
+
+# Parameters to CONVERT_TZ() what should give NULL
+select convert_tz('2003-12-31 04:00:00', NULL, 'UTC');
+select convert_tz('2003-12-31 04:00:00', 'SomeNotExistingTimeZone', 'UTC');
+select convert_tz('2003-12-31 04:00:00', 'MET', 'SomeNotExistingTimeZone');
+select convert_tz('2003-12-31 04:00:00', 'MET', NULL);
+select convert_tz( NULL, 'MET', 'UTC');
diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test
index 5a53c635e6e..8d67802d42a 100644
--- a/mysql-test/t/type_date.test
+++ b/mysql-test/t/type_date.test
@@ -79,3 +79,12 @@ SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ' , t2.
INSERT INTO t1 VALUES(1);
SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ' , t2.GMT)), DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ' , t2.GMT)) FROM t1,t2 GROUP BY t1.AFIELD;
drop table t1,t2;
+
+#
+# Multiple SELECT DATE_FORMAT gave incorrect results (Bug #4036)
+#
+
+CREATE TABLE t1 (f1 time default NULL, f2 time default NULL);
+INSERT INTO t1 (f1, f2) VALUES ('09:00', '12:00');
+SELECT DATE_FORMAT(f1, "%l.%i %p") , DATE_FORMAT(f2, "%l.%i %p") FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test
index cec2aa3582b..47866058524 100644
--- a/mysql-test/t/type_datetime.test
+++ b/mysql-test/t/type_datetime.test
@@ -7,13 +7,13 @@ drop table if exists t1;
--enable_warnings
create table t1 (t datetime);
-insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460);
+insert into t1 values (101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030100000000),(20030000000000);
select * from t1;
delete from t1 where t > 0;
optimize table t1;
check table t1;
delete from t1;
-insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460");
+insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030100000000"),("20030000000000");
select * from t1;
drop table t1;
@@ -71,3 +71,18 @@ insert into t1 values (now(), now());
insert into t1 values (now(), now());
select * from t1 where a is null or b is null;
drop table t1;
+
+#
+# Let us check if we properly treat wrong datetimes and produce proper
+# warnings (for both strings and numbers)
+#
+create table t1 (t datetime);
+insert into t1 values (20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460);
+select * from t1;
+delete from t1;
+insert into t1 values ("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460");
+select * from t1;
+delete from t1;
+insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer");
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index 3257002ae2c..414a06deaa9 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -244,6 +244,9 @@ CREATE TABLE t1 (a_dec DECIMAL(-1,0));
CREATE TABLE t1 (a_dec DECIMAL(-2,1));
--error 1064
CREATE TABLE t1 (a_dec DECIMAL(-1,1));
+CREATE TABLE t1 (a_dec DECIMAL(0,11));
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
#
# Zero prepend overflow bug
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 72633f9ef7d..9b3abc9f155 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -37,10 +37,10 @@ select date_format(a,"%Y %y"),year(a),year(now()) from t1;
drop table t1;
create table t1 (ix timestamp);
-insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000),(20030101010160),(20030101016001),(20030101240101),(20030132010101),(20031301010101);
+insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
select ix+0 from t1;
delete from t1;
-insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101");
+insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000");
select ix+0 from t1;
drop table t1;
@@ -76,6 +76,21 @@ select * from t1;
drop table t1;
#
+# Let us check if we properly treat wrong datetimes and produce proper warnings
+# (for both strings and numbers)
+#
+create table t1 (ix timestamp);
+insert into t1 values (0),(20030101010160),(20030101016001),(20030101240101),(20030132010101),(20031301010101),(20031200000000),(20030000000000);
+select ix+0 from t1;
+delete from t1;
+insert into t1 values ("00000000000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101"),("20031200000000"),("20030000000000");
+select ix+0 from t1;
+delete from t1;
+insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer");
+select ix+0 from t1;
+drop table t1;
+
+#
# Test for TIMESTAMP column with default now() and on update now() clauses
#
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index f6006a87d47..206b40f8ce7 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -527,3 +527,43 @@ CREATE TABLE t2 (i int(11) default NULL,c char(1) default NULL,KEY i (i));
--error 1054
explain (select * from t1) union (select * from t2) order by not_existing_column;
drop table t1, t2;
+
+#
+# length detecting
+#
+CREATE TABLE t1 (uid int(1));
+INSERT INTO t1 SELECT 150;
+SELECT 'a' UNION SELECT uid FROM t1;
+drop table t1;
+
+#
+# parser stack overflow
+#
+CREATE TABLE t1 ( ID1 int(10) unsigned NOT NULL DEFAULT '0' , ID2 datetime NOT NULL DEFAULT '0000-00-00 00:00:00' , DATA1 varchar(10) , DATA2 double(5,4) , DATA3 datetime , PRIMARY KEY (ID1,ID2));
+
+CREATE TABLE t2 ( ID int(3) unsigned NOT NULL DEFAULT '0' , DATA1 timestamp DEFAULT '0000-00-00 00:00:00' , PRIMARY KEY (ID));
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1) UNION
+(SELECT * FROM t1 AS PARTITIONED, t2 AS
+PARTITIONED_B WHERE PARTITIONED_B.ID=PARTITIONED.ID1);
+drop table t1,t2;
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index a28b327cf58..601724e68c8 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -99,3 +99,24 @@ select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST';
select charset(@a),collation(@a),coercibility(@a);
--error 1267
select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST' collate latin2_general_ci;
+
+# Check that user variables are binlogged correctly (BUG#3875)
+create table t1 (a varchar(50));
+reset master;
+SET TIMESTAMP=10000;
+SET @`a b`='hello';
+INSERT INTO t1 VALUES(@`a b`);
+set @var1= "';aaa";
+insert into t1 values (@var1);
+create table t2 (c char(30)) charset=ucs2;
+set @v=convert('abc' using ucs2);
+insert into t2 values (@v);
+show binlog events from 79;
+# more important than SHOW BINLOG EVENTS, mysqlbinlog (where we
+# absolutely need variables names to be quoted and strings to be
+# escaped).
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001
+drop table t1, t2;
+
+
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 81bfacf4ee7..5669d11ddac 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -303,6 +303,7 @@ set global ft_boolean_syntax = @@init_connect;
# variables are set
set global myisam_max_sort_file_size=4294967296;
+--replace_result 4294967296 MAX_FILE_SIZE 2146435072 MAX_FILE_SIZE
show global variables like 'myisam_max_sort_file_size';
set global myisam_max_sort_file_size=default;
diff --git a/mysys/ChangeLog b/mysys/ChangeLog
index e24fc00b493..7a426106667 100644
--- a/mysys/ChangeLog
+++ b/mysys/ChangeLog
@@ -91,7 +91,7 @@ Tue Mar 26 15:09:45 1991 Mikael WIDENIUS (monty at panther)
Sat Mar 23 10:49:49 1991 Michael Widenius (monty at LYNX)
- * Added init of alarm variables to skipp some warnings from gcc.
+ * Added init of alarm variables to skip some warnings from gcc.
Tue Mar 5 16:50:34 1991 Michael Widenius (monty at LYNX)
@@ -124,7 +124,7 @@ Mon Aug 27 22:20:38 1990 Michael Widenius (monty at lynx)
Sun Apr 1 23:29:47 1990 Monty (monty at monty)
* Changed mf_keydisk.c to have separate functions for read and write.
- Read can now return pointer to intern key-buffer to skipp
+ Read can now return pointer to intern key-buffer to skip
unessessary memcpy-s.
Fri Mar 23 23:03:39 1990 Monty (monty at monty)
diff --git a/mysys/charset-def.c b/mysys/charset-def.c
index a89cf866933..73e36688594 100644
--- a/mysys/charset-def.c
+++ b/mysys/charset-def.c
@@ -22,6 +22,42 @@
init_compiled_charsets() that only adds those that he wants
*/
+#ifdef HAVE_CHARSET_ucs2
+extern CHARSET_INFO my_charset_ucs2_general_uca;
+extern CHARSET_INFO my_charset_ucs2_icelandic_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_latvian_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_romanian_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_slovenian_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_polish_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_estonian_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_spanish_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_swedish_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_turkish_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_czech_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_danish_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_slovak_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_spanish2_uca_ci;
+#endif
+
+#ifdef HAVE_CHARSET_utf8
+extern CHARSET_INFO my_charset_utf8_general_uca_ci;
+extern CHARSET_INFO my_charset_utf8_icelandic_uca_ci;
+extern CHARSET_INFO my_charset_utf8_latvian_uca_ci;
+extern CHARSET_INFO my_charset_utf8_romanian_uca_ci;
+extern CHARSET_INFO my_charset_utf8_slovenian_uca_ci;
+extern CHARSET_INFO my_charset_utf8_polish_uca_ci;
+extern CHARSET_INFO my_charset_utf8_estonian_uca_ci;
+extern CHARSET_INFO my_charset_utf8_spanish_uca_ci;
+extern CHARSET_INFO my_charset_utf8_swedish_uca_ci;
+extern CHARSET_INFO my_charset_utf8_turkish_uca_ci;
+extern CHARSET_INFO my_charset_utf8_czech_uca_ci;
+extern CHARSET_INFO my_charset_utf8_danish_uca_ci;
+extern CHARSET_INFO my_charset_utf8_lithuanian_uca_ci;
+extern CHARSET_INFO my_charset_utf8_slovak_uca_ci;
+extern CHARSET_INFO my_charset_utf8_spanish2_uca_ci;
+#endif
+
my_bool init_compiled_charsets(myf flags __attribute__((unused)))
{
CHARSET_INFO *cs;
@@ -74,6 +110,20 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
add_compiled_collation(&my_charset_ucs2_general_ci);
add_compiled_collation(&my_charset_ucs2_bin);
add_compiled_collation(&my_charset_ucs2_general_uca);
+ add_compiled_collation(&my_charset_ucs2_icelandic_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_latvian_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_romanian_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_slovenian_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_polish_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_estonian_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_spanish_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_swedish_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_turkish_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_czech_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_danish_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_lithuanian_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_slovak_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_spanish2_uca_ci);
#endif
#ifdef HAVE_CHARSET_ujis
@@ -84,6 +134,21 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
#ifdef HAVE_CHARSET_utf8
add_compiled_collation(&my_charset_utf8_general_ci);
add_compiled_collation(&my_charset_utf8_bin);
+ add_compiled_collation(&my_charset_utf8_general_uca_ci);
+ add_compiled_collation(&my_charset_utf8_icelandic_uca_ci);
+ add_compiled_collation(&my_charset_utf8_latvian_uca_ci);
+ add_compiled_collation(&my_charset_utf8_romanian_uca_ci);
+ add_compiled_collation(&my_charset_utf8_slovenian_uca_ci);
+ add_compiled_collation(&my_charset_utf8_polish_uca_ci);
+ add_compiled_collation(&my_charset_utf8_estonian_uca_ci);
+ add_compiled_collation(&my_charset_utf8_spanish_uca_ci);
+ add_compiled_collation(&my_charset_utf8_swedish_uca_ci);
+ add_compiled_collation(&my_charset_utf8_turkish_uca_ci);
+ add_compiled_collation(&my_charset_utf8_czech_uca_ci);
+ add_compiled_collation(&my_charset_utf8_danish_uca_ci);
+ add_compiled_collation(&my_charset_utf8_lithuanian_uca_ci);
+ add_compiled_collation(&my_charset_utf8_slovak_uca_ci);
+ add_compiled_collation(&my_charset_utf8_spanish2_uca_ci);
#endif
/* Copy compiled charsets */
diff --git a/mysys/charset.c b/mysys/charset.c
index d801fcdbd76..1388fc40c6d 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -21,16 +21,6 @@
#include <my_dir.h>
#include <my_xml.h>
-typedef struct
-{
- int nchars;
- MY_UNI_IDX uidx;
-} uni_idx;
-
-#define PLANE_SIZE 0x100
-#define PLANE_NUM 0x100
-#define PLANE_NUMBER(x) (((x)>>8) % PLANE_NUM)
-
/*
The code below implements this functionality:
@@ -48,32 +38,21 @@ my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2)
}
-static void set_max_sort_char(CHARSET_INFO *cs)
-{
- uchar max_char;
- uint i;
-
- if (!cs->sort_order)
- return;
-
- max_char=cs->sort_order[(uchar) cs->max_sort_char];
- for (i= 0; i < 256; i++)
- {
- if ((uchar) cs->sort_order[i] > max_char)
- {
- max_char=(uchar) cs->sort_order[i];
- cs->max_sort_char= i;
- }
- }
-}
-
-
-static void init_state_maps(CHARSET_INFO *cs)
+static my_bool init_state_maps(CHARSET_INFO *cs)
{
uint i;
- uchar *state_map= cs->state_map;
- uchar *ident_map= cs->ident_map;
+ uchar *state_map;
+ uchar *ident_map;
+ if (!(cs->state_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
+ return 1;
+
+ if (!(cs->ident_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
+ return 1;
+
+ state_map= cs->state_map;
+ ident_map= cs->ident_map;
+
/* Fill state_map with states to get a faster parser */
for (i=0; i < 256 ; i++)
{
@@ -120,6 +99,7 @@ static void init_state_maps(CHARSET_INFO *cs)
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)'n']= state_map[(uchar)'N']= (uchar) MY_LEX_IDENT_OR_NCHAR;
+ return 0;
}
@@ -131,98 +111,11 @@ static void simple_cs_init_functions(CHARSET_INFO *cs)
cs->coll= &my_collation_8bit_simple_ci_handler;
cs->cset= &my_charset_8bit_handler;
- cs->mbminlen= 1;
- cs->mbmaxlen= 1;
}
-static int pcmp(const void * f, const void * s)
-{
- const uni_idx *F= (const uni_idx*) f;
- const uni_idx *S= (const uni_idx*) s;
- int res;
-
- if (!(res=((S->nchars)-(F->nchars))))
- res=((F->uidx.from)-(S->uidx.to));
- return res;
-}
-
-static my_bool create_fromuni(CHARSET_INFO *cs)
-{
- uni_idx idx[PLANE_NUM];
- int i,n;
-
- /* Clear plane statistics */
- bzero(idx,sizeof(idx));
-
- /* Count number of characters in each plane */
- for (i=0; i< 0x100; i++)
- {
- uint16 wc=cs->tab_to_uni[i];
- int pl= PLANE_NUMBER(wc);
-
- if (wc || !i)
- {
- if (!idx[pl].nchars)
- {
- idx[pl].uidx.from=wc;
- idx[pl].uidx.to=wc;
- }else
- {
- idx[pl].uidx.from=wc<idx[pl].uidx.from?wc:idx[pl].uidx.from;
- idx[pl].uidx.to=wc>idx[pl].uidx.to?wc:idx[pl].uidx.to;
- }
- idx[pl].nchars++;
- }
- }
-
- /* Sort planes in descending order */
- qsort(&idx,PLANE_NUM,sizeof(uni_idx),&pcmp);
-
- for (i=0; i < PLANE_NUM; i++)
- {
- int ch,numchars;
-
- /* Skip empty plane */
- if (!idx[i].nchars)
- break;
-
- numchars=idx[i].uidx.to-idx[i].uidx.from+1;
- if (!(idx[i].uidx.tab=(uchar*) my_once_alloc(numchars *
- sizeof(*idx[i].uidx.tab),
- MYF(MY_WME))))
- return TRUE;
-
- bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab));
-
- for (ch=1; ch < PLANE_SIZE; ch++)
- {
- uint16 wc=cs->tab_to_uni[ch];
- if (wc >= idx[i].uidx.from && wc <= idx[i].uidx.to && wc)
- {
- int ofs= wc - idx[i].uidx.from;
- idx[i].uidx.tab[ofs]= ch;
- }
- }
- }
-
- /* Allocate and fill reverse table for each plane */
- n=i;
- if (!(cs->tab_from_uni= (MY_UNI_IDX*) my_once_alloc(sizeof(MY_UNI_IDX)*(n+1),
- MYF(MY_WME))))
- return TRUE;
-
- for (i=0; i< n; i++)
- cs->tab_from_uni[i]= idx[i].uidx;
-
- /* Set end-of-list marker */
- bzero(&cs->tab_from_uni[i],sizeof(MY_UNI_IDX));
- return FALSE;
-}
-
-
-static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
+static int cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
{
to->number= from->number ? from->number : to->number;
@@ -244,7 +137,8 @@ static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
MY_CS_CTYPE_TABLE_SIZE,
MYF(MY_WME))))
goto err;
- init_state_maps(to);
+ if (init_state_maps(to))
+ goto err;
}
if (from->to_lower)
if (!(to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower,
@@ -263,7 +157,7 @@ static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
MY_CS_SORT_ORDER_TABLE_SIZE,
MYF(MY_WME))))
goto err;
- set_max_sort_char(to);
+
}
if (from->tab_to_uni)
{
@@ -271,11 +165,10 @@ static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
if (!(to->tab_to_uni= (uint16*) my_once_memdup((char*)from->tab_to_uni,
sz, MYF(MY_WME))))
goto err;
- if (create_fromuni(to))
- goto err;
}
- to->mbminlen= 1;
- to->mbmaxlen= 1;
+ if (from->tailoring)
+ if (!(to->tailoring= my_once_strdup(from->tailoring,MYF(MY_WME))))
+ goto err;
return 0;
@@ -284,6 +177,7 @@ err:
}
+
static my_bool simple_cs_is_full(CHARSET_INFO *cs)
{
return ((cs->csname && cs->tab_to_uni && cs->ctype && cs->to_upper &&
@@ -315,14 +209,34 @@ static int add_collation(CHARSET_INFO *cs)
if (!(all_charsets[cs->number]->state & MY_CS_COMPILED))
{
- simple_cs_init_functions(all_charsets[cs->number]);
- if (simple_cs_copy_data(all_charsets[cs->number],cs))
- return MY_XML_ERROR;
- if (simple_cs_is_full(all_charsets[cs->number]))
+ CHARSET_INFO *new= all_charsets[cs->number];
+ if (cs_copy_data(all_charsets[cs->number],cs))
+ return MY_XML_ERROR;
+
+ if (!strcmp(cs->csname,"ucs2") )
+ {
+#ifdef HAVE_CHARSET_ucs2
+ new->cset= my_charset_ucs2_general_uca.cset;
+ new->coll= my_charset_ucs2_general_uca.coll;
+ new->strxfrm_multiply= my_charset_ucs2_general_uca.strxfrm_multiply;
+ new->min_sort_char= my_charset_ucs2_general_uca.min_sort_char;
+ new->max_sort_char= my_charset_ucs2_general_uca.max_sort_char;
+ new->mbminlen= 2;
+ new->mbmaxlen= 2;
+ new->state |= MY_CS_AVAILABLE | MY_CS_LOADED;
+#endif
+ }
+ else
{
- all_charsets[cs->number]->state |= MY_CS_LOADED;
+ simple_cs_init_functions(all_charsets[cs->number]);
+ new->mbminlen= 1;
+ new->mbmaxlen= 1;
+ if (simple_cs_is_full(all_charsets[cs->number]))
+ {
+ all_charsets[cs->number]->state |= MY_CS_LOADED;
+ }
+ all_charsets[cs->number]->state|= MY_CS_AVAILABLE;
}
- all_charsets[cs->number]->state|= MY_CS_AVAILABLE;
}
else
{
@@ -432,6 +346,10 @@ void add_compiled_collation(CHARSET_INFO *cs)
cs->state|= MY_CS_AVAILABLE;
}
+static void *cs_alloc(uint size)
+{
+ return my_once_alloc(size, MYF(MY_WME));
+}
#ifdef __NETWARE__
@@ -465,9 +383,9 @@ static my_bool init_available_charsets(myf myflags)
{
if (*cs)
{
- set_max_sort_char(*cs);
if (cs[0]->ctype)
- init_state_maps(*cs);
+ if (init_state_maps(*cs))
+ *cs= NULL;
}
}
@@ -551,6 +469,14 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
}
cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
}
+ if (cs && !(cs->state & MY_CS_READY))
+ {
+ if ((cs->cset->init && cs->cset->init(cs, cs_alloc)) ||
+ (cs->coll->init && cs->coll->init(cs, cs_alloc)))
+ cs= NULL;
+ else
+ cs->state|= MY_CS_READY;
+ }
pthread_mutex_unlock(&THR_LOCK_charset);
return cs;
}
diff --git a/mysys/default.c b/mysys/default.c
index 056f686e16f..792233ed10d 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -222,7 +222,7 @@ int load_defaults(const char *conf_file, const char **groups,
/* copy name + found arguments + command line arguments to new array */
res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */
memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*));
- /* Skipp --defaults-file and --defaults-extra-file */
+ /* Skip --defaults-file and --defaults-extra-file */
(*argc)-= args_used;
(*argv)+= args_used;
diff --git a/mysys/hash.c b/mysys/hash.c
index b7be41a9058..11cbbd6b898 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -122,7 +122,8 @@ static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax,
-#if !defined(__SUNPRO_C) && !defined(__USLC__) /* broken compilers */
+/* for compilers which can not handle inline */
+#if !defined(__SUNPRO_C) && !defined(__USLC__) && !defined(__sgi)
inline
#endif
unsigned int rec_hashnr(HASH *hash,const byte *record)
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index 530721a79ad..f16f2b7ab72 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -55,7 +55,6 @@ TODO:
#include "mysys_err.h"
static void my_aiowait(my_aio_result *result);
#endif
-#include <assert.h>
#include <errno.h>
#ifdef THREAD
@@ -800,7 +799,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
{ /* Fix if skipped bytes */
if (info->aio_read_pos + read_length < info->pos_in_file)
{
- read_length=0; /* Skipp block */
+ read_length=0; /* Skip block */
next_pos_in_file=info->pos_in_file;
}
else
@@ -894,7 +893,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
if (aioread(info->file,read_buffer,(int) max_length,
(my_off_t) next_pos_in_file,MY_SEEK_SET,
&info->aio_result.result))
- { /* Skipp async io */
+ { /* Skip async io */
my_errno=errno;
DBUG_PRINT("error",("got error: %d, aio_result: %d from aioread, async skipped",
errno, info->aio_result.result.aio_errno));
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index 232097d355b..1f3db84304e 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -23,7 +23,6 @@
#include <m_string.h>
#include <stdarg.h>
#include <m_ctype.h>
-#include <assert.h>
my_off_t my_b_append_tell(IO_CACHE* info)
{
@@ -273,7 +272,7 @@ uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
fmt++;
/* Found one '%' */
}
- /* Skipp if max size is used (to be compatible with printf) */
+ /* Skip if max size is used (to be compatible with printf) */
while (my_isdigit(&my_charset_latin1, *fmt) || *fmt == '.' || *fmt == '-')
fmt++;
if (*fmt == 's') /* String parameter */
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 168483f276b..32b3154b8ed 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -44,7 +44,6 @@
#include "my_static.h"
#include <m_string.h>
#include <errno.h>
-#include <assert.h>
#include <stdarg.h>
/*
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index 2d0a5ea282b..9193238708d 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -43,7 +43,7 @@ void pack_dirname(my_string to, const char *from)
(void) intern_filename(to,from); /* Change to intern name */
#ifdef FN_DEVCHAR
- if ((start=strrchr(to,FN_DEVCHAR)) != 0) /* Skipp device part */
+ if ((start=strrchr(to,FN_DEVCHAR)) != 0) /* Skip device part */
start++;
else
#endif
@@ -131,7 +131,7 @@ uint cleanup_dirname(register my_string to, const char *from)
from_ptr=(my_string) from;
#ifdef FN_DEVCHAR
if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0)
- { /* Skipp device part */
+ { /* Skip device part */
length=(uint) (pos-from_ptr)+1;
start=strnmov(buff,from_ptr,length); from_ptr+=length;
}
@@ -195,7 +195,7 @@ uint cleanup_dirname(register my_string to, const char *from)
pos--; /* Remove dupplicate '/' */
}
else if (pos-start > 1 && pos[-1] == FN_CURLIB && pos[-2] == FN_LIBCHAR)
- pos-=2; /* Skipp /./ */
+ pos-=2; /* Skip /./ */
else if (pos > buff+1 && pos[-1] == FN_HOMELIB && pos[-2] == FN_LIBCHAR)
{ /* Found ..../~/ */
buff[0]=FN_HOMELIB;
@@ -409,7 +409,7 @@ uint system_filename(my_string to, const char *from)
libchar_found=0;
(void) strmov(buff,from); /* If to == from */
from_pos= buff;
- if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skipp device part */
+ if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skip device part */
{
pos++;
to_pos=strnmov(to,from_pos,(size_s) (pos-from_pos));
@@ -419,7 +419,7 @@ uint system_filename(my_string to, const char *from)
to_pos=to;
if (from_pos[0] == FN_CURLIB && from_pos[1] == FN_LIBCHAR)
- from_pos+=2; /* Skipp './' */
+ from_pos+=2; /* Skip './' */
if (strchr(from_pos,FN_LIBCHAR))
{
*(to_pos++) = FN_C_BEFORE_DIR;
@@ -487,7 +487,7 @@ my_string intern_filename(my_string to, const char *from)
convert_dirname(buff,from,NullS); /* change '<>' to '[]' */
from_pos=buff;
- if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skipp device part */
+ if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skip device part */
{
pos++;
to_pos=strnmov(to,from_pos,(size_s) (pos-from_pos));
diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c
index 27ab4892c57..c0c6105a6eb 100644
--- a/mysys/mf_soundex.c
+++ b/mysys/mf_soundex.c
@@ -52,7 +52,7 @@ void soundex(CHARSET_INFO * cs,register my_string out_pntr, my_string in_pntr,
if (remove_garbage)
{
- while (*in_pntr && !my_isalpha(cs,*in_pntr)) /* Skipp pre-space */
+ while (*in_pntr && !my_isalpha(cs,*in_pntr)) /* Skip pre-space */
in_pntr++;
}
*out_pntr++ = map[(uchar)*in_pntr]; /* Copy first letter */
@@ -82,7 +82,7 @@ void soundex(CHARSET_INFO * cs,register my_string out_pntr, my_string in_pntr,
/*
If alpha, map input letter to soundex code.
- If not alpha and remove_garbage is set then skipp to next char
+ If not alpha and remove_garbage is set then skip to next char
else return 0
*/
diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c
index 14b8fdc430c..0b337a74c19 100644
--- a/mysys/mf_tempfile.c
+++ b/mysys/mf_tempfile.c
@@ -83,7 +83,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
(*free)(res);
file=my_create(to, 0, mode, MyFlags);
}
-#elif defined(HAVE_MKSTEMP)
+#elif defined(HAVE_MKSTEMP) && !defined(__NETWARE__)
{
char prefix_buff[30];
uint pfx_len;
@@ -181,7 +181,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
for (length=0 ; length < 8 && uniq ; length++)
{
- *end_pos++= _dig_vec[(int) (uniq & 31)];
+ *end_pos++= _dig_vec_upper[(int) (uniq & 31)];
uniq >>= 5;
}
(void) strmov(end_pos,TMP_EXT);
diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c
index b964d7ee494..7d537eaa06a 100644
--- a/mysys/mf_wfile.c
+++ b/mysys/mf_wfile.c
@@ -39,7 +39,7 @@ WF_PACK *wf_comp(my_string str)
WF_PACK *ret;
DBUG_ENTER("wf_comp");
- not_pos= -1; /* Skipp space and '!' in front */
+ not_pos= -1; /* Skip space and '!' in front */
while (*str == ' ')
str++;
if (*str == '!')
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index cee46ad59b6..a596fcb6fd9 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -38,7 +38,6 @@
#include "mysys_priv.h"
#include <my_bitmap.h>
-#include <assert.h>
#include <m_string.h>
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 6fd346c89f7..8a377f63c7e 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -33,6 +33,12 @@ char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
nr Errno
MyFlags Flags
... variable list
+ NOTE
+ The following subset of printf format is supported:
+ "%[0-9.-]*l?[sdu]", where all length flags are parsed but ignored.
+
+ Additionally "%.*s" is supported and "%.*[ud]" is correctly parsed but
+ the length value is ignored.
*/
int my_error(int nr,myf MyFlags, ...)
@@ -43,7 +49,10 @@ int my_error(int nr,myf MyFlags, ...)
reg2 char *endpos;
char * par;
char ebuff[ERRMSGSIZE+20];
+ int prec_chars; /* output precision */
+ my_bool prec_supplied;
DBUG_ENTER("my_error");
+ LINT_INIT(prec_chars); /* protected by prec_supplied */
va_start(ap,MyFlags);
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno));
@@ -59,7 +68,6 @@ int my_error(int nr,myf MyFlags, ...)
if (tpos[0] != '%')
{
*endpos++= *tpos++; /* Copy ordinary char */
- olen++;
continue;
}
if (*++tpos == '%') /* test if %% */
@@ -68,43 +76,71 @@ int my_error(int nr,myf MyFlags, ...)
}
else
{
- /* Skipp if max size is used (to be compatible with printf) */
- while (my_isdigit(&my_charset_latin1, *tpos) || *tpos == '.' || *tpos == '-')
- tpos++;
- if (*tpos == 'l') /* Skipp 'l' argument */
- tpos++;
+ /*
+ Skip size/precision flags to be compatible with printf.
+ The only size/precision flag supported is "%.*s".
+ If "%.*u" or "%.*d" are encountered, the precision number is read
+ from the variable argument list but its value is ignored.
+ */
+ prec_supplied= 0;
+ if (*tpos== '.')
+ {
+ tpos++;
+ olen--;
+ if (*tpos == '*')
+ {
+ tpos++;
+ olen--;
+ prec_chars= va_arg(ap, int); /* get length parameter */
+ prec_supplied= 1;
+ }
+ }
+
+ if (!prec_supplied)
+ {
+ while (my_isdigit(&my_charset_latin1, *tpos) || *tpos == '.' ||
+ *tpos == '-')
+ tpos++;
+
+ if (*tpos == 'l') /* Skip 'l' argument */
+ tpos++;
+ }
+
if (*tpos == 's') /* String parameter */
{
- par = va_arg(ap, char *);
- plen = (uint) strlen(par);
+ par= va_arg(ap, char *);
+ plen= (uint) strlen(par);
+ if (prec_supplied && prec_chars > 0)
+ plen= min((uint)prec_chars, plen);
if (olen + plen < ERRMSGSIZE+2) /* Replace if possible */
{
- endpos=strmov(endpos,par);
- tpos++;
- olen+=plen-2;
- continue;
+ strmake(endpos, par, plen);
+ endpos+= plen;
+ tpos++;
+ olen+= plen-2;
+ continue;
}
}
else if (*tpos == 'd' || *tpos == 'u') /* Integer parameter */
{
register int iarg;
- iarg = va_arg(ap, int);
+ iarg= va_arg(ap, int);
if (*tpos == 'd')
- plen= (uint) (int2str((long) iarg,endpos, -10) - endpos);
+ plen= (uint) (int10_to_str((long) iarg, endpos, -10) - endpos);
else
- plen= (uint) (int2str((long) (uint) iarg,endpos,10)- endpos);
+ plen= (uint) (int10_to_str((long) (uint) iarg, endpos, 10) - endpos);
if (olen + plen < ERRMSGSIZE+2) /* Replace parameter if possible */
{
- endpos+=plen;
+ endpos+= plen;
tpos++;
- olen+=plen-2;
+ olen+= plen-2;
continue;
}
}
}
- *endpos++='%'; /* % used as % or unknown code */
+ *endpos++= '%'; /* % used as % or unknown code */
}
- *endpos='\0'; /* End of errmessage */
+ *endpos= '\0'; /* End of errmessage */
va_end(ap);
DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags));
}
diff --git a/mysys/my_gethostbyname.c b/mysys/my_gethostbyname.c
index 5044a505054..27281f3489d 100644
--- a/mysys/my_gethostbyname.c
+++ b/mysys/my_gethostbyname.c
@@ -18,7 +18,6 @@
/* Thread safe version of gethostbyname_r() */
#include "mysys_priv.h"
-#include <assert.h>
#if !defined(MSDOS) && !defined(__WIN__)
#include <netdb.h>
#endif
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 8d0b05d55f7..d7a9babe5e7 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -18,7 +18,6 @@
#include <m_string.h>
#include <stdlib.h>
#include <my_getopt.h>
-#include <assert.h>
#include <my_sys.h>
#include <mysys_err.h>
diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c
index a08d28d8545..fd47c532cff 100644
--- a/mysys/my_getwd.c
+++ b/mysys/my_getwd.c
@@ -108,7 +108,7 @@ int my_setwd(const char *dir, myf MyFlags)
{
uint drive,drives;
- pos++; /* Skipp FN_DEVCHAR */
+ pos++; /* Skip FN_DEVCHAR */
drive=(uint) (my_toupper(&my_charset_latin1,dir[0])-'A'+1);
drives= (uint) -1;
if ((pos-(byte*) dir) == 2 && drive > 0 && drive < 32)
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index de0fba56d21..6003808df25 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -21,13 +21,11 @@ int mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
uchar *b, uint b_length, my_bool part_key,
my_bool skip_end_space)
{
- if (part_key && b_length < a_length)
- a_length=b_length;
if (skip_end_space)
return charset_info->coll->strnncollsp(charset_info, a, a_length,
b, b_length);
return charset_info->coll->strnncoll(charset_info, a, a_length,
- b, b_length);
+ b, b_length, part_key);
}
diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c
index 2667c0670d8..37517fb8327 100644
--- a/mysys/my_pthread.c
+++ b/mysys/my_pthread.c
@@ -23,7 +23,6 @@
#include <signal.h>
#include <m_string.h>
#include <thr_alarm.h>
-#include <assert.h>
#if (defined(__BSD__) || defined(_BSDI_VERSION)) && !defined(HAVE_mit_thread)
#define SCHED_POLICY SCHED_RR
@@ -98,25 +97,23 @@ void *my_pthread_getspecific_imp(pthread_key_t key)
#undef pthread_exit
void my_pthread_exit(void *status)
{
- NXThreadId_t tid = NXThreadGetId();
+ NXThreadId_t tid;
NXContext_t ctx;
- char name[PATH_MAX] = "";
-
- /* Do not call pthread_exit if it is not a LibC thread */
- if (tid != 0)
- {
- NXThreadGetContext(tid, &ctx);
- NXContextGetName(ctx, name, PATH_MAX);
-
- /*
- "MYSQLD.NLM's LibC Reaper" or "MYSQLD.NLM's main thread"
- with a debug build of LibC the reaper can have different names
- */
- if (!strindex(name, "\'s"))
- {
- pthread_exit(status);
- }
- }
+ char name[NX_MAX_OBJECT_NAME_LEN+1] = "";
+
+ tid= NXThreadGetId();
+ if (tid == NX_INVALID_THREAD_ID || !tid)
+ return;
+ if (NXThreadGetContext(tid, &ctx) ||
+ NXContextGetName(ctx, name, sizeof(name)-1))
+ return;
+
+ /*
+ "MYSQLD.NLM's LibC Reaper" or "MYSQLD.NLM's main thread"
+ with a debug build of LibC the reaper can have different names
+ */
+ if (!strindex(name, "\'s"))
+ pthread_exit(status);
}
#endif
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index ec24a26b3d9..6af65d70fd0 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -15,7 +15,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
-#include <assert.h>
/* Seek to position in file */
/*ARGSUSED*/
diff --git a/mysys/my_static.h b/mysys/my_static.h
index bb408aa808d..51f9fbc922f 100644
--- a/mysys/my_static.h
+++ b/mysys/my_static.h
@@ -19,6 +19,7 @@
a shared library
*/
+C_MODE_START
#include <signal.h>
#define MAX_SIGNALS 10 /* Max signals under a dont-allow */
@@ -73,3 +74,4 @@ extern struct st_my_file_info my_file_info_default[MY_NFILE];
#if defined(THREAD) && !defined(__WIN__)
extern sigset_t my_signals; /* signals blocked by mf_brkhant */
#endif
+C_MODE_END
diff --git a/mysys/my_tempnam.c b/mysys/my_tempnam.c
index b4f76727ee0..9f765298fb6 100644
--- a/mysys/my_tempnam.c
+++ b/mysys/my_tempnam.c
@@ -161,7 +161,7 @@ my_string my_tempnam(const char *dir, const char *pfx,
for (length=0 ; length < 8 && uniq ; length++)
{
- *end_pos++= _dig_vec[(int) (uniq & 31)];
+ *end_pos++= _dig_vec_upper[(int) (uniq & 31)];
uniq >>= 5;
}
VOID(strmov(end_pos,TMP_EXT));
diff --git a/mysys/rijndael.c b/mysys/rijndael.c
index dd0c45445d5..43cd14101ca 100644
--- a/mysys/rijndael.c
+++ b/mysys/rijndael.c
@@ -26,7 +26,6 @@
*/
#include <my_global.h>
-#include <assert.h>
#include "rijndael.h"
/*
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 54aa4d421f6..84a8e779ae1 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -27,7 +27,6 @@
#include <m_string.h>
#include <queues.h>
#include "thr_alarm.h"
-#include <assert.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> /* AIX needs this for fd_set */
diff --git a/ndb/BinDist.sh b/ndb/BinDist.sh
deleted file mode 100644
index 2f9620549f4..00000000000
--- a/ndb/BinDist.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-#
-# Invoked from scripts/make_binary_distribution as "sh BinDist.sh".
-# Prints list of dirs and files to include under mysql/ndb.
-#
-
-# release notes
-
-grep -v '^#' <<__END__
-#ReleaseNotes.html
-mysqlclusterenv.sh
-__END__
-
-# subset of bins, libs, includes
-
-grep -v '^#' <<__END__
-bin/
-bin/ndb
-bin/mgmtsrvr
-bin/mgmtclient
-bin/mysqlcluster
-bin/mysqlcluster_install_db
-bin/mysqlclusterd
-bin/restore
-bin/ndb_rep
-bin/desc
-bin/flexBench
-bin/select_all
-bin/select_count
-bin/delete_all
-#bin/ndbsql
-bin/drop_tab
-bin/drop_index
-bin/list_tables
-bin/waiter
-lib/
-lib/libNEWTON_API.a
-lib/libNEWTON_API.so
-lib/libNDB_API.a
-lib/libNDB_API.so
-lib/libMGM_API.a
-lib/libMGM_API.so
-#lib/libNDB_ODBC.so
-lib/libMGM_API_pic.a
-lib/libNDB_API_pic.a
-include/
-include/ndb_types.h
-include/ndb_version.h
-include/mgmapi/
-include/mgmapi/mgmapi.h
-include/mgmapi/mgmapi_debug.h
-include/ndbapi/
-include/ndbapi/ndbapi_limits.h
-include/ndbapi/AttrType.hpp
-include/ndbapi/Ndb.hpp
-include/ndbapi/NdbApi.hpp
-include/ndbapi/NdbConnection.hpp
-include/ndbapi/NdbCursorOperation.hpp
-include/ndbapi/NdbDictionary.hpp
-include/ndbapi/NdbError.hpp
-include/ndbapi/NdbEventOperation.hpp
-include/ndbapi/NdbIndexOperation.hpp
-include/ndbapi/NdbOperation.hpp
-include/ndbapi/NdbPool.hpp
-include/ndbapi/NdbRecAttr.hpp
-include/ndbapi/NdbReceiver.hpp
-include/ndbapi/NdbResultSet.hpp
-include/ndbapi/NdbScanFilter.hpp
-include/ndbapi/NdbScanOperation.hpp
-include/ndbapi/NdbSchemaCon.hpp
-include/ndbapi/NdbSchemaOp.hpp
-include/newtonapi/dba.h
-include/newtonapi/defs/pcn_types.h
-__END__
-
-#if [ -f /usr/local/lib/libstdc++.a ]; then
-# cp /usr/local/lib/libstdc++.a lib/.
-# echo lib/libstdc++.a
-#fi
-#if [ -f /usr/local/lib/libstdc++.so.5 ]; then
-# cp /usr/local/lib/libstdc++.so.5 lib/.
-# echo lib/libstdc++.so.5
-#fi
-#if [ -f /usr/local/lib/libgcc_s.so.1 ]; then
-# cp /usr/local/lib/libgcc_s.so.1 lib/.
-# echo lib/libgcc_s.so.1
-#fi
-
-# docs
-
-#find docs/*.html docs/*.pdf -print | sort -t/
-
-# demos
-
-find demos -print | grep -v /SCCS | sort -t/
-
-# examples
-
-grep -v '^#' <<__END__
-examples/
-examples/Makefile
-examples/ndbapi_example1/
-examples/ndbapi_example1/Makefile
-examples/ndbapi_example1/ndbapi_example1.cpp
-examples/ndbapi_example2/
-examples/ndbapi_example2/Makefile
-examples/ndbapi_example2/ndbapi_example2.cpp
-examples/ndbapi_example3/
-examples/ndbapi_example3/Makefile
-examples/ndbapi_example3/ndbapi_example3.cpp
-examples/ndbapi_example4/
-examples/ndbapi_example4/Makefile
-examples/ndbapi_example4/ndbapi_example4.cpp
-examples/ndbapi_example5/
-examples/ndbapi_example5/Makefile
-examples/ndbapi_example5/ndbapi_example5.cpp
-examples/select_all/
-examples/select_all/Makefile
-examples/select_all/select_all.cpp
-__END__
-
-exit 0
diff --git a/ndb/Defs.mk b/ndb/Defs.mk
deleted file mode 100644
index ac4507562fd..00000000000
--- a/ndb/Defs.mk
+++ /dev/null
@@ -1,64 +0,0 @@
-include $(NDB_TOP)/config/config.mk
-include $(NDB_TOP)/config/Defs.$(NDB_VERSION).mk
-include $(NDB_TOP)/config/Defs.$(NDB_OS).$(NDB_ARCH).$(NDB_COMPILER).mk
-
-ifeq ($(NDB_OS), WIN32)
-# Windows specific definitions
-OBJEXT := obj
-LIBEXT := lib
-LIBPREFIX :=
-fixpath = `cygpath -w $1`
-ar_rcs = lib -out:`cygpath -w $1` $2
-link_so = link -DLL -OUT:`cygpath -w $1` $(WIN_LIBS) $2
-#check-odbc = Y
-USE_EDITLINE := N
-#STRCASECMP is defined in include/portlib/PortDefs.h to _strcmpi
-else
-#Common definitions for almost all non-Windows environments
-OBJEXT := o
-LIBEXT := a
-LIBPREFIX := lib
-fixpath = $1
-ar_rcs = $(AR_RCS) $1 $2
-#check-odbc = $(findstring sqlext.h, $(wildcard /usr/include/sqlext.h) $(wildcard /usr/local/include/sqlext.h))
-endif
-
-ifeq ($(NDB_OS), WIN32)
-SHLIBEXT := dll
-endif
-
-ifeq ($(NDB_OS), LINUX)
-SHLIBEXT := so
-endif
-
-ifeq ($(NDB_OS), SOLARIS)
-SHLIBEXT := so
-endif
-
-ifeq ($(NDB_OS), HPUX)
-SHLIBEXT := sl
-endif
-
-ifeq ($(NDB_OS), MACOSX)
-SHLIBEXT := dylib
-endif
-
-ifeq ($(NDB_OS), OSE)
-SHLIBEXT := so
-endif
-
-ifeq ($(NDB_OS), SOFTOSE)
-SHLIBEXT := so
-endif
-
-ifeq ($(NDB_SCI), Y)
-CCFLAGS_TOP += -DHAVE_NDB_SCI
-endif
-
-ifeq ($(NDB_SHM), Y)
-CCFLAGS_TOP += -DHAVE_NDB_SHM
-endif
-
-ifneq ($(findstring OSE, $(NDB_OS)),)
-USE_EDITLINE := N
-endif
diff --git a/ndb/Epilogue.mk b/ndb/Epilogue.mk
deleted file mode 100644
index bcdc54a87f1..00000000000
--- a/ndb/Epilogue.mk
+++ /dev/null
@@ -1,876 +0,0 @@
-# .KEEP_STATE:
-# bk test !!!
-
-###
-# For building some intermediary targets in /tmp (only useful on solaris)
-ifneq ($(NDB_BUILDROOT),)
-NDB_TOPABS := $(shell cd $(NDB_TOP) && /bin/pwd)
-NDB_BUILDDIR := $(subst $(NDB_TOPABS),$(NDB_BUILDROOT),$(CURDIR))/
-ifeq ($(wildcard $(NDB_BUILDDIR)),)
-dummy := $(shell mkdir -p $(NDB_BUILDDIR))
-endif
-endif
-
-###
-CCFLAGS_TOP += -DNDB_$(NDB_OS) -DNDB_$(NDB_ARCH) -DNDB_$(NDB_COMPILER)
-
-ifdef BIN_TARGET
-BIN_EXE = Y
-endif
-
-###
-#
-# OS specifics
-#
-
-# Disable shared libraries on HP-UX for the time being.
-ifeq ($(NDB_OS), HPUX)
- SO_LIB := N
- PIC_LIB := N
- PIC_ARCHIVE := N
- NONPIC_ARCHIVE := Y
-endif
-
-ifeq ($(NDB_OS), OSE)
- SO_LIB := N
- PIC_LIB := N
- PIC_ARCHIVE := N
- NONPIC_ARCHIVE := Y
-
-ifdef BIN_TARGET
- BIN_LIB_TARGET := lib$(BIN_TARGET).a
- BIN_TARGET := lib$(BIN_TARGET).a
-endif
-endif
-
-ifeq ($(NDB_OS), SOFTOSE)
- SO_LIB := N
- PIC_LIB := N
- PIC_ARCHIVE := N
-
-ifdef BIN_TARGET
- BIN_EXE_TARGET := $(BIN_TARGET)
- BIN_LIB_TARGET := lib$(BIN_TARGET).a
- EXTRA_MAIN := osemain.o
-endif
-endif
-
-ifeq ($(filter OSE, $(NDB_OS)),)
- BIN_EXE_TARGET := $(BIN_TARGET)
-endif
-
-
-ifeq ($(NDB_OS), MACOSX)
-.LIBPATTERNS= lib%.dylib lib%.a
-endif
-
-###
-#
-#
-
-###
-# External dependencies definition : the place we store libraries
-# we get from outside the NDB development group.
-EXTERNAL_DEPENDS_TOP=$(NDB_TOP)/src/external/$(NDB_OS).$(NDB_ARCH)
-
-
-###
-#
-# TYPE Handling
-
-#
-# TYPE := kernel
-#
-ifneq ($(filter kernel, $(TYPE)),)
-CCFLAGS_LOC += \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/vm) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/error) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel) \
- -I$(call fixpath,$(NDB_TOP)/include/kernel) \
- -I$(call fixpath,$(NDB_TOP)/include/transporter) \
- -I$(call fixpath,$(NDB_TOP)/include/debugger) \
- -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \
- -I$(call fixpath,$(NDB_TOP)/include/ndbapi) \
- -I$(call fixpath,$(NDB_TOP)/include/util) \
- -I$(call fixpath,$(NDB_TOP)/include/portlib) \
- -I$(call fixpath,$(NDB_TOP)/include/logger)
-endif
-
-#
-# TYPE := ndbapi
-#
-ifneq ($(filter ndbapi, $(TYPE)),)
-CCFLAGS_LOC += \
- -I$(call fixpath,$(NDB_TOP)/include/kernel) \
- -I$(call fixpath,$(NDB_TOP)/include/transporter) \
- -I$(call fixpath,$(NDB_TOP)/include/debugger) \
- -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \
- -I$(call fixpath,$(NDB_TOP)/include/ndbapi) \
- -I$(call fixpath,$(NDB_TOP)/include/util) \
- -I$(call fixpath,$(NDB_TOP)/include/portlib) \
- -I$(call fixpath,$(NDB_TOP)/include/logger)
-endif
-
-#
-# TYPE := ndbapiclient
-#
-ifneq ($(filter ndbapiclient, $(TYPE)),)
-CCFLAGS_LOC += \
- -I$(call fixpath,$(NDB_TOP)/include/ndbapi)
-
-BIN_TARGET_LIBS += NDB_API
-endif
-
-#
-# TYPE := mgmapiclient
-#
-ifneq ($(filter mgmapiclient, $(TYPE)),)
-CCFLAGS_LOC += \
- -I$(call fixpath,$(NDB_TOP)/include/mgmapi)
-
-BIN_TARGET_LIBS += MGM_API
-endif
-
-#
-# TYPE := ndbapitest
-#
-ifneq ($(filter ndbapitest, $(TYPE)),)
-CCFLAGS_LOC += \
- -I$(call fixpath,$(NDB_TOP)/include/ndbapi) \
- -I$(call fixpath,$(NDB_TOP)/include/util) \
- -I$(call fixpath,$(NDB_TOP)/include/portlib) \
- -I$(call fixpath,$(NDB_TOP)/test/include) \
- -I$(call fixpath,$(NDB_TOP)/include/mgmapi)
-
-BIN_TARGET_LIBS += NDBT
-LDFLAGS_LOC += -lNDB_API -lMGM_API -lm
-
-endif
-
-#
-# TYPE := signalsender
-#
-ifneq ($(filter signalsender, $(TYPE)),)
-CCFLAGS_LOC += \
- -I$(call fixpath,$(NDB_TOP)/include/ndbapi) \
- -I$(call fixpath,$(NDB_TOP)/src/ndbapi) \
- -I$(call fixpath,$(NDB_TOP)/src/ndbapi/signal-sender) \
- -I$(call fixpath,$(NDB_TOP)/include/util) \
- -I$(call fixpath,$(NDB_TOP)/include/portlib) \
- -I$(call fixpath,$(NDB_TOP)/include/transporter) \
- -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \
- -I$(call fixpath,$(NDB_TOP)/include/kernel)
-
-BIN_TARGET_LIBS += NDB_API
-BIN_TARGET_ARCHIVES += editline signal-sender
-
-endif
-
-
-#
-# TYPE := repserver
-#
-ifneq ($(filter repserver, $(TYPE)),)
-CCFLAGS_LOC += \
- -I$(call fixpath,$(NDB_TOP)/include/ndbapi) \
- -I$(call fixpath,$(NDB_TOP)/src) \
- -I$(call fixpath,$(NDB_TOP)/src/ndbapi) \
- -I$(call fixpath,$(NDB_TOP)/src/ndbapi/signal-sender) \
- -I$(call fixpath,$(NDB_TOP)/include/util) \
- -I$(call fixpath,$(NDB_TOP)/include/portlib) \
- -I$(call fixpath,$(NDB_TOP)/include/transporter) \
- -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \
- -I$(call fixpath,$(NDB_TOP)/include/kernel)
-endif
-
-#
-# TYPE := odbcclient
-#
-
-ifneq ($(filter odbcclient, $(TYPE)),)
-TYPE += util
-LDFLAGS_LOC += -lm
-#ifneq ($(call check-odbc),)
-ifneq ($(NDB_ODBC),N)
-ifeq ($(NDB_OS), SOLARIS)
-CCFLAGS_LOC += -I/usr/local/include
-BIN_TARGET_LIBS_DIRS += /usr/local/lib
-BIN_TARGET_LIBS += odbc odbcinst NDBT
-endif
-ifeq ($(NDB_OS), LINUX)
-BIN_TARGET_LIBS += odbc odbcinst NDBT
-endif
-ifeq ($(NDB_OS), MACOSX)
-BIN_TARGET_LIBS += odbc odbcinst NDBT
-endif
-ifeq ($(NDB_OS), IBMAIX)
-BIN_TARGET_LIBS += odbc odbcinst NDBT
-endif
-ifeq ($(NDB_OS), TRU64X)
-BIN_TARGET_LIBS += odbc odbcinst NDBT
-endif
-else
-BIN_EXE = N
-endif
-endif
-
-#
-# TYPE := *
-#
-#
-# TYPE := util
-#
-ifneq ($(filter util, $(TYPE)),)
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/util) \
- -I$(call fixpath,$(NDB_TOP)/include/portlib) \
- -I$(call fixpath,$(NDB_TOP)/include/logger)
-BIN_TARGET_LIBS += logger general portlib
-endif
-
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include) -I$(call fixpath,$(NDB_TOP)/../include)
-
-ifeq ($(NDB_SCI), Y)
-BIN_TARGET_LIBS += sisci
-BIN_TARGET_LIBS_DIRS += $(EXTERNAL_DEPENDS_TOP)/sci/lib
-
-CCFLAGS_LOC += -I$(call fixpath,$(EXTERNAL_DEPENDS_TOP)/sci/include)
-endif
-
-#
-# TYPE Handling
-###
-
-###
-#
-# First rule
-#
-first:
- $(MAKE) libs
- $(MAKE) bins
-
-ifeq ($(findstring all,$(replace-targets)),)
-all: first
-endif
-
-###
-#
-# Nice to have rules
-api: libs
- $(MAKE) -C $(NDB_TOP)/src/ndbapi bins
-
-mgm: libs
- $(MAKE) -C $(NDB_TOP)/src/mgmsrv bins
-
-ndb: libs
- $(MAKE) -C $(NDB_TOP)/src/kernel/ndb-main bins
-
-apitest: first
- $(MAKE) -C $(NDB_TOP)/test/ndbapi all
-
-#-lNDBT:
-# $(MAKE) -C $(NDB_TOP)/test/src all
-#
-#-lNDB_API: libs
-# $(MAKE) -C $(NDB_TOP)/src/ndbapi bins
-
-#
-# Libs/Bins
-#
-ifdef PREREQ_LOC
-_libs:: $(PREREQ_LOC)
-_bins:: $(PREREQ_LOC)
-endif
-
-L_DIRS := $(LIB_DIRS) $(DIRS)
-B_DIRS := $(BIN_DIRS) $(DIRS)
-A_DIRS := $(LIB_DIRS) $(BIN_DIRS) $(DIRS)
-
-_libs::
-
-_bins::
-
-libs: _libs $(patsubst %, _libs_%, $(L_DIRS))
-$(patsubst %, _libs_%, $(L_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _libs_%,%,$@) libs
-
-bins: _bins $(patsubst %, _bins_%, $(B_DIRS))
-$(patsubst %, _bins_%, $(B_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _bins_%,%,$@) bins
-
-###
-#
-# Links
-_links:
- -$(NDB_TOP)/tools/make-links.sh $(NDB_TOP)/include `pwd`
-
-links: _links $(patsubst %, _links_%, $(A_DIRS))
-$(patsubst %, _links_%, $(A_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _links_%,%,$@) links
-
-
-####
-#
-# OSE build_spec (
-ifdef SOURCES
-BS := Y
-endif
-
-ifdef SOURCES_c
-BS := Y
-endif
-
-_build_spec: Makefile
-ifdef BS
- @echo "TYPE = SWU" > build.spec
- @echo "include $(NDB_TOP)/Ndb.mk" >> build.spec
-# @for i in $(CCFLAGS_LOC); do echo "INC += $$i" >> build.spec ; done
- @for i in $(patsubst -I%, %, $(CCFLAGS_LOC)); do echo "INC += $$i" >> build.spec ; done
- @echo "INC += /vobs/cello/cls/rtosi_if/include" >> build.spec
- @echo "INC += /vobs/cello/cls/rtosi_if/include.@@@" >> build.spec
- @echo "INC += /vobs/cello/cls/rtosi_if/include.<<<" >> build.spec
-endif
-
-build_spec: _build_spec $(patsubst %, _build_spec_%, $(A_DIRS))
-$(patsubst %, _build_spec_%, $(A_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _build_spec_%,%,$@) build_spec
-
-###
-#
-# Phony targets
-
-.PHONY: $(A_DIRS)
-
-###
-#
-# Dummy rule
-
-DUMMY:
-
-###
-#
-# Definitions of...
-
-PIC_DIR := $(NDB_BUILDDIR).pic
-A_TMP_DIR := $(NDB_BUILDDIR).a_tmp
-SO_TMP_DIR := $(NDB_BUILDDIR).so_tmp
-PIC_TMP_DIR := $(NDB_BUILDDIR).pic_tmp
-
-$(PIC_DIR):
- mkdir -p $(PIC_DIR)
-
-SRC_C := $(filter %.C, $(SOURCES))
-SRC_CPP := $(filter %.cpp, $(SOURCES))
-SRC_CC := $(filter %.cc, $(SOURCES))
-SRC_c := $(filter %.c, $(SOURCES)) $(filter %.c, $(SOURCES.c))
-SRC_YPP := $(filter %.ypp, $(SOURCES))
-SRC_LPP := $(filter %.lpp, $(SOURCES))
-
-OBJECTS := $(SRC_C:%.C=%.$(OBJEXT)) \
- $(SRC_CPP:%.cpp=%.$(OBJEXT)) \
- $(SRC_CC:%.cc=%.$(OBJEXT)) \
- $(SRC_c:%.c=%.$(OBJEXT)) \
- $(SRC_YPP:%.ypp=%.tab.$(OBJEXT)) \
- $(SRC_LPP:%.lpp=%.yy.$(OBJEXT)) \
- $(OBJECTS_LOC)
-
-PIC_OBJS := $(OBJECTS:%=$(PIC_DIR)/%)
-
-LIB_DIR := $(NDB_TOP)/lib
-BIN_DIR := $(NDB_TOP)/bin
-
-###
-#
-# ARCHIVE_TARGET
-#
-ifdef ARCHIVE_TARGET
-
-ifndef NONPIC_ARCHIVE
-NONPIC_ARCHIVE := Y
-endif
-
-ifeq ($(NONPIC_ARCHIVE), Y)
-_libs:: $(LIB_DIR)/$(LIBPREFIX)$(ARCHIVE_TARGET).$(LIBEXT)
-$(LIB_DIR)/$(LIBPREFIX)$(ARCHIVE_TARGET).$(LIBEXT) : $(OBJECTS)
- $(call ar_rcs,$@,$(OBJECTS))
-
-endif # NONPIC_ARCHIVE := Y
-
-ifeq ($(PIC_ARCHIVE), Y)
-_libs:: $(PIC_DIR) $(LIB_DIR)/$(LIBPREFIX)$(ARCHIVE_TARGET)_pic.$(LIBEXT)
-$(LIB_DIR)/$(LIBPREFIX)$(ARCHIVE_TARGET)_pic.$(LIBEXT) : $(PIC_OBJS)
- cd $(PIC_DIR) && $(call ar_rcs,../$@,$(OBJECTS))
-
-PIC_DEP := Y
-
-endif # PIC_ARCHIVE := Y
-
-endif # ARCHIVE_TARGET
-
-###
-#
-# LIB_TARGET
-#
-ifdef LIB_TARGET
-
-ifeq ($(A_LIB), Y)
-
-A_LIB_ARCHIVES := $(LIB_TARGET_ARCHIVES:%=$(LIB_DIR)/$(LIBPREFIX)%.$(LIBEXT))
-
-_bins:: $(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET).$(LIBEXT)
-$(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET).$(LIBEXT) : $(A_LIB_ARCHIVES)
- @rm -rf $(A_TMP_DIR) && mkdir $(A_TMP_DIR)
- cd $(A_TMP_DIR) && for i in $^; do ar -x ../$$i; done && $(call ar_rcs,../$@,*.$(OBJEXT))
- $(NDB_TOP)/home/bin/ndb_deploy $@
-endif # A_LIB := Y
-
-ifeq ($(SO_LIB), Y)
-ifneq ($(NDB_OS), WIN32)
-SO_LIB_ARCHIVES := $(LIB_TARGET_ARCHIVES:%=$(LIB_DIR)/$(LIBPREFIX)%_pic.$(LIBEXT))
-
-_bins:: $(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET).$(SHLIBEXT)
-$(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET).$(SHLIBEXT) : $(SO_LIB_ARCHIVES)
- @rm -rf $(SO_TMP_DIR) && mkdir $(SO_TMP_DIR)
- cd $(SO_TMP_DIR) && for i in $^; do ar -x ../$$i; done
-ifneq ($(NDB_OS), MACOSX)
- $(SO) $@.new $(SO_TMP_DIR)/*.$(OBJEXT) -L$(LIB_DIR) $(LIB_TARGET_LIBS) $(LDFLAGS_LAST)
- rm -f $@; mv $@.new $@
-else
- $(SO) $@ $(SO_TMP_DIR)/*.$(OBJEXT) -L$(LIB_DIR) $(LIB_TARGET_LIBS) $(LDFLAGS_LAST)
-endif
-ifeq ($(NDB_VERSION), RELEASE)
-ifneq ($(NDB_OS), MACOSX)
- strip $@
-endif
-endif
- $(NDB_TOP)/home/bin/ndb_deploy $@
-else # WIN32
-SO_LIB_ARCHIVES := $(LIB_TARGET_ARCHIVES:%=$(LIB_DIR)/$(LIBPREFIX)%_pic.$(LIBEXT))
-
-_bins:: $(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET).$(SHLIBEXT)
-$(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET).$(SHLIBEXT) : $(SO_LIB_ARCHIVES)
- @rm -rf $(SO_TMP_DIR) && mkdir $(SO_TMP_DIR)
- cd $(SO_TMP_DIR) && for i in $^; do ar -x ../$$i; done
- $(call link_so,$@.new,$(SO_TMP_DIR)/*.$(OBJEXT))
- rm -f $@; mv $@.new $@
-#ifeq ($(NDB_VERSION), RELEASE)
-# strip $@
-#endif
-
-endif
-endif # SO_LIB := Y
-
-ifeq ($(PIC_LIB), Y)
-
-PIC_LIB_ARCHIVES := $(LIB_TARGET_ARCHIVES:%=$(LIB_DIR)/$(LIBPREFIX)%_pic.$(LIBEXT))
-
-_bins:: $(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET)_pic.$(LIBEXT)
-$(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET)_pic.$(LIBEXT) : $(PIC_LIB_ARCHIVES)
- @rm -rf $(PIC_TMP_DIR) && mkdir $(PIC_TMP_DIR)
- cd $(PIC_TMP_DIR) && for i in $^; do ar -x ../$$i; done && $(call ar_rcs,../$@,*.$(OBJEXT))
-
-endif # PIC_LIB := Y
-
-endif # LIB_TARGET
-
-###
-#
-# BIN_TARGET
-#
-ifeq ($(BIN_EXE), Y)
-ifneq ($(NDB_OS), WIN32)
-BIN_LIBS := $(BIN_TARGET_ARCHIVES:%=$(LIB_DIR)/$(LIBPREFIX)%.$(LIBEXT))
-BIN_LIBS += $(BIN_TARGET_LIBS:%=-l%)
-
-BIN_DEPS := $(OBJECTS) $(EXTRA_MAIN) $(BIN_LIBS)
-BIN_LIB_DIRS := $(BIN_TARGET_LIBS_DIRS:%=-L%)
-
-BIN_FLAGS := $(BIN_LIB_DIRS) $(BIN_DEPS)
-
-VPATH := $(LIB_DIR) $(BIN_TARGET_LIBS_DIRS)
-_bins:: $(BIN_DIR)/$(BIN_TARGET)
-$(BIN_DIR)/$(BIN_TARGET) : $(BIN_DEPS)
- $(LINK.cc) $(LDFLAGS) $(LDLIBS) -L$(LIB_DIR) $(BIN_FLAGS) -o $@.new $(LDFLAGS_LAST)
- rm -f $@; mv $@.new $@
-ifeq ($(NDB_VERSION), RELEASE)
-ifneq ($(NDB_OS), MACOSX)
- strip $@
-endif
-endif
- $(NDB_TOP)/home/bin/ndb_deploy $@
-else # WIN32
-BIN_LIBS := $(foreach lib,$(BIN_TARGET_ARCHIVES),$(call fixpath,$(LIB_DIR)/$(LIBPREFIX)$(lib).$(LIBEXT)))
-BIN_LIBS += $(BIN_TARGET_LIBS:%=$(LIBPREFIX)%.$(LIBEXT))
-
-BIN_DEPS := $(OBJECTS) $(BIN_TARGET_ARCHIVES:%=$(LIB_DIR)/$(LIBPREFIX)%.$(LIBEXT))
-BIN_LIB_DIRS := -libpath:$(call fixpath,$(LIB_DIR)) $(BIN_TARGET_LIBS_DIRS:%=-libpath:%)
-
-BIN_FLAGS := $(BIN_LIB_DIRS)
-
-VPATH := $(LIB_DIR) $(BIN_TARGET_LIBS_DIRS)
-_bins:: $(BIN_DIR)/$(BIN_TARGET).exe
-$(BIN_DIR)/$(BIN_TARGET).exe : $(BIN_DEPS)
- $(LINK.cc) -out:$(call fixpath,$@.new) $(OBJECTS) $(BIN_FLAGS) $(BIN_LIBS)
- rm -f $@; mv $@.new $@
-ifeq ($(NDB_VERSION), RELEASE)
- strip $@
-endif
-
-endif
-endif
-
-###
-#
-# SOURCES.sh
-#
-ifdef SOURCES.sh
-
-BIN_SRC := $(SOURCES.sh:%=$(BIN_DIR)/%)
-
-_bins:: $(BIN_SRC)
-
-$(BIN_SRC) : $(SOURCES.sh)
- rm -f $(^:%=$(BIN_DIR)/%)
- cp $^ $(BIN_DIR)
-endif
-
-#
-# Compile rules PIC objects
-#
-ifeq ($(NDB_OS), WIN32)
-OUT := -Fo
-else
-OUT := -o
-endif
-
-$(PIC_DIR)/%.$(OBJEXT): %.C
- $(C++) $(OUT)$@ -c $(CCFLAGS) $(CFLAGS_$<) $(PIC) $<
-
-$(PIC_DIR)/%.$(OBJEXT): %.cpp
- $(C++) $(OUT)$@ -c $(CCFLAGS) $(CFLAGS_$<) $(PIC) $<
-
-$(PIC_DIR)/%.$(OBJEXT): %.cc
- $(C++) $(OUT)$@ -c $(CCFLAGS) $(CFLAGS_$<) $(PIC) $<
-
-$(PIC_DIR)/%.$(OBJEXT): %.c
- $(CC) $(OUT)$@ -c $(CFLAGS) $(CFLAGS_$<) $(PIC) $<
-
-#
-# Compile rules
-#
-%.$(OBJEXT) : %.cpp
- $(C++) $(OUT)$@ -c $(CCFLAGS) $(CFLAGS_$<) $(NON_PIC) $<
-
-%.$(OBJEXT) : %.C
- $(C++) $(OUT)$@ -c $(CCFLAGS) $(CFLAGS_$<) $(NON_PIC) $<
-
-%.$(OBJEXT) : %.cc
- $(C++) $(OUT)$@ -c $(CCFLAGS) $(CFLAGS_$<) $(NON_PIC) $<
-
-%.$(OBJEXT) : %.c
- $(CC) $(OUT)$@ -c $(CFLAGS) $(CFLAGS_$<) $(NON_PIC) $<
-
-%.s : %.C
- $(C++) -S $(CCFLAGS) $(CFLAGS_$<) $(NON_PIC) $<
-
-%.s : %.cpp
- $(C++) -S $(CCFLAGS) $(CFLAGS_$<) $(NON_PIC) $<
-
-%.s : %.cc
- $(C++) -S $(CCFLAGS) $(CFLAGS_$<) $(NON_PIC) $<
-
-%.s : %.c
- $(CC) -S $(CCFLAGS) $(CFLAGS_$<) $(NON_PIC) $<
-
-BISON = bison
-BISONHACK = :
-%.tab.cpp %.tab.hpp : %.ypp
- $(BISON) $<
- $(BISONHACK) $*.tab.cpp $*.tab.hpp
-
-FLEX = flex
-FLEXHACK = :
-%.yy.cpp : %.lpp
- $(FLEX) -o$@ $<
- $(FLEXHACK) $@
-
-###
-#
-# Defines regarding dependencies
-
-DEPMK := $(NDB_BUILDDIR).depend.mk
-
-DEPDIR := $(NDB_BUILDDIR).depend
-
-DEPENDENCIES := $(SRC_C:%.C=$(DEPDIR)/%.d) \
- $(SRC_CC:%.cc=$(DEPDIR)/%.d) \
- $(SRC_CPP:%.cpp=$(DEPDIR)/%.d) \
- $(SRC_c:%.c=$(DEPDIR)/%.d) \
- $(SRC_YPP:%.ypp=$(DEPDIR)/%.tab.d) \
- $(SRC_LPP:%.lpp=$(DEPDIR)/%.yy.d)
-
-###
-#
-# Dependency rule
-
-_depend: $(DEPMK)
-
-depend: _depend $(patsubst %, _depend_%, $(A_DIRS))
-
-$(patsubst %, _depend_%, $(A_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _depend_%,%,$@) depend
-
-###
-#
-# Clean dependencies
-
-_clean_dep:
- -rm -rf $(DEPMK) $(DEPDIR)/*
-
-clean_dep: _clean_dep $(patsubst %, _clean_dep_%, $(A_DIRS))
-
-$(patsubst %, _clean_dep_%, $(A_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _clean_dep_%,%,$@) clean_dep
-
-###
-#
-# Generate dependencies
-
-$(DEPDIR):
- -@mkdir -p $(DEPDIR)
-
-$(DEPDIR)/%.d: %.C
- @echo Generating depend for $<
- @$(MAKEDEPEND) $(CCFLAGS) $(CFLAGS_$<) $< >$@
-
-$(DEPDIR)/%.d: %.c
- @echo Generating depend for $<
- @$(MAKEDEPEND) $(CCFLAGS) $(CFLAGS_$<) $< >$@
-
-$(DEPDIR)/%.d: %.cpp
- @echo Generating depend for $<
- @$(MAKEDEPEND) $(CCFLAGS) $(CFLAGS_$<) $< >$@
-
-$(DEPDIR)/%.d: %.cc
- @echo Generating depend for $<
- @$(MAKEDEPEND) $(CCFLAGS) $(CFLAGS_$<) $< >$@
-
-ifeq ($(NDB_OS), WIN32)
-ifndef PIC_DEP
-DEP_PTN := -e 's/\(.*\)\.o[ :]*/\1.$(OBJEXT) $(DEPDIR)\/\1.d : /g'
-else
-DEP_PTN := -e 's/\(.*\)\.o[ :]*/\1.$(OBJEXT) $(PIC_DIR)\/\1.$(OBJEXT) $(DEPDIR)\/\1.d : /g'
-endif
-else
-ifndef PIC_DEP
-DEP_PTN := -e 's!\(.*\)\.$(OBJEXT)[ :]*!\1.$(OBJEXT) $(DEPDIR)\/\1.d : !g'
-else
-DEP_PTN := -e 's!\(.*\)\.$(OBJEXT)[ :]*!\1.$(OBJEXT) $(PIC_DIR)\/\1.$(OBJEXT) $(DEPDIR)\/\1.d : !g'
-endif
-endif
-#DEP_PTN += -e 's!/usr/include/[-+a-zA-Z0-9_/.]*!!g'
-#DEP_PTN += -e 's!/usr/local/lib/gcc-lib/[-+a-zA-Z0-9_/.]*!!g'
-
-$(DEPMK): $(DEPDIR) $(SRC_YPP:%.ypp=%.tab.hpp) $(SRC_LPP:%.lpp=%.yy.cpp) $(DEPENDENCIES) $(wildcard $(NDB_TOP)/.update.d)
- @echo "updating .depend.mk"
- @sed $(DEP_PTN) /dev/null $(DEPENDENCIES) >$(DEPMK)
-
-###
-#
-# clean
-#
-_clean:
- -rm -rf SunWS_cache $(PIC_DIR)/SunWS_cache
-ifeq ($(NONPIC_ARCHIVE), Y)
- -rm -f $(OBJECTS) $(LIB_DIR)/$(LIBPREFIX)$(ARCHIVE_TARGET).$(LIBEXT)
-endif
-ifeq ($(PIC_ARCHIVE), Y)
- -rm -f $(PIC_OBJS) $(LIB_DIR)/$(LIBPREFIX)$(ARCHIVE_TARGET)_pic.$(LIBEXT)
-endif
-ifdef BIN_TARGET
- -rm -f $(OBJECTS)
-endif
-ifdef LIB_TARGET
-ifeq ($(A_LIB), Y)
- -rm -f $(A_TMP_DIR)/*
-endif
-ifeq ($(SO_LIB), Y)
- -rm -f $(SO_TMP_DIR)/*
-endif
-ifeq ($(PIC_LIB), Y)
- -rm -f $(PIC_TMP_DIR)/*
-endif
-endif
-ifneq ($(SRC_YPP),)
- -rm -f $(SRC_YPP:%.ypp=%.tab.[hc]pp) $(SRC_YPP:%.ypp=%.output)
-endif
-ifneq ($(SRC_LPP),)
- -rm -f $(SRC_LPP:%.lpp=%.yy.*)
-endif
-ifdef CLEAN_LOC
- -rm -f $(CLEAN_LOC)
-endif
-
-###
-#
-# clean all
-#
-clobber: cleanall
-_cleanall: _clean clean_links
- -rm -f osemain.con osemain.c
-ifdef LIB_TARGET
-ifeq ($(A_LIB), Y)
- -rm -f $(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET).$(LIBEXT)
-endif
-ifeq ($(SO_LIB), Y)
- -rm -f $(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET).$(SHLIBEXT)
-endif
-ifeq ($(PIC_LIB), Y)
- -rm -f $(LIB_DIR)/$(LIBPREFIX)$(LIB_TARGET)_pic.$(LIBEXT)
-endif
-endif
-ifdef BIN_TARGET
- -rm -f $(BIN_DIR)/$(BIN_TARGET)
-endif
-
-clean_links:
-
-###
-#
-# Dist clean
-#
-_distclean: _tidy
- rm -rf $(DEPDIR) $(PIC_DIR) $(PIC_TMP_DIR) $(SO_TMP_DIR) $(A_TMP_DIR) Sources build.spec
-
-###
-#
-# tidy
-#
-_tidy: _cleanall _clean_dep
- -rm -f *~ *.$(OBJEXT) *.$(LIBEXT) *.${SHLIBEXT}
-
-#
-# clean cleanall tidy - recursion
-#
-ifeq ($(findstring clean,$(replace-targets)),)
-clean: _clean $(patsubst %, _clean_%, $(A_DIRS))
-endif
-
-$(patsubst %, _clean_%, $(A_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _clean_%,%,$@) clean
-
-cleanall: _cleanall $(patsubst %, _cleanall_%, $(A_DIRS))
-
-$(patsubst %, _cleanall_%, $(A_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _cleanall_%,%,$@) cleanall
-
-tidy: _tidy $(patsubst %, _tidy_%, $(A_DIRS))
-
-$(patsubst %, _tidy_%, $(A_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _tidy_%,%,$@) tidy
-
-distclean: _distclean $(patsubst %, _distclean_%, $(A_DIRS))
-
-$(patsubst %, _distclean_%, $(A_DIRS)) : DUMMY
- $(MAKE) -C $(patsubst _distclean_%,%,$@) distclean
-
-###
-#
-# Guess configuration
-
-$(NDB_TOP)/config/config.mk: $(NDB_TOP)/config/GuessConfig.sh
- $(NDB_TOP)/config/GuessConfig.sh -D
-
-$(NDB_TOP)/config/Defs....mk: $(NDB_TOP)/config/config.mk
-$(NDB_TOP)/config/Defs..mk: $(NDB_TOP)/config/config.mk
-
-###
-# Soft ose envirment stuff
-#
-osemain.con: $(NDB_TOP)/src/env/softose/osemain_con.org
- cp $< $@
- echo "PRI_PROC(init_$(BIN_TARGET), init_$(BIN_TARGET), 65535, 3, ndb, 0, NULL)" >> $@
-
-osemain.c: $(OSE_LOC)/sfk-solaris2/krn-solaris2/src/osemain.c
- ln -s $< $@
-
-osemain.o : osemain.con
-
-$(DEPDIR)/osemain.d : osemain.con
-
-###
-#
-# These target dont want dependencies
-
-NO_DEP=clean clobber cleanall tidy clean_dep $(DEPDIR) build_spec \
- $(NDB_TOP)/config/config.mk distclean osemain.con osemain.c
-
-ifeq ($(filter $(NO_DEP), $(MAKECMDGOALS)),)
-ifneq ($(strip $(DEPENDENCIES)),)
- include $(DEPMK)
-endif
-endif
-
-###
-#
-# Auxiliary targets
-
-sources: Sources
-
-Sources: Makefile
- @rm -f $@
- @for f in Makefile $(A_DIRS) $(SOURCES) $(SOURCES.c); do echo $$f; done >$@
-
-###
-#
-# TAG generation for emacs and vi folks
-#
-# In emacs "Esc- ." or "M- ." to find a symbol location
-# In vi use the :\tag command
-# by convention:
-# TAGS is used with emacs
-# tags is used with vi
-#
-# Hopefully the make is being done from $(NDB_TOP)/src
-# and your TAGS/tags file then is in the same directory.
-
-TAGS: DUMMY
- rm -f TAGS
- find $(NDB_TOP) -name "*.[ch]" | xargs $(ETAGS) --append
- find $(NDB_TOP) -name "*.[ch]pp" | xargs $(ETAGS) --append
-
-tags: DUMMY
- rm -f tags
- find $(NDB_TOP) -name "*.[ch]" | xargs $(CTAGS) --append
- find $(NDB_TOP) -name "*.[ch]pp" | xargs $(CTAGS) --append
-
-install:
-
-
-ebrowse: DUMMY
- cd $(NDB_TOP); rm -f EBROWSE
- cd $(NDB_TOP); find . -name "*.hpp" -or -name "*.cpp" -or -name "*.h" -or -name "*.c" > tmpfile~
- cd $(NDB_TOP); ebrowse --file tmpfile~
- cd $(NDB_TOP); rm -f tmpfile~
-
-srcdir = $(NDB_TOP)
-top_distdir = $(NDB_TOP)/..
-mkinstalldirs := /bin/sh ../mkinstalldirs
-distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)/ndb
-
-distdir:
- $(mkinstalldirs) $(distdir)
- @list='$(shell /bin/sh SrcDist.sh)'; for file in $$list; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test "$$dir" != "$$file" && test "$$dir" != "."; then \
- dir="/$$dir"; \
- $(mkinstalldirs) "$(distdir)$$dir"; \
- else \
- dir=''; \
- fi; \
- if test -f $$d/$$file; then \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
- || exit 1; \
- fi; \
- done
diff --git a/ndb/Makefile b/ndb/Makefile
deleted file mode 100644
index 475914f6120..00000000000
--- a/ndb/Makefile
+++ /dev/null
@@ -1,69 +0,0 @@
-include .defs.mk
-
-DIRS := src test tools examples
-
-# hack before full autoconf
-replace-targets := all clean
-NDB_RELEASE := $(shell ../scripts/mysql_config --version)
-
-all:
- $(MAKE) -C src
- $(MAKE) -C test/src
- $(MAKE) -C tools
- $(MAKE) -C test/ndbapi/flexBench
- $(MAKE) -C test/tools/waiter
-
-include $(NDB_TOP)/Epilogue.mk
-
-_libs_test : _bins_src
-_libs_tools : _libs_test
-_libs_examples : _bins_src
-_bins_src : _libs_src
-_bins_tools : _bins_src
-
-# always release compile except for ndbapi static lib
-old-all:
- $(MAKE) -C src/ndbapi libs
- $(MAKE) libs NDB_VERSION=RELEASE
- $(MAKE) bins NDB_VERSION=RELEASE
-ifeq ($(NDB_OS),LINUX)
- NDB_RELEASE=$(NDB_RELEASE) $(MAKE) -j1 -C docs all </dev/null || :
-endif
-
-# old distclean matches clean better
-clean: distclean
- $(MAKE) -C docs clean
-
-nuke-deps:
- find . -name '.depend*' | xargs rm -rf
-
-vim-tags:
- bk sfiles -g | ctags --c-types=+p --extra=+fq -L -
-
-cvs-update:
-ifeq ($(NDB_VERSION),main)
- -cvs update -d
-else
-ifeq ($(NDB_TAG),HEAD)
- -cvs -q update
- -cd include && cvs -q update -d
- -cd src && cvs -q update -d
- -cd test && cvs -q update -d
- -cd tools && cvs -q update -d
-else
- -cvs -q update -r $(NDB_TAG)
- -cd include && cvs -q update -d -r $(NDB_TAG)
- -cd src && cvs -q update -d -r $(NDB_TAG)
- -cd test && cvs -q update -d -r $(NDB_TAG)
- -cd tools && cvs -q update -d -r $(NDB_TAG)
-endif
-endif
- make nuke-deps
- make vim-tags
- make TAGS
-
-bk-update:
- bk pull
- make nuke-deps
- make vim-tags
- make TAGS
diff --git a/ndb/Makefile.am b/ndb/Makefile.am
new file mode 100644
index 00000000000..82f424fcfb4
--- /dev/null
+++ b/ndb/Makefile.am
@@ -0,0 +1,19 @@
+SUBDIRS = src tools . include @ndb_opt_subdirs@
+DIST_SUBDIRS = src tools include test docs
+EXTRA_DIST = config
+
+include $(top_srcdir)/ndb/config/common.mk.am
+
+dist-hook:
+ -rm -rf `find $(distdir) -type d -name SCCS`
+ -rm -rf `find $(distdir) -type d -name old_files`
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" != "." -a "$$subdir" != "include"; then \
+ files="`find $$subdir -name '*\.h'` `find $$subdir -name '*\.hpp'`"; \
+ for f in $$files; do \
+ if test -d "$(distdir)/`dirname $$f`" -a ! -e "$(distdir)/$$f"; then \
+ cp $$f $(distdir)/$$f; \
+ fi; \
+ done; \
+ fi; \
+ done
diff --git a/ndb/README b/ndb/README
deleted file mode 100644
index 3b21fca1d48..00000000000
--- a/ndb/README
+++ /dev/null
@@ -1,7 +0,0 @@
-INSTALLATION
-To compile a pentium version of MySQL Cluster from this BK clone do:
-
-shell> cd /home/bk/mysql-4.1-ndb
-shell> BUILD/compile-pentium-debug -c --prefix=/usr/local/mysql-4.1-ndb
-shell> make
-
diff --git a/ndb/SrcDist.sh b/ndb/SrcDist.sh
deleted file mode 100644
index 03e697b1475..00000000000
--- a/ndb/SrcDist.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# Invoked from make distdir.
-# Prints list of dirs and files to include under mysql/ndb.
-#
-
-# top dir
-
-grep -v '^#' <<__END__
-#ReleaseNotes.html
-.defs.mk
-Defs.mk
-configure
-Makefile
-Epilogue.mk
-SrcDist.sh
-BinDist.sh
-mysqlclusterenv.sh
-__END__
-
-# subset of bins, libs
-
-grep -v '^#' <<__END__
-bin/
-bin/mysqlcluster
-bin/mysqlcluster_install_db
-bin/mysqlclusterd
-lib/
-__END__
-
-# docs
-
-#find docs/*.html docs/*.pdf -print
-
-# include
-
-find include -print | grep -v /SCCS
-
-# config
-
-find config -print | grep -v /SCCS
-
-# tools
-
-find tools -print | grep -v /SCCS | grep -v '\.o' | grep -v '\.depend' | grep -v tools/ndbsql
-
-# home
-
-find home -print | grep -v /SCCS
-
-# test
-
-find test -print | grep -v /SCCS | grep -v '\.o' | grep -v '\.depend' | grep -v test/odbc
-
-# src
-
-find src -print | grep -v /SCCS | grep -v '\.o' | grep -v '\.depend' | grep -v src/client/odbc | grep -v cpcc-win32
-
-# demos
-
-find demos -print | grep -v /SCCS | grep -v '\.o' | grep -v '\.depend'
-
-# examples
-
-grep -v '^#' <<__END__
-examples/
-examples/Makefile
-examples/ndbapi_example1/
-examples/ndbapi_example1/Makefile
-examples/ndbapi_example1/ndbapi_example1.cpp
-examples/ndbapi_example2/
-examples/ndbapi_example2/Makefile
-examples/ndbapi_example2/ndbapi_example2.cpp
-examples/ndbapi_example3/
-examples/ndbapi_example3/Makefile
-examples/ndbapi_example3/ndbapi_example3.cpp
-examples/ndbapi_example4/
-examples/ndbapi_example4/Makefile
-examples/ndbapi_example4/ndbapi_example4.cpp
-examples/ndbapi_example5/
-examples/ndbapi_example5/Makefile
-examples/ndbapi_example5/ndbapi_example5.cpp
-examples/select_all/
-examples/select_all/Makefile
-examples/select_all/select_all.cpp
-__END__
-
-exit 0
diff --git a/ndb/bin/mysqlcluster b/ndb/bin/mysqlcluster
deleted file mode 100755
index 81fc7308942..00000000000
--- a/ndb/bin/mysqlcluster
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-if [ -z "$MYSQLCLUSTER_TOP" -o ! -d "$MYSQLCLUSTER_TOP" ]; then
- echo "MYSQLCLUSTER_TOP not set or directory does not exist"
- exit 1
-fi
-if [ -z "$MYSQLCLUSTER_TOP" -o ! -d "$MYSQLCLUSTER_TOP/ndb" ]; then
- echo "$MYSQLCLUSTER_TOP/ndb directory does not exist"
- exit 1
-fi
-
-mysql --socket=$MYSQLCLUSTER_TOP/data/mysqlcluster.sock $*
diff --git a/ndb/bin/mysqlcluster_install_db b/ndb/bin/mysqlcluster_install_db
deleted file mode 100755
index 6fe95ff105d..00000000000
--- a/ndb/bin/mysqlcluster_install_db
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/bin/sh
-
-NDB_HOME=
-export NDB_CONNECTSTRING
-if [ -z "$MYSQLCLUSTER_TOP" ]; then
- echo "MYSQLCLUSTER_TOP not set"
- exit 1
-fi
-if [ -d "$MYSQLCLUSTER_TOP" ]; then :; else
- echo "$MYSQLCLUSTER_TOP directory does not exist"
- exit 1
-fi
-if [ -d "$MYSQLCLUSTER_TOP/ndb" ]; then :; else
- echo "$MYSQLCLUSTER_TOP/ndb directory does not exist"
- exit 1
-fi
-
-start_default_ndbcluster() {
-
-# configurable parameters, make sure to change in mysqlcluterd as well
-MYSQLCLUSTER_FILESYSTEM=$MYSQLCLUSTER_TOP/data/mysqlclusterfs
-MYSQLCLUSTER_PORT_BASE="22" # using ports MYSQLCLUSTER_PORT_BASE{"00","01", etc}
-# end configurable parameters
-
-# do some checks
-
-NDB_CONNECTSTRING=
-
-[ -d "$MYSQLCLUSTER_FILESYSTEM" ] || mkdir "$MYSQLCLUSTER_FILESYSTEM"
-if [ -d "$MYSQLCLUSTER_FILESYSTEM" ]; then :; else
- echo "$MYSQLCLUSTER_FILESYSTEM filesystem directory does not exist"
- exit 1
-fi
-
-
-# set som help variables
-
-NDB_HOST="localhost"
-NDB_PORT=$MYSQLCLUSTER_PORT_BASE"00"
-NDB_CONNECTSTRING_BASE="host=$NDB_HOST:$NDB_PORT;nodeid="
-
-
-# Edit file system path and ports in config file
-
-cd $MYSQLCLUSTER_FILESYSTEM
-sed \
- -e s,"WRITE_PATH_TO_FILESYSTEM_2_HERE",$MYSQLCLUSTER_FILESYSTEM,g \
- -e s,"CHOOSE_PORT_BASE",$MYSQLCLUSTER_PORT_BASE,g \
- < $MYSQLCLUSTER_TOP/ndb/demos/config-templates/config_template-install.ini \
- > config.ini
-
-
-# Start management server as deamon
-
-NDB_ID="1"
-NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
-#xterm -e mgmtsrvr -c $MYSQLCLUSTER_FILESYSTEM/config.ini &
-if mgmtsrvr -d -c $MYSQLCLUSTER_FILESYSTEM/config.ini ; then :; else
- echo "Unable to start mgmtsrvr"
- exit 1
-fi
-
-
-# Start database node
-
-cd $MYSQLCLUSTER_FILESYSTEM # the output from the database node gets where it starts
-NDB_ID="2"
-NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
-#xterm -T "NDB Cluster DB Node" -geometry 80x10 -xrm *.hold:true -e ndb -i &
-ndb -d -i &
-
-# Start xterm for application programs
-
-NDB_ID="3"
-NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
-#xterm -T "NDB Cluster API Node" -geometry 80x10 &
-echo set before running ndbApi programs > export NDB_CONNECTSTRING=$NDB_CONNECTSTRING
-
-# Start management client
-
-#xterm -T "NDB Management Client" -geometry 80x10 -xrm *.hold:true -e mgmtclient $NDB_HOST $NDB_PORT &
-echo "NDB Management Client starts with: mgmtclient $NDB_HOST $NDB_PORT"
-
-# test if Ndb Cluster starts properly
-
-NDB_ID="11"
-NDB_CONNECTSTRING=$NDB_CONNECTSTRING_BASE$NDB_ID
-if list_tables | grep "NDBT_ProgramExit: 0 - OK"; then :; else
- echo "Ndbcluster startup failed"
- exit 1
-fi
-}
-
-start_mysql_install_db() {
- # run install of regular MySQL Server
-
- cd $MYSQLCLUSTER_TOP
- scripts/mysql_install_db --basedir=$MYSQLCLUSTER_TOP --datadir=$MYSQLCLUSTER_TOP/data --socket=$MYSQLCLUSTER_TOP/data/mysqlcluster.sock $*
-}
-
-if test "$1" = "ndb_started"
-then
- shift
- mgmt_host=$1
- shift
- mgmt_port=$1
- shift
- if [ -z "$mgmt_host" -o -z "$mgmt_port" ]; then
- echo "syntax: ndb_started hostname port"
- exit 1
- fi
- NDB_CONNECTSTRING="host=$mgmt_host:$mgmt_port;nodeid=11"
- echo using NDB_CONNECTSTRING=$NDB_CONNECTSTRING
- start_mysql_install_db $*
-else
- start_default_ndbcluster
- start_mysql_install_db
-fi
-
diff --git a/ndb/bin/mysqlclusterd b/ndb/bin/mysqlclusterd
deleted file mode 100755
index 3b4deb3ed48..00000000000
--- a/ndb/bin/mysqlclusterd
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh
-
-# configurable parameters
-MYSQLCLUSTER_PORT_BASE="22"
-# end configurable parameters
-
-if [ -z "$MYSQLCLUSTER_TOP" -o ! -d "$MYSQLCLUSTER_TOP" ]; then
- echo "MYSQLCLUSTER_TOP not set or directory does not exist"
- exit 1
-fi
-if [ -z "$MYSQLCLUSTER_TOP" -o ! -d "$MYSQLCLUSTER_TOP/ndb" ]; then
- echo "$MYSQLCLUSTER_TOP/ndb directory does not exist"
- exit 1
-fi
-
-if test "$1" = "ndb_started"
-then
- shift
- mgmt_host=$1
- shift
- mgmt_port=$1
- shift
- if [ -z "$mgmt_host" -o -z "$mgmt_port" ]; then
- echo "syntax: ndb_started hostname port"
- exit 1
- fi
- NDB_CONNECTSTRING="host=$mgmt_host:$mgmt_port;nodeid=11"
- echo using NDB_CONNECTSTRING=$NDB_CONNECTSTRING
-else
- NDB_CONNECTSTRING="host=localhost:"$MYSQLCLUSTER_PORT_BASE"00;nodeid=11"
-fi
-export NDB_CONNECTSTRING
-
-mysqld --default-table-type=ndbcluster --basedir=$MYSQLCLUSTER_TOP --datadir=$MYSQLCLUSTER_TOP/data --socket=$MYSQLCLUSTER_TOP/data/mysqlcluster.sock $*
diff --git a/ndb/bin/regression.sh b/ndb/bin/regression.sh
deleted file mode 100644
index 5d0531c7460..00000000000
--- a/ndb/bin/regression.sh
+++ /dev/null
@@ -1,644 +0,0 @@
-#!/bin/sh
-# NAME
-# regression.sh
-#
-# SYNOPSIS
-# regression.sh
-#
-# DESCRIPTION
-#
-# This script runs a number of regression tests to verify that nothing
-# is broken. Currently it executes the same tests as in the autotest
-# regression suite.
-#
-# OPTIONS
-#
-# EXAMPLES
-#
-#
-# ENVIRONMENT
-# verbose verbose printouts
-#
-# FILES
-#
-#
-# SEE ALSO
-#
-# DIAGNOSTICTS
-#
-#
-# VERSION
-# 1.0
-#
-# AUTHOR
-#
-#
-
-
-# die prints the supplied message to stderr,
-# prefixed with the program name, and exits
-# with the exit code given by "-e num" or
-# 1, if no -e option is present.
-#
-die ()
-{
- die_code__=1
- [ "X$1" = X-e ] && { die_code__=$2; shift 2; }
- [ "X$1" = X-- ] && shift
- errmsg "$@"
- exit $die_code__
-}
-
-
-# msg prints the supplied message to stderr,
-# prefixed with the program name.
-#
-errmsg ()
-{
- echo "${progname:-<no program name set>}:" "$@" >&2
-}
-
-# rawdie prints the supplied message to stderr.
-# It then exits with the exit code given with "-e num"
-# or 1, if no -e option is present.
-#
-rawdie ()
-{
- rawdie_code__=1
- [ "X$1" = X-e ] && { rawdie_code__=$2; shift 2; }
- [ "X$1" = X-- ] && shift
- rawerrmsg "$@"
- exit $rawdie_code__
-}
-
-# Syndie prints the supplied message (if present) to stderr,
-# prefixed with the program name, on the first line.
-# On the second line, it prints $synopsis.
-# It then exits with the exit code given with "-e num"
-# or 1, if no -e option is present.
-#
-syndie ()
-{
- syndie_code__=1
- [ "X$1" = X-e ] && { syndie_code__=$2; shift 2; }
- [ "X$1" = X-- ] && shift
- [ -n "$*" ] && msg "$*"
- rawdie -e $syndie_code__ "Synopsis: $synopsis"
-}
-
-
-
-
-# msg prints the supplied message to stdout,
-# prefixed with the program name.
-#
-msg ()
-{
- echo "${progname:-<no program name set>}:" "$@"
-}
-
-rawmsg () { echo "$*"; } # print the supplied message to stdout
-rawerrmsg () { echo "$*" >&2; } # print the supplied message to stderr
-
-# trace prints the supplied message to stdout if verbose is non-null
-#
-trace ()
-{
- [ -n "$verbose" ] && msg "$@"
-}
-
-
-# errtrace prints the supplied message to stderr if verbose is non-null
-#
-errtrace ()
-{
- [ -n "$verbose" ] && msg "$@" >&2
-}
-
-
-synopsis="regression.sh"
-progname=`basename $0`
-
-numOfTestsOK=0
-numOfTestsFailed=0
-
-LOG=regression-$1.`date '+%Y-%m-%d'`
-
-executeTest()
-{
- eval "$@" | tee -a $LOG
-
- if [ $? -eq 0 ]
- then
- echo "SUCCESS: $@"
- numOfTestsOK=`expr $numOfTestsOK + 1`
- else
- echo "FAILED: $@"
- numOfTestsFailed=`expr $numOfTestsFailed + 1`
- fi
-}
-
-#
-# INFO
-#
-trace "Starting: `date`"
-trace "NDB_TOP = $NDB_TOP"
-
-#
-# THE TESTS TO EXECUTE
-#
-
-# BASIC FUNCTIONALITY
-if [ $1 = "basic" ]
-then
-executeTest 'testBasic -n PkRead'
-executeTest 'drop_all_tabs'
-
-executeTest 'testBasic -n PkUpdate'
-executeTest 'drop_all_tabs'
-
-executeTest 'testBasic -n PkDelete'
-executeTest 'drop_all_tabs'
-
-executeTest 'testBasic -n PkInsert'
-executeTest 'drop_all_tabs'
-
-executeTest 'testBasic -n UpdateAndRead'
-executeTest 'drop_all_tabs'
-
-executeTest 'testBasic -n PkReadAndLocker' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n PkReadAndLocker2' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n PkReadUpdateAndLocker' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n ReadWithLocksAndInserts' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n PkInsertTwice' T1 T6 T10
-executeTest 'drop_tab' T1 T6 T10
-
-executeTest 'testBasic -n PkDirtyRead'
-executeTest 'drop_all_tabs'
-
-executeTest 'testBasic -n Fill' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n Fill' T1
-executeTest 'drop_tab' T1
-
-executeTest 'testBasic -n NoCommitSleep' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n NoCommit626' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n NoCommitAndClose' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n Commit626' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n CommitTry626' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n CommitAsMuch626' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n NoCommit626' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n NoCommitRollback626' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n Commit630' T1 T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n CommitTry630' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n CommitAsMuch630' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n NoCommit630' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n NoCommitRollback630' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n NoCommitAndClose' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n RollbackUpdate' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n RollbackDeleteMultiple' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n ImplicitRollbackDelete' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n CommitDelete' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n RollbackNothing' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testBasic -n ReadConsistency' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testBasic -n PkRead' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_4092
-executeTest 'drop_tab' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_4092
-
-executeTest 'testBasic -n PkUpdate' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_4092
-executeTest 'drop_tab' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_4092
-
-executeTest 'testBasic -n PkDelete' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_4092
-executeTest 'drop_tab' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_4092
-
-executeTest 'testBasic -n PkInsert' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_409
-executeTest 'drop_tab' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_4092
-
-executeTest 'testBasic -n UpdateAndRead' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_4092
-#executeTest 'drop_tab' TPK_33 TPK_34 TPK_1003 TPK_2003 TPK_4092
-
-executeTest 'testBasicAsynch -n PkInsertAsynch'
-executeTest 'drop_all_tabs'
-
-executeTest 'testBasicAsynch -n PkReadAsynch'
-executeTest 'drop_all_tabs'
-
-executeTest 'testBasicAsynch -n PkUpdateAsynch'
-executeTest 'drop_all_tabs'
-
-executeTest 'testBasicAsynch -n PkDeleteAsynch'
-executeTest 'drop_all_tabs'
-fi
-
-# SCAN TESTS
-if [ $1 = "scan" ]
-then
-executeTest 'testScan -n ScanRead16'
-executeTest 'drop_all_tabs'
-
-executeTest 'testScan -n ScanRead240'
-executeTest 'drop_all_tabs'
-
-executeTest 'testScan -n ScanUpdate'
-executeTest 'drop_all_tabs'
-
-executeTest 'testScan -n ScanUpdate2' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanDelete'
-executeTest 'drop_all_tabs'
-
-executeTest 'testScan -n ScanDelete2' T10
-executeTest 'drop_tab' T10
-
-executeTest 'testScan -n ScanUpdateAndScanRead' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanReadAndLocker' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanReadAndPkRead' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanRead488' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanWithLocksAndInserts' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanReadAbort' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanReadAbort15' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanReadAbort240' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanUpdateAbort16' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanReadRestart' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ScanUpdateRestart' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n CheckGetValue' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n CloseWithoutStop' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n NextScanWhenNoMore' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n ExecuteScanWithoutOpenScan' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n OnlyOpenScanOnce' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n OnlyOneOpInScanTrans' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n OnlyOneOpBeforeOpenScan' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n OnlyOneScanPerTrans' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n NoCloseTransaction' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n CheckInactivityTimeOut' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n CheckInactivityBeforeClose' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testScan -n CheckAfterTerror' T6
-executeTest 'drop_tab' T6
-fi
-
-
-# DICT TESTS
-if [ $1 = "dict" ]
-then
-executeTest 'testDict -n CreateAndDrop'
-executeTest 'drop_all_tabs'
-
-executeTest 'testDict -n CreateAndDropWithData'
-executeTest 'drop_all_tabs'
-
-executeTest 'testDict -n CreateAndDropDuring' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testDict -n CreateInvalidTables'
-executeTest 'drop_all_tabs'
-
-executeTest 'testDict -n CreateTableWhenDbIsFull' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testDict -n CreateMaxTables' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testDict -n FragmentTypeAll' T1 T6 T7 T8
-executeTest 'drop_tab' T1 T6 T7 T8
-
-executeTest 'testDict -n FragmentTypeAllLarge' T1 T6 T7 T8
-executeTest 'drop_tab' T1 T6 T7 T8
-
-executeTest 'testDict -n TemporaryTables' T1 T6 T7 T8
-executeTest 'drop_tab' T1 T6 T7 T8
-fi
-
-# TEST NDBAPI
-if [ $1 = "api" ]
-then
-executeTest 'testNdbApi -n MaxNdb' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testNdbApi -n MaxTransactions' T1 T6 T7 T8 T13
-executeTest 'drop_tab' T1 T6 T7 T8 T13
-
-executeTest 'testNdbApi -n MaxOperations' T1 T6 T7 T8 T1
-executeTest 'drop_tab' T1 T6 T7 T8 T13
-
-executeTest 'testNdbApi -n MaxGetValue' T1 T6 T7 T8 T13
-executeTest 'drop_tab' T1 T6 T7 T8 T13
-
-executeTest 'testNdbApi -n MaxEqual'
-executeTest 'drop_all_tabs'
-
-executeTest 'testNdbApi -n DeleteNdb' T1 T6
-executeTest 'drop_tab' T1 T6
-
-executeTest 'testNdbApi -n WaitUntilReady' T1 T6 T7 T8 T13
-executeTest 'drop_tab' T1 T6 T7 T8 T13
-
-executeTest 'testNdbApi -n GetOperationNoTab' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testNdbApi -n NdbErrorOperation' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testNdbApi -n MissingOperation' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testNdbApi -n GetValueInUpdate' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testNdbApi -n UpdateWithoutKeys' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testNdbApi -n UpdateWithoutValues' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadRead' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadReadEx' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadInsert' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadUpdate' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadDelete' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadExRead' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadExReadEx' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadExInsert' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadExUpdate' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n ReadExDelete' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n InsertRead' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n InsertReadEx' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n InsertInsert' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n InsertUpdate' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n InsertDelete' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n UpdateRead' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n UpdateReadEx' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n UpdateInsert' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n UpdateUpdate' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n UpdateDelete' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n DeleteRead' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n DeleteReadEx' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n DeleteInsert' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n DeleteUpdate' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testOperations -n DeleteDelete' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testRestartGci' T6
-executeTest 'drop_tab' T6
-
-executeTest 'testIndex -n CreateAll'
-executeTest 'drop_all_tabs'
-
-executeTest 'testIndex -n InsertDeleteGentle' T1 T6 T8 T10
-executeTest 'drop_tab' T1 T6 T8 T10
-
-executeTest 'testIndex -n InsertDelete' T1 T6 T8 T10
-executeTest 'drop_tab' T1 T6 T8 T10
-
-executeTest 'testIndex -n CreateLoadDropGentle' T1 T6 T8 T10
-executeTest 'drop_tab' T1 T6 T8 T10
-
-executeTest 'testIndex -n CreateLoadDrop' T1 T6 T8 T10
-executeTest 'drop_tab' T1 T6 T8 T10
-
-executeTest 'testBackup' -n BackupOne
-
-executeTest 'testBackup' -n BackupBank T6
-executeTest 'drop_tab' T6
-fi
-
-# TEST SYSTEM RESTARTS
-if [ $1 = "sr" ]
-then
-executeTest 'testSystemRestart -n SR1' T1
-executeTest 'testSystemRestart -n SR1' T6
-executeTest 'testSystemRestart -n SR1' T7
-executeTest 'testSystemRestart -n SR1' T8
-executeTest 'testSystemRestart -n SR1' T10
-executeTest 'testSystemRestart -n SR2' T1
-executeTest 'testSystemRestart -n SR2' T6
-executeTest 'testSystemRestart -n SR2' T7
-executeTest 'testSystemRestart -n SR2' T10
-executeTest 'testSystemRestart -n SR2' T13
-executeTest 'testSystemRestart -n SR3' T6
-executeTest 'testSystemRestart -n SR3' T10
-executeTest 'testSystemRestart -n SR4' T6
-executeTest 'testSystemRestart -n SR_UNDO' T1
-executeTest 'testSystemRestart -n SR_UNDO' T6
-executeTest 'testSystemRestart -n SR_UNDO' T7
-executeTest 'testSystemRestart -n SR_UNDO' T8
-executeTest 'testSystemRestart -n SR_UNDO' T10
-executeTest 'drop_tab' T1 T6 T7 T8 T10
-fi
-
-# TEST NODE RESTARTS
-if [ $1 = "nr" ]
-then
-executeTest 'testNodeRestart -n NoLoad' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n PkRead' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n PkReadPkUpdate' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n ReadUpdateScan' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n Terror' T6 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n FullDb' T6 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n RestartRandomNode' T6 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n RestartRandomNodeError' T6 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n RestartRandomNodeInitial' T6 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n RestartNFDuringNR' T6 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n RestartNodeDuringLCP' T6 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n RestartMasterNodeError' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n TwoNodeFailure' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n TwoMasterNodeFailure' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n FiftyPercentFail' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n RestartAllNodes' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n RestartAllNodesAbort' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n RestartAllNodesError9999' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-executeTest 'testNodeRestart -n FiftyPercentStopAndWait' T6 T8 T13
-executeTest 'drop_tab' T6 T8 T13
-
-fi
-
-# TESTS FINISHED
-trace "Finished: `date`"
-
-#
-# TEST SUMMARY
-#
-if [ $numOfTestsFailed -eq 0 ]
-then
- echo "-- REGRESSION TEST SUCCESSFUL --"
-else
- echo "-- REGRESSION TEST FAILED!! --"
-fi
-echo "Number of successful tests: $numOfTestsOK"
-echo "Number of failed tests : $numOfTestsFailed"
diff --git a/ndb/config/Defs.DEBUG.mk b/ndb/config/Defs.DEBUG.mk
deleted file mode 100644
index 309ae90a0ba..00000000000
--- a/ndb/config/Defs.DEBUG.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-
-VERSION_FLAGS := -DNDB_DEBUG -DUSE_EMULATED_JAM -DVM_TRACE -DERROR_INSERT -DARRAY_GUARD
-#-DDEBUG_TRANSPORTER
-
diff --git a/ndb/config/Defs.HPUX.HPPA.GCC.mk b/ndb/config/Defs.HPUX.HPPA.GCC.mk
deleted file mode 100644
index 895c7672071..00000000000
--- a/ndb/config/Defs.HPUX.HPPA.GCC.mk
+++ /dev/null
@@ -1,50 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := g++
-CC := gcc
-AR_RCS := ar rcs
-SO := ld -b -o
-
-SHLIBEXT := sl
-
-MAKEDEPEND := g++ -M
-PIC := -fPIC
-
-RPCGENFLAGS := -MA -C -N
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-CCFLAGS_WARNINGS = -Wno-long-long -W -Wall -pedantic
-# -Wno-sign-compare Use this flag if you are annoyed with all the warnings
-CCFLAGS_TOP = -DHPUX -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -DNO_COMMAND_HANDLER
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O3
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O3 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP = -lpthread -lnsl -lrt
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
-
diff --git a/ndb/config/Defs.IBMAIX.POWERPC.GCC.mk b/ndb/config/Defs.IBMAIX.POWERPC.GCC.mk
deleted file mode 100644
index ae975fb2cb8..00000000000
--- a/ndb/config/Defs.IBMAIX.POWERPC.GCC.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := g++
-CC := gcc
-AR_RCS := $(PURE) ar rcs
-SO := g++ -shared -o
-
-MAKEDEPEND := g++ -M
-PIC := -fPIC
-
-RPCGENFLAGS := -M -C -N
-
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-CCFLAGS_WARNINGS = -Wno-long-long -Wall #-pedantic
-# Add these for more warnings -Weffc++ -W
-CCFLAGS_TOP = -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS
-CCFLAGS_TOP += -fno-rtti
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O3
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O3 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP = -lpthread -lrt
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
diff --git a/ndb/config/Defs.LINUX.x86.GCC.mk b/ndb/config/Defs.LINUX.x86.GCC.mk
deleted file mode 100644
index 6167a30ff23..00000000000
--- a/ndb/config/Defs.LINUX.x86.GCC.mk
+++ /dev/null
@@ -1,60 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := gcc$(GCC_VERSION)
-CC := gcc$(GCC_VERSION)
-AR_RCS := $(PURE) ar rcs
-SO := gcc$(GCC_VERSION) -shared -lpthread -o
-#SO := gcc$(GCC_VERSION) -shared -o
-
-MAKEDEPEND := gcc$(GCC_VERSION) -M
-#MAKEDEPEND := gcc$(GCC_VERSION) -M -nostdinc -nostdinc++
-PIC := -fPIC
-
-RPCGENFLAGS := -M -C -N
-
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-# gcc3.3 __THROW problem if -pedantic and -O2
-ifeq ($(NDB_VERSION),DEBUG)
-CCFLAGS_WARNINGS = -Wno-long-long -Wall -pedantic
-else
-CCFLAGS_WARNINGS = -Wno-long-long -Wall
-endif
-# Add these for more warnings -Weffc++ -W
-CCFLAGS_TOP =
-#CCFLAGS_TOP = -DSAFE_MUTEX
-CCFLAGS_TOP += -fno-rtti -fno-exceptions
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O2
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O2 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP =
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(CC) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
-
-LDFLAGS_LAST = -lrt -lpthread $(NDB_TOP)/src/common/portlib/gcc.cpp
-#LDFLAGS_LAST = -lrt $(NDB_TOP)/src/common/portlib/gcc.cpp $(NDB_TOP)/../mysys/libmysys.a $(NDB_TOP)/../dbug/libdbug.a $(NDB_TOP)/../regex/libregex.a $(NDB_TOP)/../strings/libmystrings.a -lpthread
diff --git a/ndb/config/Defs.LINUX.x86.ICC.mk b/ndb/config/Defs.LINUX.x86.ICC.mk
deleted file mode 100644
index 8e8540409da..00000000000
--- a/ndb/config/Defs.LINUX.x86.ICC.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := icc
-CC := icc
-AR_RCS := $(PURE) ar rcs
-SO := g++$(GCC_VERSION) -shared -lpthread -o
-
-MAKEDEPEND := g++$(GCC_VERSION) -M
-PIC := -fPIC
-
-RPCGENFLAGS := -M -C -N
-
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-# gcc3.3 __THROW problem if -pedantic and -O2
-ifeq ($(NDB_VERSION),DEBUG)
-CCFLAGS_WARNINGS =
-else
-CCFLAGS_WARNINGS =
-endif
-# Add these for more warnings -Weffc++ -W
-CCFLAGS_TOP = -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS
-CCFLAGS_TOP +=
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O2
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O2 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP = -lpthread -lrt
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
diff --git a/ndb/config/Defs.LINUX.x86_64.GCC.mk b/ndb/config/Defs.LINUX.x86_64.GCC.mk
deleted file mode 100644
index a238d29ef4c..00000000000
--- a/ndb/config/Defs.LINUX.x86_64.GCC.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := g++
-CC := gcc
-AR_RCS := $(PURE) ar rcs
-SO := g++ -shared -lpthread -o
-
-MAKEDEPEND := g++ -M
-PIC := -fPIC
-
-RPCGENFLAGS := -M -C -N
-
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-# gcc3.3 __THROW problem if -pedantic and -O2
-ifeq ($(NDB_VERSION),DEBUG)
-CCFLAGS_WARNINGS = -Wno-long-long -Wall -pedantic
-else
-CCFLAGS_WARNINGS = -Wno-long-long -Wall
-endif
-# Add these for more warnings -Weffc++ -W
-CCFLAGS_TOP = -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS
-CCFLAGS_TOP += -fno-rtti -fno-exceptions -m64
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O2
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O2 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP = -lpthread -lrt
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
diff --git a/ndb/config/Defs.MACOSX.POWERPC.GCC.mk b/ndb/config/Defs.MACOSX.POWERPC.GCC.mk
deleted file mode 100644
index bb73e9bcc61..00000000000
--- a/ndb/config/Defs.MACOSX.POWERPC.GCC.mk
+++ /dev/null
@@ -1,58 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := gcc
-CC := gcc
-CXX := gcc
-AR_RCS := $(PURE) ar rcs
-#SO := g++ -dynamiclib -Wl,-segprot,__TEXT,rwx,rwx -o
-SO := gcc -dynamiclib -o
-
-SHLIBEXT := dylib
-
-MAKEDEPEND := gcc -M
-PIC := -fPIC
-
-RPCGENFLAGS := -M -C -N
-
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-CCFLAGS_WARNINGS = -Wno-long-long -Wall -Winline #-Werror#-pedantic
-# Add these for more warnings -Weffc++ -W
-CCFLAGS_TOP = -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -D_BIG_ENDIAN
-CXX_FLAGS_TOP = -fno-rtti -felide-constructors -fno-exceptions -fno-omit-fram-pointer
-C_FLAGS_TOP += -fno-omit-frame-pointer
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O3
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O3 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(CXXFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(C_FLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP =
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
-
-#LDFLAGS_LAST = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
-LDFLAGS_LAST = -lstdc++
-
diff --git a/ndb/config/Defs.OSE.PPC750.DIAB.mk b/ndb/config/Defs.OSE.PPC750.DIAB.mk
deleted file mode 100644
index 8773021a152..00000000000
--- a/ndb/config/Defs.OSE.PPC750.DIAB.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := dplus
-CC := dcc
-AR_RCS := $(PURE) ar rcs
-SO := dar -r
-
-MAKEDEPEND := g++ -M -nostdinc
-PIC :=
-
-RPCGENFLAGS := -MA -C -N
-
-###
-#
-# Flags
-#
-CCFLAGS_INCLUDE = -I/vobs/cello/cls/rtosi_if/include -I/vobs/cello/cls/rtosi_if/include.mp750 -I/vobs/cello/cls/rtosi_if/include.ppc
-CCFLAGS_TOP = -tPPC750EH -DBIG_ENDIAN -D_BIG_ENDIAN -DPPC -DPPC750 -DOSE_DELTA -DMP -Xlint -Xforce-prototypes -DINLINE=__inline__ -Xansi -Xsmall-data=0 -Xsmall-const=0 -Xstrings-in-text
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -XO
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -XO -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_INCLUDE)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_INCLUDE)
-
-LDFLAGS_TOP =
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
-
-
-
diff --git a/ndb/config/Defs.RELEASE.mk b/ndb/config/Defs.RELEASE.mk
deleted file mode 100644
index fad72d53a43..00000000000
--- a/ndb/config/Defs.RELEASE.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-
-VERSION_FLAGS := -DNDB_RELEASE -DUSE_EMULATED_JAM -DNDEBUG
-
diff --git a/ndb/config/Defs.RELEASE_TRACE.mk b/ndb/config/Defs.RELEASE_TRACE.mk
deleted file mode 100644
index 06726f282e4..00000000000
--- a/ndb/config/Defs.RELEASE_TRACE.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-
-VERSION_FLAGS := -DNDB_RELEASE -DUSE_EMULATED_JAM -DNDEBUG -DVM_TRACE -DERROR_INSERT -DARRAY_GUARD
-
diff --git a/ndb/config/Defs.SIMCELLO.SOFTOSE.GCC.mk b/ndb/config/Defs.SIMCELLO.SOFTOSE.GCC.mk
deleted file mode 100644
index 8d73e7a752b..00000000000
--- a/ndb/config/Defs.SIMCELLO.SOFTOSE.GCC.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := g++
-CC := gcc
-AR_RCS := $(PURE) ar rcs
-SO := g++ -shared -o
-
-MAKEDEPEND := g++ -M
-PIC := -fPIC
-
-###
-#
-# Flags
-#
-NDB_STRDUP := Y
-CCFLAGS_WARNINGS = -Wall -pedantic -Wno-sign-compare
-CC_FLAGS_OSE = -DSPARC -DSIM -DOSE_DELTA -DMP
-CCFLAGS_TOP = $(CC_FLAGS_OSE) $(CC_FLAGS_WARNINGS) -DNDB_STRDUP
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O3
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O3 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-
-CCFLAGS_LOC_OSE= -I/vobs/cello/cls/rtosi_if/include.sparc
-
-
-CCFLAGS = $(CCFLAGS_LOC_OSE) $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC_OSE) $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDLIBS_LOC = -L$(NDB_TOP)/lib -L$(OSE_LOC)/sfk-solaris2/lib -L$(OSE_LOC)/sfk-solaris2/krn-solaris2/lib
-
-LDLIBS_TOP =
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(LDFLAGS)
-
-
-
diff --git a/ndb/config/Defs.SOFTOSE.SPARC.GCC.mk b/ndb/config/Defs.SOFTOSE.SPARC.GCC.mk
deleted file mode 100644
index 6788fa956bf..00000000000
--- a/ndb/config/Defs.SOFTOSE.SPARC.GCC.mk
+++ /dev/null
@@ -1,57 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := g++
-CC := gcc
-AR_RCS := $(PURE) ar rcs
-SO := g++ -shared -o
-
-MAKEDEPEND := g++ -M
-PIC := -fPIC
-
-###
-#
-# Flags
-#
-NDB_STRDUP := Y
-CCFLAGS_WARNINGS = -Wno-long-long -Wall -pedantic -Wno-sign-compare -ansi
-CC_FLAGS_OSE = -DUSE_OSEDEF_H -DOSE_DELTA -DOS_DEBUG -DBIG_ENDIAN
-CCFLAGS_TOP = $(CC_FLAGS_OSE) $(CC_FLAGS_WARNINGS) -DNDB_STRDUP
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O3
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O3 -g
-else
-VERSION_FLAGS += -g -DOS_DEBUG
-endif
-endif
-
-OSE_LOC = /opt/as/OSE/OSE4.3.1
-
-CCFLAGS_LOC_OSESTD = -I$(OSE_LOC)/sfk-solaris2/std-include
-CCFLAGS_LOC_OSE = -I$(OSE_LOC)/sfk-solaris2/include -I$(OSE_LOC)/sfk-solaris2/krn-solaris2/include -I$(NDB_TOP)/src/env/softose
-
-
-CCFLAGS = $(CCFLAGS_LOC_OSE) $(CCFLAGS_LOC_OSESTD) $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC_OSE) $(CCFLAGS_LOC_OSESTD) $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDLIBS_LOC = -L$(NDB_TOP)/lib -L$(OSE_LOC)/sfk-solaris2/lib -L$(OSE_LOC)/sfk-solaris2/krn-solaris2/lib
-
-LDLIBS_TOP =
-
-LDLIBS_LAST = -lsoftose_env -lsoftose_krn -llnh -lefs -lshell -lfss -ltosv -lrtc -lheap -linetutil -linetapi -lsoftose -lsoftose_env -lsoftose_krn -losepthread -lrtc -lnsl -lsocket -lpthread -lcrt -lm
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(LDFLAGS)
-
-
-
diff --git a/ndb/config/Defs.SOLARIS.SPARC.FORTE6.mk b/ndb/config/Defs.SOLARIS.SPARC.FORTE6.mk
deleted file mode 100644
index 8a95205703d..00000000000
--- a/ndb/config/Defs.SOLARIS.SPARC.FORTE6.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := CC
-CC := /opt/as/forte6/SUNWspro/bin/cc
-AR_RCS := $(PURE) CC -xar -o
-SO := CC -G -z text -o
-
-MAKEDEPEND := CC -xM1
-PIC := -KPIC
-ETAGS := etags
-CTAGS := ctags
-
-RPCGENFLAGS := -MA -C -N
-
-###
-#
-# Flags
-
-CCFLAGS_TOP = -mt -DSOLARIS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS
-
-ifneq ($(PURE),)
- CCFLAGS_TOP += -xs
- CCFLAGS_TOP += -DNDB_PURIFY
-endif
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -xO3
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -xO3 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS)
-
-LDFLAGS_TOP = -L/opt/as/forte6/SUNWspro/WS6/lib -lpthread -lsocket -lnsl -lrt
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) -xildoff $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
-
-
-
-
diff --git a/ndb/config/Defs.SOLARIS.SPARC.GCC.mk b/ndb/config/Defs.SOLARIS.SPARC.GCC.mk
deleted file mode 100644
index 25920515278..00000000000
--- a/ndb/config/Defs.SOLARIS.SPARC.GCC.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-CXX := gcc
-C++ := g++
-CC := gcc
-AR_RCS := ar rcs
-SO := gcc -G -o
-
-#GXX_VERSION := $(shell gcc --version | sed -e 's,.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*,\1,1' -e q)
-
-MAKEDEPEND := g++ -M
-PIC := -fPIC
-
-RPCGENFLAGS := -MA -C -N
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-CCFLAGS_WARNINGS = -Wno-long-long -W -Wall -pedantic
-# -Wno-sign-compare Use this flag if you are annoyed with all the warnings
-CCFLAGS_TOP = -DSOLARIS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -DNO_COMMAND_HANDLER
-CCFLAGS_TOP += -fno-rtti
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O2
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O2 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP =
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(CXX) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
-
-LDFLAGS_LAST = -lpthread -lsocket -lnsl -lrt -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
-
diff --git a/ndb/config/Defs.SOLARIS.SPARC_64.GCC.mk b/ndb/config/Defs.SOLARIS.SPARC_64.GCC.mk
deleted file mode 100644
index 2b8b9d4cc24..00000000000
--- a/ndb/config/Defs.SOLARIS.SPARC_64.GCC.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-###
-#
-# Note: LD_LIBRARY_PATH must be set for /usr/local/lib/sparcv9 to dynamically link
-# to 64-bit libraries
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := g++ -m64
-CC := gcc -m64
-AR_RCS := ar rcs
-SO := g++ -m64 -shared -o
-
-MAKEDEPEND := g++ -M
-PIC := -fPIC
-
-RPCGENFLAGS := -MA -C -N
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-CCFLAGS_WARNINGS = -Wno-long-long -W -Wall -pedantic
-# -Wno-sign-compare Use this flag if you are annoyed with all the warnings
-CCFLAGS_TOP = -DSOLARIS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -DNO_COMMAND_HANDLER
-CCFLAGS_TOP += -fno-rtti
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O2
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O2 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP = -lpthread -lsocket -lnsl -lrt
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
-
-
diff --git a/ndb/config/Defs.SOLARIS6.SPARC.GCC.mk b/ndb/config/Defs.SOLARIS6.SPARC.GCC.mk
deleted file mode 100644
index f1c570ba101..00000000000
--- a/ndb/config/Defs.SOLARIS6.SPARC.GCC.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := g++
-CC := gcc
-AR_RCS := $(PURE) ar rcs
-SO := g++ -shared -o
-
-MAKEDEPEND := g++ -M
-PIC := -fPIC
-
-RPCGENFLAGS := -MA -C -N
-
-###
-#
-# Flags
-#
-CCFLAGS_WARNINGS = -Wno-long-long -Wall -pedantic
-# -Wno-sign-compare Use this flag if you are annoyed with all the warnings
-CCFLAGS_TOP = -DSOLARIS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -DNO_COMMAND_HANDLER
-
-# SOLARIS 6 should use the same settings as SOLARIS7
-# if something in the SOLARIS 7 port does not work for SOLARIS 6
-# it can be ifdefed using
-# if ! defined NDB_SOLRIS6
-CCFLAGS_TOP = -DNDB_SOLARIS
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O3
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O3
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP = -lpthread -lsocket -lnsl -lposix4
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
-
-
diff --git a/ndb/config/Defs.TRU64X.ALPHA.GCC.mk b/ndb/config/Defs.TRU64X.ALPHA.GCC.mk
deleted file mode 100644
index ae975fb2cb8..00000000000
--- a/ndb/config/Defs.TRU64X.ALPHA.GCC.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-C++ := g++
-CC := gcc
-AR_RCS := $(PURE) ar rcs
-SO := g++ -shared -o
-
-MAKEDEPEND := g++ -M
-PIC := -fPIC
-
-RPCGENFLAGS := -M -C -N
-
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-CCFLAGS_WARNINGS = -Wno-long-long -Wall #-pedantic
-# Add these for more warnings -Weffc++ -W
-CCFLAGS_TOP = -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS
-CCFLAGS_TOP += -fno-rtti
-
-ifeq (RELEASE, $(NDB_VERSION))
-VERSION_FLAGS += -O3
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-VERSION_FLAGS += -O3 -g
-else
-VERSION_FLAGS += -g
-endif
-endif
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP = -lpthread -lrt
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-LINK.cc = $(PURE) $(C++) $(CCFLAGS) $(LDFLAGS)
-
-LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
diff --git a/ndb/config/Defs.WIN32.x86.VC7.mk b/ndb/config/Defs.WIN32.x86.VC7.mk
deleted file mode 100644
index e66dacb78e7..00000000000
--- a/ndb/config/Defs.WIN32.x86.VC7.mk
+++ /dev/null
@@ -1,61 +0,0 @@
-###
-#
-# Defines
-SHELL := /bin/sh
-
-
-DEFINES = -D_WIN32 -D_M_IX86=600 -D_MSC_EXTENSIONS=0 -U_cdecl -D_MT
-#
-MAKEDEPEND = g++ -M --nostdinc --nostdinc++ -I"`cygpath -u "$(MSVCDIR)\include"`" -I"`cygpath -u "$(MSVCDIR)\PlatformSDK\include"`" $(DEFINES)
-PIC = -D_LIB
-NON_PIC = -D_LIB
-
-RPCGENFLAGS := -M -C -N
-
-ETAGS := etags
-CTAGS := ctags
-
-###
-#
-# Flags
-#
-CCFLAGS_WARNINGS =
-CCFLAGS_TOP =
-CCFLAGS_LOC =
-CCFLAGS_WIN = -DWIN32 -D_WIN32_WINNT=0x0500 -DWINVER=0x0500 -D_MBCS -DNO_COMMAND_HANDLER
-CCFLAGS_WIN += -W3 -EHsc
-#CCFLAGS_WIN += -clr
-
-ifeq (RELEASE, $(NDB_VERSION))
-CCFLAGS_WIN += -MT -O2 -Ob1 -DNO_DEBUG_MESSAGES
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-CCFLAGS_WIN += -MT -O2 -Ob1 -DNO_DEBUG_MESSAGES
-else
-CCFLAGS_WIN += -MTd -Zi -Od -GS -D_DEBUG
-endif
-endif
-
-C++ = cl -nologo $(CCFLAGS_WIN)
-CC = cl -nologo $(CCFLAGS_WIN)
-
-CCFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-CFLAGS = $(CCFLAGS_LOC) $(CCFLAGS_TOP) $(USER_FLAGS) $(VERSION_FLAGS) $(CCFLAGS_WARNINGS)
-
-LDFLAGS_TOP =
-
-LDFLAGS = $(LDFLAGS_LOC) $(LDFLAGS_TOP)
-
-LDLIBS = $(LDLIBS_LOC) $(LDLIBS_TOP)
-
-WIN_LIBS := Ws2_32.lib Advapi32.lib
-
-ifeq (RELEASE, $(NDB_VERSION))
-LINK.cc = link -INCREMENTAL:NO -NOLOGO -LARGEADDRESSAWARE $(WIN_LIBS)
-else
-ifeq (RELEASE_TRACE, $(NDB_VERSION))
-LINK.cc = link -INCREMENTAL:NO -NOLOGO -LARGEADDRESSAWARE $(WIN_LIBS)
-else
-LINK.cc = link -INCREMENTAL -NOLOGO -DEBUG -LARGEADDRESSAWARE $(WIN_LIBS)
-endif
-endif
diff --git a/ndb/config/GuessConfig.sh b/ndb/config/GuessConfig.sh
deleted file mode 100755
index 3caeeaae6d0..00000000000
--- a/ndb/config/GuessConfig.sh
+++ /dev/null
@@ -1,115 +0,0 @@
-#! /bin/sh
-
-if [ -z "$NDB_TOP" ]
-then
- echo "You have not set NDB_TOP. Exiting" 1>&2
- exit 1
-fi
-
-if [ -z "$NDB_SCI" ]
-then
- NDB_SCI=N
-fi
-
-if [ -z "$NDB_SHM" ]
-then
- NDB_SHM=N
-fi
-
-os=`uname -s`
-case $os in
-Linux)
- NDB_OS=LINUX
- NDB_ARCH=x86
- NDB_COMPILER=GCC
- ;;
-Darwin)
- NDB_OS=MACOSX
- NDB_ARCH=POWERPC
- NDB_COMPILER=GCC
- ;;
-HP-UX)
- NDB_OS=HPUX
- NDB_ARCH=HPPA
- NDB_COMPILER=GCC
- ;;
-CYGWIN_NT-5.0)
- NDB_OS=WIN32
- NDB_ARCH=x86
- NDB_COMPILER=VC7
- ;;
-*)
- if [ "$os" = "SunOS" ] && [ `uname -r` = "5.6" ]
- then
- NDB_OS=OSE
- NDB_ARCH=PPC750
- NDB_COMPILER=DIAB
- else
- NDB_OS=SOLARIS
- NDB_ARCH=SPARC
- NDB_COMPILER=GCC
- fi;;
-esac
-
-if [ -z "$NDB_ODBC" ]
-then
- NDB_ODBC=N
-fi
-
-
-mch=`uname -m`
-case $mch in
-x86_64)
- NDB_ARCH=x86_64
- ;;
-*)
- ;;
-esac
-
-if [ -f $NDB_TOP/config/Makefile ]
-then
-TERMCAP_LIB=`grep TERMCAP_LIB $NDB_TOP/config/Makefile | sed -e s,"TERMCAP_LIB.*=.*-l","",g`
-fi
-if [ "$TERMCAP_LIB" = "" ]
-then
-TERMCAP_LIB=termcap
-fi
-
-# defaults
-NDB_VERSION=DEBUG
-PACKAGE=
-VERSION=
-
-parse_arguments() {
- for arg do
- case "$arg" in
- -GCC) NDB_COMPILER=GCC ;;
- -R) NDB_VERSION=RELEASE ;;
- -D) NDB_VERSION=DEBUG ;;
- --PACKAGE=*) PACKAGE=`echo "$arg" | sed -e "s;--PACKAGE=;;"` ;;
- --VERSION=*) VERSION=`echo "$arg" | sed -e "s;--VERSION=;;"` ;;
- *)
- echo "Unknown argument '$arg'"
- exit 1
- ;;
- esac
- done
-}
-
-parse_arguments "$@"
-
-(
- echo "# This file was automatically generated `date`"
- echo "NDB_OS := $NDB_OS"
- echo "NDB_ARCH := $NDB_ARCH"
- echo "NDB_COMPILER := $NDB_COMPILER"
- echo "NDB_VERSION := $NDB_VERSION"
- echo "NDB_SCI := $NDB_SCI"
- echo "NDB_ODBC := $NDB_ODBC"
- echo "TERMCAP_LIB := $TERMCAP_LIB"
- echo "PACKAGE := $PACKAGE"
- echo "VERSION := $VERSION"
-) > $NDB_TOP/config/config.mk
-
-exit 0
-
diff --git a/ndb/config/Makefile.am b/ndb/config/Makefile.am
deleted file mode 100644
index b5fd81814a1..00000000000
--- a/ndb/config/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2003 MySQL AB
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-# Process this file with automake to create Makefile.in
-
-AUTOMAKE_OPTIONS = foreign
-
-# These are built from source in the Docs directory
-EXTRA_DIST =
-SUBDIRS =
-
-# Relink after clean
-linked_sources =
-
-CLEANFILES = $(linked_sources)
-
-# This is just so that the linking is done early.
-config.h:
diff --git a/ndb/config/acinclude.m4 b/ndb/config/acinclude.m4
deleted file mode 100644
index b9edaf801ed..00000000000
--- a/ndb/config/acinclude.m4
+++ /dev/null
@@ -1,1513 +0,0 @@
-# Local macros for automake & autoconf
-
-AC_DEFUN(MYSQL_CHECK_LIBEDIT_INTERFACE,[
- AC_CACHE_CHECK([libedit variant of rl_completion_entry_function], mysql_cv_libedit_interface,
- AC_TRY_COMPILE(
- [
- #include "stdio.h"
- #include "readline/readline.h"
- ],
- [
- char res= *(*rl_completion_entry_function)(0,0);
- completion_matches(0,0);
- ],
- [
- mysql_cv_libedit_interface=yes
- AC_DEFINE_UNQUOTED(USE_LIBEDIT_INTERFACE)
- ],
- [mysql_cv_libedit_interface=no]
- )
- )
-])
-
-AC_DEFUN(MYSQL_CHECK_NEW_RL_INTERFACE,[
- AC_CACHE_CHECK([defined rl_compentry_func_t and rl_completion_func_t], mysql_cv_new_rl_interface,
- AC_TRY_COMPILE(
- [
- #include "stdio.h"
- #include "readline/readline.h"
- ],
- [
- rl_completion_func_t *func1= (rl_completion_func_t*)0;
- rl_compentry_func_t *func2= (rl_compentry_func_t*)0;
- ],
- [
- mysql_cv_new_rl_interface=yes
- AC_DEFINE_UNQUOTED(USE_NEW_READLINE_INTERFACE)
- ],
- [mysql_cv_new_rl_interface=no]
- )
- )
-])
-
-# A local version of AC_CHECK_SIZEOF that includes sys/types.h
-dnl MYSQL_CHECK_SIZEOF(TYPE [, CROSS-SIZE])
-AC_DEFUN(MYSQL_CHECK_SIZEOF,
-[changequote(<<, >>)dnl
-dnl The name to #define.
-define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
-dnl The cache variable name.
-define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
-changequote([, ])dnl
-AC_MSG_CHECKING(size of $1)
-AC_CACHE_VAL(AC_CV_NAME,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-#if STDC_HEADERS
-#include <stdlib.h>
-#include <stddef.h>
-#endif
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof($1));
- exit(0);
-}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$2], , , AC_CV_NAME=$2))])dnl
-AC_MSG_RESULT($AC_CV_NAME)
-AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME)
-undefine([AC_TYPE_NAME])dnl
-undefine([AC_CV_NAME])dnl
-])
-
-#---START: Used in for client configure
-AC_DEFUN(MYSQL_TYPE_ACCEPT,
-[ac_save_CXXFLAGS="$CXXFLAGS"
-AC_CACHE_CHECK([base type of last arg to accept], mysql_cv_btype_last_arg_accept,
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-if test "$ac_cv_prog_gxx" = "yes"
-then
- CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'`
-fi
-mysql_cv_btype_last_arg_accept=none
-[AC_TRY_COMPILE([#if defined(inline)
-#undef inline
-#endif
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-],
-[int a = accept(1, (struct sockaddr *) 0, (socklen_t *) 0); return (a != 0);],
-mysql_cv_btype_last_arg_accept=socklen_t)]
-if test "$mysql_cv_btype_last_arg_accept" = "none"; then
-[AC_TRY_COMPILE([#if defined(inline)
-#undef inline
-#endif
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-],
-[int a = accept(1, (struct sockaddr *) 0, (size_t *) 0); return (a != 0);],
-mysql_cv_btype_last_arg_accept=size_t)]
-fi
-if test "$mysql_cv_btype_last_arg_accept" = "none"; then
-mysql_cv_btype_last_arg_accept=int
-fi)
-AC_LANG_RESTORE
-AC_DEFINE_UNQUOTED(SOCKET_SIZE_TYPE, $mysql_cv_btype_last_arg_accept)
-CXXFLAGS="$ac_save_CXXFLAGS"
-])
-#---END:
-
-dnl Find type of qsort
-AC_DEFUN(MYSQL_TYPE_QSORT,
-[AC_CACHE_CHECK([return type of qsort], mysql_cv_type_qsort,
-[AC_TRY_COMPILE([#include <stdlib.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-void qsort(void *base, size_t nel, size_t width,
- int (*compar) (const void *, const void *));
-],
-[int i;], mysql_cv_type_qsort=void, mysql_cv_type_qsort=int)])
-AC_DEFINE_UNQUOTED(RETQSORTTYPE, $mysql_cv_type_qsort)
-if test "$mysql_cv_type_qsort" = "void"
-then
- AC_DEFINE_UNQUOTED(QSORT_TYPE_IS_VOID, 1)
-fi
-])
-
-AC_DEFUN(MYSQL_TIMESPEC_TS,
-[AC_CACHE_CHECK([if struct timespec has a ts_sec member], mysql_cv_timespec_ts,
-[AC_TRY_COMPILE([#include <pthread.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[struct timespec abstime;
-
-abstime.ts_sec = time(NULL)+1;
-abstime.ts_nsec = 0;
-], mysql_cv_timespec_ts=yes, mysql_cv_timespec_ts=no)])
-if test "$mysql_cv_timespec_ts" = "yes"
-then
- AC_DEFINE(HAVE_TIMESPEC_TS_SEC)
-fi
-])
-
-AC_DEFUN(MYSQL_TZNAME,
-[AC_CACHE_CHECK([if we have tzname variable], mysql_cv_tzname,
-[AC_TRY_COMPILE([#include <time.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[ tzset();
- return tzname[0] != 0;
-], mysql_cv_tzname=yes, mysql_cv_tzname=no)])
-if test "$mysql_cv_tzname" = "yes"
-then
- AC_DEFINE(HAVE_TZNAME)
-fi
-])
-
-AC_DEFUN(MYSQL_CHECK_ZLIB_WITH_COMPRESS, [
-save_LIBS="$LIBS"
-LIBS="-l$1 $LIBS"
-AC_CACHE_CHECK([if libz with compress], mysql_cv_compress,
-[AC_TRY_RUN([#include <zlib.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-int main(int argv, char **argc)
-{
- return 0;
-}
-
-int link_test()
-{
- return compress(0, (unsigned long*) 0, "", 0);
-}
-], mysql_cv_compress=yes, mysql_cv_compress=no)])
-if test "$mysql_cv_compress" = "yes"
-then
- AC_DEFINE(HAVE_COMPRESS)
-else
- LIBS="$save_LIBS"
-fi
-])
-
-#---START: Used in for client configure
-AC_DEFUN(MYSQL_CHECK_ULONG,
-[AC_MSG_CHECKING(for type ulong)
-AC_CACHE_VAL(ac_cv_ulong,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-main()
-{
- ulong foo;
- foo++;
- exit(0);
-}], ac_cv_ulong=yes, ac_cv_ulong=no, ac_cv_ulong=no)])
-AC_MSG_RESULT($ac_cv_ulong)
-if test "$ac_cv_ulong" = "yes"
-then
- AC_DEFINE(HAVE_ULONG)
-fi
-])
-
-AC_DEFUN(MYSQL_CHECK_UCHAR,
-[AC_MSG_CHECKING(for type uchar)
-AC_CACHE_VAL(ac_cv_uchar,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-main()
-{
- uchar foo;
- foo++;
- exit(0);
-}], ac_cv_uchar=yes, ac_cv_uchar=no, ac_cv_uchar=no)])
-AC_MSG_RESULT($ac_cv_uchar)
-if test "$ac_cv_uchar" = "yes"
-then
- AC_DEFINE(HAVE_UCHAR)
-fi
-])
-
-AC_DEFUN(MYSQL_CHECK_UINT,
-[AC_MSG_CHECKING(for type uint)
-AC_CACHE_VAL(ac_cv_uint,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-main()
-{
- uint foo;
- foo++;
- exit(0);
-}], ac_cv_uint=yes, ac_cv_uint=no, ac_cv_uint=no)])
-AC_MSG_RESULT($ac_cv_uint)
-if test "$ac_cv_uint" = "yes"
-then
- AC_DEFINE(HAVE_UINT)
-fi
-])
-
-
-AC_DEFUN(MYSQL_CHECK_IN_ADDR_T,
-[AC_MSG_CHECKING(for type in_addr_t)
-AC_CACHE_VAL(ac_cv_in_addr_t,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-int main(int argc, char **argv)
-{
- in_addr_t foo;
- exit(0);
-}], ac_cv_in_addr_t=yes, ac_cv_in_addr_t=no, ac_cv_in_addr_t=no)])
-AC_MSG_RESULT($ac_cv_in_addr_t)
-if test "$ac_cv_in_addr_t" = "yes"
-then
- AC_DEFINE(HAVE_IN_ADDR_T)
-fi
-])
-
-
-AC_DEFUN(MYSQL_PTHREAD_YIELD,
-[AC_CACHE_CHECK([if pthread_yield takes zero arguments], ac_cv_pthread_yield_zero_arg,
-[AC_TRY_LINK([#define _GNU_SOURCE
-#include <pthread.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[
- pthread_yield();
-], ac_cv_pthread_yield_zero_arg=yes, ac_cv_pthread_yield_zero_arg=yeso)])
-if test "$ac_cv_pthread_yield_zero_arg" = "yes"
-then
- AC_DEFINE(HAVE_PTHREAD_YIELD_ZERO_ARG)
-fi
-]
-[AC_CACHE_CHECK([if pthread_yield takes 1 argument], ac_cv_pthread_yield_one_arg,
-[AC_TRY_LINK([#define _GNU_SOURCE
-#include <pthread.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[
- pthread_yield(0);
-], ac_cv_pthread_yield_one_arg=yes, ac_cv_pthread_yield_one_arg=no)])
-if test "$ac_cv_pthread_yield_one_arg" = "yes"
-then
- AC_DEFINE(HAVE_PTHREAD_YIELD_ONE_ARG)
-fi
-]
-)
-
-
-
-#---END:
-
-AC_DEFUN(MYSQL_CHECK_FP_EXCEPT,
-[AC_MSG_CHECKING(for type fp_except)
-AC_CACHE_VAL(ac_cv_fp_except,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-#include <ieeefp.h>
-main()
-{
- fp_except foo;
- foo++;
- exit(0);
-}], ac_cv_fp_except=yes, ac_cv_fp_except=no, ac_cv_fp_except=no)])
-AC_MSG_RESULT($ac_cv_fp_except)
-if test "$ac_cv_fp_except" = "yes"
-then
- AC_DEFINE(HAVE_FP_EXCEPT)
-fi
-])
-
-# From fileutils-3.14/aclocal.m4
-
-# @defmac AC_PROG_CC_STDC
-# @maindex PROG_CC_STDC
-# @ovindex CC
-# If the C compiler in not in ANSI C mode by default, try to add an option
-# to output variable @code{CC} to make it so. This macro tries various
-# options that select ANSI C on some system or another. It considers the
-# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
-# handles function prototypes correctly.
-#
-# Patched by monty to only check if __STDC__ is defined. With the original
-# check it's impossible to get things to work with the Sunpro compiler from
-# Workshop 4.2
-#
-# If you use this macro, you should check after calling it whether the C
-# compiler has been set to accept ANSI C; if not, the shell variable
-# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
-# code in ANSI C, you can make an un-ANSIfied copy of it by using the
-# program @code{ansi2knr}, which comes with Ghostscript.
-# @end defmac
-
-AC_DEFUN(AM_PROG_CC_STDC,
-[AC_REQUIRE([AC_PROG_CC])
-AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
-AC_CACHE_VAL(am_cv_prog_cc_stdc,
-[am_cv_prog_cc_stdc=no
-ac_save_CC="$CC"
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX -qlanglvl=ansi
-# Ultrix and OSF/1 -std1
-# HP-UX -Aa -D_HPUX_SOURCE
-# SVR4 -Xc -D__EXTENSIONS__
-# removed "-Xc -D__EXTENSIONS__" beacause sun c++ does not like it.
-for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE"
-do
- CC="$ac_save_CC $ac_arg"
- AC_TRY_COMPILE(
-[#if !defined(__STDC__)
-choke me
-#endif
-/* DYNIX/ptx V4.1.3 can't compile sys/stat.h with -Xc -D__EXTENSIONS__. */
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/stat.h>
-#endif
-], [
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};],
-[am_cv_prog_cc_stdc="$ac_arg"; break])
-done
-CC="$ac_save_CC"
-])
-AC_MSG_RESULT($am_cv_prog_cc_stdc)
-case "x$am_cv_prog_cc_stdc" in
- x|xno) ;;
- *) CC="$CC $am_cv_prog_cc_stdc" ;;
-esac
-])
-
-#
-# Check to make sure that the build environment is sane.
-#
-
-AC_DEFUN(AM_SANITY_CHECK,
-[AC_MSG_CHECKING([whether build environment is sane])
-sleep 1
-echo timestamp > conftestfile
-# Do this in a subshell so we don't clobber the current shell's
-# arguments. FIXME: maybe try `-L' hack like GETLOADAVG test?
-if (set X `ls -t $srcdir/configure conftestfile`; test "[$]2" = conftestfile)
-then
- # Ok.
- :
-else
- AC_MSG_ERROR([newly created file is older than distributed files!
-Check your system clock])
-fi
-rm -f conftest*
-AC_MSG_RESULT(yes)])
-
-# Orginal from bash-2.0 aclocal.m4, Changed to use termcap last by monty.
-
-AC_DEFUN(MYSQL_CHECK_LIB_TERMCAP,
-[
-AC_CACHE_VAL(mysql_cv_termcap_lib,
-[AC_CHECK_LIB(ncurses, tgetent, mysql_cv_termcap_lib=libncurses,
- [AC_CHECK_LIB(curses, tgetent, mysql_cv_termcap_lib=libcurses,
- [AC_CHECK_LIB(termcap, tgetent, mysql_cv_termcap_lib=libtermcap,
- mysql_cv_termcap_lib=NOT_FOUND)])])])
-AC_MSG_CHECKING(for termcap functions library)
-if test "$mysql_cv_termcap_lib" = "NOT_FOUND"; then
-AC_MSG_ERROR([No curses/termcap library found])
-elif test "$mysql_cv_termcap_lib" = "libtermcap"; then
-TERMCAP_LIB=-ltermcap
-elif test "$mysql_cv_termcap_lib" = "libncurses"; then
-TERMCAP_LIB=-lncurses
-else
-TERMCAP_LIB=-lcurses
-fi
-AC_MSG_RESULT($TERMCAP_LIB)
-])
-
-dnl Check type of signal routines (posix, 4.2bsd, 4.1bsd or v7)
-AC_DEFUN(MYSQL_SIGNAL_CHECK,
-[AC_REQUIRE([AC_TYPE_SIGNAL])
-AC_MSG_CHECKING(for type of signal functions)
-AC_CACHE_VAL(mysql_cv_signal_vintage,
-[
- AC_TRY_LINK([#include <signal.h>],[
- sigset_t ss;
- struct sigaction sa;
- sigemptyset(&ss); sigsuspend(&ss);
- sigaction(SIGINT, &sa, (struct sigaction *) 0);
- sigprocmask(SIG_BLOCK, &ss, (sigset_t *) 0);
- ], mysql_cv_signal_vintage=posix,
- [
- AC_TRY_LINK([#include <signal.h>], [
- int mask = sigmask(SIGINT);
- sigsetmask(mask); sigblock(mask); sigpause(mask);
- ], mysql_cv_signal_vintage=4.2bsd,
- [
- AC_TRY_LINK([
- #include <signal.h>
- RETSIGTYPE foo() { }], [
- int mask = sigmask(SIGINT);
- sigset(SIGINT, foo); sigrelse(SIGINT);
- sighold(SIGINT); sigpause(SIGINT);
- ], mysql_cv_signal_vintage=svr3, mysql_cv_signal_vintage=v7
- )]
- )]
-)
-])
-AC_MSG_RESULT($mysql_cv_signal_vintage)
-if test "$mysql_cv_signal_vintage" = posix; then
-AC_DEFINE(HAVE_POSIX_SIGNALS)
-elif test "$mysql_cv_signal_vintage" = "4.2bsd"; then
-AC_DEFINE(HAVE_BSD_SIGNALS)
-elif test "$mysql_cv_signal_vintage" = svr3; then
-AC_DEFINE(HAVE_USG_SIGHOLD)
-fi
-])
-
-AC_DEFUN(MYSQL_CHECK_GETPW_FUNCS,
-[AC_MSG_CHECKING(whether programs are able to redeclare getpw functions)
-AC_CACHE_VAL(mysql_cv_can_redecl_getpw,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <pwd.h>
-extern struct passwd *getpwent();], [struct passwd *z; z = getpwent();],
- mysql_cv_can_redecl_getpw=yes,mysql_cv_can_redecl_getpw=no)])
-AC_MSG_RESULT($mysql_cv_can_redecl_getpw)
-if test "$mysql_cv_can_redecl_getpw" = "no"; then
-AC_DEFINE(HAVE_GETPW_DECLS)
-fi
-])
-
-AC_DEFUN(MYSQL_HAVE_TIOCGWINSZ,
-[AC_MSG_CHECKING(for TIOCGWINSZ in sys/ioctl.h)
-AC_CACHE_VAL(mysql_cv_tiocgwinsz_in_ioctl,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/ioctl.h>], [int x = TIOCGWINSZ;],
- mysql_cv_tiocgwinsz_in_ioctl=yes,mysql_cv_tiocgwinsz_in_ioctl=no)])
-AC_MSG_RESULT($mysql_cv_tiocgwinsz_in_ioctl)
-if test "$mysql_cv_tiocgwinsz_in_ioctl" = "yes"; then
-AC_DEFINE(GWINSZ_IN_SYS_IOCTL)
-fi
-])
-
-AC_DEFUN(MYSQL_HAVE_FIONREAD,
-[AC_MSG_CHECKING(for FIONREAD in sys/ioctl.h)
-AC_CACHE_VAL(mysql_cv_fionread_in_ioctl,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/ioctl.h>], [int x = FIONREAD;],
- mysql_cv_fionread_in_ioctl=yes,mysql_cv_fionread_in_ioctl=no)])
-AC_MSG_RESULT($mysql_cv_fionread_in_ioctl)
-if test "$mysql_cv_fionread_in_ioctl" = "yes"; then
-AC_DEFINE(FIONREAD_IN_SYS_IOCTL)
-fi
-])
-
-AC_DEFUN(MYSQL_HAVE_TIOCSTAT,
-[AC_MSG_CHECKING(for TIOCSTAT in sys/ioctl.h)
-AC_CACHE_VAL(mysql_cv_tiocstat_in_ioctl,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/ioctl.h>], [int x = TIOCSTAT;],
- mysql_cv_tiocstat_in_ioctl=yes,mysql_cv_tiocstat_in_ioctl=no)])
-AC_MSG_RESULT($mysql_cv_tiocstat_in_ioctl)
-if test "$mysql_cv_tiocstat_in_ioctl" = "yes"; then
-AC_DEFINE(TIOCSTAT_IN_SYS_IOCTL)
-fi
-])
-
-AC_DEFUN(MYSQL_STRUCT_DIRENT_D_INO,
-[AC_REQUIRE([AC_HEADER_DIRENT])
-AC_MSG_CHECKING(if struct dirent has a d_ino member)
-AC_CACHE_VAL(mysql_cv_dirent_has_dino,
-[AC_TRY_COMPILE([
-#include <stdio.h>
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#if defined(HAVE_DIRENT_H)
-# include <dirent.h>
-#else
-# define dirent direct
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif /* SYSNDIR */
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif /* SYSDIR */
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif /* HAVE_DIRENT_H */
-],[
-struct dirent d; int z; z = d.d_ino;
-], mysql_cv_dirent_has_dino=yes, mysql_cv_dirent_has_dino=no)])
-AC_MSG_RESULT($mysql_cv_dirent_has_dino)
-if test "$mysql_cv_dirent_has_dino" = "yes"; then
-AC_DEFINE(STRUCT_DIRENT_HAS_D_INO)
-fi
-])
-
-AC_DEFUN(MYSQL_TYPE_SIGHANDLER,
-[AC_MSG_CHECKING([whether signal handlers are of type void])
-AC_CACHE_VAL(mysql_cv_void_sighandler,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <signal.h>
-#ifdef signal
-#undef signal
-#endif
-#ifdef __cplusplus
-extern "C"
-#endif
-void (*signal ()) ();],
-[int i;], mysql_cv_void_sighandler=yes, mysql_cv_void_sighandler=no)])dnl
-AC_MSG_RESULT($mysql_cv_void_sighandler)
-if test "$mysql_cv_void_sighandler" = "yes"; then
-AC_DEFINE(VOID_SIGHANDLER)
-fi
-])
-
-AC_DEFUN(MYSQL_CXX_BOOL,
-[
-AC_REQUIRE([AC_PROG_CXX])
-AC_MSG_CHECKING(if ${CXX} supports bool types)
-AC_CACHE_VAL(mysql_cv_have_bool,
-[
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-AC_TRY_COMPILE(,[bool b = true;],
-mysql_cv_have_bool=yes,
-mysql_cv_have_bool=no)
-AC_LANG_RESTORE
-])
-AC_MSG_RESULT($mysql_cv_have_bool)
-if test "$mysql_cv_have_bool" = yes; then
-AC_DEFINE(HAVE_BOOL)
-fi
-])dnl
-
-AC_DEFUN(MYSQL_STACK_DIRECTION,
- [AC_CACHE_CHECK(stack direction for C alloca, ac_cv_c_stack_direction,
- [AC_TRY_RUN([#include <stdlib.h>
- int find_stack_direction ()
- {
- static char *addr = 0;
- auto char dummy;
- if (addr == 0)
- {
- addr = &dummy;
- return find_stack_direction ();
- }
- else
- return (&dummy > addr) ? 1 : -1;
- }
- int main ()
- {
- exit (find_stack_direction() < 0);
- }], ac_cv_c_stack_direction=1, ac_cv_c_stack_direction=-1,
- ac_cv_c_stack_direction=0)])
- AC_DEFINE_UNQUOTED(STACK_DIRECTION, $ac_cv_c_stack_direction)
-])dnl
-
-AC_DEFUN(MYSQL_FUNC_ALLOCA,
-[
-# Since we have heard that alloca fails on IRIX never define it on a
-# SGI machine
-if test ! "$host_vendor" = "sgi"
-then
- AC_REQUIRE_CPP()dnl Set CPP; we run AC_EGREP_CPP conditionally.
- # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
- # for constant arguments. Useless!
- AC_CACHE_CHECK([for working alloca.h], ac_cv_header_alloca_h,
- [AC_TRY_LINK([#include <alloca.h>], [char *p = alloca(2 * sizeof(int));],
- ac_cv_header_alloca_h=yes, ac_cv_header_alloca_h=no)])
- if test "$ac_cv_header_alloca_h" = "yes"
- then
- AC_DEFINE(HAVE_ALLOCA)
- fi
-
- AC_CACHE_CHECK([for alloca], ac_cv_func_alloca_works,
- [AC_TRY_LINK([
- #ifdef __GNUC__
- # define alloca __builtin_alloca
- #else
- # if HAVE_ALLOCA_H
- # include <alloca.h>
- # else
- # ifdef _AIX
- #pragma alloca
- # else
- # ifndef alloca /* predefined by HP cc +Olibcalls */
- char *alloca ();
- # endif
- # endif
- # endif
- #endif
- ], [char *p = (char *) alloca(1);],
- ac_cv_func_alloca_works=yes, ac_cv_func_alloca_works=no)])
- if test "$ac_cv_func_alloca_works" = "yes"; then
- AC_DEFINE(HAVE_ALLOCA)
- fi
-
- if test "$ac_cv_func_alloca_works" = "no"; then
- # The SVR3 libPW and SVR4 libucb both contain incompatible functions
- # that cause trouble. Some versions do not even contain alloca or
- # contain a buggy version. If you still want to use their alloca,
- # use ar to extract alloca.o from them instead of compiling alloca.c.
- ALLOCA=alloca.o
- AC_DEFINE(C_ALLOCA)
-
- AC_CACHE_CHECK(whether alloca needs Cray hooks, ac_cv_os_cray,
- [AC_EGREP_CPP(webecray,
- [#if defined(CRAY) && ! defined(CRAY2)
- webecray
- #else
- wenotbecray
- #endif
- ], ac_cv_os_cray=yes, ac_cv_os_cray=no)])
- if test "$ac_cv_os_cray" = "yes"; then
- for ac_func in _getb67 GETB67 getb67; do
- AC_CHECK_FUNC($ac_func, [AC_DEFINE_UNQUOTED(CRAY_STACKSEG_END, $ac_func)
- break])
- done
- fi
- fi
- AC_SUBST(ALLOCA)dnl
-else
- AC_MSG_RESULT("Skipped alloca tests")
-fi
-])
-
-AC_DEFUN(MYSQL_CHECK_LONGLONG_TO_FLOAT,
-[
-AC_MSG_CHECKING(if conversion of longlong to float works)
-AC_CACHE_VAL(ac_cv_conv_longlong_to_float,
-[AC_TRY_RUN([#include <stdio.h>
-typedef long long longlong;
-main()
-{
- longlong ll=1;
- float f;
- FILE *file=fopen("conftestval", "w");
- f = (float) ll;
- fprintf(file,"%g\n",f);
- fclose(file);
- exit (0);
-}], ac_cv_conv_longlong_to_float=`cat conftestval`, ac_cv_conv_longlong_to_float=0, ifelse([$2], , , ac_cv_conv_longlong_to_float=$2))])dnl
-if test "$ac_cv_conv_longlong_to_float" = "1" -o "$ac_cv_conv_longlong_to_float" = "yes"
-then
- ac_cv_conv_longlong_to_float=yes
-else
- ac_cv_conv_longlong_to_float=no
-fi
-AC_MSG_RESULT($ac_cv_conv_longlong_to_float)
-])
-
-AC_DEFUN(MYSQL_CHECK_CPU,
-[AC_CACHE_CHECK([if compiler supports optimizations for current cpu],
-mysql_cv_cpu,[
-
-ac_save_CFLAGS="$CFLAGS"
-if test -r /proc/cpuinfo ; then
- cpuinfo="cat /proc/cpuinfo"
- cpu_family=`$cpuinfo | grep 'cpu family' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1`
- cpu_vendor=`$cpuinfo | grep 'vendor_id' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1`
-fi
-if test "$cpu_vendor" = "AuthenticAMD"; then
- if test $cpu_family -ge 6; then
- cpu_set="athlon pentiumpro k5 pentium i486 i386";
- elif test $cpu_family -eq 5; then
- cpu_set="k5 pentium i486 i386";
- elif test $cpu_family -eq 4; then
- cpu_set="i486 i386"
- else
- cpu_set="i386"
- fi
-elif test "$cpu_vendor" = "GenuineIntel"; then
- if test $cpu_family -ge 6; then
- cpu_set="pentiumpro pentium i486 i386";
- elif test $cpu_family -eq 5; then
- cpu_set="pentium i486 i386";
- elif test $cpu_family -eq 4; then
- cpu_set="i486 i386"
- else
- cpu_set="i386"
- fi
-fi
-
-for ac_arg in $cpu_set;
-do
- CFLAGS="$ac_save_CFLAGS -mcpu=$ac_arg -march=$ac_arg -DCPU=$ac_arg"
- AC_TRY_COMPILE([],[int i],mysql_cv_cpu=$ac_arg; break;, mysql_cv_cpu="unknown")
-done
-
-if test "$mysql_cv_cpu" = "unknown"
-then
- CFLAGS="$ac_save_CFLAGS"
- AC_MSG_RESULT(none)
-else
- AC_MSG_RESULT($mysql_cv_cpu)
-fi
-]]))
-
-AC_DEFUN(MYSQL_CHECK_VIO, [
- AC_ARG_WITH([vio],
- [ --with-vio Include the Virtual IO support],
- [vio="$withval"],
- [vio=no])
-
- if test "$vio" = "yes"
- then
- vio_dir="vio"
- vio_libs="../vio/libvio.la"
- AC_DEFINE(HAVE_VIO)
- else
- vio_dir=""
- vio_libs=""
- fi
- AC_SUBST([vio_dir])
- AC_SUBST([vio_libs])
-])
-
-AC_DEFUN(MYSQL_FIND_OPENSSL, [
- incs="$1"
- libs="$2"
- case "$incs---$libs" in
- ---)
- for d in /usr/ssl/include /usr/local/ssl/include /usr/include \
-/usr/include/ssl /opt/ssl/include /opt/openssl/include \
-/usr/local/ssl/include /usr/local/include ; do
- if test -f $d/openssl/ssl.h ; then
- OPENSSL_INCLUDE=-I$d
- fi
- done
-
- for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \
-/usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib /usr/local/lib/ ; do
- if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl.dylib ; then
- OPENSSL_LIB=$d
- fi
- done
- ;;
- ---* | *---)
- AC_MSG_ERROR([if either 'includes' or 'libs' is specified, both must be specified])
- ;;
- * )
- if test -f $incs/openssl/ssl.h ; then
- OPENSSL_INCLUDE=-I$incs
- fi
- if test -f $libs/libssl.a || test -f $libs/libssl.so || test -f $libs/libssl.dylib ; then
- OPENSSL_LIB=$libs
- fi
- ;;
- esac
-
- # On RedHat 9 we need kerberos to compile openssl
- for d in /usr/kerberos/include
- do
- if test -f $d/krb5.h ; then
- OPENSSL_KERBEROS_INCLUDE="$d"
- fi
- done
-
-
- if test -z "$OPENSSL_LIB" -o -z "$OPENSSL_INCLUDE" ; then
- echo "Could not find an installation of OpenSSL"
- if test -n "$OPENSSL_LIB" ; then
- if test "$IS_LINUX" = "true"; then
- echo "Looks like you've forgotten to install OpenSSL development RPM"
- fi
- fi
- exit 1
- fi
-
-])
-
-AC_DEFUN(MYSQL_CHECK_OPENSSL, [
-AC_MSG_CHECKING(for OpenSSL)
- AC_ARG_WITH([openssl],
- [ --with-openssl Include the OpenSSL support],
- [openssl="$withval"],
- [openssl=no])
-
- AC_ARG_WITH([openssl-includes],
- [
- --with-openssl-includes=DIR
- Find OpenSSL headers in DIR],
- [openssl_includes="$withval"],
- [openssl_includes=""])
-
- AC_ARG_WITH([openssl-libs],
- [
- --with-openssl-libs=DIR
- Find OpenSSL libraries in DIR],
- [openssl_libs="$withval"],
- [openssl_libs=""])
-
- if test "$openssl" = "yes"
- then
- MYSQL_FIND_OPENSSL([$openssl_includes], [$openssl_libs])
- #force VIO use
- vio_dir="vio"
- vio_libs="../vio/libvio.la"
- AC_DEFINE(HAVE_VIO)
- AC_MSG_RESULT(yes)
- openssl_libs="-L$OPENSSL_LIB -lssl -lcrypto"
- # Don't set openssl_includes to /usr/include as this gives us a lot of
- # compiler warnings when using gcc 3.x
- openssl_includes=""
- if test "$OPENSSL_INCLUDE" != "-I/usr/include"
- then
- openssl_includes="$OPENSSL_INCLUDE"
- fi
- if test "$OPENSSL_KERBEROS_INCLUDE"
- then
- openssl_includes="$openssl_includes -I$OPENSSL_KERBEROS_INCLUDE"
- fi
- AC_DEFINE(HAVE_OPENSSL)
-
- # openssl-devel-0.9.6 requires dlopen() and we can't link staticly
- # on many platforms (We should actually test this here, but it's quite
- # hard) to do as we are doing libtool for linking.
- using_static=""
- case "$CLIENT_EXTRA_LDFLAGS $MYSQLD_EXTRA_LDFLAGS" in
- *-all-static*) using_static="yes" ;;
- esac
- if test "$using_static" = "yes"
- then
- echo "You can't use the --all-static link option when using openssl."
- exit 1
- fi
- NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS $openssl_libs"
- else
- AC_MSG_RESULT(no)
- fi
- AC_SUBST(openssl_libs)
- AC_SUBST(openssl_includes)
-])
-
-
-AC_DEFUN(MYSQL_CHECK_MYSQLFS, [
- AC_ARG_WITH([mysqlfs],
- [
- --with-mysqlfs Include the corba-based MySQL file system],
- [mysqlfs="$withval"],
- [mysqlfs=no])
-
-dnl Call MYSQL_CHECK_ORBIT even if mysqlfs == no, so that @orbit_*@
-dnl get substituted.
- MYSQL_CHECK_ORBIT
-
- AC_MSG_CHECKING(if we should build MySQLFS)
- fs_dirs=""
- if test "$mysqlfs" = "yes"
- then
- if test -n "$orbit_exec_prefix"
- then
- fs_dirs=fs
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT(disabled because ORBIT, the CORBA ORB, was not found)
- fi
- else
- AC_MSG_RESULT([no])
- fi
- AC_SUBST([fs_dirs])
-])
-
-AC_DEFUN(MYSQL_CHECK_ORBIT, [
-AC_MSG_CHECKING(for ORBit)
-orbit_config_path=`which orbit-config`
-if test -n "$orbit_config_path" -a $? = 0
-then
- orbit_exec_prefix=`orbit-config --exec-prefix`
- orbit_includes=`orbit-config --cflags server`
- orbit_libs=`orbit-config --libs server`
- orbit_idl="$orbit_exec_prefix/bin/orbit-idl"
- AC_MSG_RESULT(found!)
- AC_DEFINE(HAVE_ORBIT)
-else
- orbit_exec_prefix=
- orbit_includes=
- orbit_libs=
- orbit_idl=
- AC_MSG_RESULT(not found)
-fi
-AC_SUBST(orbit_includes)
-AC_SUBST(orbit_libs)
-AC_SUBST(orbit_idl)
-])
-
-AC_DEFUN([MYSQL_CHECK_ISAM], [
- AC_ARG_WITH([isam], [
- --with-isam Enable the ISAM table type],
- [with_isam="$withval"],
- [with_isam=no])
-
- isam_libs=
- if test X"$with_isam" = X"yes"
- then
- AC_DEFINE(HAVE_ISAM)
- isam_libs="\$(top_builddir)/isam/libnisam.a\
- \$(top_builddir)/merge/libmerge.a"
- fi
- AC_SUBST(isam_libs)
-])
-
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_BDB
-dnl Sets HAVE_BERKELEY_DB if inst library is found
-dnl Makes sure db version is correct.
-dnl Looks in $srcdir for Berkeley distribution if not told otherwise
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_CHECK_BDB], [
- AC_ARG_WITH([berkeley-db],
- [
- --with-berkeley-db[=DIR]
- Use BerkeleyDB located in DIR],
- [bdb="$withval"],
- [bdb=no])
-
- AC_ARG_WITH([berkeley-db-includes],
- [
- --with-berkeley-db-includes=DIR
- Find Berkeley DB headers in DIR],
- [bdb_includes="$withval"],
- [bdb_includes=default])
-
- AC_ARG_WITH([berkeley-db-libs],
- [
- --with-berkeley-db-libs=DIR
- Find Berkeley DB libraries in DIR],
- [bdb_libs="$withval"],
- [bdb_libs=default])
-
- AC_MSG_CHECKING([for BerkeleyDB])
-
-dnl SORT OUT THE SUPPLIED ARGUMENTS TO DETERMINE WHAT TO DO
-dnl echo "DBG1: bdb='$bdb'; incl='$bdb_includes'; lib='$bdb_libs'"
- have_berkeley_db=no
- case "$bdb" in
- no )
- mode=no
- AC_MSG_RESULT([no])
- ;;
- yes | default )
- case "$bdb_includes---$bdb_libs" in
- default---default )
- mode=search-$bdb
- AC_MSG_RESULT([searching...])
- ;;
- default---* | *---default | yes---* | *---yes )
- AC_MSG_ERROR([if either 'includes' or 'libs' is specified, both must be specified])
- ;;
- * )
- mode=supplied-two
- AC_MSG_RESULT([supplied])
- ;;
- esac
- ;;
- * )
- mode=supplied-one
- AC_MSG_RESULT([supplied])
- ;;
- esac
-
-dnl echo "DBG2: [$mode] bdb='$bdb'; incl='$bdb_includes'; lib='$bdb_libs'"
-
- case $mode in
- no )
- bdb_includes=
- bdb_libs=
- bdb_libs_with_path=
- ;;
- supplied-two )
- MYSQL_CHECK_INSTALLED_BDB([$bdb_includes], [$bdb_libs])
- case $bdb_dir_ok in
- installed ) mode=yes ;;
- * ) AC_MSG_ERROR([didn't find valid BerkeleyDB: $bdb_dir_ok]) ;;
- esac
- ;;
- supplied-one )
- MYSQL_CHECK_BDB_DIR([$bdb])
- case $bdb_dir_ok in
- source ) mode=compile ;;
- installed ) mode=yes ;;
- * ) AC_MSG_ERROR([didn't find valid BerkeleyDB: $bdb_dir_ok]) ;;
- esac
- ;;
- search-* )
- MYSQL_SEARCH_FOR_BDB
- case $bdb_dir_ok in
- source ) mode=compile ;;
- installed ) mode=yes ;;
- * )
- # not found
- case $mode in
- *-yes ) AC_MSG_ERROR([no suitable BerkeleyDB found]) ;;
- * ) mode=no ;;
- esac
- bdb_includes=
- bdb_libs=
- bdb_libs_with_path=
- ;;
- esac
- ;;
- *)
- AC_MSG_ERROR([impossible case condition '$mode': please report this to bugs@lists.mysql.com])
- ;;
- esac
-
-dnl echo "DBG3: [$mode] bdb='$bdb'; incl='$bdb_includes'; lib='$bdb_libs'"
- case $mode in
- no )
- AC_MSG_RESULT([Not using Berkeley DB])
- ;;
- yes )
- have_berkeley_db="yes"
- AC_MSG_RESULT([Using Berkeley DB in '$bdb_includes'])
- ;;
- compile )
- have_berkeley_db="$bdb"
- AC_MSG_RESULT([Compiling Berekeley DB in '$have_berkeley_db'])
- ;;
- * )
- AC_MSG_ERROR([impossible case condition '$mode': please report this to bugs@lists.mysql.com])
- ;;
- esac
-
- AC_SUBST(bdb_includes)
- AC_SUBST(bdb_libs)
- AC_SUBST(bdb_libs_with_path)
-])
-
-AC_DEFUN([MYSQL_CHECK_INSTALLED_BDB], [
-dnl echo ["MYSQL_CHECK_INSTALLED_BDB ($1) ($2)"]
- inc="$1"
- lib="$2"
- if test -f "$inc/db.h"
- then
- MYSQL_CHECK_BDB_VERSION([$inc/db.h],
- [.*#define[ ]*], [[ ][ ]*])
-
- if test X"$bdb_version_ok" = Xyes; then
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="-L$lib $LDFLAGS"
- AC_CHECK_LIB(db,db_env_create, [
- bdb_dir_ok=installed
- MYSQL_TOP_BUILDDIR([inc])
- MYSQL_TOP_BUILDDIR([lib])
- bdb_includes="-I$inc"
- bdb_libs="-L$lib -ldb"
- bdb_libs_with_path="$lib/libdb.a"
- ])
- LDFLAGS="$save_LDFLAGS"
- else
- bdb_dir_ok="$bdb_version_ok"
- fi
- else
- bdb_dir_ok="no db.h file in '$inc'"
- fi
-])
-
-AC_DEFUN([MYSQL_CHECK_BDB_DIR], [
-dnl ([$bdb])
-dnl echo ["MYSQL_CHECK_BDB_DIR ($1)"]
- dir="$1"
-
- MYSQL_CHECK_INSTALLED_BDB([$dir/include], [$dir/lib])
-
- if test X"$bdb_dir_ok" != Xinstalled; then
- # test to see if it's a source dir
- rel="$dir/dist/RELEASE"
- if test -f "$rel"; then
- MYSQL_CHECK_BDB_VERSION([$rel], [], [=])
- if test X"$bdb_version_ok" = Xyes; then
- bdb_dir_ok=source
- bdb="$dir"
- MYSQL_TOP_BUILDDIR([dir])
- bdb_includes="-I$dir/build_unix"
- bdb_libs="-L$dir/build_unix -ldb"
- bdb_libs_with_path="$dir/build_unix/libdb.a"
- else
- bdb_dir_ok="$bdb_version_ok"
- fi
- else
- bdb_dir_ok="'$dir' doesn't look like a BDB directory ($bdb_dir_ok)"
- fi
- fi
-])
-
-AC_DEFUN([MYSQL_SEARCH_FOR_BDB], [
-dnl echo ["MYSQL_SEARCH_FOR_BDB"]
- bdb_dir_ok="no BerkeleyDB found"
-
- for test_dir in $srcdir/bdb $srcdir/db-*.*.* /usr/local/BerkeleyDB*; do
-dnl echo "-----------> Looking at ($test_dir; `cd $test_dir && pwd`)"
- MYSQL_CHECK_BDB_DIR([$test_dir])
- if test X"$bdb_dir_ok" = Xsource || test X"$bdb_dir_ok" = Xinstalled; then
-dnl echo "-----------> Found it ($bdb), ($srcdir)"
-dnl This is needed so that 'make distcheck' works properly (VPATH build).
-dnl VPATH build won't work if bdb is not under the source tree; but in
-dnl that case, hopefully people will just make and install inside the
-dnl tree, or install BDB first, and then use the installed version.
- case "$bdb" in
- "$srcdir/"* ) bdb=`echo "$bdb" | sed -e "s,^$srcdir/,,"` ;;
- esac
- break
- fi
- done
-])
-
-dnl MYSQL_CHECK_BDB_VERSION takes 3 arguments:
-dnl 1) the file to look in
-dnl 2) the search pattern before DB_VERSION_XXX
-dnl 3) the search pattern between DB_VERSION_XXX and the number
-dnl It assumes that the number is the last thing on the line
-AC_DEFUN([MYSQL_CHECK_BDB_VERSION], [
- db_major=`sed -e '/^[$2]DB_VERSION_MAJOR[$3]/ !d' -e 's///' [$1]`
- db_minor=`sed -e '/^[$2]DB_VERSION_MINOR[$3]/ !d' -e 's///' [$1]`
- db_patch=`sed -e '/^[$2]DB_VERSION_PATCH[$3]/ !d' -e 's///' [$1]`
- test -z "$db_major" && db_major=0
- test -z "$db_minor" && db_minor=0
- test -z "$db_patch" && db_patch=0
-
- # This is ugly, but about as good as it can get
-# mysql_bdb=
-# if test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 3
-# then
-# mysql_bdb=h
-# elif test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 9
-# then
-# want_bdb_version="3.2.9a" # hopefully this will stay up-to-date
-# mysql_bdb=a
-# fi
-
-dnl RAM:
-want_bdb_version="4.1.24"
-bdb_version_ok=yes
-
-# if test -n "$mysql_bdb" && \
-# grep "DB_VERSION_STRING.*:.*$mysql_bdb: " [$1] > /dev/null
-# then
-# bdb_version_ok=yes
-# else
-# bdb_version_ok="invalid version $db_major.$db_minor.$db_patch"
-# bdb_version_ok="$bdb_version_ok (must be version 3.2.3h or $want_bdb_version)"
-# fi
-])
-
-AC_DEFUN([MYSQL_TOP_BUILDDIR], [
- case "$[$1]" in
- /* ) ;; # don't do anything with an absolute path
- "$srcdir"/* )
- # If BDB is under the source directory, we need to look under the
- # build directory for bdb/build_unix.
- # NOTE: I'm being lazy, and assuming the user did not specify
- # something like --with-berkeley-db=bdb (it would be missing "./").
- [$1]="\$(top_builddir)/"`echo "$[$1]" | sed -e "s,^$srcdir/,,"`
- ;;
- * )
- AC_MSG_ERROR([The BDB directory must be directly under the MySQL source directory, or be specified using the full path. ('$srcdir'; '$[$1]')])
- ;;
- esac
- if test X"$[$1]" != "/"
- then
- [$1]=`echo $[$1] | sed -e 's,/$,,'`
- fi
-])
-
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_BDB SECTION
-dnl ---------------------------------------------------------------------------
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_INNODB
-dnl Sets HAVE_INNOBASE_DB if --with-innodb is used
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_CHECK_INNODB], [
- AC_ARG_WITH([innodb],
- [
- --without-innodb Do not include the InnoDB table handler],
- [innodb="$withval"],
- [innodb=yes])
-
- AC_MSG_CHECKING([for Innodb])
-
- have_innodb=no
- innodb_includes=
- innodb_libs=
- case "$innodb" in
- yes )
- AC_MSG_RESULT([Using Innodb])
- AC_DEFINE(HAVE_INNOBASE_DB)
- have_innodb="yes"
- innodb_includes="-I../innobase/include"
- innodb_system_libs=""
-dnl Some libs are listed several times, in order for gcc to sort out
-dnl circular references.
- innodb_libs="\
- \$(top_builddir)/innobase/usr/libusr.a\
- \$(top_builddir)/innobase/srv/libsrv.a\
- \$(top_builddir)/innobase/dict/libdict.a\
- \$(top_builddir)/innobase/que/libque.a\
- \$(top_builddir)/innobase/srv/libsrv.a\
- \$(top_builddir)/innobase/ibuf/libibuf.a\
- \$(top_builddir)/innobase/row/librow.a\
- \$(top_builddir)/innobase/pars/libpars.a\
- \$(top_builddir)/innobase/btr/libbtr.a\
- \$(top_builddir)/innobase/trx/libtrx.a\
- \$(top_builddir)/innobase/read/libread.a\
- \$(top_builddir)/innobase/usr/libusr.a\
- \$(top_builddir)/innobase/buf/libbuf.a\
- \$(top_builddir)/innobase/ibuf/libibuf.a\
- \$(top_builddir)/innobase/eval/libeval.a\
- \$(top_builddir)/innobase/log/liblog.a\
- \$(top_builddir)/innobase/fsp/libfsp.a\
- \$(top_builddir)/innobase/fut/libfut.a\
- \$(top_builddir)/innobase/fil/libfil.a\
- \$(top_builddir)/innobase/lock/liblock.a\
- \$(top_builddir)/innobase/mtr/libmtr.a\
- \$(top_builddir)/innobase/page/libpage.a\
- \$(top_builddir)/innobase/rem/librem.a\
- \$(top_builddir)/innobase/thr/libthr.a\
- \$(top_builddir)/innobase/sync/libsync.a\
- \$(top_builddir)/innobase/data/libdata.a\
- \$(top_builddir)/innobase/mach/libmach.a\
- \$(top_builddir)/innobase/ha/libha.a\
- \$(top_builddir)/innobase/dyn/libdyn.a\
- \$(top_builddir)/innobase/mem/libmem.a\
- \$(top_builddir)/innobase/sync/libsync.a\
- \$(top_builddir)/innobase/ut/libut.a\
- \$(top_builddir)/innobase/os/libos.a\
- \$(top_builddir)/innobase/ut/libut.a"
-
- AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
- ;;
- * )
- AC_MSG_RESULT([Not using Innodb])
- ;;
- esac
-
- AC_SUBST(innodb_includes)
- AC_SUBST(innodb_libs)
- AC_SUBST(innodb_system_libs)
-])
-
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_INNODB SECTION
-dnl ---------------------------------------------------------------------------
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_NDBCLUSTER
-dnl Sets HAVE_NDBCLUSTER_DB if --with-ndbcluster is used
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [
- AC_ARG_WITH([ndbcluster],
- [
- --without-ndbcluster Do not include the Ndb Cluster table handler],
- [ndbcluster="$withval"],
- [ndbcluster=yes])
-
- AC_MSG_CHECKING([for Ndb Cluster])
-
- have_ndbcluster=no
- ndbcluster_includes=
- ndbcluster_libs=
- case "$ndbcluster" in
- yes )
- AC_MSG_RESULT([Using Ndb Cluster])
- AC_DEFINE(HAVE_NDBCLUSTER_DB)
- have_ndbcluster="yes"
- ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi"
- ndbcluster_libs="\$(top_builddir)/ndb/lib/libNDB_API.a"
- ndbcluster_system_libs=""
- esac
-
- AC_SUBST(ndbcluster_includes)
- AC_SUBST(ndbcluster_libs)
- AC_SUBST(ndbcluster_system_libs)
-])
-
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_NDBCLUSTER SECTION
-dnl ---------------------------------------------------------------------------
-
-dnl By default, many hosts won't let programs access large files;
-dnl one must use special compiler options to get large-file access to work.
-dnl For more details about this brain damage please see:
-dnl http://www.sas.com/standards/large.file/x_open.20Mar96.html
-
-dnl Written by Paul Eggert <eggert@twinsun.com>.
-
-dnl Internal subroutine of AC_SYS_LARGEFILE.
-dnl AC_SYS_LARGEFILE_FLAGS(FLAGSNAME)
-AC_DEFUN(AC_SYS_LARGEFILE_FLAGS,
- [AC_CACHE_CHECK([for $1 value to request large file support],
- ac_cv_sys_largefile_$1,
- [if ($GETCONF LFS_$1) >conftest.1 2>conftest.2 && test ! -s conftest.2
- then
- ac_cv_sys_largefile_$1=`cat conftest.1`
- else
- ac_cv_sys_largefile_$1=no
- ifelse($1, CFLAGS,
- [case "$host_os" in
- # HP-UX 10.20 requires -D__STDC_EXT__ with gcc 2.95.1.
-changequote(, )dnl
- hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
-changequote([, ])dnl
- if test "$GCC" = yes; then
- case `$CC --version 2>/dev/null` in
- 2.95.*) ac_cv_sys_largefile_CFLAGS=-D__STDC_EXT__ ;;
- esac
- fi
- ;;
- # IRIX 6.2 and later require cc -n32.
-changequote(, )dnl
- irix6.[2-9]* | irix6.1[0-9]* | irix[7-9].* | irix[1-9][0-9]*)
-changequote([, ])dnl
- if test "$GCC" != yes; then
- ac_cv_sys_largefile_CFLAGS=-n32
- fi
- esac
- if test "$ac_cv_sys_largefile_CFLAGS" != no; then
- ac_save_CC="$CC"
- CC="$CC $ac_cv_sys_largefile_CFLAGS"
- AC_TRY_LINK(, , , ac_cv_sys_largefile_CFLAGS=no)
- CC="$ac_save_CC"
- fi])
- fi
- rm -f conftest*])])
-
-dnl Internal subroutine of AC_SYS_LARGEFILE.
-dnl AC_SYS_LARGEFILE_SPACE_APPEND(VAR, VAL)
-AC_DEFUN(AC_SYS_LARGEFILE_SPACE_APPEND,
- [case $2 in
- no) ;;
- ?*)
- case "[$]$1" in
- '') $1=$2 ;;
- *) $1=[$]$1' '$2 ;;
- esac ;;
- esac])
-
-dnl Internal subroutine of AC_SYS_LARGEFILE.
-dnl AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, CACHE-VAR, COMMENT, CODE-TO-SET-DEFAULT)
-AC_DEFUN(AC_SYS_LARGEFILE_MACRO_VALUE,
- [AC_CACHE_CHECK([for $1], $2,
- [$2=no
-changequote(, )dnl
- for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
- case "$ac_flag" in
- -D$1)
- $2=1 ;;
- -D$1=*)
- $2=`expr " $ac_flag" : '[^=]*=\(.*\)'` ;;
- esac
- done
- $4
-changequote([, ])dnl
- ])
- if test "[$]$2" != no; then
- AC_DEFINE_UNQUOTED([$1], [$]$2, [$3])
- fi])
-
-AC_DEFUN(MYSQL_SYS_LARGEFILE,
- [AC_REQUIRE([AC_CANONICAL_HOST])
- AC_ARG_ENABLE(largefile,
- [ --disable-largefile Omit support for large files])
- if test "$enable_largefile" != no; then
- AC_CHECK_TOOL(GETCONF, getconf)
- AC_SYS_LARGEFILE_FLAGS(CFLAGS)
- AC_SYS_LARGEFILE_FLAGS(LDFLAGS)
- AC_SYS_LARGEFILE_FLAGS(LIBS)
-
- for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
- case "$ac_flag" in
- no) ;;
- -D_FILE_OFFSET_BITS=*) ;;
- -D_LARGEFILE_SOURCE | -D_LARGEFILE_SOURCE=*) ;;
- -D_LARGE_FILES | -D_LARGE_FILES=*) ;;
- -D?* | -I?*)
- AC_SYS_LARGEFILE_SPACE_APPEND(CPPFLAGS, "$ac_flag") ;;
- *)
- AC_SYS_LARGEFILE_SPACE_APPEND(CFLAGS, "$ac_flag") ;;
- esac
- done
- AC_SYS_LARGEFILE_SPACE_APPEND(LDFLAGS, "$ac_cv_sys_largefile_LDFLAGS")
- AC_SYS_LARGEFILE_SPACE_APPEND(LIBS, "$ac_cv_sys_largefile_LIBS")
-
- AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS,
- ac_cv_sys_file_offset_bits,
- [Number of bits in a file offset, on hosts where this is settable.],
- [case "$host_os" in
- # HP-UX 10.20 and later
- hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
- ac_cv_sys_file_offset_bits=64 ;;
- # We can't declare _FILE_OFFSET_BITS here as this will cause
- # compile errors as AC_PROG_CC adds include files in confdefs.h
- # We solve this (until autoconf is fixed) by instead declaring it
- # as define instead
- solaris2.[8,9])
- CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64"
- CXXFLAGS="$CXXFLAGS -D_FILE_OFFSET_BITS=64"
- ac_cv_sys_file_offset_bits=no ;;
- esac])
- AC_SYS_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE,
- ac_cv_sys_largefile_source,
- [Define to make fseeko etc. visible, on some hosts.],
- [case "$host_os" in
- # HP-UX 10.20 and later
- hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
- ac_cv_sys_largefile_source=1 ;;
- esac])
- AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES,
- ac_cv_sys_large_files,
- [Define for large files, on AIX-style hosts.],
- [case "$host_os" in
- # AIX 4.2 and later
- aix4.[2-9]* | aix4.1[0-9]* | aix[5-9].* | aix[1-9][0-9]*)
- ac_cv_sys_large_files=1 ;;
- esac])
- fi
- ])
-
-
-# Local version of _AC_PROG_CXX_EXIT_DECLARATION that does not
-# include #stdlib.h as default as this breaks things on Solaris
-# (Conflicts with pthreads and big file handling)
-
-m4_define([_AC_PROG_CXX_EXIT_DECLARATION],
-[for ac_declaration in \
- ''\
- 'extern "C" void std::exit (int) throw (); using std::exit;' \
- 'extern "C" void std::exit (int); using std::exit;' \
- 'extern "C" void exit (int) throw ();' \
- 'extern "C" void exit (int);' \
- 'void exit (int);' \
- '#include <stdlib.h>'
-do
- _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include <stdlib.h>
-$ac_declaration],
- [exit (42);])],
- [],
- [continue])
- _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_declaration],
- [exit (42);])],
- [break])
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
- echo '#ifdef __cplusplus' >>confdefs.h
- echo $ac_declaration >>confdefs.h
- echo '#endif' >>confdefs.h
-fi
-])# _AC_PROG_CXX_EXIT_DECLARATION
-
-dnl ---------------------------------------------------------------------------
-
diff --git a/ndb/config/common.mk.am b/ndb/config/common.mk.am
new file mode 100644
index 00000000000..869e2fae91d
--- /dev/null
+++ b/ndb/config/common.mk.am
@@ -0,0 +1,12 @@
+ndbbindir = "$(libexecdir)"
+ndbtoolsdir = "$(bindir)"
+ndbtestdir = "$(bindir)"
+ndblibdir = "$(pkglibdir)"
+ndbincludedir = "$(pkgincludedir)/ndb"
+ndbapiincludedir = "$(pkgincludedir)/ndb/ndbapi"
+mgmapiincludedir = "$(pkgincludedir)/ndb/mgmapi"
+
+INCLUDES = $(INCLUDES_LOC)
+LDADD = $(top_srcdir)/ndb/src/common/portlib/gcc.cpp $(LDADD_LOC)
+DEFS = @DEFS@ @NDB_DEFS@ $(DEFS_LOC) $(NDB_EXTRA_FLAGS)
+NDB_CXXFLAGS=@ndb_cxxflags_fix@ $(NDB_CXXFLAGS_LOC)
diff --git a/ndb/config/config.h.in b/ndb/config/config.h.in
deleted file mode 100644
index 82749d5ece6..00000000000
--- a/ndb/config/config.h.in
+++ /dev/null
@@ -1,993 +0,0 @@
-/* config.h.in. Generated from configure.in by autoheader. */
-/* acconfig.h
- This file is in the public domain.
-
- Descriptive text for the C preprocessor macros that
- the distributed Autoconf macros can define.
- No software package will use all of them; autoheader copies the ones
- your configure.in uses into your configuration header file templates.
-
- The entries are in sort -df order: alphabetical, case insensitive,
- ignoring punctuation (such as underscores). Although this order
- can split up related entries, it makes it easier to check whether
- a given entry is in the file.
-
- Leave the following blank line there!! Autoheader needs it. */
-
-
-#undef C_ALLOCA
-
-#undef CRAY_STACKSEG_END
-
-/* Define the default charset name */
-#undef MYSQL_DEFAULT_CHARSET_NAME
-
-/* Define the default charset name */
-#undef MYSQL_DEFAULT_COLLATION_NAME
-
-/* Version of .frm files */
-#undef DOT_FRM_VERSION
-
-/* If LOAD DATA LOCAL INFILE should be enabled by default */
-#undef ENABLED_LOCAL_INFILE
-
-/* READLINE: */
-#undef FIONREAD_IN_SYS_IOCTL
-
-/* READLINE: Define if your system defines TIOCGWINSZ in sys/ioctl.h. */
-#undef GWINSZ_IN_SYS_IOCTL
-
-/* Handing of large files on Solaris 2.6 */
-#undef _FILE_OFFSET_BITS
-
-/* Do we have FIONREAD */
-#undef FIONREAD_IN_SYS_IOCTL
-
-/* Do we need to define _GNU_SOURCE */
-#undef _GNU_SOURCE
-
-/* atomic_add() from <asm/atomic.h> (Linux only) */
-#undef HAVE_ATOMIC_ADD
-
-/* atomic_sub() from <asm/atomic.h> (Linux only) */
-#undef HAVE_ATOMIC_SUB
-
-/* If we have a working alloca() implementation */
-#undef HAVE_ALLOCA
-
-/* bool is not defined by all C++ compilators */
-#undef HAVE_BOOL
-
-/* Have berkeley db installed */
-#undef HAVE_BERKELEY_DB
-
-/* DSB style signals ? */
-#undef HAVE_BSD_SIGNALS
-
-/* Can netinet be included */
-#undef HAVE_BROKEN_NETINET_INCLUDES
-
-/* READLINE: */
-#undef HAVE_BSD_SIGNALS
-
-/* Define charsets you want */
-#undef HAVE_CHARSET_armscii8
-#undef HAVE_CHARSET_ascii
-#undef HAVE_CHARSET_big5
-#undef HAVE_CHARSET_cp1250
-#undef HAVE_CHARSET_cp1251
-#undef HAVE_CHARSET_cp1256
-#undef HAVE_CHARSET_cp1257
-#undef HAVE_CHARSET_cp850
-#undef HAVE_CHARSET_cp852
-#undef HAVE_CHARSET_cp866
-#undef HAVE_CHARSET_dec8
-#undef HAVE_CHARSET_euckr
-#undef HAVE_CHARSET_gb2312
-#undef HAVE_CHARSET_gbk
-#undef HAVE_CHARSET_greek
-#undef HAVE_CHARSET_hebrew
-#undef HAVE_CHARSET_hp8
-#undef HAVE_CHARSET_keybcs2
-#undef HAVE_CHARSET_koi8r
-#undef HAVE_CHARSET_koi8u
-#undef HAVE_CHARSET_latin1
-#undef HAVE_CHARSET_latin2
-#undef HAVE_CHARSET_latin5
-#undef HAVE_CHARSET_latin7
-#undef HAVE_CHARSET_macce
-#undef HAVE_CHARSET_macroman
-#undef HAVE_CHARSET_sjis
-#undef HAVE_CHARSET_swe7
-#undef HAVE_CHARSET_tis620
-#undef HAVE_CHARSET_ucs2
-#undef HAVE_CHARSET_ujis
-#undef HAVE_CHARSET_utf8
-
-/* ZLIB and compress: */
-#undef HAVE_COMPRESS
-
-/* Define if we are using OSF1 DEC threads */
-#undef HAVE_DEC_THREADS
-
-/* Define if we are using OSF1 DEC threads on 3.2 */
-#undef HAVE_DEC_3_2_THREADS
-
-/* fp_except from ieeefp.h */
-#undef HAVE_FP_EXCEPT
-
-/* READLINE: */
-#undef HAVE_GETPW_DECLS
-
-/* Solaris define gethostbyname_r with 5 arguments. glibc2 defines
- this with 6 arguments */
-#undef HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE
-
-/* In OSF 4.0f the 3'd argument to gethostname_r is hostent_data * */
-#undef HAVE_GETHOSTBYNAME_R_RETURN_INT
-
-/* Define if int8, int16 and int32 types exist */
-#undef HAVE_INT_8_16_32
-
-/* Using Innobase DB */
-#undef HAVE_INNOBASE_DB
-
-/* Using old ISAM tables */
-#undef HAVE_ISAM
-
-/* Define if we have GNU readline */
-#undef HAVE_LIBREADLINE
-
-/* Define if have -lwrap */
-#undef HAVE_LIBWRAP
-
-/* Define if we are using Xavier Leroy's LinuxThreads */
-#undef HAVE_LINUXTHREADS
-
-/* Do we have lstat */
-#undef HAVE_LSTAT
-
-/* Do we use user level threads */
-#undef HAVE_mit_thread
-
-/* Using Ndb Cluster DB */
-#undef HAVE_NDBCLUSTER_DB
-
-/* For some non posix threads */
-#undef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC
-
-/* For some non posix threads */
-#undef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT
-
-/* READLINE: */
-#undef HAVE_POSIX_SIGNALS
-
-/* Well.. */
-#undef HAVE_POSIX_SIGSETJMP
-
-/* sigwait with one argument */
-#undef HAVE_NONPOSIX_SIGWAIT
-
-/* ORBIT */
-#undef HAVE_ORBIT
-
-/* pthread_attr_setscope */
-#undef HAVE_PTHREAD_ATTR_SETSCOPE
-
-/* pthread_yield that doesn't take any arguments */
-#undef HAVE_PTHREAD_YIELD_ZERO_ARG
-
-/* pthread_yield function with one argument */
-#undef HAVE_PTHREAD_YIELD_ONE_ARG
-
-/* POSIX readdir_r */
-#undef HAVE_READDIR_R
-
-/* Have Gemini db installed */
-#undef HAVE_GEMINI_DB
-
-/* POSIX sigwait */
-#undef HAVE_SIGWAIT
-
-/* crypt */
-#undef HAVE_CRYPT
-
-/* If we want to have query cache */
-#undef HAVE_QUERY_CACHE
-
-/* Solaris define gethostbyaddr_r with 7 arguments. glibc2 defines
- this with 8 arguments */
-#undef HAVE_SOLARIS_STYLE_GETHOST
-
-/* MIT pthreads does not support connecting with unix sockets */
-#undef HAVE_THREADS_WITHOUT_SOCKETS
-
-/* Timespec has a ts_sec instead of tv_sev */
-#undef HAVE_TIMESPEC_TS_SEC
-
-/* Have the tzname variable */
-#undef HAVE_TZNAME
-
-/* Define if the system files define uchar */
-#undef HAVE_UCHAR
-
-/* Define if the system files define uint */
-#undef HAVE_UINT
-
-/* Define if the system files define ulong */
-#undef HAVE_ULONG
-
-/* Define if the system files define in_addr_t */
-#undef HAVE_IN_ADDR_T
-
-/* UNIXWARE7 threads are not posix */
-#undef HAVE_UNIXWARE7_THREADS
-
-/* new UNIXWARE7 threads that are not yet posix */
-#undef HAVE_UNIXWARE7_POSIX
-
-/* OpenSSL */
-#undef HAVE_OPENSSL
-
-/* READLINE: */
-#undef HAVE_USG_SIGHOLD
-
-/* Virtual IO */
-#undef HAVE_VIO
-
-/* Handling of large files on Solaris 2.6 */
-#undef _LARGEFILE_SOURCE
-
-/* Handling of large files on Solaris 2.6 */
-#undef _LARGEFILE64_SOURCE
-
-/* Define if want -lwrap */
-#undef LIBWRAP
-
-/* Define to machine type name eg sun10 */
-#undef MACHINE_TYPE
-
-#undef MUST_REINSTALL_SIGHANDLERS
-
-/* Defined to used character set */
-#undef MY_CHARSET_CURRENT
-
-/* READLINE: no sys file*/
-#undef NO_SYS_FILE
-
-/* Program name */
-#undef PACKAGE
-
-/* mysql client protocoll version */
-#undef PROTOCOL_VERSION
-
-/* Define if qsort returns void */
-#undef QSORT_TYPE_IS_VOID
-
-/* Define as the return type of qsort (int or void). */
-#undef RETQSORTTYPE
-
-/* Size of off_t */
-#undef SIZEOF_OFF_T
-
-/* Define as the base type of the last arg to accept */
-#undef SOCKET_SIZE_TYPE
-
-/* Last argument to get/setsockopt */
-#undef SOCKOPT_OPTLEN_TYPE
-
-#undef SPEED_T_IN_SYS_TYPES
-#undef SPRINTF_RETURNS_PTR
-#undef SPRINTF_RETURNS_INT
-#undef SPRINTF_RETURNS_GARBAGE
-
-/* Needed to get large file support on HPUX 10.20 */
-#undef __STDC_EXT__
-
-#undef STACK_DIRECTION
-
-#undef STRCOLL_BROKEN
-
-#undef STRUCT_DIRENT_HAS_D_FILENO
-#undef STRUCT_DIRENT_HAS_D_INO
-
-#undef STRUCT_WINSIZE_IN_SYS_IOCTL
-#undef STRUCT_WINSIZE_IN_TERMIOS
-
-/* Define to name of system eg solaris*/
-#undef SYSTEM_TYPE
-
-/* Define if you want to have threaded code. This may be undef on client code */
-#undef THREAD
-
-/* Should be client be thread safe */
-#undef THREAD_SAFE_CLIENT
-
-/* READLINE: */
-#undef TIOCSTAT_IN_SYS_IOCTL
-
-/* Use multi-byte character routines */
-#undef USE_MB
-#undef USE_MB_IDENT
-
-/* the pstack backtrace library */
-#undef USE_PSTACK
-
-/* Use MySQL RAID */
-#undef USE_RAID
-
-/* Program version */
-#undef VERSION
-
-/* READLINE: */
-#undef VOID_SIGHANDLER
-
-/* used libedit interface (can we dereference result of rl_completion_entry_function?) */
-#undef USE_LIBEDIT_INTERFACE
-
-/* used new readline interface (does rl_completion_func_t and rl_compentry_func_t defined?) */
-#undef USE_NEW_READLINE_INTERFACE
-
-/* macro for libedit */
-#undef HAVE_VIS_H
-#undef HAVE_FGETLN
-#undef HAVE_ISSETUGID
-#undef HAVE_STRLCPY
-#undef HAVE_GETLINE
-#undef HAVE_FLOCKFILE
-#undef HAVE_SYS_TYPES_H
-#undef HAVE_SYS_CDEFS_H
-
-
-/* Leave that blank line there!! Autoheader needs it.
- If you're adding to this file, keep in mind:
- The entries are in sort -df order: alphabetical, case insensitive,
- ignoring punctuation (such as underscores). */
-
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
- systems. This function is required for `alloca.c' support on those systems.
- */
-#undef CRAY_STACKSEG_END
-
-/* Define to 1 if using `alloca.c'. */
-#undef C_ALLOCA
-
-/* Define to 1 if you have the `alarm' function. */
-#undef HAVE_ALARM
-
-/* Define to 1 if you have `alloca', as a function or macro. */
-#undef HAVE_ALLOCA
-
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
- */
-#undef HAVE_ALLOCA_H
-
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-#undef HAVE_ARPA_INET_H
-
-/* Define to 1 if you have the <asm/termbits.h> header file. */
-#undef HAVE_ASM_TERMBITS_H
-
-/* Define to 1 if you have the `bcmp' function. */
-#undef HAVE_BCMP
-
-/* Define to 1 if you have the `bfill' function. */
-#undef HAVE_BFILL
-
-/* Define to 1 if you have the `bmove' function. */
-#undef HAVE_BMOVE
-
-/* Define to 1 if you have the `bzero' function. */
-#undef HAVE_BZERO
-
-/* Define to 1 if you have the `chsize' function. */
-#undef HAVE_CHSIZE
-
-/* Define to 1 if you have the `clock_gettime' function. */
-#undef HAVE_CLOCK_GETTIME
-
-/* Define to 1 if you have the <crypt.h> header file. */
-#undef HAVE_CRYPT_H
-
-/* Define to 1 if you have the <curses.h> header file. */
-#undef HAVE_CURSES_H
-
-/* Define to 1 if you have the `cuserid' function. */
-#undef HAVE_CUSERID
-
-/* Define to 1 if you have the <dirent.h> header file. */
-#undef HAVE_DIRENT_H
-
-/* Define to 1 if you have the `dlerror' function. */
-#undef HAVE_DLERROR
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if you have the `dlopen' function. */
-#undef HAVE_DLOPEN
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-#undef HAVE_DOPRNT
-
-/* Define to 1 if you have the `fchmod' function. */
-#undef HAVE_FCHMOD
-
-/* Define to 1 if you have the `fcntl' function. */
-#undef HAVE_FCNTL
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
-/* Define to 1 if you have the `fconvert' function. */
-#undef HAVE_FCONVERT
-
-/* Define to 1 if you have the `fdatasync' function. */
-#undef HAVE_FDATASYNC
-
-/* Define to 1 if you have the `fgetln' function. */
-#undef HAVE_FGETLN
-
-/* Define to 1 if you have the `finite' function. */
-#undef HAVE_FINITE
-
-/* Define to 1 if you have the <floatingpoint.h> header file. */
-#undef HAVE_FLOATINGPOINT_H
-
-/* Define to 1 if you have the <float.h> header file. */
-#undef HAVE_FLOAT_H
-
-/* Define to 1 if you have the `flockfile' function. */
-#undef HAVE_FLOCKFILE
-
-/* Define to 1 if you have the `fpresetsticky' function. */
-#undef HAVE_FPRESETSTICKY
-
-/* Define to 1 if you have the `fpsetmask' function. */
-#undef HAVE_FPSETMASK
-
-/* Define to 1 if you have the `fsync' function. */
-#undef HAVE_FSYNC
-
-/* Define to 1 if you have the `ftruncate' function. */
-#undef HAVE_FTRUNCATE
-
-/* Define to 1 if you have the `getcwd' function. */
-#undef HAVE_GETCWD
-
-/* Define to 1 if you have the `gethostbyaddr_r' function. */
-#undef HAVE_GETHOSTBYADDR_R
-
-/* Define to 1 if you have the `gethostbyname_r' function. */
-#undef HAVE_GETHOSTBYNAME_R
-
-/* Define to 1 if you have the `getline' function. */
-#undef HAVE_GETLINE
-
-/* Define to 1 if you have the `getpagesize' function. */
-#undef HAVE_GETPAGESIZE
-
-/* Define to 1 if you have the `getpass' function. */
-#undef HAVE_GETPASS
-
-/* Define to 1 if you have the `getpassphrase' function. */
-#undef HAVE_GETPASSPHRASE
-
-/* Define to 1 if you have the `getpwnam' function. */
-#undef HAVE_GETPWNAM
-
-/* Define to 1 if you have the `getpwuid' function. */
-#undef HAVE_GETPWUID
-
-/* Define to 1 if you have the `getrlimit' function. */
-#undef HAVE_GETRLIMIT
-
-/* Define to 1 if you have the `getrusage' function. */
-#undef HAVE_GETRUSAGE
-
-/* Define to 1 if you have the `getwd' function. */
-#undef HAVE_GETWD
-
-/* Define to 1 if you have the `gmtime_r' function. */
-#undef HAVE_GMTIME_R
-
-/* Define to 1 if you have the <grp.h> header file. */
-#undef HAVE_GRP_H
-
-/* Define to 1 if you have the <ieeefp.h> header file. */
-#undef HAVE_IEEEFP_H
-
-/* Define to 1 if you have the `index' function. */
-#undef HAVE_INDEX
-
-/* Define to 1 if you have the `initgroups' function. */
-#undef HAVE_INITGROUPS
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* isinf() macro or function */
-#undef HAVE_ISINF
-
-/* Define to 1 if you have the `isnan' function. */
-#undef HAVE_ISNAN
-
-/* Define to 1 if you have the `issetugid' function. */
-#undef HAVE_ISSETUGID
-
-/* Define to 1 if you have the `bind' library (-lbind). */
-#undef HAVE_LIBBIND
-
-/* Define to 1 if you have the `compat' library (-lcompat). */
-#undef HAVE_LIBCOMPAT
-
-/* Define to 1 if you have the `crypt' library (-lcrypt). */
-#undef HAVE_LIBCRYPT
-
-/* Define to 1 if you have the `c_r' library (-lc_r). */
-#undef HAVE_LIBC_R
-
-/* Define to 1 if you have the `dl' library (-ldl). */
-#undef HAVE_LIBDL
-
-/* Define to 1 if you have the `gen' library (-lgen). */
-#undef HAVE_LIBGEN
-
-/* Define to 1 if you have the `m' library (-lm). */
-#undef HAVE_LIBM
-
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-#undef HAVE_LIBNSL
-
-/* Define to 1 if you have the `nsl_r' library (-lnsl_r). */
-#undef HAVE_LIBNSL_R
-
-/* Define to 1 if you have the `posix4' library (-lposix4). */
-#undef HAVE_LIBPOSIX4
-
-/* Define to 1 if you have the `pthread' library (-lpthread). */
-#undef HAVE_LIBPTHREAD
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-#undef HAVE_LIBSOCKET
-
-/* Define to 1 if you have the <limits.h> header file. */
-#undef HAVE_LIMITS_H
-
-/* Define to 1 if you have the <linux/config.h> header file. */
-#undef HAVE_LINUX_CONFIG_H
-
-/* Define to 1 if you have the <locale.h> header file. */
-#undef HAVE_LOCALE_H
-
-/* Define to 1 if you have the `localtime_r' function. */
-#undef HAVE_LOCALTIME_R
-
-/* Define to 1 if you have the `locking' function. */
-#undef HAVE_LOCKING
-
-/* Define to 1 if you have the `longjmp' function. */
-#undef HAVE_LONGJMP
-
-/* Define to 1 if you have the `lrand48' function. */
-#undef HAVE_LRAND48
-
-/* Define to 1 if you have the `lstat' function. */
-#undef HAVE_LSTAT
-
-/* Define to 1 if you have the `madvise' function. */
-#undef HAVE_MADVISE
-
-/* Define to 1 if you have the `mallinfo' function. */
-#undef HAVE_MALLINFO
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#undef HAVE_MALLOC_H
-
-/* Define to 1 if you have the `memcpy' function. */
-#undef HAVE_MEMCPY
-
-/* Define to 1 if you have the `memmove' function. */
-#undef HAVE_MEMMOVE
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the `mkstemp' function. */
-#undef HAVE_MKSTEMP
-
-/* Define to 1 if you have the `mlockall' function. */
-#undef HAVE_MLOCKALL
-
-/* Define to 1 if you have a working `mmap' system call. */
-#undef HAVE_MMAP
-
-/* Define to 1 if you have the <ndir.h> header file. */
-#undef HAVE_NDIR_H
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#undef HAVE_NETINET_IN_H
-
-/* Define to 1 if you have the <paths.h> header file. */
-#undef HAVE_PATHS_H
-
-/* Define to 1 if you have the `perror' function. */
-#undef HAVE_PERROR
-
-/* Define to 1 if you have the `poll' function. */
-#undef HAVE_POLL
-
-/* Define to 1 if you have the `pread' function. */
-#undef HAVE_PREAD
-
-/* Define to 1 if you have the `pthread_attr_create' function. */
-#undef HAVE_PTHREAD_ATTR_CREATE
-
-/* Define to 1 if you have the `pthread_attr_getstacksize' function. */
-#undef HAVE_PTHREAD_ATTR_GETSTACKSIZE
-
-/* Define to 1 if you have the `pthread_attr_setprio' function. */
-#undef HAVE_PTHREAD_ATTR_SETPRIO
-
-/* Define to 1 if you have the `pthread_attr_setschedparam' function. */
-#undef HAVE_PTHREAD_ATTR_SETSCHEDPARAM
-
-/* Define to 1 if you have the `pthread_attr_setstacksize' function. */
-#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE
-
-/* Define to 1 if you have the `pthread_condattr_create' function. */
-#undef HAVE_PTHREAD_CONDATTR_CREATE
-
-/* Define to 1 if you have the `pthread_getsequence_np' function. */
-#undef HAVE_PTHREAD_GETSEQUENCE_NP
-
-/* Define to 1 if you have the `pthread_init' function. */
-#undef HAVE_PTHREAD_INIT
-
-/* Define to 1 if you have the `pthread_key_delete' function. */
-#undef HAVE_PTHREAD_KEY_DELETE
-
-/* Define to 1 if you have the `pthread_rwlock_rdlock' function. */
-#undef HAVE_PTHREAD_RWLOCK_RDLOCK
-
-/* Define to 1 if you have the `pthread_setprio' function. */
-#undef HAVE_PTHREAD_SETPRIO
-
-/* Define to 1 if you have the `pthread_setprio_np' function. */
-#undef HAVE_PTHREAD_SETPRIO_NP
-
-/* Define to 1 if you have the `pthread_setschedparam' function. */
-#undef HAVE_PTHREAD_SETSCHEDPARAM
-
-/* Define to 1 if you have the `pthread_sigmask' function. */
-#undef HAVE_PTHREAD_SIGMASK
-
-/* Define to 1 if you have the `putenv' function. */
-#undef HAVE_PUTENV
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#undef HAVE_PWD_H
-
-/* Define to 1 if you have the `readlink' function. */
-#undef HAVE_READLINK
-
-/* Define to 1 if you have the `realpath' function. */
-#undef HAVE_REALPATH
-
-/* Define to 1 if you have the `regcomp' function. */
-#undef HAVE_REGCOMP
-
-/* Define to 1 if you have the `rename' function. */
-#undef HAVE_RENAME
-
-/* Define to 1 if system calls automatically restart after interruption by a
- signal. */
-#undef HAVE_RESTARTABLE_SYSCALLS
-
-/* Define to 1 if you have the `re_comp' function. */
-#undef HAVE_RE_COMP
-
-/* Define to 1 if you have the `rint' function. */
-#undef HAVE_RINT
-
-/* Define to 1 if you have the `rwlock_init' function. */
-#undef HAVE_RWLOCK_INIT
-
-/* Define to 1 if you have the <sched.h> header file. */
-#undef HAVE_SCHED_H
-
-/* Define to 1 if you have the `select' function. */
-#undef HAVE_SELECT
-
-/* Define to 1 if you have the <select.h> header file. */
-#undef HAVE_SELECT_H
-
-/* Define to 1 if you have the <semaphore.h> header file. */
-#undef HAVE_SEMAPHORE_H
-
-/* Define to 1 if you have the `setenv' function. */
-#undef HAVE_SETENV
-
-/* Define to 1 if you have the `setlocale' function. */
-#undef HAVE_SETLOCALE
-
-/* Define to 1 if you have the `setupterm' function. */
-#undef HAVE_SETUPTERM
-
-/* Define to 1 if you have the `sighold' function. */
-#undef HAVE_SIGHOLD
-
-/* Define to 1 if you have the `sigset' function. */
-#undef HAVE_SIGSET
-
-/* Define to 1 if you have the `sigthreadmask' function. */
-#undef HAVE_SIGTHREADMASK
-
-/* Define to 1 if you have the `snprintf' function. */
-#undef HAVE_SNPRINTF
-
-/* Define to 1 if you have the `socket' function. */
-#undef HAVE_SOCKET
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#undef HAVE_STDARG_H
-
-/* Define to 1 if you have the <stddef.h> header file. */
-#undef HAVE_STDDEF_H
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the `stpcpy' function. */
-#undef HAVE_STPCPY
-
-/* Define to 1 if you have the `strcasecmp' function. */
-#undef HAVE_STRCASECMP
-
-/* Define to 1 if you have the `strcoll' function. */
-#undef HAVE_STRCOLL
-
-/* Define to 1 if you have the `strdup' function. */
-#undef HAVE_STRDUP
-
-/* Define to 1 if you have the `strerror' function. */
-#undef HAVE_STRERROR
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strlcat' function. */
-#undef HAVE_STRLCAT
-
-/* Define to 1 if you have the `strlcpy' function. */
-#undef HAVE_STRLCPY
-
-/* Define to 1 if you have the `strnlen' function. */
-#undef HAVE_STRNLEN
-
-/* Define to 1 if you have the `strpbrk' function. */
-#undef HAVE_STRPBRK
-
-/* Define to 1 if you have the `strstr' function. */
-#undef HAVE_STRSTR
-
-/* Define to 1 if you have the `strtok_r' function. */
-#undef HAVE_STRTOK_R
-
-/* Define to 1 if you have the `strtol' function. */
-#undef HAVE_STRTOL
-
-/* Define to 1 if you have the `strtoll' function. */
-#undef HAVE_STRTOLL
-
-/* Define to 1 if you have the `strtoul' function. */
-#undef HAVE_STRTOUL
-
-/* Define to 1 if you have the `strtoull' function. */
-#undef HAVE_STRTOULL
-
-/* Define to 1 if `st_rdev' is member of `struct stat'. */
-#undef HAVE_STRUCT_STAT_ST_RDEV
-
-/* Define to 1 if your `struct stat' has `st_rdev'. Deprecated, use
- `HAVE_STRUCT_STAT_ST_RDEV' instead. */
-#undef HAVE_ST_RDEV
-
-/* Define to 1 if you have the <synch.h> header file. */
-#undef HAVE_SYNCH_H
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#undef HAVE_SYS_CDEFS_H
-
-/* Define to 1 if you have the <sys/dir.h> header file. */
-#undef HAVE_SYS_DIR_H
-
-/* Define to 1 if you have the <sys/file.h> header file. */
-#undef HAVE_SYS_FILE_H
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#undef HAVE_SYS_IOCTL_H
-
-/* Define to 1 if you have the <sys/malloc.h> header file. */
-#undef HAVE_SYS_MALLOC_H
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#undef HAVE_SYS_MMAN_H
-
-/* Define to 1 if you have the <sys/ndir.h> header file. */
-#undef HAVE_SYS_NDIR_H
-
-/* Define to 1 if you have the <sys/ptem.h> header file. */
-#undef HAVE_SYS_PTEM_H
-
-/* Define to 1 if you have the <sys/pte.h> header file. */
-#undef HAVE_SYS_PTE_H
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#undef HAVE_SYS_SELECT_H
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#undef HAVE_SYS_SOCKET_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/stream.h> header file. */
-#undef HAVE_SYS_STREAM_H
-
-/* Define to 1 if you have the <sys/timeb.h> header file. */
-#undef HAVE_SYS_TIMEB_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <sys/un.h> header file. */
-#undef HAVE_SYS_UN_H
-
-/* Define to 1 if you have the <sys/utime.h> header file. */
-#undef HAVE_SYS_UTIME_H
-
-/* Define to 1 if you have the <sys/vadvise.h> header file. */
-#undef HAVE_SYS_VADVISE_H
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#undef HAVE_SYS_WAIT_H
-
-/* Define to 1 if you have the `tcgetattr' function. */
-#undef HAVE_TCGETATTR
-
-/* Define to 1 if you have the `tell' function. */
-#undef HAVE_TELL
-
-/* Define to 1 if you have the `tempnam' function. */
-#undef HAVE_TEMPNAM
-
-/* Define to 1 if you have the <termbits.h> header file. */
-#undef HAVE_TERMBITS_H
-
-/* Define to 1 if you have the <termcap.h> header file. */
-#undef HAVE_TERMCAP_H
-
-/* Define to 1 if you have the <termios.h> header file. */
-#undef HAVE_TERMIOS_H
-
-/* Define to 1 if you have the <termio.h> header file. */
-#undef HAVE_TERMIO_H
-
-/* Define to 1 if you have the <term.h> header file. */
-#undef HAVE_TERM_H
-
-/* Define to 1 if you have the `thr_setconcurrency' function. */
-#undef HAVE_THR_SETCONCURRENCY
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the <utime.h> header file. */
-#undef HAVE_UTIME_H
-
-/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
-#undef HAVE_UTIME_NULL
-
-/* Define to 1 if you have the <varargs.h> header file. */
-#undef HAVE_VARARGS_H
-
-/* Define to 1 if you have the `vidattr' function. */
-#undef HAVE_VIDATTR
-
-/* Define to 1 if you have the <vis.h> header file. */
-#undef HAVE_VIS_H
-
-/* Define to 1 if you have the `vprintf' function. */
-#undef HAVE_VPRINTF
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#undef RETSIGTYPE
-
-/* The size of a `char', as computed by sizeof. */
-#undef SIZEOF_CHAR
-
-/* The size of a `char*', as computed by sizeof. */
-#undef SIZEOF_CHARP
-
-/* The size of a `int', as computed by sizeof. */
-#undef SIZEOF_INT
-
-/* The size of a `long', as computed by sizeof. */
-#undef SIZEOF_LONG
-
-/* The size of a `long long', as computed by sizeof. */
-#undef SIZEOF_LONG_LONG
-
-/* If using the C implementation of alloca, define if you know the
- direction of stack growth for your system; otherwise it will be
- automatically deduced at run-time.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
-#undef STACK_DIRECTION
-
-/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
-#undef STAT_MACROS_BROKEN
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#undef TIME_WITH_SYS_TIME
-
-/* Define to 1 if your <sys/time.h> declares `struct tm'. */
-#undef TM_IN_SYS_TIME
-
-/* Version number of package */
-#undef VERSION
-
-/* Define to 1 if your processor stores words with the most significant byte
- first (like Motorola and SPARC, unlike Intel and VAX). */
-#undef WORDS_BIGENDIAN
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
-
-/* Define to make fseeko etc. visible, on some hosts. */
-#undef _LARGEFILE_SOURCE
-
-/* Define for large files, on AIX-style hosts. */
-#undef _LARGE_FILES
-
-/* Define to empty if `const' does not conform to ANSI C. */
-#undef const
-
-/* Define as `__inline' if that's what the C compiler calls it, or to nothing
- if it is not supported. */
-#undef inline
-
-/* Define to `long' if <sys/types.h> does not define. */
-#undef off_t
-
-/* Define to `unsigned' if <sys/types.h> does not define. */
-#undef size_t
diff --git a/ndb/config/configure.in b/ndb/config/configure.in
deleted file mode 100644
index 4fa5ccdb672..00000000000
--- a/ndb/config/configure.in
+++ /dev/null
@@ -1,2085 +0,0 @@
-dnl -*- ksh -*-
-dnl Process this file with autoconf to produce a configure script.
-
-AC_INIT(../../sql/mysqld.cc)
-AC_CANONICAL_SYSTEM
-# The Docs Makefile.am parses this line!
-AM_INIT_AUTOMAKE(mysql, 4.1.2-3.4.3-alpha)
-AM_CONFIG_HEADER(config.h)
-
-PROTOCOL_VERSION=10
-DOT_FRM_VERSION=6
-# See the libtool docs for information on how to do shared lib versions.
-SHARED_LIB_VERSION=14:0:0
-
-# Set all version vars based on $VERSION. How do we do this more elegant ?
-# Remember that regexps needs to quote [ and ] since this is run through m4
-MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[[a-z]]*-.*$||"`
-MYSQL_BASE_VERSION=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|\.[[^.]]*$||"`
-MYSQL_VERSION_ID=`echo $MYSQL_NO_DASH_VERSION. | sed -e 's/\./ /g; s/ \([[0-9]]\) / 0\\1 /g; s/ //g'`
-
-# The port should be constant for a LONG time
-MYSQL_TCP_PORT_DEFAULT=3306
-MYSQL_UNIX_ADDR_DEFAULT="/tmp/mysql.sock"
-
-#####
-#####
-
-AC_SUBST(MYSQL_NO_DASH_VERSION)
-AC_SUBST(MYSQL_BASE_VERSION)
-AC_SUBST(MYSQL_VERSION_ID)
-AC_SUBST(PROTOCOL_VERSION)
-AC_DEFINE_UNQUOTED(PROTOCOL_VERSION, $PROTOCOL_VERSION)
-AC_SUBST(DOT_FRM_VERSION)
-AC_DEFINE_UNQUOTED(DOT_FRM_VERSION, $DOT_FRM_VERSION)
-AC_SUBST(SHARED_LIB_VERSION)
-
-# Canonicalize the configuration name.
-SYSTEM_TYPE="$host_vendor-$host_os"
-MACHINE_TYPE="$host_cpu"
-AC_SUBST(SYSTEM_TYPE)
-AC_DEFINE_UNQUOTED(SYSTEM_TYPE, "$SYSTEM_TYPE")
-AC_SUBST(MACHINE_TYPE)
-AC_DEFINE_UNQUOTED(MACHINE_TYPE, "$MACHINE_TYPE")
-
-# Detect intel x86 like processor
-BASE_MACHINE_TYPE=$MACHINE_TYPE
-case $MACHINE_TYPE in
- i?86) BASE_MACHINE_TYPE=i386 ;;
-esac
-
-# Save some variables and the command line options for mysqlbug
-SAVE_ASFLAGS="$ASFLAGS"
-SAVE_CFLAGS="$CFLAGS"
-SAVE_CXXFLAGS="$CXXFLAGS"
-SAVE_LDFLAGS="$LDFLAGS"
-SAVE_CXXLDFLAGS="$CXXLDFLAGS"
-CONF_COMMAND="$0 $ac_configure_args"
-AC_SUBST(CONF_COMMAND)
-AC_SUBST(SAVE_ASFLAGS)
-AC_SUBST(SAVE_CFLAGS)
-AC_SUBST(SAVE_CXXFLAGS)
-AC_SUBST(SAVE_LDFLAGS)
-AC_SUBST(SAVE_CXXLDFLAGS)
-AC_SUBST(CXXLDFLAGS)
-
-AC_PREREQ(2.12)dnl Minimum Autoconf version required.
-
-AM_MAINTAINER_MODE
-#AC_ARG_PROGRAM # Automaticly invoked by AM_INIT_AUTOMAKE
-AM_SANITY_CHECK
-# This is needed is SUBDIRS is set
-AC_PROG_MAKE_SET
-
-# This is need before AC_PROG_CC
-#
-
-if test "x${CFLAGS-}" = x ; then
- cflags_is_set=no
-else
- cflags_is_set=yes
-fi
-
-if test "x${CPPFLAGS-}" = x ; then
- cppflags_is_set=no
-else
- cppflags_is_set=yes
-fi
-
-if test "x${LDFLAGS-}" = x ; then
- ldflags_is_set=no
-else
- ldflags_is_set=yes
-fi
-
-# The following hack should ensure that configure doesn't add optimizing
-# or debugging flags to CFLAGS or CXXFLAGS
-CFLAGS="$CFLAGS "
-CXXFLAGS="$CXXFLAGS "
-
-dnl Checks for programs.
-AC_PROG_AWK
-AC_PROG_CC
-AC_PROG_CXX
-AC_PROG_CPP
-
-# Print version of CC and CXX compiler (if they support --version)
-case $SYSTEM_TYPE in
- *netware*)
-CC_VERSION=`$CC -version | grep -i version`
- ;;
- *)
-CC_VERSION=`$CC --version | sed 1q`
- ;;
-esac
-if test $? -eq "0"
-then
- AC_MSG_CHECKING("C Compiler version");
- AC_MSG_RESULT("$CC $CC_VERSION")
-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)
-
-# Fix for sgi gcc / sgiCC which tries to emulate gcc
-if test "$CC" = "sgicc"
-then
- ac_cv_prog_gcc="no"
-fi
-if test "$CXX" = "sgi++"
-then
- GXX="no"
-fi
-
-if test "$ac_cv_prog_gcc" = "yes"
-then
- AS="$CC -c"
- AC_SUBST(AS)
-else
- AC_PATH_PROG(AS, as, as)
-fi
-# Still need ranlib for readline; local static use only so no libtool.
-AC_PROG_RANLIB
-# We use libtool
-#AC_LIBTOOL_WIN32_DLL
-AC_PROG_LIBTOOL
-
-# Ensure that we have --preserve-dup-deps defines, otherwise we get link
-# problems of 'mysql' with CXX=g++
-LIBTOOL="$LIBTOOL --preserve-dup-deps"
-AC_SUBST(LIBTOOL)dnl
-
-#AC_LIBTOOL_DLOPEN AC_LIBTOOL_WIN32_DLL AC_DISABLE_FAST_INSTALL AC_DISABLE_SHARED AC_DISABLE_STATIC
-
-# AC_PROG_INSTALL
-AC_PROG_INSTALL
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
-
-# Not critical since the generated file is distributed
-AC_PROG_YACC
-AC_CHECK_PROG(PDFMANUAL, pdftex, manual.pdf)
-AC_CHECK_PROG(DVIS, tex, manual.dvi)
-
-AC_MSG_CHECKING("return type of sprintf")
-
-#check the return type of sprintf
-case $SYSTEM_TYPE in
- *netware*)
- AC_DEFINE(SPRINTF_RETURNS_INT) AC_MSG_RESULT("int")
- ;;
- *)
-AC_TRY_RUN([
- int main()
- {
- char* s = "hello";
- char buf[6];
- if((int)sprintf(buf, s) == strlen(s))
- return 0;
-
- return -1;
- }
- ],
-AC_DEFINE(SPRINTF_RETURNS_INT) AC_MSG_RESULT("int"),
- AC_TRY_RUN([
- int main()
- {
- char* s = "hello";
- char buf[6];
- if((char*)sprintf(buf,s) == buf + strlen(s))
- return 0;
- return -1;
- }
-], AC_DEFINE(SPRINTF_RETURNS_PTR) AC_MSG_RESULT("ptr"),
- AC_DEFINE(SPRINTF_RETURNS_GARBAGE) AC_MSG_RESULT("garbage")))
- ;;
-esac
-
-
-# option, cache_name, variable,
-# code to execute if yes, code to exectute if fail
-AC_DEFUN(AC_SYS_COMPILER_FLAG,
-[
- AC_MSG_CHECKING($1)
- OLD_CFLAGS="[$]CFLAGS"
- AC_CACHE_VAL(mysql_cv_option_$2,
- [
- CFLAGS="[$]OLD_CFLAGS $1"
- AC_TRY_RUN([int main(){exit(0);}],mysql_cv_option_$2=yes,mysql_cv_option_$2=no,mysql_cv_option_$2=no)
- ])
-
- CFLAGS="[$]OLD_CFLAGS"
-
- if test x"[$]mysql_cv_option_$2" = "xyes" ; then
- $3="[$]$3 $1"
- AC_MSG_RESULT(yes)
- $5
- else
- AC_MSG_RESULT(no)
- $4
- fi
-])
-
-# arch, option, cache_name, variable
-AC_DEFUN(AC_SYS_CPU_COMPILER_FLAG,
-[
- if test "`uname -m 2>/dev/null`" = "$1" ; then
- AC_SYS_COMPILER_FLAG($2,$3,$4)
- fi
-])
-
-# os, option, cache_name, variable
-AC_DEFUN(AC_SYS_OS_COMPILER_FLAG,
-[
- if test "x$mysql_cv_sys_os" = "x$1" ; then
- AC_SYS_COMPILER_FLAG($2,$3,$4)
- fi
-])
-
-# We need some special hacks when running slowaris
-AC_PATH_PROG(uname_prog, uname, no)
-
-# We should go through this and put all the explictly system dependent
-# stuff in one place
-AC_MSG_CHECKING(operating system)
-AC_CACHE_VAL(mysql_cv_sys_os,
-[
-if test "$uname_prog" != "no"; then
- mysql_cv_sys_os="`uname`"
-else
- mysql_cv_sys_os="Not Solaris"
-fi
-])
-AC_MSG_RESULT($mysql_cv_sys_os)
-
-# This should be rewritten to use $target_os
-case "$target_os" in
- sco3.2v5*)
- CFLAGS="$CFLAGS -DSCO"
- CXXFLAGS="$CXXFLAGS -DSCO"
- LD='$(CC) $(CFLAGS)'
- case "$CFLAGS" in
- *-belf*)
- AC_SYS_COMPILER_FLAG(-belf,sco_belf_option,CFLAGS,[],[
- case "$LDFLAGS" in
- *-belf*) ;;
- *) echo "Adding -belf option to ldflags."
- LDFLAGS="$LDFLAGS -belf"
- ;;
- esac
- ])
- ;;
- *)
- AC_SYS_COMPILER_FLAG(-belf,sco_belf_option,CFLAGS,[],[
- case "$LDFLAGS" in
- *-belf*) ;;
- *)
- echo "Adding -belf option to ldflags."
- LDFLAGS="$LDFLAGS -belf"
- ;;
- esac
- ])
- ;;
- esac
- ;;
- sysv5UnixWare*)
- if test "$GCC" != "yes"; then
- # We are using built-in inline function
- CFLAGS="$CFLAGS -Kalloca"
- fi
- CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA"
- ;;
- sysv5OpenUNIX8*)
- if test "$GCC" != "yes"; then
- # We are using built-in inline function
- CFLAGS="$CFLAGS -Kalloca"
- fi
- CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA"
- ;;
-esac
-AC_SUBST(CC)
-AC_SUBST(CFLAGS)
-AC_SUBST(CXX)
-AC_SUBST(CXXFLAGS)
-AC_SUBST(LD)
-AC_SUBST(INSTALL_SCRIPT)
-
-export CC CXX CFLAGS LD LDFLAGS AR
-
-if test "$GXX" = "yes"
-then
- # mysqld requires -fno-implicit-templates.
- # 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"
-
- # If you are using 'gcc' 3.0 (not g++) to compile C++ programs on Linux,
- # we will gets some problems when linking static programs.
- # The following code is used to fix this problem.
-
- if test "$CXX" = "gcc" -o "$CXX" = "ccache gcc"
- then
- if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1
- then
- CXXFLAGS="$CXXFLAGS -DUSE_MYSYS_NEW -DDEFINE_CXA_PURE_VIRTUAL"
- fi
- fi
-fi
-
-# Avoid bug in fcntl on some versions of linux
-AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os")
-# Any wariation of Linux
-if expr "$target_os" : "[[Ll]]inux.*" > /dev/null
-then
- MYSQLD_DEFAULT_SWITCHES="--skip-locking"
- IS_LINUX="true"
- AC_MSG_RESULT("yes");
-else
- MYSQLD_DEFAULT_SWITCHES=""
- IS_LINUX="false"
- AC_MSG_RESULT("no");
-fi
-AC_SUBST(MYSQLD_DEFAULT_SWITCHES)
-AC_SUBST(IS_LINUX)
-
-dnl Find paths to some shell programs
-AC_PATH_PROG(LN, ln, ln)
-# This must be able to take a -f flag like normal unix ln.
-AC_PATH_PROG(LN_CP_F, ln, ln)
-if ! ( expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null ); then
-# If ln -f does not exists use -s (AFS systems)
-if test -n "$LN_CP_F"; then
- LN_CP_F="$LN_CP_F -s"
-fi
-fi
-
-AC_PATH_PROG(MV, mv, mv)
-AC_PATH_PROG(RM, rm, rm)
-AC_PATH_PROG(CP, cp, cp)
-AC_PATH_PROG(SED, sed, sed)
-AC_PATH_PROG(CMP, cmp, cmp)
-AC_PATH_PROG(CHMOD, chmod, chmod)
-AC_PATH_PROG(HOSTNAME, hostname, hostname)
-# Check for a GNU tar named 'gtar', or 'gnutar' (MacOS X) and
-# fall back to 'tar' otherwise and hope that it's a GNU tar as well
-AC_CHECK_PROGS(TAR, gnutar gtar tar)
-
-dnl We use a path for perl so the script startup works
-dnl We make sure to use perl, not perl5, in hopes that the RPMs will
-dnl not depend on the perl5 binary being installed (probably a bug in RPM)
-AC_PATH_PROG(PERL, perl, no)
-if test "$PERL" != "no" && $PERL -e 'require 5' > /dev/null 2>&1
-then
- PERL5=$PERL
-else
- AC_PATH_PROG(PERL5, perl5, no)
- if test "$PERL5" != no
- then
- PERL=$PERL5
- ac_cv_path_PERL=$ac_cv_path_PERL5
- fi
-fi
-
-AC_SUBST(HOSTNAME)
-AC_SUBST(PERL)
-AC_SUBST(PERL5)
-
-# Lock for PS
-AC_PATH_PROG(PS, ps, ps)
-AC_MSG_CHECKING("how to check if pid exists")
-PS=$ac_cv_path_PS
-# Linux style
-if $PS p $$ 2> /dev/null | grep $0 > /dev/null
-then
- FIND_PROC="$PS p \$\$PID | grep mysqld > /dev/null"
-# Solaris
-elif $PS -p $$ 2> /dev/null | grep $0 > /dev/null
-then
- FIND_PROC="$PS -p \$\$PID | grep mysqld > /dev/null"
-# BSD style
-elif $PS -uaxww 2> /dev/null | grep $0 > /dev/null
-then
- FIND_PROC="$PS -uaxww | grep mysqld | grep \" \$\$PID \" > /dev/null"
-# SysV style
-elif $PS -ef 2> /dev/null | grep $0 > /dev/null
-then
- FIND_PROC="$PS -ef | grep mysqld | grep \" \$\$PID \" > /dev/null"
-# Do anybody use this?
-elif $PS $$ 2> /dev/null | grep $0 > /dev/null
-then
- FIND_PROC="$PS \$\$PID | grep mysqld > /dev/null"
-else
- case $SYSTEM_TYPE in
- *freebsd*)
- FIND_PROC="$PS p \$\$PID | grep mysqld > /dev/null"
- ;;
- *darwin*)
- FIND_PROC="$PS -uaxww | grep mysqld | grep \" \$\$PID \" > /dev/null"
- ;;
- *cygwin*)
- FIND_PROC="$PS -e | grep mysqld | grep \" \$\$PID \" > /dev/null"
- ;;
- *netware* | *modesto*)
- FIND_PROC=
- ;;
- *)
- AC_MSG_ERROR([Could not find the right ps switches. Which OS is this ?. See the Installation chapter in the Reference Manual.])
- esac
-fi
-AC_SUBST(FIND_PROC)
-AC_MSG_RESULT("$FIND_PROC")
-
-# Check if a pid is valid
-AC_PATH_PROG(KILL, kill, kill)
-AC_MSG_CHECKING("for kill switches")
-if $ac_cv_path_KILL -0 $$
-then
- CHECK_PID="$ac_cv_path_KILL -0 \$\$PID > /dev/null 2> /dev/null"
-elif kill -s 0 $$
-then
- CHECK_PID="$ac_cv_path_KILL -s 0 \$\$PID > /dev/null 2> /dev/null"
-else
- AC_MSG_WARN([kill -0 to check for pid seems to fail])
- CHECK_PID="$ac_cv_path_KILL -s SIGCONT \$\$PID > /dev/null 2> /dev/null"
-fi
-AC_SUBST(CHECK_PID)
-AC_MSG_RESULT("$CHECK_PID")
-
-# We need a ANSI C compiler
-AM_PROG_CC_STDC
-
-# We need an assembler, too
-AM_PROG_AS
-
-if test "$am_cv_prog_cc_stdc" = "no"
-then
- AC_MSG_ERROR([MySQL requires a ANSI C compiler (and a C++ compiler). Try gcc. See the Installation chapter in the Reference Manual.])
-fi
-
-NOINST_LDFLAGS=
-
-static_nss=""
-STATIC_NSS_FLAGS=""
-OTHER_LIBC_LIB=""
-AC_ARG_WITH(other-libc,
- [ --with-other-libc=DIR Link against libc and other standard libraries
- installed in the specified non-standard location
- overriding default. Originally added to be able to
- link against glibc 2.2 without making the user
- upgrade the standard libc installation.],
- [
- other_libc_include="$withval/include"
- other_libc_lib="$withval/lib"
- with_other_libc="yes"
- enable_shared="no"
- all_is_static="yes"
- CFLAGS="$CFLAGS -I$other_libc_include"
- # There seems to be a feature in gcc that treats system and libc headers
- # silently when they violatate ANSI C++ standard, but it is strict otherwise
- # since gcc cannot now recognize that our headers are libc, we work around
- # by telling it to be permissive. Note that this option only works with
- # new versions of gcc (2.95.x and above)
- CXXFLAGS="$CXXFLAGS -fpermissive -I$other_libc_include"
- if test -f "$other_libc_lib/libnss_files.a"
- then
- # libc has been compiled with --enable-static-nss
- # we need special flags, but we will have to add those later
- STATIC_NSS_FLAGS="-lc -lnss_files -lnss_dns -lresolv"
- STATIC_NSS_FLAGS="$STATIC_NSS_FLAGS $STATIC_NSS_FLAGS"
- OTHER_LIBC_LIB="-static -L$other_libc_lib"
- static_nss=1
- else
- # this is a dirty hack. We if we detect static nss glibc in the special
- # location, we do not re-direct the linker to get libraries from there
- # during check. The reason is that if we did, we would have to find a
- # way to append the special static nss flags to LIBS every time we do
- # any check - this is definitely feasible, but not worthwhile the risk
- # of breaking other things. So for our purposes it would be sufficient
- # to assume that whoever is using static NSS knows what he is doing and
- # has sensible libraries in the regular location
- LDFLAGS="$LDFLAGS -static -L$other_libc_lib "
- fi
-
- # When linking against custom libc installed separately, we want to force
- # all binary builds to be static, including the build done by configure
- # itself to test for system features.
- with_mysqld_ldflags="-all-static"
- with_client_ldflags="-all-static"
- NOINST_LDFLAGS="-all-static"
- ],
- [
- other_libc_include=
- other_libc_lib=
- with_other_libc="no"
- ]
-)
-AC_SUBST(NOINST_LDFLAGS)
-
-#
-# Check if we are using Linux and a glibc compiled with static nss
-# (this is true on the MySQL build machines to avoid NSS problems)
-#
-
-if test "$IS_LINUX" = "true" -a "$static_nss" = ""
-then
- tmp=`nm /usr/lib/libc.a | grep _nss_files_getaliasent_r`
- if test -n "$tmp"
- then
- STATIC_NSS_FLAGS="-lc -lnss_files -lnss_dns -lresolv"
- STATIC_NSS_FLAGS="$STATIC_NSS_FLAGS $STATIC_NSS_FLAGS"
- static_nss=1
- fi
-fi
-
-
-AC_ARG_WITH(server-suffix,
- [ --with-server-suffix Append value to the version string.],
- [ MYSQL_SERVER_SUFFIX=`echo "$withval" | sed -e 's/^\(...................................\)..*$/\1/'` ],
- [ MYSQL_SERVER_SUFFIX= ]
- )
-AC_SUBST(MYSQL_SERVER_SUFFIX)
-
-# Set flags if we wants to have MIT threads.
-AC_ARG_WITH(mit-threads,
- [ --with-mit-threads Always use included thread lib.],
- [ with_mit_threads=$withval ],
- [ with_mit_threads=no ]
- )
-
-if test "$with_mit_threads" = "yes"
-then
- enable_largefile="no" # Will not work on Linux.
-fi
-
-# Set flags if we want to force to use pthreads
-AC_ARG_WITH(pthread,
- [ --with-pthread Force use of pthread library.],
- [ with_pthread=$withval ],
- [ with_pthread=no ]
- )
-
-# Force use of thread libs LIBS
-AC_ARG_WITH(named-thread-libs,
- [ --with-named-thread-libs=ARG
- Use specified thread libraries instead of
- those automatically found by configure.],
- [ with_named_thread=$withval ],
- [ with_named_thread=no ]
- )
-
-# Force use of a curses libs
-AC_ARG_WITH(named-curses-libs,
- [ --with-named-curses-libs=ARG
- Use specified curses libraries instead of
- those automatically found by configure.],
- [ with_named_curses=$withval ],
- [ with_named_curses=no ]
- )
-
-# Force use of a zlib (compress)
-AC_ARG_WITH(named-z-libs,
- [ --with-named-z-libs=ARG
- Use specified zlib libraries instead of
- those automatically found by configure.],
- [ with_named_zlib=$withval ],
- [ with_named_zlib=z ]
- )
-
-# Make thread safe client
-AC_ARG_ENABLE(thread-safe-client,
- [ --enable-thread-safe-client
- Compile the client with threads.],
- [ THREAD_SAFE_CLIENT=$enableval ],
- [ THREAD_SAFE_CLIENT=no ]
- )
-
-# compile with strings functions in assembler
-AC_ARG_ENABLE(assembler,
- [ --enable-assembler Use assembler versions of some string
- functions if available.],
- [ ENABLE_ASSEMBLER=$enableval ],
- [ ENABLE_ASSEMBLER=no ]
- )
-
-AC_MSG_CHECKING(if we should use assembler functions)
-# For now we only support assembler on i386 and sparc systems
-AM_CONDITIONAL(ASSEMBLER_x86, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "i386")
-AM_CONDITIONAL(ASSEMBLER_sparc32, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparc")
-AM_CONDITIONAL(ASSEMBLER_sparc64, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparcv9")
-AM_CONDITIONAL(ASSEMBLER, test "$ASSEMBLER_x86_TRUE" = "" -o "$ASSEMBLER_sparc32_TRUE" = "")
-
-if test "$ASSEMBLER_TRUE" = ""
-then
- AC_MSG_RESULT([yes])
-else
- AC_MSG_RESULT([no])
-fi
-
-
-AC_MSG_CHECKING(if we should use RAID)
-AC_ARG_WITH(raid,
- [ --with-raid Enable RAID Support],
- [ USE_RAID=$withval ],
- [ USE_RAID=no ]
- )
-if test "$USE_RAID" = "yes"
-then
- AC_MSG_RESULT([yes])
- AC_DEFINE([USE_RAID])
-else
- AC_MSG_RESULT([no])
-fi
-
-# Use this to set the place used for unix socket used to local communication.
-AC_ARG_WITH(unix-socket-path,
- [ --with-unix-socket-path=SOCKET
- Where to put the unix-domain socket. SOCKET must be
- an absolute file name.],
- [ MYSQL_UNIX_ADDR=$withval ],
- [ MYSQL_UNIX_ADDR=$MYSQL_UNIX_ADDR_DEFAULT ]
- )
-AC_SUBST(MYSQL_UNIX_ADDR)
-
-AC_ARG_WITH(tcp-port,
- [ --with-tcp-port=port-number
- Which port to use for MySQL services (default 3306)],
- [ MYSQL_TCP_PORT=$withval ],
- [ MYSQL_TCP_PORT=$MYSQL_TCP_PORT_DEFAULT ]
- )
-AC_SUBST(MYSQL_TCP_PORT)
-# We might want to document the assigned port in the manual.
-AC_SUBST(MYSQL_TCP_PORT_DEFAULT)
-
-# Use this to set the place used for unix socket used to local communication.
-AC_ARG_WITH(mysqld-user,
- [ --with-mysqld-user=username
- What user the mysqld daemon shall be run as.],
- [ MYSQLD_USER=$withval ],
- [ MYSQLD_USER=mysql ]
- )
-AC_SUBST(MYSQLD_USER)
-
-# If we should allow LOAD DATA LOCAL
-AC_MSG_CHECKING(If we should should enable LOAD DATA LOCAL by default)
-AC_ARG_ENABLE(local-infile,
- [ --enable-local-infile Enable LOAD DATA LOCAL INFILE (default: disabled)],
- [ ENABLED_LOCAL_INFILE=$enableval ],
- [ ENABLED_LOCAL_INFILE=no ]
- )
-if test "$ENABLED_LOCAL_INFILE" = "yes"
-then
- AC_MSG_RESULT([yes])
- AC_DEFINE([ENABLED_LOCAL_INFILE])
-else
- AC_MSG_RESULT([no])
-fi
-
-MYSQL_SYS_LARGEFILE
-
-# Types that must be checked AFTER large file support is checked
-AC_TYPE_SIZE_T
-
-#--------------------------------------------------------------------
-# Check for system header files
-#--------------------------------------------------------------------
-
-AC_HEADER_DIRENT
-AC_HEADER_STDC
-AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \
- memory.h pwd.h select.h \
- stdlib.h stddef.h \
- strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \
- sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
- unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \
- sys/ioctl.h malloc.h sys/malloc.h linux/config.h)
-
-#--------------------------------------------------------------------
-# Check for system libraries. Adds the library to $LIBS
-# and defines HAVE_LIBM etc
-#--------------------------------------------------------------------
-
-AC_CHECK_LIB(m, floor, [], AC_CHECK_LIB(m, __infinity))
-
-AC_CHECK_LIB(nsl_r, gethostbyname_r, [],
- AC_CHECK_LIB(nsl, gethostbyname_r))
-AC_CHECK_FUNC(gethostbyname_r)
-
-AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt))
-AC_CHECK_FUNC(yp_get_default_domain, ,
- AC_CHECK_LIB(nsl, yp_get_default_domain))
-AC_CHECK_FUNC(p2open, , AC_CHECK_LIB(gen, p2open))
-# This may get things to compile even if bind-8 is installed
-AC_CHECK_FUNC(bind, , AC_CHECK_LIB(bind, bind))
-# For crypt() on Linux
-AC_CHECK_LIB(crypt, crypt)
-AC_CHECK_FUNC(crypt, AC_DEFINE(HAVE_CRYPT))
-
-# For sem_xxx functions on Solaris 2.6
-AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4, sem_init))
-
-# For compress in zlib
-MYSQL_CHECK_ZLIB_WITH_COMPRESS($with_named_zlib)
-
-#--------------------------------------------------------------------
-# Check for TCP wrapper support
-#--------------------------------------------------------------------
-
-AC_ARG_WITH(libwrap,
-[ --with-libwrap[=DIR] Compile in libwrap (tcp_wrappers) support],[
- case "$with_libwrap" in
- no) : ;;
- yes|*)
- _cppflags=${CPPFLAGS}
- _ldflags=${LDFLAGS}
-
- if test "$with_libwrap" != "yes"; then
- CPPFLAGS="${CPPFLAGS} -I$with_libwrap/include"
- LDFLAGS="${LDFLAGS} -L$with_libwrap/lib"
- fi
-
- _libs=${LIBS}
- AC_CHECK_HEADER(tcpd.h,
- LIBS="-lwrap $LIBS"
- AC_MSG_CHECKING(for TCP wrappers library -lwrap)
- AC_TRY_LINK([#include <tcpd.h>
-int allow_severity = 0;
-int deny_severity = 0;
-
-struct request_info *req;
-],[hosts_access (req)],
- AC_MSG_RESULT(yes)
- AC_DEFINE(LIBWRAP)
- AC_DEFINE(HAVE_LIBWRAP)
- if test "$with_libwrap" != "yes"; then
- WRAPLIBS="-L${with_libwrap}/lib"
- fi
- WRAPLIBS="${WRAPLIBS} -lwrap",
- AC_MSG_RESULT(no)
- CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}),
- CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags})
- LDFLAGS=${_ldflags} LIBS=${_libs}
- ;;
- esac
-])
-AC_SUBST(WRAPLIBS)
-
-if test "$IS_LINUX" = "true"; then
- AC_MSG_CHECKING([for atomic operations])
-
- atom_ops=
- AC_TRY_RUN([
-#include <asm/atomic.h>
-int main()
-{
- atomic_t v;
-
- atomic_set(&v, 23);
- atomic_add(5, &v);
- return atomic_read(&v) == 28 ? 0 : -1;
-}
- ], AC_DEFINE(HAVE_ATOMIC_ADD) atom_ops="${atom_ops}atomic_add ",
- )
- AC_TRY_RUN([
-#include <asm/atomic.h>
-int main()
-{
- atomic_t v;
-
- atomic_set(&v, 23);
- atomic_sub(5, &v);
- return atomic_read(&v) == 18 ? 0 : -1;
-}
- ], AC_DEFINE(HAVE_ATOMIC_SUB) atom_ops="${atom_ops}atomic_sub ",
- )
-
- if test -z "$atom_ops"; then atom_ops="no"; fi
- AC_MSG_RESULT($atom_ops)
-
- AC_ARG_WITH(pstack,
- [ --with-pstack Use the pstack backtrace library],
- [ USE_PSTACK=$withval ],
- [ USE_PSTACK=no ])
- pstack_libs=
- pstack_dirs=
- if test "$USE_PSTACK" = yes -a "$IS_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" -a "$with_mit_threads" = "no"
- then
- have_libiberty= have_libbfd=
- my_save_LIBS="$LIBS"
-dnl I have no idea if this is a good test - can not find docs for libiberty
- AC_CHECK_LIB([iberty], [fdmatch],
- [have_libiberty=yes
- AC_CHECK_LIB([bfd], [bfd_openr], [have_libbfd=yes], , [-liberty])])
- LIBS="$my_save_LIBS"
-
- if test x"$have_libiberty" = xyes -a x"$have_libbfd" = xyes
- then
- pstack_dirs='$(top_srcdir)'/pstack
- pstack_libs="../pstack/libpstack.a -lbfd -liberty"
- # We must link staticly when using pstack
- with_mysqld_ldflags="-all-static"
- AC_SUBST([pstack_dirs])
- AC_SUBST([pstack_libs])
- AC_DEFINE([USE_PSTACK])
-dnl This check isn't needed, but might be nice to give some feedback....
-dnl AC_CHECK_HEADER(libiberty.h,
-dnl have_libiberty_h=yes,
-dnl have_libiberty_h=no)
- else
- USE_PSTACK="no"
- fi
- else
- USE_PSTACK="no"
- fi
-fi
-AM_CONDITIONAL(COMPILE_PSTACK, test "$USE_PSTACK" = "yes")
-AC_MSG_CHECKING([if we should use pstack])
-AC_MSG_RESULT([$USE_PSTACK])
-
-# Check for gtty if termio.h doesn't exists
-if test "$ac_cv_header_termio_h" = "no" -a "$ac_cv_header_termios_h" = "no"
-then
- AC_CHECK_FUNC(gtty, , AC_CHECK_LIB(compat, gtty))
-fi
-# We make a special variable for client library's to avoid including
-# thread libs in the client.
-NON_THREADED_CLIENT_LIBS="$LIBS"
-
-AC_MSG_CHECKING([for int8])
-case $SYSTEM_TYPE in
- *netware)
- AC_MSG_RESULT([no])
- ;;
- *)
-AC_TRY_RUN([
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_STDDEF_H
-#include <stddef.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-int main()
-{
- int8 i;
- return 0;
-}
-], AC_DEFINE(HAVE_INT_8_16_32) AC_MSG_RESULT([yes]), AC_MSG_RESULT([no])
-)
- ;;
-esac
-
-#
-# Some system specific hacks
-#
-
-MAX_C_OPTIMIZE="-O3"
-MAX_CXX_OPTIMIZE="-O3"
-
-case $SYSTEM_TYPE in
- *solaris2.7*)
- # Solaris 2.7 has a broken /usr/include/widec.h
- # Make a fixed copy in ./include
- echo "Fixing broken include files for $SYSTEM_TYPE"
- echo " - Creating local copy of widec.h"
- if test ! -d include
- then
- mkdir ./include
- fi
- builddir=`pwd`
- sed -e "s|^#if[ ]*!defined(lint) && !defined(__lint)|#if !defined\(lint\) \&\& !defined\(__lint\) \&\& !defined\(getwc\)|" < /usr/include/widec.h > include/widec.h
- CFLAGS="$CFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
- CXXFLAGS="$CXXFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
- ;;
- *solaris2.8*)
- # Solaris 2.8 has a broken /usr/include/widec.h
- # Make a fixed copy in ./include
- echo "Fixing broken include files for $SYSTEM_TYPE"
- echo " - Creating local copy of widec.h"
- if test ! -d include
- then
- mkdir ./include
- fi
- builddir=`pwd`
- sed -e "s|^#if[ ]*!defined(__lint)|#if !defined\(__lint\) \&\& !defined\(getwc\)|" < /usr/include/widec.h > include/widec.h
- CFLAGS="$CFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
- CXXFLAGS="$CXXFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
- ;;
- *solaris2.5.1*)
- echo "Enabling getpass() workaround for Solaris 2.5.1"
- CFLAGS="$CFLAGS -DHAVE_BROKEN_GETPASS -DSOLARIS -DHAVE_RWLOCK_T";
- CXXFLAGS="$CXXFLAGS -DHAVE_RWLOCK_T -DSOLARIS"
- ;;
- *solaris*)
- CFLAGS="$CFLAGS -DHAVE_RWLOCK_T"
- CXXFLAGS="$CXXFLAGS -DHAVE_RWLOCK_T"
- ;;
- *SunOS*)
- echo "Enabling getpass() workaround for SunOS"
- CFLAGS="$CFLAGS -DHAVE_BROKEN_GETPASS -DSOLARIS";
- ;;
- *hpux10.20*)
- echo "Enabling workarounds for hpux 10.20"
- CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
- CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
- if test "$with_named_thread" = "no"
- then
- echo "Using --with-named-thread=-lpthread"
- with_named_thread="-lcma"
- fi
- ;;
- *hpux11.*)
- echo "Enabling workarounds for hpux 11"
- CFLAGS="$CFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
- CXXFLAGS="$CXXFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
- if test "$with_named_thread" = "no"
- then
- echo "Using --with-named-thread=-lpthread"
- with_named_thread="-lpthread"
- fi
- # Fixes for HPUX 11.0 compiler
- if test "$ac_cv_prog_gcc" = "no"
- then
- CFLAGS="$CFLAGS -DHAVE_BROKEN_INLINE"
- CXXFLAGS="$CXXFLAGS +O2"
- MAX_C_OPTIMIZE=""
- MAX_CXX_OPTIMIZE=""
- fi
- ;;
- *rhapsody*)
- if test "$ac_cv_prog_gcc" = "yes"
- then
- CPPFLAGS="$CPPFLAGS -traditional-cpp "
- CFLAGS="-DHAVE_CTHREADS_WRAPPER -DDO_NOT_REMOVE_THREAD_WRAPPERS"
- CXXFLAGS="-DHAVE_CTHREADS_WRAPPER"
- if test $with_named_curses = "no"
- then
- with_named_curses=""
- fi
- fi
- ;;
- *darwin5*)
- if test "$ac_cv_prog_gcc" = "yes"
- then
- FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH"
- CFLAGS="$CFLAGS $FLAGS"
- CXXFLAGS="$CXXFLAGS $FLAGS"
- MAX_C_OPTIMIZE="-O"
- with_named_curses=""
- fi
- ;;
- *darwin6*)
- if test "$ac_cv_prog_gcc" = "yes"
- then
- FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH"
- CFLAGS="$CFLAGS $FLAGS"
- CXXFLAGS="$CXXFLAGS $FLAGS"
- MAX_C_OPTIMIZE="-O"
- fi
- ;;
- *darwin7*)
- if test "$ac_cv_prog_gcc" = "yes"
- then
- FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ"
- CFLAGS="$CFLAGS $FLAGS"
- CXXFLAGS="$CXXFLAGS $FLAGS"
- MAX_C_OPTIMIZE="-O"
- fi
- ;;
- *freebsd*)
- echo "Adding fix for interrupted reads"
- OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
- if test "$OSVERSION" -gt "480100" && \
- test "$OSVERSION" -lt "500000" || \
- test "$OSVERSION" -gt "500109"
- then
- CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000"
- else
- CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
- CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
- fi
- ;;
- *netbsd*)
- echo "Adding flag -Dunix"
- CFLAGS="$CFLAGS -Dunix"
- CXXFLAGS="$CXXFLAGS -Dunix"
- OVERRIDE_MT_LD_ADD="\$(top_srcdir)/mit-pthreads/obj/libpthread.a"
- ;;
- *bsdi*)
- echo "Adding fix for BSDI"
- CFLAGS="$CFLAGS -D__BSD__ -DHAVE_BROKEN_REALPATH"
- AC_DEFINE_UNQUOTED(SOCKOPT_OPTLEN_TYPE, size_t)
- ;;
- *sgi-irix6*)
- if test "$with_named_thread" = "no"
- then
- echo "Using --with-named-thread=-lpthread"
- with_named_thread="-lpthread"
- fi
- CXXFLAGS="$CXXFLAGS -D_BOOL"
- ;;
- *aix4.3*)
- echo "Adding defines for AIX"
- CFLAGS="$CFLAGS -Wa,-many -DUNDEF_HAVE_INITGROUPS -DSIGNALS_DONT_BREAK_READ"
- CXXFLAGS="$CXXFLAGS -Wa,-many -DUNDEF_HAVE_INITGROUPS -DSIGNALS_DONT_BREAK_READ"
- ;;
-dnl Is this the right match for DEC OSF on alpha?
- *dec-osf*)
- if test "$ac_cv_prog_gcc" = "yes" && test "$host_cpu" = "alpha"
- then
- echo "Adding defines for DEC OSF on alpha"
- CFLAGS="$CFLAGS -mieee"
- CXXFLAGS="$CXXFLAGS -mieee"
- fi
- echo "Adding defines for OSF1"
- # gethostbyname_r is deprecated and doesn't work ok on OSF1
- CFLAGS="$CFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R"
- CXXFLAGS="$CXXFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R"
- ;;
- *netware*)
- # No need for curses library so set it to null
- with_named_curses=""
-
- # No thread library - in LibC
- with_named_thread=""
-
- #
- # Edit Makefile.in files.
- #
- echo -n "configuring Makefile.in files for NetWare... "
- for file in sql/Makefile.in libmysql/Makefile.in libmysql_r/Makefile.in sql/share/Makefile.in strings/Makefile.in client/Makefile.in
- do
- # echo "#### $file ####"
- filedir="`dirname $file`"
- filebase="`basename $file`"
- filesed=$filedir/$filebase.sed
- #
- # Backup and always use original file
- #
- if test -f $file.bk
- then
- cp -fp $file.bk $file
- else
- cp -fp $file $file.bk
- fi
- case $file in
- sql/Makefile.in)
- # Use gen_lex_hash.linux instead of gen_lex_hash
- # Add library dependencies to mysqld_DEPENDENCIES
- lib_DEPENDENCIES="\$(bdb_libs_with_path) \$(innodb_libs) \$(pstack_libs) \$(innodb_system_libs) \$(openssl_libs)"
- cat > $filesed << EOF
-s,\(^.*\$(MAKE) gen_lex_hash\),#\1,
-s,\(\./gen_lex_hash\),\1.linux,
-s%\(mysqld_DEPENDENCIES = \) %\1$lib_DEPENDENCIES %
-EOF
- ;;
- sql/share/Makefile.in)
- cat > $filesed << EOF
-s,\(extra/comp_err\),\1.linux,
-EOF
- ;;
- libmysql/Makefile.in)
- cat > $filesed << EOF
-s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
-s,\(: conf_to_src\),\1.linux,
-EOF
- ;;
- libmysql_r/Makefile.in)
- cat > $filesed << EOF
-s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
-s,\(: conf_to_src\),\1.linux,
-EOF
- ;;
- strings/Makefile.in)
- cat > $filesed << EOF
-s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
-s,\(: conf_to_src\),\1.linux,
-EOF
- ;;
- client/Makefile.in)
- #
- cat > $filesed << EOF
-s,libmysqlclient.la,.libs/libmysqlclient.a,
-EOF
- ;;
- esac
- if `sed -f $filesed $file > $file.nw`;\
- then
- mv -f $file.nw $file
- rm -f $filesed
- else
- exit 1
- fi
- # wait for file system changes to complete
- sleep 1
- done
- echo "done"
-
- #
- # Make sure the following files are writable.
- #
- # When the files are retrieved from some source code control systems they are read-only.
- #
- echo -n "making sure specific build files are writable... "
- for file in \
- Docs/include.texi \
- Docs/mysql.info \
- Docs/manual.txt \
- Docs/manual_toc.html \
- Docs/manual.html \
- Docs/INSTALL-BINARY \
- INSTALL-SOURCE \
- COPYING \
- COPYING.LIB \
- MIRRORS
- do
- if test -e $file; then
- chmod +w $file
- fi
- done
- echo "done"
-
- ;;
-esac
-
-
-#---START: Used in for client configure
-# Check if we threads are in libc or if we should use
-# -lpthread, -lpthreads or mit-pthreads
-# We have to check libc last because else it fails on Solaris 2.6
-
-with_posix_threads="no"
-# Hack for DEC-UNIX (OSF1)
-if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
-then
- # Look for LinuxThreads.
- AC_MSG_CHECKING("LinuxThreads")
- res=`grep Linuxthreads /usr/include/pthread.h 2>/dev/null | wc -l`
- if test "$res" -gt 0
- then
- AC_MSG_RESULT("Found")
- AC_DEFINE(HAVE_LINUXTHREADS)
- # Linux 2.0 sanity check
- AC_TRY_COMPILE([#include <sched.h>], [int a = sched_get_priority_min(1);], ,
- AC_MSG_ERROR([Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual]))
- # RedHat 5.0 does not work with dynamic linking of this. -static also
- # gives a speed increase in linux so it does not hurt on other systems.
- with_named_thread="-lpthread"
- else
- AC_MSG_RESULT("Not found")
- # If this is a linux machine we should barf
- if test "$IS_LINUX" = "true"
- then
- AC_MSG_ERROR([This is a linux system and Linuxthreads was not
-found. On linux Linuxthreads should be used. Please install Linuxthreads
-(or a new glibc) and try again. See the Installation chapter in the
-Reference Manual for more information.])
- else
- AC_MSG_CHECKING("DEC threads")
- if test -f /usr/shlib/libpthread.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a
- then
- with_named_thread="-lpthread -lmach -lexc"
- CFLAGS="$CFLAGS -D_REENTRANT"
- CXXFLAGS="$CXXFLAGS -D_REENTRANT"
- AC_DEFINE(HAVE_DEC_THREADS)
- AC_MSG_RESULT("yes")
- else
- AC_MSG_RESULT("no")
- AC_MSG_CHECKING("DEC 3.2 threads")
- if test -f /usr/shlib/libpthreads.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a
- then
- with_named_thread="-lpthreads -lmach -lc_r"
- AC_DEFINE(HAVE_DEC_THREADS)
- AC_DEFINE(HAVE_DEC_3_2_THREADS)
- with_osf32_threads="yes"
- MYSQLD_DEFAULT_SWITCHES="--skip-thread-priority"
- AC_MSG_RESULT("yes")
- else
- AC_MSG_RESULT("no")
- fi
- fi
- fi
- fi
-fi
-
-
-dnl This is needed because -lsocket has to come after the thread
-dnl library on SCO.
-AC_DEFUN([MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK], [
- LIBS=`echo " $LIBS " | sed -e 's/ -lsocket / /g'`
-])
-# Hack for SCO UNIX
-if test "$with_named_thread" = "no"
-then
- AC_MSG_CHECKING("SCO threads")
- if expr "$SYSTEM_TYPE" : ".*sco.*" > /dev/null
- then
- if test -f /usr/lib/libgthreads.a -o -f /usr/lib/libgthreads.so
- then
- MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
- with_named_thread="-lgthreads -lsocket -lgthreads"
- # sched.h conflicts with fsu-threads
- touch ./include/sched.h
-
- # We must have gcc
- if expr "$CC" : ".*gcc.*"
- then
- AC_MSG_RESULT("yes")
- else
- AC_MSG_ERROR([On SCO UNIX MySQL must be compiled with gcc. See the Installation chapter in the Reference Manual.]);
- fi
- AC_MSG_RESULT("yes")
- elif test -f /usr/local/lib/libpthread.a -o -f /usr/local/lib/libpthread.so
- then
- MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
- with_named_thread="-lpthread -lsocket"
- # sched.h conflicts with fsu-threads
- # touch ./include/sched.h
-
- AC_MSG_CHECKING("for gcc")
- # We must have gcc
- if expr "$CC" : ".*gcc.*"
- then
- AC_MSG_RESULT("yes")
- else
- AC_MSG_ERROR([On SCO UNIX MySQL must be compiled with gcc. See the Installation chapter in the Reference Manual.]);
- fi
- AC_MSG_RESULT("yes")
- # Hack for SCO UnixWare 7.1.x
- #
- elif test "$with_named_thread" = "no"
- then
- AC_MSG_RESULT("no")
- AC_MSG_CHECKING("SCO UnixWare 7.1.x native threads")
- if expr "$SYSTEM_TYPE" : ".*sco.*" > /dev/null
- then
- if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
- then
- MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
- if expr "$CC" : ".*gcc.*"
- then
- with_named_thread="-pthread -lsocket -lnsl"
- else
- with_named_thread="-Kthread -lsocket -lnsl"
- fi
- if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
- then
- AC_DEFINE(HAVE_UNIXWARE7_THREADS)
- else
- AC_DEFINE(HAVE_UNIXWARE7_POSIX)
- fi
- AC_MSG_RESULT("yes")
- # We must have cc
- AC_MSG_CHECKING("for gcc")
- if expr "$CC" : ".*gcc.*"
- then
- CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- else
- CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- fi
- else
- { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
- fi
- else
- AC_MSG_RESULT("no")
- fi
- else
- AC_MSG_ERROR([On SCO UNIX MySQL requires that the FSUThreads package is installed. See the Installation chapter in the Reference Manual.]);
- fi
- else
- AC_MSG_RESULT("no")
- fi
-fi
-# Hack for SCO UnixWare7
-#
-if test "$with_named_thread" = "no"
-then
- AC_MSG_CHECKING("SCO UnixWare7 native threads")
- if expr "$SYSTEM_TYPE" : ".*UnixWare*" > /dev/null
- then
- if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
- then
- MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
- if expr "$CC" : ".*gcc.*"
- then
- with_named_thread="-pthread -lsocket -lnsl"
- else
- with_named_thread="-Kthread -lsocket -lnsl"
- fi
- if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
- then
- AC_DEFINE(HAVE_UNIXWARE7_THREADS)
- else
- AC_DEFINE(HAVE_UNIXWARE7_POSIX)
- fi
- # We must have cc
- AC_MSG_CHECKING("for gcc")
- if expr "$CC" : ".*gcc.*"
- then
- CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- else
- CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- fi
- AC_MSG_RESULT("yes")
- else
- { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
- fi
- else
- AC_MSG_RESULT("no")
- fi
-fi
-
-# Hack for Caldera OpenUNIX8
-#
-if test "$with_named_thread" = "no"
-then
- AC_MSG_CHECKING("OpenUNIX8 native threads")
- if expr "$SYSTEM_TYPE" : ".*OpenUNIX*" > /dev/null
- then
- if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
- then
- MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
- if expr "$CC" : ".*gcc.*"
- then
- with_named_thread="-pthread -lsocket -lnsl"
- else
- with_named_thread="-Kthread -lsocket -lnsl"
- fi
- if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
- then
- AC_DEFINE(HAVE_UNIXWARE7_THREADS)
- else
- AC_DEFINE(HAVE_UNIXWARE7_POSIX)
- fi
- # We must have cc
- AC_MSG_CHECKING("for gcc")
- if expr "$CC" : ".*gcc.*"
- then
- CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- else
- CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- fi
- AC_MSG_RESULT("yes")
- else
- { echo "configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
- fi
- else
- AC_MSG_RESULT("no")
- fi
-fi
-
-# Hack for Siemens UNIX
-if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
-then
- AC_MSG_CHECKING("Siemens threads")
- if test -f /usr/lib/libxnet.so -a "$SYSTEM_TYPE" = "sni-sysv4"
- then
- LIBS="-lxnet $LIBS"
- NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS -lxnet"
- with_named_thread="-Kthread $LDFLAGS -lxnet"
- LD_FLAGS=""
- CFLAGS="-Kthread $CFLAGS"
- CXXFLAGS="-Kthread $CXXFLAGS"
- AC_MSG_RESULT("yes")
- else
- AC_MSG_RESULT("no")
- fi
-fi
-
-# Use library named -lpthread
-if test "$with_named_thread" = "no" -a "$with_pthread" = "yes"
-then
- with_named_thread="-lpthread"
-fi
-
-#---END:
-
-# Hack for Solaris >= 2.5
-# We want both the new and the old interface
-
-if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
-then
- AC_MSG_CHECKING("Solaris threads")
- if test -f /usr/lib/libpthread.so -a -f /usr/lib/libthread.so
- then
- with_named_thread="-lpthread -lthread"
- AC_MSG_RESULT("yes")
- else
- AC_MSG_RESULT("no")
- fi
-fi
-
-TOOLS_LIBS="$NON_THREADED_CLIENT_LIBS"
-
-# Should we use named pthread library ?
-AC_MSG_CHECKING("named thread libs:")
-if test "$with_named_thread" != "no"
-then
- LIBS="$with_named_thread $LIBS $with_named_thread"
- TOOLS_LIBS="$with_named_thread $TOOLS_LIBS $with_named_thread"
- with_posix_threads="yes"
- with_mit_threads="no"
- AC_MSG_RESULT("$with_named_thread")
-else
- AC_MSG_RESULT("no")
- if test "$with_mit_threads" = "no"
- then
- # pthread_create is in standard libraries (As in BSDI 3.0)
- AC_MSG_CHECKING("for pthread_create in -libc");
- AC_TRY_LINK(
- [#include <pthread.h>],
- [ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
- with_posix_threads=yes, with_posix_threads=no)
- AC_MSG_RESULT("$with_posix_threads")
- if test "$with_posix_threads" = "no"
- then
- AC_MSG_CHECKING("for pthread_create in -lpthread");
- ac_save_LIBS="$LIBS"
- ac_save_TOOLS_LIBS="$TOOLS_LIBS"
- LIBS="$LIBS -lpthread"
- TOOLS_LIBS="$TOOLS_LIBS -lpthread"
- AC_TRY_LINK(
- [#include <pthread.h>],
- [ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
- with_posix_threads=yes, with_posix_threads=no)
- AC_MSG_RESULT("$with_posix_threads")
- if test "$with_posix_threads" = "no"
- then
- LIBS=" $ac_save_LIBS -lpthreads"
- TOOLS_LIBS=" $ac_save_TOOLS_LIBS -lpthreads"
- AC_MSG_CHECKING("for pthread_create in -lpthreads");
- AC_TRY_LINK(
- [#include <pthread.h>],
- [ pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
- with_posix_threads=yes, with_posix_threads=no)
- AC_MSG_RESULT("$with_posix_threads")
- if test "$with_posix_threads" = "no"
- then
- # This is for FreeBSD
- LIBS="$ac_save_LIBS -pthread"
- TOOLS_LIBS="$ac_save_TOOLS_LIBS -pthread"
- AC_MSG_CHECKING("for pthread_create in -pthread");
- AC_TRY_LINK(
- [#include <pthread.h>],
- [ pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
- with_posix_threads=yes, with_posix_threads=no)
- AC_MSG_RESULT("$with_posix_threads")
- if test "$with_posix_threads" = "no"
- then
- with_mit_threads="yes"
- LIBS="$ac_save_LIBS"
- TOOLS_LIBS="$ac_save_TOOLS_LIBS"
- fi
- fi
- fi
- fi
- fi
-fi
-
-#---START: Used in for client configure
-# Must be checked after, because strtok_r may be in -lpthread
-# On AIX strtok_r is in libc_r
-
-my_save_LIBS="$LIBS"
-AC_CHECK_LIB(pthread,strtok_r)
-LIBS="$my_save_LIBS"
-if test "$ac_cv_lib_pthread_strtok_r" = "no"
-then
- AC_CHECK_LIB(c_r,strtok_r)
- case "$with_osf32_threads---$target_os" in
- # Don't keep -lc_r in LIBS; -pthread handles it magically
- yes---* | *---freebsd* | *---hpux*) LIBS="$my_save_LIBS" ;;
-
- esac
- AC_CHECK_FUNCS(strtok_r pthread_init)
-else
- AC_CHECK_FUNCS(strtok_r)
-fi
-#---END:
-
-# Check for dlopen, needed for user definable functions
-# This must be checked after threads on AIX
-# We only need this for mysqld, not for the clients.
-
-my_save_LIBS="$LIBS"
-LIBS=""
-AC_CHECK_LIB(dl,dlopen)
-LIBDL=$LIBS
-LIBS="$my_save_LIBS"
-AC_SUBST(LIBDL)
-
-# System characteristics
-case $SYSTEM_TYPE in
- *netware* | *modesto*) ;;
- *)
-AC_SYS_RESTARTABLE_SYSCALLS
- ;;
-esac
-
-# Build optimized or debug version ?
-# First check for gcc and g++
-if test "$ac_cv_prog_gcc" = "yes"
-then
- DEBUG_CFLAGS="-g"
- DEBUG_OPTIMIZE_CC="-O"
- OPTIMIZE_CFLAGS="$MAX_C_OPTIMIZE"
-else
- DEBUG_CFLAGS="-g"
- DEBUG_OPTIMIZE_CC=""
- OPTIMIZE_CFLAGS="-O"
-fi
-if test "$ac_cv_prog_cxx_g" = "yes"
-then
- DEBUG_CXXFLAGS="-g"
- DEBUG_OPTIMIZE_CXX="-O"
- OPTIMIZE_CXXFLAGS="$MAX_CXX_OPTIMIZE"
-else
- DEBUG_CXXFLAGS="-g"
- DEBUG_OPTIMIZE_CXX=""
- OPTIMIZE_CXXFLAGS="-O"
-fi
-
-if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then
- DEBUG_CFLAGS="$DEBUG_CFLAGS -DDEBUG -sym internal,codeview4"
- DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -DDEBUG -sym internal,codeview4"
- OPTIMIZE_CFLAGS="$OPTIMIZE_CFLAGS -DNDEBUG"
- OPTIMIZE_CXXFLAGS="$OPTIMIZE_CXXFLAGS -DNDEBUG"
-fi
-
-AC_ARG_WITH(debug,
- [ --without-debug Build a production version without debugging code],
- [with_debug=$withval],
- [with_debug=no])
-if test "$with_debug" = "yes"
-then
- # Medium debug.
- CFLAGS="$DEBUG_CFLAGS $DEBUG_OPTIMIZE_CC -DDBUG_ON -DSAFE_MUTEX $CFLAGS"
- CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DSAFE_MUTEX $CXXFLAGS"
-elif test "$with_debug" = "full"
-then
- # Full debug. Very slow in some cases
- CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS"
- CXXFLAGS="$DEBUG_CXXFLAGS -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS"
-else
- # Optimized version. No debug
- CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS"
- CXXFLAGS="$OPTIMIZE_CXXFLAGS -DDBUG_OFF $CXXFLAGS"
-fi
-
-# Force static compilation to avoid linking problems/get more speed
-AC_ARG_WITH(mysqld-ldflags,
- [ --with-mysqld-ldflags Extra linking arguments for mysqld],
- [MYSQLD_EXTRA_LDFLAGS=$withval],
- [MYSQLD_EXTRA_LDFLAGS=])
-AC_SUBST(MYSQLD_EXTRA_LDFLAGS)
-
-AC_ARG_WITH(client-ldflags,
- [ --with-client-ldflags Extra linking arguments for clients],
- [CLIENT_EXTRA_LDFLAGS=$withval],
- [CLIENT_EXTRA_LDFLAGS=])
-AC_SUBST(CLIENT_EXTRA_LDFLAGS)
-
-AC_ARG_WITH(lib-ccflags,
- [ --with-lib-ccflags Extra CC options for libraries],
- [LIB_EXTRA_CCFLAGS=$withval],
- [LIB_EXTRA_CCFLAGS=])
-AC_SUBST(LIB_EXTRA_CCFLAGS)
-
-# Avoid stupid bug on some OS
-AC_ARG_WITH(low-memory,
- [ --with-low-memory Try to use less memory to compile to avoid
- memory limitations.],
- [with_lowmem=$withval],
- [with_lowmem=no])
-if test "$with_lowmem" = "yes"
-then
- if test "$ac_cv_prog_gcc" = "yes"
- then
- LM_CFLAGS="-fno-inline"
- else
- LM_CFLAGS="-O0"
- fi
-else
- LM_CFLAGS=""
-fi
-AC_SUBST(LM_CFLAGS)
-
-AC_ARG_WITH(comment,
- [ --with-comment Comment about compilation environment.],
- [with_comment=$withval],
- [with_comment=no])
-if test "$with_comment" != "no"
-then
- COMPILATION_COMMENT=$with_comment
-else
- COMPILATION_COMMENT="Source distribution"
-fi
-AC_SUBST(COMPILATION_COMMENT)
-
-AC_MSG_CHECKING("need of special linking flags")
-if test "$IS_LINUX" = "true" -a "$ac_cv_prog_gcc" = "yes" -a "$all_is_static" != "yes"
-then
- LDFLAGS="$LDFLAGS -rdynamic"
- AC_MSG_RESULT("-rdynamic")
-else
- AC_MSG_RESULT("none")
-fi
-
-dnl Checks for typedefs, structures, and compiler characteristics.
-AC_C_CONST
-AC_C_INLINE
-AC_TYPE_OFF_T
-AC_STRUCT_ST_RDEV
-AC_HEADER_TIME
-AC_STRUCT_TM
-# AC_CHECK_SIZEOF return 0 when it does not find the size of a
-# type. We want a error instead.
-AC_CHECK_SIZEOF(char, 1)
-if test "$ac_cv_sizeof_char" -eq 0
-then
- AC_MSG_ERROR([No size for char type.
-A likely cause for this could be that there isn't any
-static libraries installed. You can verify this by checking if you have libm.a
-in /lib, /usr/lib or some other standard place. If this is the problem,
-install the static libraries and try again. If this isn't the problem,
-examine config.log for possible errors. If you want to report this, use
-'scripts/mysqlbug' and include at least the last 20 rows from config.log!])
-fi
-AC_CHECK_SIZEOF(char*, 4)
-AC_CHECK_SIZEOF(int, 4)
-if test "$ac_cv_sizeof_int" -eq 0
-then
- AC_MSG_ERROR("No size for int type.")
-fi
-AC_CHECK_SIZEOF(long, 4)
-if test "$ac_cv_sizeof_long" -eq 0
-then
- AC_MSG_ERROR("No size for long type.")
-fi
-AC_CHECK_SIZEOF(long long, 8)
-if test "$ac_cv_sizeof_long_long" -eq 0
-then
- AC_MSG_ERROR("MySQL needs a long long type.")
-fi
-# off_t is not a builtin type
-MYSQL_CHECK_SIZEOF(off_t, 4)
-if test "$ac_cv_sizeof_off_t" -eq 0
-then
- AC_MSG_ERROR("MySQL needs a off_t type.")
-fi
-# This always gives a warning. Ignore it unless you are cross compiling
-AC_C_BIGENDIAN
-#---START: Used in for client configure
-# Check base type of last arg to accept
-MYSQL_TYPE_ACCEPT
-
-#---END:
-# Find where the stack goes
-MYSQL_STACK_DIRECTION
-# We want to skip alloca on irix unconditionally. It may work on some version..
-MYSQL_FUNC_ALLOCA
-# Do struct timespec have members tv_sec or ts_sec
-MYSQL_TIMESPEC_TS
-# Do we have the tzname variable
-MYSQL_TZNAME
-# Do the system files define ulong
-MYSQL_CHECK_ULONG
-# Do the system files define uchar
-MYSQL_CHECK_UCHAR
-# Do the system files define uint
-MYSQL_CHECK_UINT
-# Check for fp_except in ieeefp.h
-MYSQL_CHECK_FP_EXCEPT
-# Check for IN_ADDR_T
-MYSQL_CHECK_IN_ADDR_T
-# Do the c++ compiler have a bool type
-MYSQL_CXX_BOOL
-# Check some common bugs with gcc 2.8.# on sparc
-if ! ( expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null ); then
-MYSQL_CHECK_LONGLONG_TO_FLOAT
-if test "$ac_cv_conv_longlong_to_float" != "yes"
-then
- AC_MSG_ERROR([Your compiler cannot convert a longlong value to a float!
-If you are using gcc 2.8.# you should upgrade to egcs 1.0.3 or newer and try
-again]);
-fi
-fi
-MYSQL_PTHREAD_YIELD
-
-######################################################################
-# For readline/libedit (We simply move the mimimum amount of stuff from
-# the readline/libedit configure.in here)
-
-dnl Checks for header files.
-AC_CHECK_HEADERS(malloc.h sys/cdefs.h)
-
-dnl Checks for library functions.
-AC_FUNC_ALLOCA
-AC_PROG_GCC_TRADITIONAL
-AC_TYPE_SIGNAL
-AC_CHECK_FUNCS(re_comp regcomp strdup)
-
-AC_CHECK_HEADERS(vis.h)
-AC_CHECK_FUNCS(strlcat strlcpy)
-AC_CHECK_FUNCS(issetugid)
-AC_CHECK_FUNCS(fgetln)
-AC_CHECK_FUNCS(getline flockfile)
-
-# from old readline settting:
-
-MAKE_SHELL=/bin/sh
-AC_SUBST(MAKE_SHELL)
-
-# Already-done: stdlib.h string.h unistd.h termios.h
-AC_CHECK_HEADERS(varargs.h stdarg.h dirent.h locale.h ndir.h sys/dir.h \
- sys/file.h sys/ndir.h sys/ptem.h sys/pte.h sys/select.h sys/stream.h \
- sys/mman.h curses.h termcap.h termio.h termbits.h asm/termbits.h grp.h \
-paths.h semaphore.h)
-
-# Already-done: strcasecmp
-AC_CHECK_FUNCS(lstat putenv select setenv setlocale strcoll tcgetattr)
-
-AC_STAT_MACROS_BROKEN
-MYSQL_SIGNAL_CHECK
-MYSQL_CHECK_GETPW_FUNCS
-MYSQL_HAVE_TIOCGWINSZ
-MYSQL_HAVE_FIONREAD
-MYSQL_HAVE_TIOCSTAT
-MYSQL_STRUCT_DIRENT_D_INO
-MYSQL_TYPE_SIGHANDLER
-if test "$with_named_curses" = "no"
-then
- MYSQL_CHECK_LIB_TERMCAP
-else
- TERMCAP_LIB="$with_named_curses"
-fi
-AC_SUBST(TERMCAP_LIB)
-
-# End of readline/libedit stuff
-#########################################################################
-
-dnl Checks for library functions.
-
-#
-# The following code disables intrinsic function support while we test for
-# library functions. This is to avoid configure problems with Intel ecc
-# compiler
-
-ORG_CFLAGS="$CFLAGS"
-if test "$GCC" != "yes"; then
- AC_SYS_COMPILER_FLAG(-nolib_inline,nolib_inline,CFLAGS,[],[])
-fi
-
-AC_FUNC_MMAP
-AC_TYPE_SIGNAL
-MYSQL_TYPE_QSORT
-AC_FUNC_UTIME_NULL
-AC_FUNC_VPRINTF
-
-AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
- fconvert fdatasync finite fpresetsticky fpsetmask fsync ftruncate \
- getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
- getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
- localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \
- mkstemp mlockall perror poll pread pthread_attr_create clock_gettime \
- pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \
- pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
- pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
- pthread_setprio_np pthread_setschedparam pthread_sigmask readlink \
- realpath rename rint rwlock_init setupterm sighold sigset sigthreadmask \
- snprintf socket stpcpy strcasecmp strerror strnlen strpbrk strstr strtol \
- strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr)
-
-# isinf() could be a function or a macro (HPUX)
-AC_MSG_CHECKING(for isinf with <math.h>)
-AC_TRY_LINK([#include <math.h>], [float f = 0.0; isinf(f)],
- AC_MSG_RESULT(yes) AC_DEFINE(HAVE_ISINF,,[isinf() macro or function]),
- AC_MSG_RESULT(no))
-
-CFLAGS="$ORG_CFLAGS"
-
-# Sanity check: We chould not have any fseeko symbol unless
-# large_file_support=yes
-AC_CHECK_FUNC(fseeko,
-[if test "$large_file_support" = no -a "$IS_LINUX" = "true";
-then
- AC_MSG_ERROR("Found fseeko symbol but large_file_support is not enabled!");
-fi]
-)
-
-my_save_LIBS="$LIBS"
-LIBS="$LIBS $LIBDL"
-AC_CHECK_FUNCS(dlopen dlerror)
-LIBS="$my_save_LIBS"
-
-# Check definition of gethostbyaddr_r (glibc2 defines this with 8 arguments)
-ac_save_CXXFLAGS="$CXXFLAGS"
-AC_CACHE_CHECK([style of gethost* routines], mysql_cv_gethost_style,
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-
-# Do not treat warnings as errors if we are linking against other libc
-# this is to work around gcc not being permissive on non-system includes
-# with respect to ANSI C++
-# We also remove the -fbranch-probabilities option as this will give warnings
-# about not profiled code, which confuses configure
-if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
-then
- CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'`
-fi
-
-AC_TRY_COMPILE(
-[#undef inline
-#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
-#define _REENTRANT
-#endif
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>],
-[int skr;
- struct hostent *foo = gethostbyaddr_r((const char *) 0,
- 0, 0, (struct hostent *) 0, (char *) NULL, 0, &skr); return (foo == 0);],
-mysql_cv_gethost_style=solaris, mysql_cv_gethost_style=other))
-AC_LANG_RESTORE
-CXXFLAGS="$ac_save_CXXFLAGS"
-if test "$mysql_cv_gethost_style" = "solaris"
-then
- AC_DEFINE(HAVE_SOLARIS_STYLE_GETHOST)
-fi
-
-#---START: Used in for client configure
-
-# Check definition of gethostbyname_r (glibc2.0.100 is different from Solaris)
-ac_save_CXXFLAGS="$CXXFLAGS"
-AC_CACHE_CHECK([style of gethostname_r routines], mysql_cv_gethostname_style,
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
-then
- CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'`
-fi
-AC_TRY_COMPILE(
-[#undef inline
-#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
-#define _REENTRANT
-#endif
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>],
-[int skr;
-
- skr = gethostbyname_r((const char *) 0,
- (struct hostent*) 0, (char*) 0, 0, (struct hostent **) 0, &skr);],
-mysql_cv_gethostname_style=glibc2, mysql_cv_gethostname_style=other))
-AC_LANG_RESTORE
-CXXFLAGS="$ac_save_CXXFLAGS"
-if test "$mysql_cv_gethostname_style" = "glibc2"
-then
- AC_DEFINE(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE)
-fi
-
-# Check 3rd argument of getthostbyname_r
-ac_save_CXXFLAGS="$CXXFLAGS"
-AC_CACHE_CHECK([3 argument to gethostname_r routines], mysql_cv_gethostname_arg,
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
-then
- CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'`
-fi
-AC_TRY_COMPILE(
-[#undef inline
-#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
-#define _REENTRANT
-#endif
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>],
-[int skr;
-
- skr = gethostbyname_r((const char *) 0, (struct hostent*) 0, (struct hostent_data*) 0);],
-mysql_cv_gethostname_arg=hostent_data, mysql_cv_gethostname_arg=char))
-AC_LANG_RESTORE
-CXXFLAGS="$ac_save_CXXFLAGS"
-if test "$mysql_cv_gethostname_arg" = "hostent_data"
-then
- AC_DEFINE(HAVE_GETHOSTBYNAME_R_RETURN_INT)
-fi
-
-
-if test "$with_mit_threads" = "no"
-then
- # Check definition of pthread_getspecific
- AC_CACHE_CHECK("args to pthread_getspecific", mysql_cv_getspecific_args,
- AC_TRY_COMPILE(
-[#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
-#define _REENTRANT
-#endif
-#define _POSIX_PTHREAD_SEMANTICS
-#include <pthread.h> ],
-[ void *pthread_getspecific(pthread_key_t key);
-pthread_getspecific((pthread_key_t) NULL); ],
-mysql_cv_getspecific_args=POSIX, mysql_cv_getspecific_args=other))
- if test "$mysql_cv_getspecific_args" = "other"
- then
- AC_DEFINE(HAVE_NONPOSIX_PTHREAD_GETSPECIFIC)
- fi
-
- # Check definition of pthread_mutex_init
- AC_CACHE_CHECK("args to pthread_mutex_init", mysql_cv_mutex_init_args,
- AC_TRY_COMPILE(
-[#if !defined(SCO) && !defined(__osf__)
-#define _REENTRANT
-#endif
-#define _POSIX_PTHREAD_SEMANTICS
-#include <pthread.h> ],
-[
- pthread_mutexattr_t attr;
- pthread_mutex_t mp;
- pthread_mutex_init(&mp,&attr); ],
-mysql_cv_mutex_init_args=POSIX, mysql_cv_mutex_init_args=other))
- if test "$mysql_cv_mutex_init_args" = "other"
- then
- AC_DEFINE(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT)
- fi
-fi
-#---END:
-
-#---START: Used in for client configure
-# Check definition of readdir_r
-AC_CACHE_CHECK("args to readdir_r", mysql_cv_readdir_r,
-AC_TRY_LINK(
-[#if !defined(SCO) && !defined(__osf__)
-#define _REENTRANT
-#endif
-#define _POSIX_PTHREAD_SEMANTICS
-#include <pthread.h>
-#include <dirent.h>],
-[ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
-readdir_r((DIR *) NULL, (struct dirent *) NULL, (struct dirent **) NULL); ],
-mysql_cv_readdir_r=POSIX, mysql_cv_readdir_r=other))
-if test "$mysql_cv_readdir_r" = "POSIX"
-then
- AC_DEFINE(HAVE_READDIR_R)
-fi
-
-# Check definition of posix sigwait()
-AC_CACHE_CHECK("style of sigwait", mysql_cv_sigwait,
-AC_TRY_LINK(
-[#if !defined(SCO) && !defined(__osf__)
-#define _REENTRANT
-#endif
-#define _POSIX_PTHREAD_SEMANTICS
-#include <pthread.h>
-#include <signal.h>],
-[#ifndef _AIX
-sigset_t set;
-int sig;
-sigwait(&set,&sig);
-#endif],
-mysql_cv_sigwait=POSIX, mysql_cv_sigwait=other))
-if test "$mysql_cv_sigwait" = "POSIX"
-then
- AC_DEFINE(HAVE_SIGWAIT)
-fi
-
-if test "$mysql_cv_sigwait" != "POSIX"
-then
-unset mysql_cv_sigwait
-# Check definition of posix sigwait()
-AC_CACHE_CHECK("style of sigwait", mysql_cv_sigwait,
-AC_TRY_LINK(
-[#if !defined(SCO) && !defined(__osf__)
-#define _REENTRANT
-#endif
-#define _POSIX_PTHREAD_SEMANTICS
-#include <pthread.h>
-#include <signal.h>],
-[sigset_t set;
-int sig;
-sigwait(&set);],
-mysql_cv_sigwait=NONPOSIX, mysql_cv_sigwait=other))
-if test "$mysql_cv_sigwait" = "NONPOSIX"
-then
- AC_DEFINE(HAVE_NONPOSIX_SIGWAIT)
-fi
-fi
-#---END:
-
-# Check if pthread_attr_setscope() exists
-AC_CACHE_CHECK("for pthread_attr_setscope", mysql_cv_pthread_attr_setscope,
-AC_TRY_LINK(
-[#if !defined(SCO) && !defined(__osf__)
-#define _REENTRANT
-#endif
-#define _POSIX_PTHREAD_SEMANTICS
-#include <pthread.h>],
-[pthread_attr_t thr_attr;
-pthread_attr_setscope(&thr_attr,0);],
-mysql_cv_pthread_attr_setscope=yes, mysql_cv_pthread_attr_setscope=no))
-if test "$mysql_cv_pthread_attr_setscope" = "yes"
-then
- AC_DEFINE(HAVE_PTHREAD_ATTR_SETSCOPE)
-fi
-
-# Check for bad includes
-AC_MSG_CHECKING("can netinet files be included")
-AC_TRY_COMPILE(
-[#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>],
-[ printf("1\n"); ],
-netinet_inc=yes, netinet_inc=no)
-if test "$netinet_inc" = "no"
-then
- AC_DEFINE(HAVE_BROKEN_NETINET_INCLUDES)
-fi
-AC_MSG_RESULT("$netinet_inc")
-
-# Some usefull subst
-AC_SUBST(CC)
-AC_SUBST(GXX)
-
-# Output results
-AC_OUTPUT(Makefile dnl
- , , [
- test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
- ])
diff --git a/ndb/config/type_kernel.mk.am b/ndb/config/type_kernel.mk.am
new file mode 100644
index 00000000000..703876ee2e9
--- /dev/null
+++ b/ndb/config/type_kernel.mk.am
@@ -0,0 +1,18 @@
+
+INCLUDES += \
+ -I$(srcdir) -I$(top_srcdir)/include \
+ -I$(top_srcdir)/ndb/include \
+ -I$(top_srcdir)/ndb/src/kernel/vm \
+ -I$(top_srcdir)/ndb/src/kernel/error \
+ -I$(top_srcdir)/ndb/src/kernel \
+ -I$(top_srcdir)/ndb/include/kernel \
+ -I$(top_srcdir)/ndb/include/transporter \
+ -I$(top_srcdir)/ndb/include/debugger \
+ -I$(top_srcdir)/ndb/include/mgmapi \
+ -I$(top_srcdir)/ndb/include/mgmcommon \
+ -I$(top_srcdir)/ndb/include/ndbapi \
+ -I$(top_srcdir)/ndb/include/util \
+ -I$(top_srcdir)/ndb/include/portlib \
+ -I$(top_srcdir)/ndb/include/logger
+
+#AM_LDFLAGS = @ndb_ldflags@
diff --git a/ndb/config/type_mgmapiclient.mk.am b/ndb/config/type_mgmapiclient.mk.am
new file mode 100644
index 00000000000..1ef4a81d67e
--- /dev/null
+++ b/ndb/config/type_mgmapiclient.mk.am
@@ -0,0 +1,2 @@
+
+INCLUDES += -I$(top_srcdir)/ndb/include/mgmapi
diff --git a/ndb/config/type_ndbapi.mk.am b/ndb/config/type_ndbapi.mk.am
new file mode 100644
index 00000000000..ed648273aea
--- /dev/null
+++ b/ndb/config/type_ndbapi.mk.am
@@ -0,0 +1,12 @@
+
+INCLUDES += \
+ -I$(srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/ndb/include \
+ -I$(top_srcdir)/ndb/include/kernel \
+ -I$(top_srcdir)/ndb/include/transporter \
+ -I$(top_srcdir)/ndb/include/debugger \
+ -I$(top_srcdir)/ndb/include/mgmapi \
+ -I$(top_srcdir)/ndb/include/mgmcommon \
+ -I$(top_srcdir)/ndb/include/ndbapi \
+ -I$(top_srcdir)/ndb/include/util \
+ -I$(top_srcdir)/ndb/include/portlib \
+ -I$(top_srcdir)/ndb/include/logger
diff --git a/ndb/config/type_ndbapiclient.mk.am b/ndb/config/type_ndbapiclient.mk.am
new file mode 100644
index 00000000000..88b57e49e19
--- /dev/null
+++ b/ndb/config/type_ndbapiclient.mk.am
@@ -0,0 +1,2 @@
+
+INCLUDES += -I$(top_srcdir)/ndb/include/ndbapi
diff --git a/ndb/config/type_ndbapitest.mk.am b/ndb/config/type_ndbapitest.mk.am
new file mode 100644
index 00000000000..3132dd30f0b
--- /dev/null
+++ b/ndb/config/type_ndbapitest.mk.am
@@ -0,0 +1,11 @@
+
+LDADD += $(top_builddir)/ndb/test/src/libNDBT.a \
+ $(top_builddir)/ndb/src/libndbclient.la
+
+INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \
+ -I$(top_srcdir)/ndb/include \
+ -I$(top_srcdir)/ndb/include/ndbapi \
+ -I$(top_srcdir)/ndb/include/util \
+ -I$(top_srcdir)/ndb/include/portlib \
+ -I$(top_srcdir)/ndb/test/include \
+ -I$(top_srcdir)/ndb/include/mgmapi
diff --git a/ndb/config/type_ndbapitools.mk.am b/ndb/config/type_ndbapitools.mk.am
new file mode 100644
index 00000000000..a8b511d3637
--- /dev/null
+++ b/ndb/config/type_ndbapitools.mk.am
@@ -0,0 +1,10 @@
+
+LDADD += $(top_builddir)/ndb/src/libndbclient.la
+
+INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \
+ -I$(top_srcdir)/ndb/include \
+ -I$(top_srcdir)/ndb/include/ndbapi \
+ -I$(top_srcdir)/ndb/include/util \
+ -I$(top_srcdir)/ndb/include/portlib \
+ -I$(top_srcdir)/ndb/test/include \
+ -I$(top_srcdir)/ndb/include/mgmapi
diff --git a/ndb/config/type_util.mk.am b/ndb/config/type_util.mk.am
new file mode 100644
index 00000000000..0dfa77b7a7c
--- /dev/null
+++ b/ndb/config/type_util.mk.am
@@ -0,0 +1,6 @@
+
+INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \
+ -I$(top_srcdir)/ndb/include \
+ -I$(top_srcdir)/ndb/include/util \
+ -I$(top_srcdir)/ndb/include/portlib \
+ -I$(top_srcdir)/ndb/include/logger
diff --git a/ndb/configure b/ndb/configure
deleted file mode 100755
index f0fc197f45e..00000000000
--- a/ndb/configure
+++ /dev/null
@@ -1,33 +0,0 @@
-#! /bin/sh
-
-if [ $# -gt 0 -a "$1" = "-p" ]
-then
- shift
- NDB_TOP=$1
- shift
-else
- NDB_TOP=`pwd`
-fi
-
-cd $NDB_TOP
-NDB_TOP=`pwd`
-
-for i in `find . -name 'Makefile' -exec dirname {} \;`
-do
- cd $i
- rel_path=.
- while [ $NDB_TOP != `pwd` ]
- do
- rel_path=$rel_path"/.."
- cd ..
- done
-
- (
- echo "NDB_TOP=$rel_path"
- echo "include $rel_path/Defs.mk"
- ) > $i/.defs.mk
-done
-
-( cd config ; aclocal ; automake ; aclocal ; autoconf ; ./configure )
-export NDB_TOP
-. config/GuessConfig.sh $*
diff --git a/ndb/docs/Makefile b/ndb/docs/Makefile
deleted file mode 100644
index a2139b66044..00000000000
--- a/ndb/docs/Makefile
+++ /dev/null
@@ -1,97 +0,0 @@
-include .defs.mk
-#
-# hack before full autoconf
-replace-targets := all clean
-first-docs: all
-
-include $(NDB_TOP)/Epilogue.mk
-
-all: ndbapidoc mgmapidoc
-
-DOXYGEN = doxygen
-DOXYTOP = $(shell cd $(NDB_TOP); pwd)/docs
-DOXYDIR = $(DOXYTOP)/doxygen
-DOXYTMP = $(DOXYTOP)/.doxytmp
-DOXYOUT = $(DOXYTOP)/.doxyout
-
-clean:
- rm -rf ndbapi.pdf ndbapi.html mgmapi.pdf mgmapi.html
- rm -rf $(DOXYTMP) $(DOXYOUT)
-
-###
-#
-# NDB API Programmer's Guide
-#
-ndbapidoc: ndbapi.pdf
-
-ndbapi.pdf: $(NDB_TOP)/include/ndb_version.h
- @set -x; \
- rm -rf ndbapi.pdf ndbapi.html; \
- rm -rf $(DOXYTMP) $(DOXYOUT); \
- mkdir -p $(DOXYTMP) $(DOXYOUT); \
- (cd $(NDB_TOP)/include/ndbapi && \
- find . -type f -print | \
- grep -v /SCCS | \
- cpio -pdm $(DOXYTMP)); \
- (cd $(NDB_TOP)/examples && \
- cp -p */*.[ch]pp $(DOXYTMP)); \
- $(DOXYDIR)/predoxy.pl; \
- mv footer.html $(DOXYTMP); \
- (cd $(DOXYTMP) && \
- $(DOXYGEN) $(DOXYDIR)/Doxyfile.ndbapi); \
- $(DOXYDIR)/postdoxy.pl $(DOXYOUT)/ndbapi.latex "NDB API Programmer Guide"; \
- (cd $(DOXYOUT) && \
- find ndbapi.html -print | cpio -pdm $(DOXYTOP)); \
- (cd $(DOXYOUT)/ndbapi.latex && \
- pdflatex refman.tex && makeindex refman && pdflatex refman.tex && \
- cp -p refman.pdf $(DOXYTOP)/ndbapi.pdf);
-
-###
-#
-# MGM API Guide
-#
-mgmapidoc: mgmapi.pdf
-
-mgmapi.pdf: $(NDB_TOP)/include/ndb_version.h
- @set -x; \
- rm -rf mgmapi.pdf mgmapi.html; \
- rm -rf $(DOXYTMP) $(DOXYOUT); \
- mkdir -p $(DOXYTMP) $(DOXYOUT); \
- (cd $(NDB_TOP)/include/mgmapi && \
- find . -type f -print | \
- grep -v /SCCS | \
- cpio -pdm $(DOXYTMP)); \
- $(DOXYDIR)/predoxy.pl; \
- mv footer.html $(DOXYTMP); \
- (cd $(DOXYTMP) && \
- $(DOXYGEN) $(DOXYDIR)/Doxyfile.mgmapi); \
- $(DOXYDIR)/postdoxy.pl $(OUTDIR)/mgmapi.latex "NDB Cluster MGM API Guide"; \
- (cd $(DOXYOUT) && \
- find mgmapi.html -print | cpio -pdm $(DOXYTOP)); \
- (cd $(DOXYOUT)/mgmapi.latex && \
- pdflatex refman.tex && makeindex refman && pdflatex refman.tex && \
- cp -p refman.pdf $(DOXYTOP)/mgmapi.pdf);
-
-###
-#
-# Complete Source Browser except for
-# ndbapi odbc test tools win32 lib examples docs CVS config bin
-# include/ndbapi
-# include/newtonapi src/newtonapi
-# include/mgmapi src/mgmapi
-# src/client
-ndbdoc: DUMMY
- mkdir -p $(OUTDIR)
- cd $(NDB_TOP) ; $(DOXYGEN) $(DOXYDIR)/Doxyfile.ndb
-
-###
-#
-# odbcdoc - Complete Source Browser for NDB ODBC (src/client/odbc)
-
-odbcdoc: DUMMY
- mkdir -p $(OUTDIR)
- cd $(NDB_TOP) ; $(DOXYGEN) $(DOXYDIR)/Doxyfile.odbc
-
-testdoc: DUMMY
- mkdir -p $(OUTDIR)
- cd $(NDB_TOP) ; $(DOXYGEN) $(DOXYDIR)/Doxyfile.test
diff --git a/ndb/docs/Makefile.am b/ndb/docs/Makefile.am
new file mode 100644
index 00000000000..554b2fb256e
--- /dev/null
+++ b/ndb/docs/Makefile.am
@@ -0,0 +1,102 @@
+DOXYDIR = doxygen
+noinst_HEADERS = $(DOXYDIR)/predoxy.pl $(DOXYDIR)/postdoxy.pl $(DOXYDIR)/Doxyfile.ndbapi $(DOXYDIR)/Doxyfile.mgmapi $(DOXYDIR)/header.ndbapi.tex $(DOXYDIR)/header.mgmapi.tex
+
+all: do-check ndbapidoc mgmapidoc
+
+DOXYTMP = .doxytmp
+DOXYOUT = .doxyout
+
+NDB_RELEASE = @NDB_VERSION_MAJOR@.@NDB_VERSION_MINOR@.@NDB_VERSION_BUILD@-@NDB_VERSION_STATUS@
+
+clean:
+ rm -rf ndbapi.pdf ndbapi.html mgmapi.pdf mgmapi.html
+ rm -rf $(DOXYTMP) $(DOXYOUT)
+
+do-check:
+ @set -x; \
+ if test @PERL@ = no ; then \
+ echo "Perl needed to make docs"; \
+ exit 1; \
+ fi; \
+ if test @DOXYGEN@ = no ; then \
+ echo "Doxygen needed to make docs"; \
+ exit 1; \
+ fi; \
+ if test @PDFLATEX@ = no ; then \
+ echo "Pdflatex needed to make docs"; \
+ exit 1; \
+ fi; \
+ if test @MAKEINDEX@ = no ; then \
+ echo "Makeindex needed to make docs"; \
+ exit 1; \
+ fi;
+###
+#
+# NDB API Programmer's Guide
+#
+ndbapidoc: ndbapi.pdf
+
+ndbapi.pdf: $(noinst_HEADERS)
+ @set -x; \
+ export NDB_RELEASE=$(NDB_RELEASE) \
+ @RM@ -f ndbapi.pdf ndbapi.html; \
+ @RM@ -rf $(DOXYTMP) $(DOXYOUT); \
+ mkdir -p $(DOXYTMP) $(DOXYOUT); \
+ @CP@ $(top_srcdir)/ndb/include/ndbapi/* $(DOXYTMP); \
+ @CP@ $(top_srcdir)/ndb/examples/*/*.[ch]pp $(DOXYTMP); \
+ @PERL@ $(DOXYDIR)/predoxy.pl; \
+ mv footer.html $(DOXYTMP); \
+ (cd $(DOXYTMP) ; @DOXYGEN@ ../$(DOXYDIR)/Doxyfile.ndbapi); \
+ @PERL@ $(DOXYDIR)/postdoxy.pl $(DOXYOUT)/ndbapi.latex "NDB API Programmer Guide"; \
+ (cd $(DOXYOUT) && \
+ find ndbapi.html -print | cpio -pdm ..); \
+ (cd $(DOXYOUT)/ndbapi.latex && \
+ @PDFLATEX@ refman.tex && @MAKEINDEX@ refman && @PDFLATEX@ refman.tex && \
+ cp -p refman.pdf ../../ndbapi.pdf);
+
+###
+#
+# MGM API Guide
+#
+mgmapidoc: mgmapi.pdf
+
+mgmapi.pdf: $(noinst_HEADERS)
+ @set -x; \
+ export NDB_RELEASE=$(NDB_RELEASE) \
+ @RM@ -f mgmapi.pdf mgmapi.html; \
+ @RM@ -rf $(DOXYTMP) $(DOXYOUT); \
+ mkdir -p $(DOXYTMP) $(DOXYOUT); \
+ @CP@ $(top_srcdir)/ndb/include/mgmapi/* $(DOXYTMP); \
+ @PERL@ $(DOXYDIR)/predoxy.pl; \
+ mv footer.html $(DOXYTMP); \
+ (cd $(DOXYTMP) ; @DOXYGEN@ ../$(DOXYDIR)/Doxyfile.mgmapi); \
+ @PERL@ $(DOXYDIR)/postdoxy.pl $(DOXYOUT)/mgmapi.latex "NDB Cluster MGM API Guide"; \
+ (cd $(DOXYOUT) && \
+ find mgmapi.html -print | cpio -pdm ..); \
+ (cd $(DOXYOUT)/mgmapi.latex && \
+ @PDFLATEX@ refman.tex && @MAKEINDEX@ refman && @PDFLATEX@ refman.tex && \
+ cp -p refman.pdf ../../mgmapi.pdf);
+
+###
+#
+# Complete Source Browser except for
+# ndbapi odbc test tools win32 lib examples docs CVS config bin
+# include/ndbapi
+# include/newtonapi src/newtonapi
+# include/mgmapi src/mgmapi
+# src/client
+ndbdoc: DUMMY
+ mkdir -p $(OUTDIR)
+ cd $(top_srcdir)/ndb ; $(DOXYGEN) $(DOXYDIR)/Doxyfile.ndb
+
+###
+#
+# odbcdoc - Complete Source Browser for NDB ODBC (src/client/odbc)
+
+odbcdoc: DUMMY
+ mkdir -p $(OUTDIR)
+ cd $(top_srcdir)/ndb ; $(DOXYGEN) $(DOXYDIR)/Doxyfile.odbc
+
+testdoc: DUMMY
+ mkdir -p $(OUTDIR)
+ cd $(top_srcdir)/ndb ; $(DOXYGEN) $(DOXYDIR)/Doxyfile.test
diff --git a/ndb/docs/doxygen/postdoxy.pl b/ndb/docs/doxygen/postdoxy.pl
index 95062d1899f..ad0edb44a31 100755
--- a/ndb/docs/doxygen/postdoxy.pl
+++ b/ndb/docs/doxygen/postdoxy.pl
@@ -1,4 +1,3 @@
-#!/usr/local/bin/perl
#
# Written by Lars Thalmann, lars@mysql.com, 2003.
#
diff --git a/ndb/docs/doxygen/predoxy.pl b/ndb/docs/doxygen/predoxy.pl
index 461ad02478a..8dad1d964d0 100755
--- a/ndb/docs/doxygen/predoxy.pl
+++ b/ndb/docs/doxygen/predoxy.pl
@@ -1,4 +1,3 @@
-#!/usr/local/bin/perl
#
# Written by Lars Thalmann, lars@mysql.com, 2003.
#
diff --git a/ndb/env.sh b/ndb/env.sh
deleted file mode 100644
index c84a61b2c6f..00000000000
--- a/ndb/env.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-
-NDB_TOP=`pwd`
-export NDB_TOP
-
-NDB_PROJ_HOME=$NDB_TOP/home
-export NDB_PROJ_HOME
-
diff --git a/ndb/include/Makefile.am b/ndb/include/Makefile.am
new file mode 100644
index 00000000000..2565a78238b
--- /dev/null
+++ b/ndb/include/Makefile.am
@@ -0,0 +1,42 @@
+
+include $(top_srcdir)/ndb/config/common.mk.am
+
+ndbinclude_HEADERS = \
+ndb_types.h \
+ndb_version.h
+
+ndbapiinclude_HEADERS = \
+ndbapi/ndbapi_limits.h \
+ndbapi/Ndb.hpp \
+ndbapi/NdbApi.hpp \
+ndbapi/NdbConnection.hpp \
+ndbapi/NdbCursorOperation.hpp \
+ndbapi/NdbDictionary.hpp \
+ndbapi/NdbError.hpp \
+ndbapi/NdbEventOperation.hpp \
+ndbapi/NdbIndexOperation.hpp \
+ndbapi/NdbOperation.hpp \
+ndbapi/NdbBlob.hpp \
+ndbapi/NdbPool.hpp \
+ndbapi/NdbRecAttr.hpp \
+ndbapi/NdbReceiver.hpp \
+ndbapi/NdbResultSet.hpp \
+ndbapi/NdbScanFilter.hpp \
+ndbapi/NdbScanOperation.hpp \
+ndbapi/ndberror.h
+
+mgmapiinclude_HEADERS = \
+mgmapi/mgmapi.h \
+mgmapi/mgmapi_debug.h
+
+noinst_HEADERS = \
+ndb_global.h \
+ndb_net.h \
+mgmapi/mgmapi_config_parameters.h \
+mgmapi/mgmapi_config_parameters_debug.h
+
+EXTRA_DIST = debugger editline kernel logger mgmcommon \
+portlib transporter util
+
+dist-hook:
+ -rm -rf `find $(distdir) -type d -name SCCS`
diff --git a/ndb/include/kernel/BlockNumbers.h b/ndb/include/kernel/BlockNumbers.h
index 84c3fc656a9..e89a82ee0cb 100644
--- a/ndb/include/kernel/BlockNumbers.h
+++ b/ndb/include/kernel/BlockNumbers.h
@@ -37,6 +37,7 @@
#define DBTUP 0xF9
#define DBDICT 0xFA
#define NDBCNTR 0xFB
+#define CNTR 0xFB
#define QMGR 0xFC
#define NDBFS 0xFD
#define CMVMI 0xFE
diff --git a/ndb/include/kernel/GlobalSignalNumbers.h b/ndb/include/kernel/GlobalSignalNumbers.h
index 87385de1f14..7b70f4c3ac0 100644
--- a/ndb/include/kernel/GlobalSignalNumbers.h
+++ b/ndb/include/kernel/GlobalSignalNumbers.h
@@ -177,43 +177,43 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_API_FAILCONF 113
#define GSN_API_FAILREQ 114
-#define GSN_APPL_CHANGEREP 115
+#define GSN_CNTR_START_REQ 115
// 116 not unused
-#define GSN_APPL_HB 117
-#define GSN_APPL_HBREQ 118
-#define GSN_APPL_REGCONF 119
-#define GSN_APPL_REGREF 120
-#define GSN_APPL_REGREQ 121
-#define GSN_APPL_RUN 122
-#define GSN_APPL_STARTCONF 123
-#define GSN_APPL_STARTREG 124
+#define GSN_CNTR_START_REF 117
+#define GSN_CNTR_START_CONF 118
+#define GSN_CNTR_START_REP 119
+// 120 unused
+// 121 unused
+// 122 unused
+// 123 unused
+// 124 unused
#define GSN_CHECK_LCP_STOP 125
-#define GSN_CLOSE_COMCONF 126
-#define GSN_CLOSE_COMREQ 127
-#define GSN_CM_ACKADD 128
-#define GSN_CM_ACKALARM 129
-#define GSN_CM_ADD 130
-#define GSN_CM_APPCHG 131
+#define GSN_CLOSE_COMCONF 126 // local
+#define GSN_CLOSE_COMREQ 127 // local
+#define GSN_CM_ACKADD 128 // distr.
+// 129 unused
+#define GSN_CM_ADD 130 // distr.
+// 131 unused
// 132 not unused
// 133 not unused
-#define GSN_CM_HEARTBEAT 134
-#define GSN_CM_INFOCONF 135
-#define GSN_CM_INFOREQ 136
-#define GSN_CM_INIT 137
-#define GSN_CM_NODEINFOCONF 138
-#define GSN_CM_NODEINFOREF 139
-#define GSN_CM_NODEINFOREQ 140
-#define GSN_CM_REGCONF 141
-#define GSN_CM_REGREF 142
-#define GSN_CM_REGREQ 143
-#define GSN_CM_RUN 144
-#define GSN_CMVMI_CFGCONF 145
-#define GSN_CMVMI_CFGREQ 146
-#define GSN_CNTR_CHANGEREP 147
-#define GSN_CNTR_MASTERCONF 148
-#define GSN_CNTR_MASTERREF 149
-#define GSN_CNTR_MASTERREQ 150
-#define GSN_CNTR_WAITREP 151
+#define GSN_CM_HEARTBEAT 134 // distr.
+// 135 unused
+// 136 unused
+// 137 unused
+#define GSN_CM_NODEINFOCONF 138 // distr.
+#define GSN_CM_NODEINFOREF 139 // distr.
+#define GSN_CM_NODEINFOREQ 140 // distr.
+#define GSN_CM_REGCONF 141 // distr.
+#define GSN_CM_REGREF 142 // distr.
+#define GSN_CM_REGREQ 143 // distr.
+// 144 unused
+// 145 unused
+// 146 unused
+#define GSN_CM_ADD_REP 147 // local
+// 148 unused
+// 149 unused
+// 150 unused
+#define GSN_CNTR_WAITREP 151 // distr.
#define GSN_COMMIT 152
#define GSN_COMMIT_FAILCONF 153
#define GSN_COMMIT_FAILREQ 154
@@ -426,11 +426,13 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_NEXT_SCANREF 331
#define GSN_NEXT_SCANREQ 332
#define GSN_NEXTOPERATION 333
-#define GSN_SIZEALT_ACK 334
-#define GSN_SIZEALT_REP 335
-#define GSN_NODE_STATESCONF 336
-#define GSN_NODE_STATESREF 337
-#define GSN_NODE_STATESREQ 338
+
+#define GSN_READ_CONFIG_REQ 334 // new name for sizealt, local
+#define GSN_READ_CONFIG_CONF 335 // new name for sizealt, local
+
+// 336 unused
+// 337 unused
+// 338 unused
#define GSN_OPEN_COMCONF 339
#define GSN_OPEN_COMREF 340
#define GSN_OPEN_COMREQ 341
@@ -511,8 +513,8 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_TEST_ORD 407
#define GSN_TESTSIG 408
#define GSN_TIME_SIGNAL 409
-#define GSN_VOTE_MASTERORD 410
-// 411 unused
+// 410 unused
+// 411 unused
// 412 unused
#define GSN_TUP_ABORTREQ 414
#define GSN_TUP_ADD_ATTCONF 415
@@ -580,7 +582,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_CHECKNODEGROUPSREQ 471
#define GSN_CHECKNODEGROUPSCONF 472
-#define GSN_ARBIT_CFG 473
+// 473 unused
#define GSN_ARBIT_PREPREQ 474
#define GSN_ARBIT_PREPCONF 475
#define GSN_ARBIT_PREPREF 476
diff --git a/ndb/include/kernel/LogLevel.hpp b/ndb/include/kernel/LogLevel.hpp
index 3363dc2befd..10cd0d43bee 100644
--- a/ndb/include/kernel/LogLevel.hpp
+++ b/ndb/include/kernel/LogLevel.hpp
@@ -18,6 +18,7 @@
#define _LOG_LEVEL_HPP
#include <ndb_global.h>
+#include <mgmapi_config_parameters.h>
/**
*
@@ -45,53 +46,60 @@ public:
*/
LogLevel & operator= (const LogLevel &);
+ static const Uint32 MIN_LOGLEVEL_ID = CFG_LOGLEVEL_STARTUP;
+
enum EventCategory {
/**
* Events during all kind of startups
*/
- llStartUp = 0,
+ llStartUp = CFG_LOGLEVEL_STARTUP - MIN_LOGLEVEL_ID,
/**
* Events during shutdown
*/
- llShutdown = 1,
+ llShutdown = CFG_LOGLEVEL_SHUTDOWN - MIN_LOGLEVEL_ID,
/**
* Transaction statistics
* Job level
* TCP/IP speed
*/
- llStatistic = 2,
+ llStatistic = CFG_LOGLEVEL_STATISTICS - MIN_LOGLEVEL_ID,
/**
* Checkpoints
*/
- llCheckpoint = 3,
+ llCheckpoint = CFG_LOGLEVEL_CHECKPOINT - MIN_LOGLEVEL_ID,
/**
* Events during node restart
*/
- llNodeRestart = 4,
+ llNodeRestart = CFG_LOGLEVEL_NODERESTART - MIN_LOGLEVEL_ID,
/**
* Events related to connection / communication
*/
- llConnection = 5,
+ llConnection = CFG_LOGLEVEL_CONNECTION - MIN_LOGLEVEL_ID,
/**
* Assorted event w.r.t unexpected happenings
*/
- llError = 6,
+ llError = CFG_LOGLEVEL_ERROR - MIN_LOGLEVEL_ID,
+
+ /**
+ * Assorted event w.r.t warning
+ */
+ llWarning = CFG_LOGLEVEL_WARNING - MIN_LOGLEVEL_ID,
/**
* Assorted event w.r.t information
*/
- llInfo = 7,
+ llInfo = CFG_LOGLEVEL_INFO - MIN_LOGLEVEL_ID,
/**
* Events related to global replication
*/
- llGrep = 8
+ llGrep = CFG_LOGLEVEL_GREP - MIN_LOGLEVEL_ID
};
struct LogLevelCategoryName {
@@ -107,7 +115,7 @@ public:
/**
* No of categories
*/
-#define _LOGLEVEL_CATEGORIES 9
+#define _LOGLEVEL_CATEGORIES 10
static const Uint32 LOGLEVEL_CATEGORIES = _LOGLEVEL_CATEGORIES;
void clear();
diff --git a/ndb/include/kernel/kernel_config_parameters.h b/ndb/include/kernel/kernel_config_parameters.h
new file mode 100644
index 00000000000..2f63efa4b6c
--- /dev/null
+++ b/ndb/include/kernel/kernel_config_parameters.h
@@ -0,0 +1,56 @@
+#ifndef DB_CONFIG_PARAMTERS_H
+#define DB_CONFIG_PARAMTERS_H
+
+#define PRIVATE_BASE 14000
+
+#define CFG_ACC_DIR_RANGE (PRIVATE_BASE + 1)
+#define CFG_ACC_DIR_ARRAY (PRIVATE_BASE + 2)
+#define CFG_ACC_FRAGMENT (PRIVATE_BASE + 3)
+#define CFG_ACC_OP_RECS (PRIVATE_BASE + 4)
+#define CFG_ACC_OVERFLOW_RECS (PRIVATE_BASE + 5)
+#define CFG_ACC_PAGE8 (PRIVATE_BASE + 6)
+#define CFG_ACC_ROOT_FRAG (PRIVATE_BASE + 7)
+#define CFG_ACC_TABLE (PRIVATE_BASE + 8)
+#define CFG_ACC_SCAN (PRIVATE_BASE + 9)
+
+#define CFG_DICT_ATTRIBUTE (PRIVATE_BASE + 10)
+#define CFG_DICT_CONNECT (PRIVATE_BASE + 11)
+#define CFG_DICT_FRAG_CONNECT (PRIVATE_BASE + 12)
+#define CFG_DICT_TABLE (PRIVATE_BASE + 13)
+#define CFG_DICT_TC_CONNECT (PRIVATE_BASE + 14)
+
+#define CFG_DIH_API_CONNECT (PRIVATE_BASE + 15)
+#define CFG_DIH_CONNECT (PRIVATE_BASE + 16)
+#define CFG_DIH_FRAG_CONNECT (PRIVATE_BASE + 17)
+#define CFG_DIH_MORE_NODES (PRIVATE_BASE + 18)
+#define CFG_DIH_REPLICAS (PRIVATE_BASE + 19)
+#define CFG_DIH_TABLE (PRIVATE_BASE + 20)
+
+#define CFG_LQH_FRAG (PRIVATE_BASE + 21)
+#define CFG_LQH_CONNECT (PRIVATE_BASE + 22)
+#define CFG_LQH_TABLE (PRIVATE_BASE + 23)
+#define CFG_LQH_TC_CONNECT (PRIVATE_BASE + 24)
+#define CFG_LQH_REPLICAS (PRIVATE_BASE + 25)
+#define CFG_LQH_LOG_FILES (PRIVATE_BASE + 26)
+#define CFG_LQH_SCAN (PRIVATE_BASE + 27)
+
+#define CFG_TC_API_CONNECT (PRIVATE_BASE + 28)
+#define CFG_TC_TC_CONNECT (PRIVATE_BASE + 29)
+#define CFG_TC_TABLE (PRIVATE_BASE + 30)
+#define CFG_TC_SCAN (PRIVATE_BASE + 31)
+#define CFG_TC_LOCAL_SCAN (PRIVATE_BASE + 32)
+
+#define CFG_TUP_FRAG (PRIVATE_BASE + 33)
+#define CFG_TUP_OP_RECS (PRIVATE_BASE + 34)
+#define CFG_TUP_PAGE (PRIVATE_BASE + 35)
+#define CFG_TUP_PAGE_RANGE (PRIVATE_BASE + 36)
+#define CFG_TUP_TABLE (PRIVATE_BASE + 37)
+#define CFG_TUP_TABLE_DESC (PRIVATE_BASE + 38)
+#define CFG_TUP_STORED_PROC (PRIVATE_BASE + 39)
+
+#define CFG_TUX_INDEX (PRIVATE_BASE + 40)
+#define CFG_TUX_FRAGMENT (PRIVATE_BASE + 41)
+#define CFG_TUX_ATTRIBUTE (PRIVATE_BASE + 42)
+#define CFG_TUX_SCAN_OP (PRIVATE_BASE + 43)
+
+#endif
diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h
index 65f729af1f2..68ffe310328 100644
--- a/ndb/include/kernel/ndb_limits.h
+++ b/ndb/include/kernel/ndb_limits.h
@@ -91,4 +91,9 @@
#define MAX_TTREE_PREF_SIZE 4 // words in min/max prefix each
#define MAX_TTREE_NODE_SLACK 3 // diff between max and min occupancy
+/*
+ * Blobs.
+ */
+#define NDB_BLOB_HEAD_SIZE 2 // sizeof(NdbBlob::Head) >> 2
+
#endif
diff --git a/ndb/include/kernel/signaldata/CheckNodeGroups.hpp b/ndb/include/kernel/signaldata/CheckNodeGroups.hpp
index 9b2f847e128..b3e79949c68 100644
--- a/ndb/include/kernel/signaldata/CheckNodeGroups.hpp
+++ b/ndb/include/kernel/signaldata/CheckNodeGroups.hpp
@@ -37,13 +37,11 @@ public:
Uint32 requestType; // direct flag, output code
Uint32 output;
};
- union {
- Uint32 nodeId; // nodeId input for GetNodeGroupMembers
- NodeBitmask mask; /* set of NDB nodes, input for ArbitCheck,
- * output for GetNodeGroupMembers
- */
- };
+ Uint32 nodeId; // nodeId input for GetNodeGroupMembers
+ NodeBitmask mask; /* set of NDB nodes, input for ArbitCheck,
+ * output for GetNodeGroupMembers
+ */
enum RequestType {
Direct = 0x1,
ArbitCheck = 0x2,
@@ -57,7 +55,7 @@ public:
Partitioning = 3 // possible network partitioning
};
- STATIC_CONST( SignalLength = 2 + NodeBitmask::Size );
+ STATIC_CONST( SignalLength = 3 + NodeBitmask::Size );
};
#endif
diff --git a/ndb/include/kernel/signaldata/CntrStart.hpp b/ndb/include/kernel/signaldata/CntrStart.hpp
new file mode 100644
index 00000000000..abdd1003c0f
--- /dev/null
+++ b/ndb/include/kernel/signaldata/CntrStart.hpp
@@ -0,0 +1,69 @@
+#ifndef CNTR_START_HPP
+#define CNTR_START_HPP
+
+#include <NodeBitmask.hpp>
+
+/**
+ *
+ */
+class CntrStartReq {
+ /**
+ * Sender(s) / Reciver(s)
+ */
+ friend class Ndbcntr;
+
+ friend bool printCNTR_START_REQ(FILE*, const Uint32 *, Uint32, Uint16);
+
+public:
+ STATIC_CONST( SignalLength = 3 );
+private:
+
+ Uint32 nodeId;
+ Uint32 startType;
+ Uint32 lastGci;
+};
+
+class CntrStartRef {
+ /**
+ * Sender(s) / Reciver(s)
+ */
+ friend class Ndbcntr;
+
+ friend bool printCNTR_START_REF(FILE*, const Uint32 *, Uint32, Uint16);
+public:
+ STATIC_CONST( SignalLength = 2 );
+
+ enum ErrorCode {
+ OK = 0,
+ NotMaster = 1,
+ StopInProgress = 2
+ };
+private:
+
+ Uint32 errorCode;
+ Uint32 masterNodeId;
+};
+
+class CntrStartConf {
+ /**
+ * Sender(s) / Reciver(s)
+ */
+ friend class Ndbcntr;
+ friend struct UpgradeStartup;
+
+ friend bool printCNTR_START_CONF(FILE*, const Uint32 *, Uint32, Uint16);
+
+public:
+ STATIC_CONST( SignalLength = 4 + 2 * NdbNodeBitmask::Size );
+
+private:
+
+ Uint32 startType;
+ Uint32 startGci;
+ Uint32 masterNodeId;
+ Uint32 noStartNodes;
+ Uint32 startedNodes[NdbNodeBitmask::Size];
+ Uint32 startingNodes[NdbNodeBitmask::Size];
+};
+
+#endif
diff --git a/ndb/include/kernel/signaldata/CreateEvnt.hpp b/ndb/include/kernel/signaldata/CreateEvnt.hpp
index 7398fb6d8cc..65a07c122a2 100644
--- a/ndb/include/kernel/signaldata/CreateEvnt.hpp
+++ b/ndb/include/kernel/signaldata/CreateEvnt.hpp
@@ -250,7 +250,7 @@ struct CreateEvntReq {
return tmp;
}
void setAttrListBitmask(const AttributeMask & val) {
- m_attrListBitmask = val;
+ AttributeMask::assign(m_attrListBitmask.data, val);
}
Uint32 getEventType() const {
return m_eventType;
diff --git a/ndb/include/kernel/signaldata/DictTabInfo.hpp b/ndb/include/kernel/signaldata/DictTabInfo.hpp
index 791388d5df8..67610f9d2be 100644
--- a/ndb/include/kernel/signaldata/DictTabInfo.hpp
+++ b/ndb/include/kernel/signaldata/DictTabInfo.hpp
@@ -307,7 +307,9 @@ public:
ExtBinary = NdbSqlUtil::Type::Binary,
ExtVarbinary = NdbSqlUtil::Type::Varbinary,
ExtDatetime = NdbSqlUtil::Type::Datetime,
- ExtTimespec = NdbSqlUtil::Type::Timespec
+ ExtTimespec = NdbSqlUtil::Type::Timespec,
+ ExtBlob = NdbSqlUtil::Type::Blob,
+ ExtClob = NdbSqlUtil::Type::Clob
};
// Attribute data interpretation
@@ -430,6 +432,13 @@ public:
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 12 * AttributeExtLength;
return true;
+ case DictTabInfo::ExtBlob:
+ case DictTabInfo::ExtClob:
+ AttributeType = DictTabInfo::StringType;
+ AttributeSize = DictTabInfo::an8Bit;
+ // head + inline part [ attr precision ]
+ AttributeArraySize = (NDB_BLOB_HEAD_SIZE << 2) + AttributeExtPrecision;
+ return true;
};
return false;
}
diff --git a/ndb/include/kernel/signaldata/EventSubscribeReq.hpp b/ndb/include/kernel/signaldata/EventSubscribeReq.hpp
index 2ac62be19a3..fd2821ea31d 100644
--- a/ndb/include/kernel/signaldata/EventSubscribeReq.hpp
+++ b/ndb/include/kernel/signaldata/EventSubscribeReq.hpp
@@ -39,7 +39,7 @@ class EventSubscribeReq {
friend class MgmtSrvr;
public:
- STATIC_CONST( SignalLength = 14 );
+ STATIC_CONST( SignalLength = 22 );
private:
/**
* Note: If you use the same blockRef as you have used earlier,
@@ -53,8 +53,8 @@ private:
*/
Uint32 noOfEntries;
- Uint32 theCategories[6];
- Uint32 theLevels[6];
+ Uint32 theCategories[10];
+ Uint32 theLevels[10];
};
#endif
diff --git a/ndb/include/kernel/signaldata/FsOpenReq.hpp b/ndb/include/kernel/signaldata/FsOpenReq.hpp
index b84d78ba9dd..906bb947128 100644
--- a/ndb/include/kernel/signaldata/FsOpenReq.hpp
+++ b/ndb/include/kernel/signaldata/FsOpenReq.hpp
@@ -39,6 +39,7 @@ class FsOpenReq {
friend class Backup;
friend class Dbdict;
friend class Ndbcntr; // For initial start...
+ friend class Dbdih;
/**
* For printing
diff --git a/ndb/include/kernel/signaldata/ReadConfig.hpp b/ndb/include/kernel/signaldata/ReadConfig.hpp
new file mode 100644
index 00000000000..0835b252a32
--- /dev/null
+++ b/ndb/include/kernel/signaldata/ReadConfig.hpp
@@ -0,0 +1,24 @@
+#ifndef READ_CONFIG_HPP
+#define READ_CONFIG_HPP
+
+/**
+ */
+class ReadConfigReq {
+public:
+ STATIC_CONST( SignalLength = 3 );
+
+ Uint32 senderRef;
+ Uint32 senderData;
+ Uint32 noOfParameters; // 0 Means read all relevant for block
+ Uint32 parameters[1]; // see mgmapi_config_parameters.h
+};
+
+class ReadConfigConf {
+public:
+ STATIC_CONST( SignalLength = 2 );
+
+ Uint32 senderRef;
+ Uint32 senderData;
+};
+
+#endif
diff --git a/ndb/include/kernel/signaldata/ReadNodesConf.hpp b/ndb/include/kernel/signaldata/ReadNodesConf.hpp
index f3176cbf0e8..0507007f71a 100644
--- a/ndb/include/kernel/signaldata/ReadNodesConf.hpp
+++ b/ndb/include/kernel/signaldata/ReadNodesConf.hpp
@@ -48,11 +48,13 @@ class ReadNodesConf {
friend class Suma;
friend class Grep;
+ friend bool printREAD_NODES_CONF(FILE*, const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 2 + 6*NodeBitmask::Size );
+ STATIC_CONST( SignalLength = 3 + 5*NdbNodeBitmask::Size );
private:
Uint32 noOfNodes;
+ Uint32 ndynamicId;
/**
*
@@ -63,47 +65,21 @@ private:
/**
* This array defines all the ndb nodes in the system
*/
- Uint32 allNodes[NodeBitmask::Size];
-
- /**
- * This array describes wheather the nodes are currently active
- *
- * NOTE Not valid when send from Qmgr
- */
- Uint32 inactiveNodes[NodeBitmask::Size];
+ union {
+ Uint32 allNodes[NdbNodeBitmask::Size];
+ Uint32 definedNodes[NdbNodeBitmask::Size];
+ };
/**
- * This array describes the version id of the nodes
- * The version id is a 4 bit number
+ * This array describes wheather the nodes are currently active
*
* NOTE Not valid when send from Qmgr
*/
- Uint32 theVersionIds[4*NodeBitmask::Size];
+ Uint32 inactiveNodes[NdbNodeBitmask::Size];
- static void setVersionId(NodeId, Uint8 versionId, Uint32 theVersionIds[]);
- static Uint8 getVersionId(NodeId, const Uint32 theVersionIds[]);
+ Uint32 clusterNodes[NdbNodeBitmask::Size]; // From Qmgr
+ Uint32 startingNodes[NdbNodeBitmask::Size]; // From Cntr
+ Uint32 startedNodes[NdbNodeBitmask::Size]; // From Cntr
};
-inline
-void
-ReadNodesConf::setVersionId(NodeId nodeId, Uint8 versionId,
- Uint32 theVersionIds[]){
- const int word = nodeId >> 3;
- const int shift = (nodeId & 7) << 2;
-
- const Uint32 mask = ~(((Uint32)15) << shift);
- const Uint32 tmp = theVersionIds[word];
-
- theVersionIds[word] = (tmp & mask) | ((((Uint32)versionId) & 15) << shift);
-}
-
-inline
-Uint8
-ReadNodesConf::getVersionId(NodeId nodeId, const Uint32 theVersionIds[]){
- const int word = nodeId >> 3;
- const int shift = (nodeId & 7) << 2;
-
- return (theVersionIds[word] >> shift) & 15;
-}
-
#endif
diff --git a/ndb/include/kernel/signaldata/SetLogLevelOrd.hpp b/ndb/include/kernel/signaldata/SetLogLevelOrd.hpp
index 680e9b25a49..c3be808cc41 100644
--- a/ndb/include/kernel/signaldata/SetLogLevelOrd.hpp
+++ b/ndb/include/kernel/signaldata/SetLogLevelOrd.hpp
@@ -18,6 +18,7 @@
#define SET_LOGLEVEL_ORD_HPP
#include <LogLevel.hpp>
+#include "SignalData.hpp"
/**
*
diff --git a/ndb/include/kernel/signaldata/TcKeyConf.hpp b/ndb/include/kernel/signaldata/TcKeyConf.hpp
index bfd684b4af4..27ff344f793 100644
--- a/ndb/include/kernel/signaldata/TcKeyConf.hpp
+++ b/ndb/include/kernel/signaldata/TcKeyConf.hpp
@@ -111,7 +111,7 @@ inline
void
TcKeyConf::setNoOfOperations(Uint32 & confInfo, Uint32 noOfOps){
ASSERT_MAX(noOfOps, 65535, "TcKeyConf::setNoOfOperations");
- confInfo |= noOfOps;
+ confInfo = (confInfo & 0xFFFF0000) | noOfOps;
}
inline
diff --git a/ndb/include/kernel/signaldata/TupAccess.hpp b/ndb/include/kernel/signaldata/TupAccess.hpp
index 5cfb8c0d153..ab56a73322c 100644
--- a/ndb/include/kernel/signaldata/TupAccess.hpp
+++ b/ndb/include/kernel/signaldata/TupAccess.hpp
@@ -129,6 +129,8 @@ private:
/*
* Operate on entire tuple. Used by TUX where the table has a single
* Uint32 array attribute representing an index tree node.
+ *
+ * XXX this signal is no longer used by TUX and can be removed
*/
class TupStoreTh {
friend class Dbtup;
diff --git a/ndb/include/kernel/signaldata/TupFrag.hpp b/ndb/include/kernel/signaldata/TupFrag.hpp
index ffde2217893..fc88dacd48f 100644
--- a/ndb/include/kernel/signaldata/TupFrag.hpp
+++ b/ndb/include/kernel/signaldata/TupFrag.hpp
@@ -69,7 +69,7 @@ class TuxFragReq {
friend class Dblqh;
friend class Dbtux;
public:
- STATIC_CONST( SignalLength = 9 );
+ STATIC_CONST( SignalLength = 14 );
private:
Uint32 userPtr;
Uint32 userRef;
@@ -80,6 +80,9 @@ private:
Uint32 fragOff;
Uint32 tableType;
Uint32 primaryTableId;
+ Uint32 tupIndexFragPtrI;
+ Uint32 tupTableFragPtrI[2];
+ Uint32 accTableFragPtrI[2];
};
class TuxFragConf {
diff --git a/ndb/include/kernel/signaldata/TuxMaint.hpp b/ndb/include/kernel/signaldata/TuxMaint.hpp
index 44deb33be80..9fee031dc41 100644
--- a/ndb/include/kernel/signaldata/TuxMaint.hpp
+++ b/ndb/include/kernel/signaldata/TuxMaint.hpp
@@ -39,7 +39,7 @@ public:
SearchError = 895, // add + found or remove + not found
NoMemError = 827
};
- STATIC_CONST( SignalLength = 7 );
+ STATIC_CONST( SignalLength = 8 );
private:
/*
* Error code set by TUX. Zero means no error.
@@ -52,10 +52,11 @@ private:
Uint32 indexId;
Uint32 fragId;
/*
- * Tuple version identified by logical address of "original" tuple and
- * version number.
+ * Tuple version identified by physical address of "original" tuple
+ * and version number.
*/
- Uint32 tupAddr;
+ Uint32 pageId;
+ Uint32 pageOffset;
Uint32 tupVersion;
/*
* Operation code and flags.
diff --git a/ndb/include/kernel/signaldata/UpgradeStartup.hpp b/ndb/include/kernel/signaldata/UpgradeStartup.hpp
new file mode 100644
index 00000000000..badc7ca0e4d
--- /dev/null
+++ b/ndb/include/kernel/signaldata/UpgradeStartup.hpp
@@ -0,0 +1,36 @@
+#ifndef NDB_UPGRADE_STARTUP
+#define NDB_UPGRADE_STARTUP
+
+struct UpgradeStartup {
+
+ static void installEXEC(SimulatedBlock*);
+
+ static const Uint32 GSN_CM_APPCHG = 131;
+ static const Uint32 GSN_CNTR_MASTERCONF = 148;
+ static const Uint32 GSN_CNTR_MASTERREF = 149;
+ static const Uint32 GSN_CNTR_MASTERREQ = 150;
+
+ static void sendCmAppChg(Ndbcntr&, Signal *, Uint32 startLevel);
+ static void execCM_APPCHG(SimulatedBlock& block, Signal*);
+ static void sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n);
+ static void execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal);
+
+ struct CntrMasterReq {
+ STATIC_CONST( SignalLength = 4 + NdbNodeBitmask::Size );
+
+ Uint32 userBlockRef;
+ Uint32 userNodeId;
+ Uint32 typeOfStart;
+ Uint32 noRestartNodes;
+ Uint32 theNodes[NdbNodeBitmask::Size];
+ };
+
+ struct CntrMasterConf {
+ STATIC_CONST( SignalLength = 1 + NdbNodeBitmask::Size );
+
+ Uint32 noStartNodes;
+ Uint32 theNodes[NdbNodeBitmask::Size];
+ };
+};
+
+#endif
diff --git a/ndb/include/kernel/trigger_definitions.h b/ndb/include/kernel/trigger_definitions.h
index a5e7fb1953c..439d65c6c30 100644
--- a/ndb/include/kernel/trigger_definitions.h
+++ b/ndb/include/kernel/trigger_definitions.h
@@ -17,6 +17,7 @@
#ifndef NDB_TRIGGER_DEFINITIONS_H
#define NDB_TRIGGER_DEFINITIONS_H
+#include <ndb_global.h>
#include "ndb_limits.h"
#ifndef MIN
diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h
index 0ecb19eaa76..7b2f728bda8 100644
--- a/ndb/include/mgmapi/mgmapi.h
+++ b/ndb/include/mgmapi/mgmapi.h
@@ -84,9 +84,10 @@ extern "C" {
NDB_MGM_NODE_TYPE_API = 0, /*/< An application node (API)*/
NDB_MGM_NODE_TYPE_NDB = 1, /*/< A database node (DB)*/
NDB_MGM_NODE_TYPE_MGM = 2, /*/< A management server node (MGM)*/
+ NDB_MGM_NODE_TYPE_REP = 3, ///< A replication node
NDB_MGM_NODE_TYPE_MIN = 0, /*/< Min valid value*/
- NDB_MGM_NODE_TYPE_MAX = 2 /*/< Max valid value*/
+ NDB_MGM_NODE_TYPE_MAX = 3 /*/< Max valid value*/
};
/**
@@ -199,6 +200,8 @@ extern "C" {
int node_group; ///< Node group of node
///< (only valid for DB nodes)
int version; ///< Internal version number
+ int connect_count; ///< No of times node has connected
+ ///< or disconnected to the mgm srv
};
/**
@@ -654,6 +657,36 @@ extern "C" {
int ndb_mgm_exit_single_user(NdbMgmHandle handle,
struct ndb_mgm_reply* reply);
+ /**
+ * Get configuration
+ * @param handle NDB management handle.
+ * @param version Version of configuration, 0 means latest
+ * @see MAKE_VERSION
+ * @Note the caller must free the pointer returned.
+ */
+ struct ndb_mgm_configuration * ndb_mgm_get_configuration(NdbMgmHandle handle,
+ unsigned version);
+ /**
+ * Config iterator
+ */
+ typedef struct ndb_mgm_configuration_iterator ndb_mgm_configuration_iterator;
+
+ ndb_mgm_configuration_iterator* ndb_mgm_create_configuration_iterator
+ (struct ndb_mgm_configuration *, unsigned type_of_section);
+ void ndb_mgm_destroy_iterator(ndb_mgm_configuration_iterator*);
+
+ int ndb_mgm_first(ndb_mgm_configuration_iterator*);
+ int ndb_mgm_next(ndb_mgm_configuration_iterator*);
+ int ndb_mgm_valid(const ndb_mgm_configuration_iterator*);
+ int ndb_mgm_find(ndb_mgm_configuration_iterator*,
+ int param, unsigned value);
+
+ int ndb_mgm_get_int_parameter(const ndb_mgm_configuration_iterator*,
+ int param, unsigned * value);
+ int ndb_mgm_get_int64_parameter(const ndb_mgm_configuration_iterator*,
+ int param, unsigned long long * value);
+ int ndb_mgm_get_string_parameter(const ndb_mgm_configuration_iterator*,
+ int param, const char ** value);
#ifdef __cplusplus
}
#endif
diff --git a/ndb/include/mgmapi/mgmapi_config_parameters.h b/ndb/include/mgmapi/mgmapi_config_parameters.h
new file mode 100644
index 00000000000..d3bb44c1523
--- /dev/null
+++ b/ndb/include/mgmapi/mgmapi_config_parameters.h
@@ -0,0 +1,144 @@
+#ifndef MGMAPI_CONFIG_PARAMTERS_H
+#define MGMAPI_CONFIG_PARAMTERS_H
+
+
+#define CFG_SYS_NAME 3
+#define CFG_SYS_PRIMARY_MGM_NODE 1
+#define CFG_SYS_CONFIG_GENERATION 2
+#define CFG_SYS_REPLICATION_ROLE 7
+
+#define CFG_NODE_ID 3
+#define CFG_NODE_BYTE_ORDER 4
+#define CFG_NODE_HOST 5
+#define CFG_NODE_SYSTEM 6
+
+/**
+ * DB config parameters
+ */
+#define CFG_DB_NO_SAVE_MSGS 100
+
+#define CFG_DB_NO_REPLICAS 101
+#define CFG_DB_NO_TABLES 102
+#define CFG_DB_NO_ATTRIBUTES 103
+#define CFG_DB_NO_INDEXES 104
+#define CFG_DB_NO_TRIGGERS 105
+
+#define CFG_DB_NO_TRANSACTIONS 106
+#define CFG_DB_NO_OPS 107
+#define CFG_DB_NO_SCANS 108
+#define CFG_DB_NO_TRIGGER_OPS 109
+#define CFG_DB_NO_INDEX_OPS 110
+
+#define CFG_DB_TRANS_BUFFER_MEM 111
+#define CFG_DB_DATA_MEM 112
+#define CFG_DB_INDEX_MEM 113
+#define CFG_DB_MEMLOCK 114
+
+#define CFG_DB_START_PARTIAL_TIMEOUT 115
+#define CFG_DB_START_PARTITION_TIMEOUT 116
+#define CFG_DB_START_FAILURE_TIMEOUT 117
+
+#define CFG_DB_HEARTBEAT_INTERVAL 118
+#define CFG_DB_API_HEARTBEAT_INTERVAL 119
+#define CFG_DB_LCP_INTERVAL 120
+#define CFG_DB_GCP_INTERVAL 121
+#define CFG_DB_ARBIT_TIMEOUT 122
+
+#define CFG_DB_WATCHDOG_INTERVAL 123
+#define CFG_DB_STOP_ON_ERROR 124
+
+#define CFG_DB_FILESYSTEM_PATH 125
+#define CFG_DB_NO_REDOLOG_FILES 126
+#define CFG_DB_DISC_BANDWIDTH 127
+#define CFG_DB_SR_DISC_BANDWITH 128
+
+#define CFG_DB_TRANSACTION_CHECK_INTERVAL 129
+#define CFG_DB_TRANSACTION_INACTIVE_TIMEOUT 130
+#define CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT 131
+
+#define CFG_DB_PARALLEL_BACKUPS 132
+#define CFG_DB_BACKUP_MEM 133
+#define CFG_DB_BACKUP_DATA_BUFFER_MEM 134
+#define CFG_DB_BACKUP_LOG_BUFFER_MEM 135
+#define CFG_DB_BACKUP_WRITE_SIZE 136
+
+#define CFG_LOGLEVEL_STARTUP 137
+#define CFG_LOGLEVEL_SHUTDOWN 138
+#define CFG_LOGLEVEL_STATISTICS 139
+#define CFG_LOGLEVEL_CHECKPOINT 140
+#define CFG_LOGLEVEL_NODERESTART 141
+#define CFG_LOGLEVEL_CONNECTION 142
+#define CFG_LOGLEVEL_INFO 143
+#define CFG_LOGLEVEL_WARNING 144
+#define CFG_LOGLEVEL_ERROR 145
+#define CFG_LOGLEVEL_GREP 146
+#define CFG_LOG_DESTINATION 147
+
+#define CFG_DB_DISCLESS 148
+
+#define CFG_NODE_ARBIT_RANK 200
+#define CFG_NODE_ARBIT_DELAY 201
+
+#define CFG_MGM_PORT 300
+
+#define CFG_CONNECTION_NODE_1 400
+#define CFG_CONNECTION_NODE_2 401
+#define CFG_CONNECTION_SEND_SIGNAL_ID 402
+#define CFG_CONNECTION_CHECKSUM 403
+#define CFG_CONNECTION_NODE_1_SYSTEM 404
+#define CFG_CONNECTION_NODE_2_SYSTEM 405
+
+#define CFG_TCP_HOSTNAME_1 450
+#define CFG_TCP_HOSTNAME_2 451
+#define CFG_TCP_SERVER 452
+#define CFG_TCP_SERVER_PORT 453
+#define CFG_TCP_SEND_BUFFER_SIZE 454
+#define CFG_TCP_RECEIVE_BUFFER_SIZE 455
+#define CFG_TCP_PROXY 456
+
+#define CFG_SHM_SEND_SIGNAL_ID 500
+#define CFG_SHM_CHECKSUM 501
+#define CFG_SHM_KEY 502
+#define CFG_SHM_BUFFER_MEM 503
+
+#define CFG_SCI_ID_0 550
+#define CFG_SCI_ID_1 551
+#define CFG_SCI_SEND_LIMIT 552
+#define CFG_SCI_BUFFER_MEM 553
+#define CFG_SCI_NODE1_ADAPTERS 554
+#define CFG_SCI_NODE1_ADAPTER0 555
+#define CFG_SCI_NODE1_ADAPTER1 556
+#define CFG_SCI_NODE2_ADAPTERS 554
+#define CFG_SCI_NODE2_ADAPTER0 555
+#define CFG_SCI_NODE2_ADAPTER1 556
+
+#define CFG_OSE_HOSTNAME_1 600
+#define CFG_OSE_HOSTNAME_2 601
+#define CFG_OSE_PRIO_A_SIZE 602
+#define CFG_OSE_PRIO_B_SIZE 603
+#define CFG_OSE_RECEIVE_ARRAY_SIZE 604
+
+#define CFG_REP_HEARTBEAT_INTERVAL 700
+
+/**
+ * Internal
+ */
+#define CFG_DB_STOP_ON_ERROR_INSERT 1
+
+#define CFG_TYPE_OF_SECTION 999
+#define CFG_SECTION_SYSTEM 1000
+#define CFG_SECTION_NODE 2000
+#define CFG_SECTION_CONNECTION 3000
+
+#define NODE_TYPE_DB 0
+#define NODE_TYPE_API 1
+#define NODE_TYPE_MGM 2
+#define NODE_TYPE_REP 3
+#define NODE_TYPE_EXT_REP 4
+
+#define CONNECTION_TYPE_TCP 0
+#define CONNECTION_TYPE_SHM 1
+#define CONNECTION_TYPE_SCI 2
+#define CONNECTION_TYPE_OSE 3
+
+#endif
diff --git a/ndb/include/mgmapi/mgmapi_config_parameters_debug.h b/ndb/include/mgmapi/mgmapi_config_parameters_debug.h
new file mode 100644
index 00000000000..0241dca90ef
--- /dev/null
+++ b/ndb/include/mgmapi/mgmapi_config_parameters_debug.h
@@ -0,0 +1,8 @@
+#ifndef MGMAPI_CONFIG_PARAMTERS_DEBUG_H
+#define MGMAPI_CONFIG_PARAMTERS_DEBUG_H
+
+#include "mgmapi_config_parameters.h"
+
+#define CFG_DB_STOP_ON_ERROR_INSERT 1
+
+#endif
diff --git a/ndb/include/mgmcommon/ConfigRetriever.hpp b/ndb/include/mgmcommon/ConfigRetriever.hpp
index ff60e730d45..50d333b54dd 100644
--- a/ndb/include/mgmcommon/ConfigRetriever.hpp
+++ b/ndb/include/mgmcommon/ConfigRetriever.hpp
@@ -18,7 +18,7 @@
#define ConfigRetriever_H
#include <ndb_types.h>
-#include <Properties.hpp>
+#include <mgmapi.h>
/**
* @class ConfigRetriever
@@ -44,11 +44,11 @@ public:
* to establish a connection. This is repeated until a connection is
* established, so the function hangs until a connection is established.
*
- * @return Properties object if succeeded,
+ * @return ndb_mgm_configuration object if succeeded,
* NULL if erroneous local config file or configuration error.
*/
- class Properties * getConfig(const char * nodeType, int versionId);
-
+ struct ndb_mgm_configuration * getConfig(int versionId, int nodeType);
+
const char * getErrorString();
/**
@@ -71,22 +71,17 @@ public:
* @return Node id of this node (as stated in local config or connectString)
*/
inline Uint32 getOwnNodeId() { return _ownNodeId; }
-
- /**
- * Get configuration object
- */
- class Properties * getConfig(int versionId);
+
/**
* Get config using socket
*/
- class Properties * getConfig(const char * mgmhost, unsigned int port,
- Uint32 nodeId, int versionId);
+ struct ndb_mgm_configuration * getConfig(const char * mgmhost, short port,
+ int versionId);
/**
* Get config from file
*/
- class Properties * getConfig(const char * filename, Uint32 nodeId,
- int versionId);
+ struct ndb_mgm_configuration * getConfig(const char * file, int versionId);
private:
char * errorString;
enum ErrorType {
@@ -97,18 +92,17 @@ private:
void setError(ErrorType, const char * errorMsg);
- /**
- * Verifies that received configuration is correct
- */
- bool verifyProperties(const char* nodeType, Properties *p,
- Uint32 nodeId, int versionId);
-
char * _localConfigFileName;
struct LocalConfig * _localConfig;
int _ownNodeId;
char * m_connectString;
char * m_defaultConnectString;
+
+ /**
+ * Verify config
+ */
+ bool verifyConfig(const struct ndb_mgm_configuration *, int type);
};
#endif
diff --git a/ndb/include/mgmcommon/IPCConfig.hpp b/ndb/include/mgmcommon/IPCConfig.hpp
index 626242865cb..ebe65b53b59 100644
--- a/ndb/include/mgmcommon/IPCConfig.hpp
+++ b/ndb/include/mgmcommon/IPCConfig.hpp
@@ -58,6 +58,10 @@ public:
void print() const { props->print(); }
+ static Uint32 configureTransporters(Uint32 nodeId,
+ const class ndb_mgm_configuration &,
+ class TransporterRegistry &);
+
private:
NodeId the_ownId;
Properties * props;
diff --git a/ndb/include/ndb_global.h b/ndb/include/ndb_global.h
index 5e03b972268..f871acbc075 100644
--- a/ndb/include/ndb_global.h
+++ b/ndb/include/ndb_global.h
@@ -25,7 +25,13 @@
#endif
#include <sys/param.h>
#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
+ #if defined(__cplusplus) && defined(_APP32_64BIT_OFF_T) && defined(_INCLUDE_AES_SOURCE)
+ #undef _INCLUDE_AES_SOURCE
+ #include <sys/stat.h>
+ #define _INCLUDE_AES_SOURCE
+ #else
+ #include <sys/stat.h>
+ #endif
#endif
#include <sys/resource.h>
#ifdef HAVE_SYS_WAIT_H
@@ -49,6 +55,8 @@
#endif
+static const char table_name_separator = '/';
+
#ifdef NDB_VC98
#define STATIC_CONST(x) enum { x }
#else
diff --git a/ndb/include/ndb_types.h b/ndb/include/ndb_types.h
index 5e7b952cfc5..87ebd3d6c6b 100644
--- a/ndb/include/ndb_types.h
+++ b/ndb/include/ndb_types.h
@@ -33,7 +33,7 @@ typedef unsigned int UintR;
#ifdef __SIZE_TYPE__
typedef __SIZE_TYPE__ UintPtr;
#else
-#include <my_config.h>
+#include <my_global.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
diff --git a/ndb/include/ndb_version.h b/ndb/include/ndb_version.h
index 9bb6af59590..56362020ebf 100644
--- a/ndb/include/ndb_version.h
+++ b/ndb/include/ndb_version.h
@@ -17,19 +17,11 @@
#ifndef NDB_VERSION_H
#define NDB_VERSION_H
+#include <ndb_global.h>
#include <version.h>
#define MAKE_VERSION(A,B,C) (((A) << 16) | ((B) << 8) | ((C) << 0))
-/**
- * version of this build
- */
-
-#define NDB_VERSION_MAJOR 3
-#define NDB_VERSION_MINOR 5
-#define NDB_VERSION_BUILD 0
-#define NDB_VERSION_STATUS "alpha"
-
#define NDB_VERSION_D MAKE_VERSION(NDB_VERSION_MAJOR, NDB_VERSION_MINOR, NDB_VERSION_BUILD)
#define NDB_VERSION_STRING (getVersionString(NDB_VERSION, NDB_VERSION_STATUS))
diff --git a/ndb/include/ndbapi/AttrType.hpp b/ndb/include/ndbapi/AttrType.hpp
deleted file mode 100644
index e6e00c77130..00000000000
--- a/ndb/include/ndbapi/AttrType.hpp
+++ /dev/null
@@ -1,329 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/**
- * @file AttrType.hpp
- */
-
-#ifndef AttrType_H
-#define AttrType_H
-
-/**
- * Max number of Ndb objects in different threads.
- * (Ndb objects should not be shared by different threads.)
- */
-const unsigned MAX_NO_THREADS = 4711;
-
-/**
- * Max number of attributes in a table.
- */
-const unsigned MAXNROFATTRIBUTES = 128;
-
-/**
- * Max number of tuple keys for a table in NDB Cluster.
- *
- * A <em>tuple key</em> of a table is an attribute
- * which is either part of the
- * <em>primary key</em> or the <em>tuple id</em> of a table.
- */
-const unsigned MAXNROFTUPLEKEY = 16;
-
-/**
- * Max number of words in a tuple key attribute.
- *
- * Tuple keys can not have values larger than
- * 4092 bytes (i.e. 1023 words).
- */
-const unsigned MAXTUPLEKEYLENOFATTERIBUTEINWORD = 1023;
-
-/**
- * Max number of ErrorCode in NDB Cluster range 0 - 1999.
- */
-const unsigned MAXNDBCLUSTERERROR = 1999;
-
-/**
- * Max number of theErrorCode NDB API range 4000 - 4999.
- */
-const unsigned MAXNROFERRORCODE = 5000;
-
-/**
- * <i>Missing explanation</i>
- */
-enum ReturnType {
- ReturnSuccess, ///< <i>Missing explanation</i>
- ReturnFailure ///< <i>Missing explanation</i>
-};
-
-/**
- *
- */
-enum SendStatusType {
- NotInit, ///< <i>Missing explanation</i>
- InitState, ///< <i>Missing explanation</i>
- sendOperations, ///< <i>Missing explanation</i>
- sendCompleted, ///< <i>Missing explanation</i>
- sendCOMMITstate, ///< <i>Missing explanation</i>
- sendABORT, ///< <i>Missing explanation</i>
- sendABORTfail, ///< <i>Missing explanation</i>
- sendTC_ROLLBACK, ///< <i>Missing explanation</i>
- sendTC_COMMIT, ///< <i>Missing explanation</i>
- sendTC_OP ///< <i>Missing explanation</i>
-};
-
-/**
- * <i>Missing explanation</i>
- */
-enum ListState {
- NotInList, ///< <i>Missing explanation</i>
- InPreparedList, ///< <i>Missing explanation</i>
- InSendList, ///< <i>Missing explanation</i>
- InCompletedList ///< <i>Missing explanation</i>
-};
-
-/**
- * Commit status of the transaction
- */
-enum CommitStatusType {
- NotStarted, ///< Transaction not yet started
- Started, ///< <i>Missing explanation</i>
- Committed, ///< Transaction has been committed
- Aborted, ///< Transaction has been aborted
- NeedAbort ///< <i>Missing explanation</i>
-};
-
-/**
- * Commit type of transaction
- */
-enum AbortOption {
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
- CommitIfFailFree = 0,
- CommitAsMuchAsPossible = 2, ///< Commit transaction with as many
- TryCommit = 0, ///< <i>Missing explanation</i>
-#endif
- AbortOnError = 0, ///< Abort transaction on failed operation
- IgnoreError = 2 ///< Transaction continues on failed operation
-};
-
-typedef AbortOption CommitType;
-
-/**
- * <i>Missing explanation</i>
- */
-enum InitType {
- NotConstructed, ///< <i>Missing explanation</i>
- NotInitialised, ///< <i>Missing explanation</i>
- StartingInit, ///< <i>Missing explanation</i>
- Initialised, ///< <i>Missing explanation</i>
- InitConfigError ///< <i>Missing explanation</i>
-};
-
-/**
- * Type of attribute
- */
-enum AttrType {
- Signed, ///< Attributes of this type can be read with:
- ///< NdbRecAttr::int64_value,
- ///< NdbRecAttr::int32_value,
- ///< NdbRecAttr::short_value,
- ///< NdbRecAttr::char_value
- UnSigned, ///< Attributes of this type can be read with:
- ///< NdbRecAttr::u_64_value,
- ///< NdbRecAttr::u_32_value,
- ///< NdbRecAttr::u_short_value,
- ///< NdbRecAttr::u_char_value
- Float, ///< Attributes of this type can be read with:
- ///< NdbRecAttr::float_value and
- ///< NdbRecAttr::double_value
- String, ///< Attributes of this type can be read with:
- ///< NdbRecAttr::aRef,
- ///< NdbRecAttr::getAttributeObject
- NoAttrTypeDef ///< Used for debugging only
-};
-
-/**
- * Execution type of transaction
- */
-enum ExecType {
- NoExecTypeDef = -1, ///< Erroneous type (Used for debugging only)
- Prepare, ///< <i>Missing explanation</i>
- NoCommit, ///< Execute the transaction as far as it has
- ///< been defined, but do not yet commit it
- Commit, ///< Execute and try to commit the transaction
- Rollback ///< Rollback transaction
-};
-
-/**
- * Indicates whether the attribute is part of a primary key or not
- */
-enum KeyType {
- Undefined = -1, ///< Used for debugging only
- NoKey, ///< Attribute is not part of primary key
- ///< or tuple identity
- TupleKey, ///< Attribute is part of primary key
- TupleId ///< Attribute is part of tuple identity
- ///< (This type of attribute is created
- ///< internally, and should not be
- ///< manually created.)
-};
-
-/**
- * Indicate whether the attribute should be stored on disk or not
- */
-enum StorageMode {
- MMBased = 0, ///< Main memory
- DiskBased = 1, ///< Disk (Not yet supported.)
- NoStorageTypeDef ///< Used for debugging only
-};
-
-/**
- * Where attribute is stored.
- *
- * This is used to indicate whether a primary key
- * should only be stored in the index storage and not in the data storage
- * or if it should be stored in both places.
- * The first alternative makes the attribute take less space,
- * but makes it impossible to scan using attribute.
- *
- * @note Use NormalStorageAttribute for most cases.
- * (IndexStorageAttribute should only be used on primary key
- * attributes and only if you do not want to scan using the attribute.)
- */
-enum StorageAttributeType {
- NoStorageAttributeTypeDefined = -1, ///< <i>Missing explanation</i>
- IndexStorageAttribute, ///< Attribute is only stored in
- ///< index storage (ACC)
- NormalStorageAttribute ///< Attribute values are stored
- ///< both in the index (ACC) and
- ///< in the data storage (TUP)
-};
-
-/**
- * <i>Missing explanation</i>
- */
-enum OperationStatus{
- Init, ///< <i>Missing explanation</i>
- OperationDefined, ///< <i>Missing explanation</i>
- TupleKeyDefined, ///< <i>Missing explanation</i>
- GetValue, ///< <i>Missing explanation</i>
- SetValue, ///< <i>Missing explanation</i>
- ExecInterpretedValue, ///< <i>Missing explanation</i>
- SetValueInterpreted, ///< <i>Missing explanation</i>
- FinalGetValue, ///< <i>Missing explanation</i>
- SubroutineExec, ///< <i>Missing explanation</i>
- SubroutineEnd, ///< <i>Missing explanation</i>
- SetBound, ///< Setting bounds in range scan
- WaitResponse, ///< <i>Missing explanation</i>
- WaitCommitResponse, ///< <i>Missing explanation</i>
- Finished, ///< <i>Missing explanation</i>
- ReceiveFinished ///< <i>Missing explanation</i>
-};
-
-/**
- * Type of operation
- */
-enum OperationType {
- ReadRequest = 0, ///< Read operation
- UpdateRequest = 1, ///< Update Operation
- InsertRequest = 2, ///< Insert Operation
- DeleteRequest = 3, ///< Delete Operation
- WriteRequest = 4, ///< Write Operation
- ReadExclusive = 5, ///< Read exclusive
- OpenScanRequest, ///< Scan Operation
- OpenRangeScanRequest, ///< Range scan operation
- NotDefined2, ///< <i>Missing explanation</i>
- NotDefined ///< <i>Missing explanation</i>
-};
-
-/**
- * <i>Missing explanation</i>
- */
-enum ConStatusType {
- NotConnected, ///< <i>Missing explanation</i>
- Connecting, ///< <i>Missing explanation</i>
- Connected, ///< <i>Missing explanation</i>
- DisConnecting, ///< <i>Missing explanation</i>
- ConnectFailure ///< <i>Missing explanation</i>
-};
-
-/**
- * <i>Missing explanation</i>
- */
-enum CompletionStatus {
- NotCompleted, ///< <i>Missing explanation</i>
- CompletedSuccess, ///< <i>Missing explanation</i>
- CompletedFailure, ///< <i>Missing explanation</i>
- DefinitionFailure ///< <i>Missing explanation</i>
-};
-
-/**
- * Type of fragmentation used for a table
- */
-enum FragmentType {
- Default = 0, ///< (All is default!)
- Single = 1, ///< Only one fragment
- All = 2, ///< Default value. One fragment per node group
- DistributionGroup = 3, ///< Distribution Group used for fragmentation.
- ///< One fragment per node group
- DistributionKey = 4, ///< Distribution Key used for fragmentation.
- ///< One fragment per node group.
- AllLarge = 5, ///< Sixten fragments per node group.
- DGroupLarge = 6, ///< Distribution Group used for fragmentation.
- ///< Sixten fragments per node group
- DKeyLarge = 7 ///< Distribution Key used for fragmentation.
- ///< Sixten fragments per node group
-};
-
-/**
- * Type of table or index.
- */
-enum TableType {
- UndefTableType = 0,
- SystemTable = 1, ///< Internal. Table cannot be updated by user
- UserTable = 2, ///< Normal application table
- UniqueHashIndex = 3, ///< Unique un-ordered hash index
- HashIndex = 4, ///< Non-unique un-ordered hash index
- UniqueOrderedIndex = 5, ///< Unique ordered index
- OrderedIndex = 6 ///< Non-unique ordered index
-};
-
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
-/**
- * Different types of tampering with the NDB Cluster.
- * <b>Only for debugging purposes only.</b>
- */
-enum TamperType {
- LockGlbChp = 1, ///< Lock GCP
- UnlockGlbChp, ///< Unlock GCP
- CrashNode, ///< Crash an NDB node
- ReadRestartGCI, ///< Request the restart GCI id from NDB Cluster
- InsertError ///< Execute an error in NDB Cluster
- ///< (may crash system)
-};
-#endif
-
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
-/**
- * @deprecated
- */
-enum NullAttributeType {
- NoNullTypeDefined = -1,
- NotNullAttribute,
- NullAttribute,
- AttributeDefined
-};
-#endif
-
-#endif
diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp
index fd6e827ceb4..27da5c3fa39 100644
--- a/ndb/include/ndbapi/Ndb.hpp
+++ b/ndb/include/ndbapi/Ndb.hpp
@@ -860,7 +860,6 @@
#include <ndb_types.h>
#include <ndbapi_limits.h>
-#include <AttrType.hpp>
#include <NdbError.hpp>
#include <NdbDictionary.hpp>
@@ -870,8 +869,6 @@ class NdbEventOperationImpl;
class NdbScanOperation;
class NdbIndexOperation;
class NdbConnection;
-class NdbSchemaOp;
-class NdbSchemaCon;
class NdbApiSignal;
class NdbRecAttr;
class NdbLabel;
@@ -882,6 +879,7 @@ class NdbScanReceiver;
class Table;
class BaseString;
class NdbEventOperation;
+class NdbBlob;
typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
@@ -961,14 +959,13 @@ class Ndb
friend class NdbOperation;
friend class NdbEventOperationImpl;
friend class NdbConnection;
- friend class NdbSchemaOp;
- friend class NdbSchemaCon;
friend class Table;
friend class NdbApiSignal;
friend class NdbScanReceiver;
friend class NdbIndexOperation;
friend class NdbDictionaryImpl;
friend class NdbDictInterface;
+ friend class NdbBlob;
public:
/**
@@ -1064,8 +1061,6 @@ public:
* A value larger than 1024 will be downgraded to 1024.
* This means that one Ndb object can handle at most 1024 parallel
* transactions.
- * There is a maximum of 128 simultaneous
- * Ndb object within one application process.
* @return 0 if successful, -1 otherwise.
*
* @note The internal implementation multiplies this value
@@ -1245,22 +1240,6 @@ public:
*/
void closeTransaction(NdbConnection* aConnection);
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
- /**
- * To create a table it is necessary to obtain a schema transaction
- * object.
- * All schema transactions need to closed when they are
- * completed.
- *
- * @return NdbSchemaCon
- */
- NdbSchemaCon* startSchemaTransaction();
-
- /**
- * Close schema transaction when finished.
- */
- void closeSchemaTransaction(NdbSchemaCon* aSchemaCon);
-#endif
/** @} *********************************************************************/
@@ -1384,13 +1363,27 @@ public:
* index names as DATABASENAME/SCHEMANAME/TABLENAME/INDEXNAME
* @param turnNamingOn bool true - turn naming on, false - turn naming off
*/
- static void useFullyQualifiedNames(bool turnNamingOn = true);
+ void useFullyQualifiedNames(bool turnNamingOn = true);
- static bool usingFullyQualifiedNames();
+ bool usingFullyQualifiedNames();
/** @} *********************************************************************/
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
+ /**
+ * Different types of tampering with the NDB Cluster.
+ * <b>Only for debugging purposes only.</b>
+ */
+ enum TamperType {
+ LockGlbChp = 1, ///< Lock GCP
+ UnlockGlbChp, ///< Unlock GCP
+ CrashNode, ///< Crash an NDB node
+ ReadRestartGCI, ///< Request the restart GCI id from NDB Cluster
+ InsertError ///< Execute an error in NDB Cluster
+ ///< (may crash system)
+ };
+
/**
* For testing purposes it is possible to tamper with the NDB Cluster
* (i.e. send a special signal to DBDIH, the NDB distribution handler).
@@ -1398,14 +1391,7 @@ public:
* In a release versions of NDB Cluster,
* this call always return -1 and does nothing.
*
- * @param aAction Action to be taken
- * - 1: Lock global checkpointing
- * (Can only be sent to master DIH,
- * Parameter aNode ignored).
- * - 2: UnLock global checkpointing
- * (Can only be sent to master DIH,
- * Parameter aNode ignored).
- * - 3: Crash node.
+ * @param aAction Action to be taken according to TamperType above
*
* @param aNode Which node the action will be taken
* -1: Master DIH.
@@ -1468,6 +1454,7 @@ private:
NdbIndexOperation* getIndexOperation();// Get an index operation from idle
class NdbGlobalEventBufferHandle* getGlobalEventBufferHandle();
+ NdbBlob* getNdbBlob();// Get a blob handle etc
void releaseSignal(NdbApiSignal* anApiSignal);
void releaseSignalsInList(NdbApiSignal** pList);
@@ -1479,6 +1466,7 @@ private:
void releaseRecAttr (NdbRecAttr* aRecAttr);
void releaseOperation(NdbOperation* anOperation);
void releaseScanOperation(NdbScanOperation* aScanOperation);
+ void releaseNdbBlob(NdbBlob* aBlob);
void check_send_timeout();
void remove_sent_list(Uint32);
@@ -1521,6 +1509,7 @@ private:
void freeNdbSubroutine();// Free the first idle NdbSubroutine obj
void freeNdbCall(); // Free the first idle NdbCall obj
void freeNdbScanRec(); // Free the first idle NdbScanRec obj
+ void freeNdbBlob(); // Free the first etc
NdbConnection* getNdbCon(); // Get a connection from idle list
@@ -1558,10 +1547,12 @@ private:
void abortTransactionsAfterNodeFailure(Uint16 aNodeId);
static
+ const char * externalizeTableName(const char * internalTableName, bool fullyQualifiedNames);
const char * externalizeTableName(const char * internalTableName);
const char * internalizeTableName(const char * externalTableName);
static
+ const char * externalizeIndexName(const char * internalIndexName, bool fullyQualifiedNames);
const char * externalizeIndexName(const char * internalIndexName);
const char * internalizeIndexName(const NdbTableImpl * table,
const char * externalIndexName);
@@ -1598,6 +1589,8 @@ private:
NdbWaiter theWaiter;
+ bool fullyQualifiedNames;
+
// Ndb database name.
char theDataBase[NDB_MAX_DATABASE_NAME_SIZE];
// Ndb database schema name.
@@ -1616,9 +1609,6 @@ private:
NdbScanOperation* theScanOpIdleList; // First scan operation in the idle list.
NdbIndexOperation* theIndexOpIdleList; // First index operation in the idle list.
- NdbSchemaCon* theSchemaConIdleList; // First schemaCon in idle list.
-
- NdbSchemaCon* theSchemaConToNdbList; // Connected schemaCon object.
NdbConnection* theTransactionList;
NdbConnection** theConnectionArray;
NdbRecAttr* theRecAttrIdleList;
@@ -1628,6 +1618,7 @@ private:
NdbSubroutine* theSubroutineList; // First subroutine descriptor in
NdbCall* theCallList; // First call descriptor in list
NdbScanReceiver* theScanList;
+ NdbBlob* theNdbBlobIdleList;
Uint32 theMyRef; // My block reference
Uint32 theNode; // The node number of our node
@@ -1649,7 +1640,14 @@ private:
NdbError theError;
Int32 theNdbBlockNumber;
- InitType theInitState;
+
+ enum InitType {
+ NotConstructed,
+ NotInitialised,
+ StartingInit,
+ Initialised,
+ InitConfigError
+ } theInitState;
// Ensure good distribution of connects
Uint32 theCurrentConnectIndex;
diff --git a/ndb/include/ndbapi/NdbApi.hpp b/ndb/include/ndbapi/NdbApi.hpp
index e5efc9756ce..515f39433e4 100644
--- a/ndb/include/ndbapi/NdbApi.hpp
+++ b/ndb/include/ndbapi/NdbApi.hpp
@@ -17,17 +17,16 @@
#ifndef NdbApi_H
#define NdbApi_H
+#include "ndbapi_limits.h"
#include "Ndb.hpp"
-#include "AttrType.hpp"
#include "NdbConnection.hpp"
#include "NdbOperation.hpp"
#include "NdbScanOperation.hpp"
#include "NdbIndexOperation.hpp"
-#include "NdbSchemaCon.hpp"
-#include "NdbSchemaOp.hpp"
#include "NdbRecAttr.hpp"
#include "NdbResultSet.hpp"
#include "NdbDictionary.hpp"
#include "NdbEventOperation.hpp"
#include "NdbPool.hpp"
+#include "NdbBlob.hpp"
#endif
diff --git a/ndb/include/ndbapi/NdbBlob.hpp b/ndb/include/ndbapi/NdbBlob.hpp
new file mode 100644
index 00000000000..9398f77c474
--- /dev/null
+++ b/ndb/include/ndbapi/NdbBlob.hpp
@@ -0,0 +1,293 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef NdbBlob_H
+#define NdbBlob_H
+
+#include <ndb_types.h>
+#include <NdbDictionary.hpp>
+#include <NdbConnection.hpp>
+#include <NdbError.hpp>
+
+class Ndb;
+class NdbConnection;
+class NdbOperation;
+class NdbRecAttr;
+class NdbTableImpl;
+class NdbColumnImpl;
+
+/**
+ * @class NdbBlob
+ * @brief Blob handle
+ *
+ * Blob data is stored in 2 places:
+ *
+ * - "header" and "inline bytes" stored in the blob attribute
+ * - "blob parts" stored in a separate table NDB$BLOB_<t>_<v>_<c>
+ *
+ * Inline and part sizes can be set via NdbDictionary::Column methods
+ * when the table is created.
+ *
+ * NdbBlob is a blob handle. To access blob data, the handle must be
+ * created using NdbOperation::getBlobHandle in operation prepare phase.
+ * The handle has following states:
+ *
+ * - prepared: before the operation is executed
+ * - active: after execute or next result but before transaction commit
+ * - closed: after transaction commit
+ * - invalid: after rollback or transaction close
+ *
+ * NdbBlob supports 2 styles of data access:
+ *
+ * - in prepare phase, NdbBlob methods getValue and setValue are used to
+ * prepare a read or write of a single blob value of known size
+ *
+ * - in active phase, NdbBlob methods readData and writeData are used to
+ * read or write blob data of undetermined size
+ *
+ * NdbBlob methods return -1 on error and 0 on success, and use output
+ * parameters when necessary.
+ *
+ * Notes:
+ * - table and its blob part tables are not created atomically
+ * - blob data operations take effect at next transaction execute
+ * - NdbBlob may need to do implicit executes on the transaction
+ * - read and write of complete parts is much more efficient
+ * - scan must use the "new" interface NdbScanOperation
+ * - scan with blobs applies hold-read-lock (at minimum)
+ * - to update a blob in a read op requires exclusive tuple lock
+ * - update op in scan must do its own getBlobHandle
+ * - delete creates implicit, not-accessible blob handles
+ * - NdbOperation::writeTuple does not support blobs
+ * - there is no support for an asynchronous interface
+ *
+ * Bugs / limitations:
+ * - scan must use exclusive locking for now
+ *
+ * Todo:
+ * - add scan method hold-read-lock-until-next + return-keyinfo
+ * - better check of keyinfo length when setting keys
+ * - better check of allowed blob op vs locking mode
+ */
+class NdbBlob {
+public:
+ enum State {
+ Idle = 0,
+ Prepared = 1,
+ Active = 2,
+ Closed = 3,
+ Invalid = 9
+ };
+ State getState();
+ /**
+ * Prepare to read blob value. The value is available after execute.
+ * Use isNull to check for NULL and getLength to get the real length
+ * and to check for truncation. Sets current read/write position to
+ * after the data read.
+ */
+ int getValue(void* data, Uint32 bytes);
+ /**
+ * Prepare to insert or update blob value. An existing longer blob
+ * value will be truncated. The data buffer must remain valid until
+ * execute. Sets current read/write position to after the data. Set
+ * data to null pointer (0) to create a NULL value.
+ */
+ int setValue(const void* data, Uint32 bytes);
+ /**
+ * Check if blob is null.
+ */
+ int getNull(bool& isNull);
+ /**
+ * Set blob to NULL.
+ */
+ int setNull();
+ /**
+ * Get current length in bytes. Use isNull to distinguish between
+ * length 0 blob and NULL blob.
+ */
+ int getLength(Uint64& length);
+ /**
+ * Truncate blob to given length. Has no effect if the length is
+ * larger than current length.
+ */
+ int truncate(Uint64 length = 0);
+ /**
+ * Get current read/write position.
+ */
+ int getPos(Uint64& pos);
+ /**
+ * Set read/write position. Must be between 0 and current length.
+ * "Sparse blobs" are not supported.
+ */
+ int setPos(Uint64 pos);
+ /**
+ * Read at current position and set new position to first byte after
+ * the data read. A read past blob end returns actual number of bytes
+ * read in the in/out bytes parameter.
+ */
+ int readData(void* data, Uint32& bytes);
+ /**
+ * Read at given position. Does not use or update current position.
+ */
+ int readData(Uint64 pos, void* data, Uint32& bytes);
+ /**
+ * Write at current position and set new position to first byte after
+ * the data written. A write past blob end extends the blob value.
+ */
+ int writeData(const void* data, Uint32 bytes);
+ /**
+ * Write at given position. Does not use or update current position.
+ */
+ int writeData(Uint64 pos, const void* data, Uint32 bytes);
+ /**
+ * Return the blob column.
+ */
+ const NdbDictionary::Column* getColumn();
+ /**
+ * Get blob parts table name. Useful only to test programs.
+ */
+ static const unsigned BlobTableNameSize = 40;
+ static int getBlobTableName(char* btname, Ndb* anNdb, const char* tableName, const char* columnName);
+ /**
+ * Return error object. The error may be blob specific (below) or may
+ * be copied from a failed implicit operation.
+ */
+ const NdbError& getNdbError() const;
+ // "Invalid blob attributes or invalid blob parts table"
+ static const int ErrTable = 4263;
+ // "Invalid usage of blob attribute"
+ static const int ErrUsage = 4264;
+ // "Method is not valid in current blob state"
+ static const int ErrState = 4265;
+ // "Invalid blob seek position"
+ static const int ErrSeek = 4266;
+ // "Corrupted blob value"
+ static const int ErrCorrupt = 4267;
+ // "Error in blob head update forced rollback of transaction"
+ static const int ErrAbort = 4268;
+ // "Unknown blob error"
+ static const int ErrUnknown = 4269;
+
+private:
+ friend class Ndb;
+ friend class NdbConnection;
+ friend class NdbOperation;
+ friend class NdbScanOperation;
+ friend class NdbDictionaryImpl;
+ // state
+ State theState;
+ void setState(State newState);
+ // define blob table
+ static void getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnImpl* c);
+ static void getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnImpl* c);
+ // table name
+ char theBlobTableName[BlobTableNameSize];
+ // ndb api stuff
+ Ndb* theNdb;
+ NdbConnection* theNdbCon;
+ NdbOperation* theNdbOp;
+ NdbTableImpl* theTable;
+ NdbTableImpl* theAccessTable;
+ const NdbColumnImpl* theColumn;
+ char theFillChar;
+ // sizes
+ Uint32 theInlineSize;
+ Uint32 thePartSize;
+ Uint32 theStripeSize;
+ // getValue/setValue
+ bool theGetFlag;
+ char* theGetBuf;
+ bool theSetFlag;
+ const char* theSetBuf;
+ Uint32 theGetSetBytes;
+ // head
+ struct Head {
+ Uint64 length;
+ };
+ // buffers
+ struct Buf {
+ char* data;
+ unsigned size;
+ unsigned maxsize;
+ Buf();
+ ~Buf();
+ void alloc(unsigned n);
+ };
+ Buf theKeyBuf;
+ Buf theAccessKeyBuf;
+ Buf theHeadInlineBuf;
+ Buf thePartBuf;
+ Head* theHead;
+ char* theInlineData;
+ NdbRecAttr* theHeadInlineRecAttr;
+ bool theHeadInlineUpdateFlag;
+ bool theNewPartFlag;
+ // length and read/write position
+ int theNullFlag;
+ Uint64 theLength;
+ Uint64 thePos;
+ // errors
+ NdbError theError;
+ // for keeping in lists
+ NdbBlob* theNext;
+ // initialization
+ NdbBlob();
+ void init();
+ void release();
+ // classify operations
+ bool isTableOp();
+ bool isIndexOp();
+ bool isKeyOp();
+ bool isReadOp();
+ bool isInsertOp();
+ bool isUpdateOp();
+ bool isDeleteOp();
+ bool isScanOp();
+ // computations
+ Uint32 getPartNumber(Uint64 pos);
+ Uint32 getPartCount();
+ Uint32 getDistKey(Uint32 part);
+ // getters and setters
+ int getTableKeyValue(NdbOperation* anOp);
+ int setTableKeyValue(NdbOperation* anOp);
+ int setAccessKeyValue(NdbOperation* anOp);
+ int setPartKeyValue(NdbOperation* anOp, Uint32 part);
+ int getHeadInlineValue(NdbOperation* anOp);
+ void getHeadFromRecAttr();
+ int setHeadInlineValue(NdbOperation* anOp);
+ // data operations
+ int readDataPrivate(Uint64 pos, char* buf, Uint32& bytes);
+ int writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes);
+ int readParts(char* buf, Uint32 part, Uint32 count);
+ int insertParts(const char* buf, Uint32 part, Uint32 count);
+ int updateParts(const char* buf, Uint32 part, Uint32 count);
+ int deleteParts(Uint32 part, Uint32 count);
+ // blob handle maintenance
+ int atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn);
+ int preExecute(ExecType anExecType, bool& batch);
+ int postExecute(ExecType anExecType);
+ int preCommit();
+ int atNextResult();
+ // errors
+ void setErrorCode(int anErrorCode, bool invalidFlag = true);
+ void setErrorCode(NdbOperation* anOp, bool invalidFlag = true);
+ void setErrorCode(NdbConnection* aCon, bool invalidFlag = true);
+#ifdef VM_TRACE
+ friend class NdbOut& operator<<(NdbOut&, const NdbBlob&);
+#endif
+};
+
+#endif
diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp
index c775dd5e33d..c620578cabd 100644
--- a/ndb/include/ndbapi/NdbConnection.hpp
+++ b/ndb/include/ndbapi/NdbConnection.hpp
@@ -18,7 +18,6 @@
#define NdbConnection_H
#include <ndb_types.h>
-#include <AttrType.hpp>
#include <NdbError.hpp>
class NdbConnection;
@@ -29,6 +28,7 @@ class NdbIndexOperation;
class NdbApiSignal;
class Ndb;
class NdbScanReceiver;
+class NdbBlob;
/**
@@ -41,6 +41,35 @@ class NdbScanReceiver;
typedef void (* NdbAsynchCallback)(int, NdbConnection*, void*);
/**
+ * Commit type of transaction
+ */
+enum AbortOption {
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ CommitIfFailFree = 0,
+ CommitAsMuchAsPossible = 2, ///< Commit transaction with as many
+ TryCommit = 0, ///< <i>Missing explanation</i>
+#endif
+ AbortOnError = 0, ///< Abort transaction on failed operation
+ IgnoreError = 2 ///< Transaction continues on failed operation
+};
+
+typedef AbortOption CommitType;
+
+
+/**
+ * Execution type of transaction
+ */
+enum ExecType {
+ NoExecTypeDef = -1, ///< Erroneous type (Used for debugging only)
+ Prepare, ///< <i>Missing explanation</i>
+ NoCommit, ///< Execute the transaction as far as it has
+ ///< been defined, but do not yet commit it
+ Commit, ///< Execute and try to commit the transaction
+ Rollback ///< Rollback transaction
+};
+
+
+/**
* @class NdbConnection
* @brief Represents a transaction.
*
@@ -132,6 +161,7 @@ class NdbConnection
friend class NdbScanOperation;
friend class NdbIndexOperation;
friend class NdbScanReceiver;
+ friend class NdbBlob;
public:
@@ -419,6 +449,14 @@ public:
* @return The commit status of the transaction, i.e. one of
* { NotStarted, Started, TimeOut, Committed, Aborted, NeedAbort }
*/
+ enum CommitStatusType {
+ NotStarted, ///< Transaction not yet started
+ Started, ///< <i>Missing explanation</i>
+ Committed, ///< Transaction has been committed
+ Aborted, ///< Transaction has been aborted
+ NeedAbort ///< <i>Missing explanation</i>
+ };
+
CommitStatusType commitStatus();
/** @} *********************************************************************/
@@ -500,6 +538,10 @@ private:
~NdbConnection();
void init(); // Initialize connection object for new transaction
+
+ int executeNoBlobs(ExecType execType,
+ AbortOption abortOption = AbortOnError,
+ int force = 0 );
/**
* Set Connected node id
@@ -515,8 +557,17 @@ private:
Uint32 getBuddyConPtr(); // Gets Buddy Con Ptr
NdbConnection* next(); // Returns the next pointer
void next(NdbConnection*); // Sets the next pointer
- ConStatusType Status(); // Read the status information
- void Status(ConStatusType); // Set the status information
+
+ enum ConStatusType {
+ NotConnected,
+ Connecting,
+ Connected,
+ DisConnecting,
+ ConnectFailure
+ };
+ ConStatusType Status(); // Read the status information
+ void Status(ConStatusType); // Set the status information
+
Uint32 get_send_size(); // Get size to send
void set_send_size(Uint32); // Set size to send;
@@ -580,10 +631,12 @@ private:
void setOperationErrorCodeAbort(int anErrorCode);
int checkMagicNumber(); // Verify correct object
- NdbOperation* getNdbOperation(class NdbTableImpl* aTable);
+ NdbOperation* getNdbOperation(class NdbTableImpl* aTable,
+ NdbOperation* aNextOp = 0);
NdbScanOperation* getNdbScanOperation(class NdbTableImpl* aTable);
NdbIndexOperation* getNdbIndexOperation(class NdbIndexImpl* anIndex,
- class NdbTableImpl* aTable);
+ class NdbTableImpl* aTable,
+ NdbOperation* aNextOp = 0);
void handleExecuteCompletion();
@@ -595,6 +648,18 @@ private:
Uint32 theId;
// Keeps track of what the send method should do.
+ enum SendStatusType {
+ NotInit,
+ InitState,
+ sendOperations,
+ sendCompleted,
+ sendCOMMITstate,
+ sendABORT,
+ sendABORTfail,
+ sendTC_ROLLBACK,
+ sendTC_COMMIT,
+ sendTC_OP
+ };
SendStatusType theSendStatus;
NdbAsynchCallback theCallbackFunction; // Pointer to the callback function
void* theCallbackObject; // The callback object pointer
@@ -628,12 +693,18 @@ private:
Uint64 theTransactionId; // theTransactionId of the transaction
Uint32 theGlobalCheckpointId; // The gloabl checkpoint identity of the transaction
ConStatusType theStatus; // The status of the connection
-
- CompletionStatus theCompletionStatus; // The Completion status of the transaction
+ enum CompletionStatus {
+ NotCompleted,
+ CompletedSuccess,
+ CompletedFailure,
+ DefinitionFailure
+ } theCompletionStatus; // The Completion status of the transaction
CommitStatusType theCommitStatus; // The commit status of the transaction
Uint32 theMagicNumber; // Magic Number to verify correct object
Uint32 thePriority; // Transaction Priority
+
+ enum ReturnType { ReturnSuccess, ReturnFailure };
ReturnType theReturnStatus; // Did we have any read/update/delete failing
// to find the tuple.
bool theTransactionIsStarted;
@@ -641,7 +712,12 @@ private:
bool theSimpleState;
Uint8 m_abortOption; // Type of commit
- ListState theListState;
+ enum ListState {
+ NotInList,
+ InPreparedList,
+ InSendList,
+ InCompletedList
+ } theListState;
Uint32 theDBnode; // The database node we are connected to
Uint32 theNodeSequence; // The sequence no of the db node
@@ -662,6 +738,8 @@ private:
// nextScanResult.
NdbOperation* theScanningOp; // The operation actually performing the scan
Uint32 theBuddyConPtr;
+ // optim: any blobs
+ bool theBlobFlag;
static void sendTC_COMMIT_ACK(NdbApiSignal *,
Uint32 transId1, Uint32 transId2,
@@ -687,6 +765,10 @@ NdbConnection::set_send_size(Uint32 send_size)
return;
}
+#ifdef NDB_NO_DROPPED_SIGNAL
+#include <stdlib.h>
+#endif
+
inline
int
NdbConnection::checkMagicNumber()
@@ -830,7 +912,7 @@ Parameters: aStatus: The status.
Remark: Sets Connect status.
******************************************************************************/
inline
-ConStatusType
+NdbConnection::ConStatusType
NdbConnection::Status()
{
return theStatus;
@@ -849,6 +931,7 @@ NdbConnection::Status( ConStatusType aStatus )
theStatus = aStatus;
}
+
/******************************************************************************
void setGCI();
diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp
index a8a3bc86786..3b38e33ec91 100644
--- a/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/ndb/include/ndbapi/NdbDictionary.hpp
@@ -182,7 +182,8 @@ public:
Varbinary, ///< Max len
Datetime, ///< Precision down to 1 sec (sizeof(Datetime) == 8 bytes )
Timespec, ///< Precision down to 1 nsec(sizeof(Datetime) == 12 bytes )
- Blob ///< Binary large object (see NdbBlob)
+ Blob, ///< Binary large object (see NdbBlob)
+ Clob ///< Text blob
};
/**
@@ -297,7 +298,34 @@ public:
* Array length for column or max length for variable length arrays.
*/
int getLength() const;
-
+
+ /**
+ * For blob, set or get "inline size" i.e. number of initial bytes
+ * to store in table's blob attribute. This part is normally in
+ * main memory and can be indexed and interpreted.
+ */
+ void setInlineSize(int size) { setPrecision(size); }
+ int getInlineSize() const { return getPrecision(); }
+
+ /**
+ * For blob, set or get "part size" i.e. number of bytes to store in
+ * each tuple of the "blob table". Must be less than 64k.
+ */
+ void setPartSize(int size) { setScale(size); }
+ int getPartSize() const { return getScale(); }
+
+ /**
+ * For blob, set or get "stripe size" i.e. number of consecutive
+ * <em>parts</em> to store in each node group.
+ */
+ void setStripeSize(int size) { setLength(size); }
+ int getStripeSize() const { return getLength(); }
+
+ /**
+ * Get size of element
+ */
+ int Column::getSize() const;
+
/**
* Set distribution key
*
@@ -349,6 +377,7 @@ public:
#endif
private:
+ friend class NdbRecAttr;
friend class NdbColumnImpl;
class NdbColumnImpl & m_impl;
Column(NdbColumnImpl&);
@@ -1023,6 +1052,7 @@ public:
private:
friend class NdbDictionaryImpl;
friend class UtilTransactions;
+ friend class NdbBlob;
class NdbDictionaryImpl & m_impl;
Dictionary(NdbDictionaryImpl&);
const Table * getIndexTable(const char * indexName,
@@ -1030,4 +1060,6 @@ public:
};
};
+class NdbOut& operator <<(class NdbOut& ndbout, const NdbDictionary::Column::Type type);
+
#endif
diff --git a/ndb/include/ndbapi/NdbIndexOperation.hpp b/ndb/include/ndbapi/NdbIndexOperation.hpp
index 3b8e5f7a888..baf31dca0ee 100644
--- a/ndb/include/ndbapi/NdbIndexOperation.hpp
+++ b/ndb/include/ndbapi/NdbIndexOperation.hpp
@@ -184,7 +184,7 @@ private:
// Private attributes
NdbIndexImpl* m_theIndex;
- Uint32 m_theIndexDefined[MAXNROFTUPLEKEY][3];
+ Uint32 m_theIndexDefined[NDB_MAX_ATTRIBUTES_IN_INDEX][3];
Uint32 m_theIndexLen; // Length of the index in words
Uint32 m_theNoOfIndexDefined; // The number of index attributes
};
diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp
index 3c515fe84ef..cfa656cb2d5 100644
--- a/ndb/include/ndbapi/NdbOperation.hpp
+++ b/ndb/include/ndbapi/NdbOperation.hpp
@@ -18,10 +18,9 @@
#define NdbOperation_H
#include <ndb_types.h>
-
-#include <AttrType.hpp>
-#include <NdbError.hpp>
-#include <NdbReceiver.hpp>
+#include "ndbapi_limits.h"
+#include "NdbError.hpp"
+#include "NdbReceiver.hpp"
class Ndb;
class NdbApiSignal;
@@ -29,6 +28,7 @@ class NdbRecAttr;
class NdbOperation;
class NdbConnection;
class NdbColumnImpl;
+class NdbBlob;
/**
* @class NdbOperation
@@ -42,7 +42,8 @@ class NdbOperation
friend class NdbScanReceiver;
friend class NdbScanFilter;
friend class NdbScanFilterImpl;
-
+ friend class NdbBlob;
+
public:
/**
* @name Define Standard Operation Type
@@ -526,6 +527,17 @@ public:
virtual int setValue(Uint32 anAttrId, Int64 aValue);
virtual int setValue(Uint32 anAttrId, float aValue);
virtual int setValue(Uint32 anAttrId, double aValue);
+
+ /**
+ * This method replaces getValue/setValue for blobs. It creates
+ * a blob handle NdbBlob. A second call with same argument returns
+ * the previously created handle. The handle is linked to the
+ * operation and is maintained automatically.
+ *
+ * See NdbBlob for details.
+ */
+ virtual NdbBlob* getBlobHandle(const char* anAttrName);
+ virtual NdbBlob* getBlobHandle(Uint32 anAttrId);
/** @} *********************************************************************/
/**
@@ -833,8 +845,29 @@ public:
*/
int getNdbErrorLine();
+ /**
+ * Get table name of this operation.
+ */
+ const char* getTableName() const;
+
/** @} *********************************************************************/
+ /**
+ * Type of operation
+ */
+ enum OperationType {
+ ReadRequest = 0, ///< Read operation
+ UpdateRequest = 1, ///< Update Operation
+ InsertRequest = 2, ///< Insert Operation
+ DeleteRequest = 3, ///< Delete Operation
+ WriteRequest = 4, ///< Write Operation
+ ReadExclusive = 5, ///< Read exclusive
+ OpenScanRequest, ///< Scan Operation
+ OpenRangeScanRequest, ///< Range scan operation
+ NotDefined2, ///< Internal for debugging
+ NotDefined ///< Internal for debugging
+ };
+
protected:
/******************************************************************************
* These are the methods used to create and delete the NdbOperation objects.
@@ -865,11 +898,27 @@ protected:
NdbOperation* next(); // Get next pointer
+ enum OperationStatus{
+ Init,
+ OperationDefined,
+ TupleKeyDefined,
+ GetValue,
+ SetValue,
+ ExecInterpretedValue,
+ SetValueInterpreted,
+ FinalGetValue,
+ SubroutineExec,
+ SubroutineEnd,
+ SetBound,
+ WaitResponse,
+ WaitCommitResponse,
+ Finished,
+ ReceiveFinished
+ };
+
OperationStatus Status(); // Read the status information
void Status(OperationStatus); // Set the status information
-
- OperationType RequestType();
void NdbCon(NdbConnection*); // Set reference to connection
// object.
@@ -879,8 +928,6 @@ protected:
// the operations object.
void setStartIndicator();
- void setCommitIndicator(CommitType aCommitType);
-
/******************************************************************************
* The methods below is the execution part of the NdbOperation
* class. This is where the NDB signals are sent and received. The
@@ -924,6 +971,7 @@ protected:
Uint32 len);
NdbRecAttr* getValue(const NdbColumnImpl* anAttrObject, char* aValue = 0);
int setValue(const NdbColumnImpl* anAttrObject, const char* aValue, Uint32 len);
+ NdbBlob* getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* anAttrObject);
int incValue(const NdbColumnImpl* anAttrObject, Uint32 aValue);
int incValue(const NdbColumnImpl* anAttrObject, Uint64 aValue);
int subValue(const NdbColumnImpl* anAttrObject, Uint32 aValue);
@@ -968,6 +1016,10 @@ protected:
NdbOperation*
takeOverScanOp(OperationType opType, NdbConnection* updateTrans);
+ // get table or index key from prepared signals
+ int getKeyFromTCREQ(Uint32* data, unsigned size);
+ int getKeyFromKEYINFO20(Uint32* data, unsigned size);
+
/******************************************************************************
* These are the private variables that are defined in the operation objects.
*****************************************************************************/
@@ -1013,18 +1065,13 @@ protected:
Uint32 theCurrRecAI_Len; // The currently received length
Uint32 theAI_ElementLen; // How many words long is this element
Uint32* theCurrElemPtr; // The current pointer to the element
- //Uint32 theTableId; // Table id.
- //Uint32 theAccessTableId; // The id of table for initial access,
- // changed by NdbIndexOperation
- //Uint32 theSchemaVersion; // The schema version on the table.
class NdbTableImpl* m_currentTable; // The current table
class NdbTableImpl* m_accessTable;
// Set to TRUE when a tuple key attribute has been defined.
- // A tuple key is allowed to consist of 64 attributes.
- Uint32 theTupleKeyDefined[MAXNROFTUPLEKEY][3];
+ Uint32 theTupleKeyDefined[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY][3];
- Uint32 theTotalNrOfKeyWordInSignal; // The total number of
+ Uint32 theTotalNrOfKeyWordInSignal; // The total number of
// keyword in signal.
Uint32 theTupKeyLen; // Length of the tuple key in words
@@ -1071,9 +1118,16 @@ protected:
// saveBoundATTRINFO() moves ATTRINFO here when setBound() is ready
NdbApiSignal* theBoundATTRINFO;
Uint32 theTotalBoundAI_Len;
+ // Blobs in this operation
+ NdbBlob* theBlobList;
};
+#ifdef NDB_NO_DROPPED_SIGNAL
+#include <stdlib.h>
+#endif
+
+
inline
int
NdbOperation::checkMagicNumber()
@@ -1094,16 +1148,6 @@ NdbOperation::setStartIndicator()
theStartIndicator = 1;
}
-#if 0
-inline
-void
-NdbOperation::setCommitIndicator(CommitType aTypeOfCommit)
-{
- theCommitIndicator = 1;
- theCommitType = (Uint8)aTypeOfCommit;
-}
-#endif
-
inline
int
NdbOperation::getNdbErrorLine()
@@ -1145,7 +1189,7 @@ Parameters: aStatus: The status.
Remark: Sets Operation status.
******************************************************************************/
inline
-OperationStatus
+NdbOperation::OperationStatus
NdbOperation::Status()
{
return theStatus;
@@ -1178,18 +1222,6 @@ NdbOperation::NdbCon(NdbConnection* aNdbCon)
theNdbCon = aNdbCon;
}
-/******************************************************************************
-OperationType RequestType();
-
-Remark: Return the request typ of the operation..
-******************************************************************************/
-inline
-OperationType
-NdbOperation::RequestType()
-{
- return theOperationType;
-}
-
inline
int
NdbOperation::equal(const char* anAttrName, Int32 aPar)
diff --git a/ndb/include/ndbapi/NdbRecAttr.hpp b/ndb/include/ndbapi/NdbRecAttr.hpp
index 7eeff88671d..36b54035d96 100644
--- a/ndb/include/ndbapi/NdbRecAttr.hpp
+++ b/ndb/include/ndbapi/NdbRecAttr.hpp
@@ -18,10 +18,8 @@
#define NdbRecAttr_H
#include <NdbDictionary.hpp>
-#include "AttrType.hpp"
class NdbOperation;
-class AttrInfo;
/**
* @class NdbRecAttr
@@ -78,20 +76,19 @@ class NdbRecAttr
friend class NdbEventOperationImpl;
friend class NdbScanReceiver;
friend class Ndb;
-
+ friend class NdbOut& operator<<(class NdbOut&, const class AttributeS&);
+
public:
/**
* @name Getting meta information
* @{
*/
const NdbDictionary::Column * getColumn() const;
-
+
/**
- * Get attribute type.
- *
- * @return Type of attribute: { Signed, UnSigned, Float, String }
+ * Get type of column
+ * @return Data type of the column
*/
- AttrType attrType() const ;
NdbDictionary::Column::Type getType() const;
/**
@@ -257,6 +254,7 @@ private:
void next(NdbRecAttr* aRecAttr);
NdbRecAttr* next() const;
+ int setup(const class NdbDictionary::Column* col, char* aValue);
int setup(const class NdbColumnImpl* anAttrInfo, char* aValue);
/* Set up attributes and buffers */
bool copyoutRequired() const; /* Need to copy data to application */
@@ -317,33 +315,6 @@ NdbRecAttr::attrSize() const {
}
inline
-AttrType
-NdbRecAttr::attrType() const {
- switch(getType()){
- case NdbDictionary::Column::Bigint:
- case NdbDictionary::Column::Int:
- return Signed;
- case NdbDictionary::Column::Bigunsigned:
- case NdbDictionary::Column::Unsigned:
- return UnSigned;
- case NdbDictionary::Column::Float:
- case NdbDictionary::Column::Decimal:
- case NdbDictionary::Column::Double:
- return Float;
- case NdbDictionary::Column::Char:
- case NdbDictionary::Column::Varchar:
- case NdbDictionary::Column::Binary:
- case NdbDictionary::Column::Varbinary:
- return String;
- case NdbDictionary::Column::Datetime:
- case NdbDictionary::Column::Timespec:
- case NdbDictionary::Column::Undefined:
- default:
- return NoAttrTypeDef;
- }
-}
-
-inline
Uint32
NdbRecAttr::arraySize() const
{
@@ -505,5 +476,7 @@ NdbRecAttr::isNULL() const
return theNULLind;
}
+class NdbOut& operator <<(class NdbOut&, const NdbRecAttr &);
+
#endif
diff --git a/ndb/include/ndbapi/NdbReceiver.hpp b/ndb/include/ndbapi/NdbReceiver.hpp
index bc11207a112..a1a08a9735a 100644
--- a/ndb/include/ndbapi/NdbReceiver.hpp
+++ b/ndb/include/ndbapi/NdbReceiver.hpp
@@ -56,6 +56,10 @@ private:
void* m_owner;
};
+#ifdef NDB_NO_DROPPED_SIGNAL
+#include <stdlib.h>
+#endif
+
inline
bool
NdbReceiver::checkMagicNumber() const {
diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp
index f83669fb616..151dc5bb99f 100644
--- a/ndb/include/ndbapi/NdbScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbScanOperation.hpp
@@ -33,6 +33,8 @@
#include <NdbOperation.hpp>
#include <NdbCursorOperation.hpp>
+class NdbBlob;
+
/**
* @class NdbScanOperation
* @brief Class of scan operations for use in transactions.
@@ -82,6 +84,10 @@ public:
int setValue(Uint32 anAttrId, float aValue);
int setValue(Uint32 anAttrId, double aValue);
#endif
+
+ NdbBlob* getBlobHandle(const char* anAttrName);
+ NdbBlob* getBlobHandle(Uint32 anAttrId);
+
private:
NdbScanOperation(Ndb* aNdb);
diff --git a/ndb/include/ndbapi/NdbSchemaCon.hpp b/ndb/include/ndbapi/NdbSchemaCon.hpp
deleted file mode 100644
index 9d6b49df8f9..00000000000
--- a/ndb/include/ndbapi/NdbSchemaCon.hpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef NdbSchemaCon_H
-#define NdbSchemaCon_H
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
-
-#include <ndb_types.h>
-#include "AttrType.hpp"
-#include "NdbError.hpp"
-
-class NdbSchemaOp;
-class NdbApiSignal;
-class Ndb;
-
-/**
- * @class NdbSchemaCon
- * @brief Represents a schema transaction.
- *
- * When creating a new table,
- * the first step is to get a NdbSchemaCon object to represent
- * the schema transaction.
- * This is done by calling Ndb::startSchemaTransaction.
- *
- * The next step is to get a NdbSchemaOp object by calling
- * NdbSchemaCon::getNdbSchemaOp.
- * The NdbSchemaOp object then has methods to define the table and
- * its attributes.
- *
- * Finally, the NdbSchemaCon::execute method inserts the table
- * into the database.
- *
- * @note Currently only one table can be added per transaction.
- */
-class NdbSchemaCon
-{
-friend class Ndb;
-friend class NdbSchemaOp;
-
-public:
- /**
- * Execute a schema transaction.
- *
- * @return 0 if successful otherwise -1.
- */
- int execute();
-
- /**
- * Get a schemaoperation.
- *
- * @note Currently, only one operation per transaction is allowed.
- *
- * @return Pointer to a NdbSchemaOp or NULL if unsuccessful.
- */
- NdbSchemaOp* getNdbSchemaOp();
-
- /**
- * Get the latest error
- *
- * @return Error object.
- */
- const NdbError & getNdbError() const;
-
-private:
-/******************************************************************************
- * These are the create and delete methods of this class.
- *****************************************************************************/
-
- NdbSchemaCon(Ndb* aNdb);
- ~NdbSchemaCon();
-
-/******************************************************************************
- * These are the private methods of this class.
- *****************************************************************************/
- void init(); // Initialise connection object for new
- // transaction.
-
- void release(); // Release all schemaop in schemaCon
-
- /***************************************************************************
- * These methods are service methods to other classes in the NDBAPI.
- ***************************************************************************/
-
- int checkMagicNumber(); // Verify correct object
- int receiveDICTTABCONF(NdbApiSignal* aSignal);
- int receiveDICTTABREF(NdbApiSignal* aSignal);
-
-
- int receiveCREATE_INDX_CONF(NdbApiSignal*);
- int receiveCREATE_INDX_REF(NdbApiSignal*);
- int receiveDROP_INDX_CONF(NdbApiSignal*);
- int receiveDROP_INDX_REF(NdbApiSignal*);
-
-
-
-/*****************************************************************************
- * These are the private variables of this class.
- *****************************************************************************/
-
-
- NdbError theError; // Errorcode
- Ndb* theNdb; // Pointer to Ndb object
-
- NdbSchemaOp* theFirstSchemaOpInList; // First operation in operation list.
- int theMagicNumber; // Magic number
-};
-
-inline
-int
-NdbSchemaCon::checkMagicNumber()
-{
- if (theMagicNumber != 0x75318642)
- return -1;
- return 0;
-}//NdbSchemaCon::checkMagicNumber()
-#endif
-#endif
-
-
diff --git a/ndb/include/ndbapi/NdbSchemaOp.hpp b/ndb/include/ndbapi/NdbSchemaOp.hpp
deleted file mode 100644
index c3a3827a6b4..00000000000
--- a/ndb/include/ndbapi/NdbSchemaOp.hpp
+++ /dev/null
@@ -1,456 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef NdbSchemaOp_H
-#define NdbSchemaOp_H
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
-
-#include "NdbDictionary.hpp"
-#include "AttrType.hpp"
-#include "NdbSchemaCon.hpp"
-
-class NdbApiSignal;
-class Ndb;
-
-/**
- * @class NdbSchemaOp
- * @brief Represents various operations for use in schema transactions
- *
- * This class is used for schema operations, e.g. creating tables and
- * attributes.
- *
- * The NdbSchemaOp object is created using NdbSchemaCon::getNdbSchemaOp.
- *
- * @note This class is depricated and is now replaced with the class
- * NdbDictionary.
- */
-class NdbSchemaOp
-{
- friend class Ndb;
- friend class NdbSchemaCon;
-
-public:
- /**
- * Create a new table in the database.
- *
- * @note The NdbSchemaCon should be closed with
- * Ndb::closeSchemaTransaction, even if this method fails.
- *
- * @param aTableName Table name. Should not be NULL.
- * @param aTableSize (Performance parameter.)
- * Initial size of the data part of the table
- * expressed in kByte.
- * The database handles
- * bad parameter setting but at a certain
- * loss in performance.
- * The size given here is
- * the initial size allocated for the table
- * storage (the data part).
- * When calculating the data storage one should
- * add the size of all attributes (each attribute
- * consumes at least 4 bytes) and also an overhead
- * of 12 byte.
- * Variable size attributes (not supported yet)
- * will have a size of 12 bytes plus the actual
- * data storage parts where there is an
- * additional overhead based on the size of the
- * variable part.
- * <br>
- * An example table with 5 attributes:
- * one 64 bit attribute, one 32 bit attribute,
- * two 16 bit attributes and one array of 64 8 bits.
- * This table will consume
- * 12 (overhead) + 8 + 4 + 2*4 (4 is minimum) + 64 =
- * 96 bytes per record.
- * Additionally an overhead of about 2 % as page
- * headers and waste should be allocated.
- * Thus, 1 million records should consume 96 MBytes
- * plus the overhead 2 MByte and rounded up to
- * 100 000 kBytes.
- * <br><em>
- * This parameter is currently not used.
- * </em>
- * @param aTupleKey Indicates if the table has a primary key or not.
- * <br>
- * <b>TupleKey</b> means that a <em>primary key</em>
- * consisting of one to four attributes
- * (at most one of variable size)
- * uniquely identifies each record in the created
- * table.
- * <br>
- * <b>TupleId</b> means that a <em>tuple identity</em>
- * is used. The tuple identity is
- * a unique key indentifying each record of the
- * created table.
- * The tuple identity is a (non-stored)
- * 64 bit attribute named <b>NDB$TID</b>.
- * <br>
- * When inserting a record (tuple), the method
- * NdbOperation::setTupleId
- * will generate a unique tuple identity
- * and return it to the user.
- * <br>
- * When reading, updating or deleting a record
- * in a table with <b>TupleId</b>,
- * NdbOperation::equal("NDB$TID", value_Uint64)
- * can be used to identify the record.
- * <br>
- * Legal values: TupleKey or TupleId.
- * @param aNrOfPages (Performance parameter.)
- * Specifies the initial size of the index storage.
- * When calculating the index storage,
- * each key has approximately 14 byte of
- * overhead plus the size of the key.
- * Each key attribute takes up at least 4 bytes
- * of storage.
- * Thus a mixed key consisting of a
- * 64 bit attribute, a 32 bit attribute
- * and a 16 bit attribute will
- * consume approx. 30 bytes per key.
- * Thus, the if initial size is to be 1 million rows,
- * then aNrOfPages should be set to
- * 30 M / 8k = 2670 pages.
- * <br><em>
- * This parameter is currently not used.
- * </em>
- * @param aFragmentType Type of fragmentation.<br>
- * <b>All</b> (default) means that the
- * table fragments are automatically
- * distributed on all nodes in the system.<br>
- * <b>DistributionGroup</b> and
- * <b>DistributionKey</b> are
- * also supported. For further details about
- * these types see the documentation of
- * Ndb::startTransaction.
- * @param aKValue (Hash parameter.)
- * Only allowed value is 6.
- * Later implementations might add flexibility
- * in this parameter.
- * @param aMinLoadFactor (Hash parameter.)
- * This value specifies the load factor when
- * starting to shrink the hash table.
- * It must be smaller than aMaxLoadFactor.
- * Both these factors are given in percentage.
- * @param aMaxLoadFactor (Hash parameter.)
- * This value specifies the load factor when
- * starting to split the containers in the local
- * hash tables. 100 is the maximum which will
- * optimize memory usage (this is the figure
- * used for the above calculations).
- * A lower figure will store less information in
- * each container and thus
- * find the key faster but consume more memory.
- * @param aMemoryType Currently only 1 is allowed which specifies
- * storage of table in main memory.
- * Later 2 will be added where the table is stored
- * completely on disk
- * and 3 where the index is in main memory but
- * data is on disk.
- * If 1 is chosen an individual attribute can
- * still be specified as a disk attribute.
- * @param aStoredTable If set to false it indicates that the table is
- * a temporary table and should not be logged
- * to disk.
- * In case of a system restart the table will still
- * be defined and exist but will be empty.
- * Thus no checkpointing and
- * no logging is performed on the table.
- * The default value is true and indicates a
- * normal table with full checkpointing and
- * logging activated.
- * @return Returns 0 when successful and returns -1 otherwise.
- */
- int createTable( const char* aTableName,
- Uint32 aTableSize = 8,
- KeyType aTupleKey = TupleKey,
- int aNrOfPages = 2,
- FragmentType aFragmentType = All,
- int aKValue = 6,
- int aMinLoadFactor = 78,
- int aMaxLoadFactor = 80,
- int aMemoryType = 1,
- bool aStoredTable = true);
-
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
- /**
- * This is the old function declaration, don't use.
- *
- * @deprecated do not use!
- */
- inline int createTable( const char* aTableName,
- Uint32 aTableSize,
- KeyType aTupleKey,
- int aNrOfPages,
- FragmentType aFragmentType,
- int aKValue,
- int aMinLoadFactor,
- int aMaxLoadFactor,
- int aMemoryType,
- int aStoredTable){
- return createTable(aTableName,
- aTableSize,
- aTupleKey,
- aNrOfPages,
- aFragmentType,
- aKValue,
- aMinLoadFactor,
- aMaxLoadFactor,
- aMemoryType,
- (aStoredTable == 1 ? true : false));
- }
-#endif
-
- /**
- * Add a new attribute to a database table.
- *
- * Attributes can only be added to a table in the same transaction
- * as the transaction creating the table.
- *
- * @note The NdbSchemaCon transaction should be closed with
- * Ndb::closeSchemaTransaction, even if this method fails.
- *
- * Example creating an unsigned int attribute belonging to the primary key
- * of the table it is created in:
- * @code
- * MySchemaOp->createAttribute("Attr1", // Attribute name
- * TupleKey, // Belongs to primary key
- * 32, // 32 bits
- * 1, // Not an array attribute
- * UnSigned, // Unsigned type
- * );
- * @endcode
- *
- * Example creating a string attribute belonging to the primary key
- * of the table it is created in:
- * @code
- * MySchemaOp->createAttribute("Attr1", // Attribute name
- * TupleKey, // Belongs to primary key
- * 8, // Each character is 8 bits
- * 12, // Max 12 chars in string
- * String, // Attribute if of type string
- * );
- * @endcode
- *
- * A <em>distribution key</em> is a set of attributes which are used
- * to distribute the tuples onto the NDB nodes.
- * A <em>distribution group</em> is a part (currently 16 bits)
- * of an attribute used to distribute the tuples onto the NDB nodes.
- * The distribution key uses the NDB Cluster hashing function,
- * while the distribution group uses a simpler function.
- *
- * @param aAttrName Attribute name. Should not be NULL.
- * @param aTupleKey This parameter specifies whether the
- * attribute is part of the primary key or not.
- * Floats are not allowed in the primary key.
- * <br>
- * Legal values: NoKey, TupleKey
- * @param aAttrSize Specifies the size of the elements of the
- * attribute. (An attribute can consist
- * of an array of elements.)
- * <br>
- * Legal values: 8, 16, 32, 64 and 128 bits.
- * @param aArraySize Size of array.
- * <br>
- * Legal values:
- * 0 = variable-sized array,
- * 1 = no array, and
- * 2- = fixed size array.
- * <br>
- * <em>
- * Variable-sized array attributes are
- * not yet supported.
- * </em>
- * <br>
- * There is no upper limit of the array size
- * for a single attribute.
- * @param aAttrType The attribute type.
- * This is only of interest if calculations are
- * made within NDB.
- * <br>
- * Legal values: UnSigned, Signed, Float, String
- * @param aStorageMode Main memory based or disk based attribute.<br>
- * Legal values: MMBased, DiskBased
- * <br>
- * <em>
- * Disk-based attributes are not yet supported.
- * </em>
- * @param nullable Set to true if NULL is a correct value for
- * the attribute.
- * <br>
- * Legal values: true, false
- * @param aStType Stored in both index and data storage or
- * only store in index data storage.
- * <br>
- * This parameter is only of interest for tuple
- * key attributes.
- * All tuple key attributes values are always stored
- * in the index storage part.
- * If this parameter is set to
- * IndexStorageAttribute, then the attribute values
- * will <em>only</em> be stored in the index
- * storage part and <em>not</em> in the data
- * storage part.
- * <br>
- * If there will be no scans using the primary
- * key attribute and if the size of the attribute
- * is large, then this might be of interest.
- * A typical example is a table where
- * http-addresses are used as primary key.
- * <br>
- * Legal values: NormalStorageAttribute,
- * IndexStorageAttribute
- * @param aDistributionKey Sometimes it is preferable to use a subset
- * of the primary key as the distribution key.
- * An example is TPC-C where it might be
- * good to use the warehouse id and district id
- * as the distribution key.
- * <br>
- * Locally in the fragments the full primary key
- * will still be used with the hashing algorithm.
- * Set to 1 if this attribute is part of the
- * distribution key.
- * All distribution key attributes must be
- * defined before
- * any other attributes are defined.
- * @param aDistributionGroup In other applications it is desirable to use
- * only a part of an attribute to create the
- * distribution key.
- * This is applicable for some telecom
- * applications.
- * <br>
- * In these situations one must provide how many
- * bits of the attribute that is to
- * be used as the distribution hash value.
- * <br>
- * This provides some control to the
- * application of the distribution.
- * It still needs to be part of a primary key
- * the attribute and must be defined as the
- * first attribute.
- * @param aDistributionGroupNoOfBits
- * Number of bits to use of the
- * distribution group attribute in the
- * distribution hash value.
- * <br>
- * Currently, only 16 bits is supported. It will
- * always be the last 16 bits in the attribute
- * which is used for the distribution group.
- * @param aAutoIncrement Set to autoincrement attribute.
- * @param aDefaultValue Set a default value of attribute.
- *
- * @return Returns 0 when successful and returns -1 otherwise.
- ****************************************************************************/
- int createAttribute(const char* aAttrName,
- KeyType aTupleKey = NoKey,
- int aAttrSize = 32,
- int aArraySize = 1,
- AttrType aAttrType = UnSigned,
- StorageMode aStorageMode = MMBased,
- bool nullable = false,
- StorageAttributeType aStType= NormalStorageAttribute,
- int aDistributionKey = 0,
- int aDistributionGroup = 0,
- int aDistributionGroupNoOfBits = 16,
- bool aAutoIncrement = false,
- const char* aDefaultValue = 0);
-
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
- /**
- * @deprecated do not use!
- */
- int createAttribute(const char* aAttrName,
- KeyType aTupleKey,
- int aAttrSize,
- int aArraySize,
- AttrType aAttrType,
- StorageMode aStorageMode,
- NullAttributeType aNullAttr,
- StorageAttributeType aStType = NormalStorageAttribute,
- int aDistributionKey = 0,
- int aDistributionGroup = 0,
- int aDistributionGroupNoOfBits = 16){
- return createAttribute(aAttrName,
- aTupleKey,
- aAttrSize,
- aArraySize,
- aAttrType,
- aStorageMode,
- aNullAttr == NullAttribute,
- aStType,
- aDistributionKey,
- aDistributionGroup,
- aDistributionGroupNoOfBits);
- }
-#endif
-
- /**
- * Get the last error which occurred during the transaction.
- *
- * If an error occured (NdbSchemaCon::execute returned -1 or
- * NdbSchemaCon::getNdbSchemaOp returned NULL), then this method
- * retrieves the error object containing information about
- * the error.
- *
- * @return Error object containing information about last error.
- */
- const NdbError & getNdbError() const;
-
-protected:
-
-/*****************************************************************************
- * These are the methods used to create and delete the NdbOperation objects.
- ****************************************************************************/
- NdbSchemaOp(Ndb* aNdb);
-
- ~NdbSchemaOp();
-
-/******************************************************************************
- * These methods are service routines used by the other NDBAPI classes.
- *****************************************************************************/
-
- void release(); // Release all memory connected
- // to the operations object.
-
-/****************************************************************************
- * The methods below is the execution part of the NdbSchemaOp class.
- *****************************************************************************/
-
- int sendRec();
- int sendSignals(Uint32 aNodeId, bool HaveMutex);
-
- int init(NdbSchemaCon* aSchemaCon);
-
- /**************************************************************************
- * These are the private variables that are defined in the operation
- * objects.
- **************************************************************************/
- Ndb* theNdb; // Point back to the Ndb object.
- NdbSchemaCon* theSchemaCon; // Point back to the connection object.
-
- class NdbDictionary::Table * m_currentTable;
-};
-
-inline
-const NdbError &
-NdbSchemaOp::getNdbError() const
-{
- return theSchemaCon->getNdbError();
-}
-
-#endif
-#endif
-
-
diff --git a/ndb/include/ndbapi/ndbapi_limits.h b/ndb/include/ndbapi/ndbapi_limits.h
index bcfba7d3f9d..1cf2d9b342d 100644
--- a/ndb/include/ndbapi/ndbapi_limits.h
+++ b/ndb/include/ndbapi/ndbapi_limits.h
@@ -18,30 +18,16 @@
#define NDBAPI_LIMITS_H
#define NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY 32
-#define NDB_MAX_TABLES 1600
+#define NDB_MAX_ATTRIBUTES_IN_INDEX NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY
#define NDB_MAX_DATABASE_NAME_SIZE 128
#define NDB_MAX_SCHEMA_NAME_SIZE 128
#define NDB_MAX_TAB_NAME_SIZE 128
-#define NDB_MAX_ATTR_NAME_SIZE 32
-#define NDB_MAX_ATTR_DEFAULT_VALUE_SIZE 128
#define NDB_MAX_ATTRIBUTES_IN_TABLE 91
-#define NDB_MAX_ATTRIBUTES_IN_INDEX NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY
+
#define NDB_MAX_TUPLE_SIZE_IN_WORDS 1023
-#define NDB_MAX_FIXED_KEY_LENGTH_IN_WORDS 8
#define NDB_MAX_KEYSIZE_IN_WORDS 1023
#define NDB_MAX_KEY_SIZE NDB_MAX_KEYSIZE_IN_WORDS*sizeof(Uint32)
-#define NDB_MAX_TUPLE_SIZE 8191
-#define NDB_MAX_CONNECTIONS 127
-#define NDB_MAX_TRANSACTIONS 1024
-#define NDB_MAX_PARALLEL_SCANS 12
+#define NDB_MAX_TUPLE_SIZE NDB_MAX_TUPLE_SIZE_IN_WORDS*sizeof(uint32)
#define NDB_MAX_ACTIVE_EVENTS 100
-#ifndef MIN
-#define MIN(x,y) (((x)<(y))?(x):(y))
-#endif
-
-#ifndef MAX
-#define MAX(x,y) (((x)>(y))?(x):(y))
-#endif
-
#endif
diff --git a/ndb/include/portlib/PortDefs.h b/ndb/include/portlib/PortDefs.h
index 6cd5be0149f..5e24e08ec61 100644
--- a/ndb/include/portlib/PortDefs.h
+++ b/ndb/include/portlib/PortDefs.h
@@ -49,7 +49,7 @@ int getopt(int, char **, char *opts);
#endif // NDB_WIN32
#ifdef NDB_ALPHA
-#ifdef NDB_GCC
+#ifdef NDB_GCC // only for NDB_ALPHA
extern int gnuShouldNotUseRPCC();
#define RPCC() gnuShouldNotUseRPCC();
#else
diff --git a/ndb/include/util/Base64.hpp b/ndb/include/util/Base64.hpp
index a8678da946c..1156636eec8 100644
--- a/ndb/include/util/Base64.hpp
+++ b/ndb/include/util/Base64.hpp
@@ -20,7 +20,8 @@
#include <UtilBuffer.hpp>
#include <BaseString.hpp>
-int base64_encode(UtilBuffer &src, BaseString &dst);
-int base64_decode(BaseString &src, UtilBuffer &dst);
+int base64_encode(const UtilBuffer &src, BaseString &dst);
+int base64_decode(const BaseString &src, UtilBuffer &dst);
+int base64_decode(const char * s, size_t len, UtilBuffer &dst);
#endif /* !__BASE64_HPP_INCLUDED__ */
diff --git a/ndb/include/util/BaseString.hpp b/ndb/include/util/BaseString.hpp
index 75a1c291594..8755c13e9bb 100644
--- a/ndb/include/util/BaseString.hpp
+++ b/ndb/include/util/BaseString.hpp
@@ -203,13 +203,13 @@ BaseString::empty() const
inline void
BaseString::ndb_toupper() {
for(unsigned i = 0; i < length(); i++)
- m_chr[i] = ::toupper(m_chr[i]);
+ m_chr[i] = toupper(m_chr[i]);
}
inline void
BaseString::ndb_tolower() {
for(unsigned i = 0; i < length(); i++)
- m_chr[i] = ::tolower(m_chr[i]);
+ m_chr[i] = tolower(m_chr[i]);
}
inline bool
diff --git a/ndb/include/util/Bitmask.hpp b/ndb/include/util/Bitmask.hpp
index ed981743512..7355742f845 100644
--- a/ndb/include/util/Bitmask.hpp
+++ b/ndb/include/util/Bitmask.hpp
@@ -134,7 +134,7 @@ public:
/**
* getText - Return as hex-digits (only for debug routines).
*/
- static void getText(unsigned size, const Uint32 data[], char* buf);
+ static char* getText(unsigned size, const Uint32 data[], char* buf);
};
inline bool
@@ -302,9 +302,10 @@ BitmaskImpl::setField(unsigned size, Uint32 data[],
set(size, data, pos + i, val & (1 << i));
}
-inline void
+inline char *
BitmaskImpl::getText(unsigned size, const Uint32 data[], char* buf)
{
+ char * org = buf;
const char* const hex = "0123456789abcdef";
for (int i = (size-1); i >= 0; i--) {
Uint32 x = data[i];
@@ -315,6 +316,7 @@ BitmaskImpl::getText(unsigned size, const Uint32 data[], char* buf)
buf += 8;
}
*buf = 0;
+ return org;
}
/**
@@ -331,11 +333,12 @@ public:
*/
struct Data {
Uint32 data[size];
-
+#if 0
Data & operator=(const Bitmask<size> & src) {
- src.assign(size, data);
+ src.copyto(size, data);
return *this;
}
+#endif
};
private:
@@ -345,21 +348,24 @@ public:
STATIC_CONST( NotFound = BitmaskImpl::NotFound );
STATIC_CONST( TextLength = size * 8 );
+ Bitmask() { clear();}
+
/**
* assign - Set all bits in <em>dst</em> to corresponding in <em>src/<em>
*/
- void assign(const Bitmask<size>::Data & src);
+ void assign(const typename Bitmask<size>::Data & src);
/**
* assign - Set all bits in <em>dst</em> to corresponding in <em>src/<em>
*/
static void assign(Uint32 dst[], const Uint32 src[]);
+ static void assign(Uint32 dst[], const Bitmask<size> & src);
void assign(const Bitmask<size> & src);
/**
- * assign <em>dst</em> of size <em>sz</em> to <em>this</em>
+ * copy this to <em>dst</em>
*/
- void assign(unsigned sz, Uint32 dst[]) const;
+ void copyto(unsigned sz, Uint32 dst[]) const;
/**
* assign <em>this</em> according to <em>src/em>
@@ -467,7 +473,7 @@ public:
/**
* getText - Return as hex-digits (only for debug routines).
*/
- static void getText(const Uint32 data[], char* buf);
+ static char* getText(const Uint32 data[], char* buf);
char* getText(char* buf) const;
};
@@ -480,7 +486,14 @@ Bitmask<size>::assign(Uint32 dst[], const Uint32 src[])
template <unsigned size>
inline void
-Bitmask<size>::assign(const Bitmask<size>::Data & src)
+Bitmask<size>::assign(Uint32 dst[], const Bitmask<size> & src)
+{
+ BitmaskImpl::assign(size, dst, src.rep.data);
+}
+
+template <unsigned size>
+inline void
+Bitmask<size>::assign(const typename Bitmask<size>::Data & src)
{
assign(rep.data, src.data);
}
@@ -489,12 +502,12 @@ template <unsigned size>
inline void
Bitmask<size>::assign(const Bitmask<size> & src)
{
- assign(rep.data, src);
+ assign(rep.data, src.rep.data);
}
template <unsigned size>
inline void
-Bitmask<size>::assign(unsigned sz, Uint32 dst[]) const
+Bitmask<size>::copyto(unsigned sz, Uint32 dst[]) const
{
BitmaskImpl::assign(sz, dst, rep.data);
}
@@ -707,18 +720,17 @@ Bitmask<size>::bitXOR(const Bitmask<size>& mask2)
}
template <unsigned size>
-void
+char *
Bitmask<size>::getText(const Uint32 data[], char* buf)
{
- BitmaskImpl::getText(size, data, buf);
+ return BitmaskImpl::getText(size, data, buf);
}
template <unsigned size>
inline char *
Bitmask<size>::getText(char* buf) const
{
- getText(rep.data, buf);
- return buf;
+ return getText(rep.data, buf);
}
template <unsigned size>
diff --git a/ndb/include/util/ConfigValues.hpp b/ndb/include/util/ConfigValues.hpp
new file mode 100644
index 00000000000..48e1363bf4a
--- /dev/null
+++ b/ndb/include/util/ConfigValues.hpp
@@ -0,0 +1,252 @@
+#ifndef __CONFIG_VALUES_HPP
+#define __CONFIG_VALUES_HPP
+
+#include <ndb_types.h>
+#include <UtilBuffer.hpp>
+
+class ConfigValues {
+ friend class ConfigValuesFactory;
+ ConfigValues(Uint32 sz, Uint32 data);
+
+public:
+ ~ConfigValues();
+
+ enum ValueType {
+ InvalidType = 0,
+ IntType = 1,
+ StringType = 2,
+ SectionType = 3,
+ Int64Type = 4
+ };
+
+ struct Entry {
+ Uint32 m_key;
+ ValueType m_type;
+ union {
+ Uint32 m_int;
+ const char * m_string;
+ Uint64 m_int64;
+ };
+ };
+
+ class ConstIterator {
+ friend class ConfigValuesFactory;
+ const ConfigValues & m_cfg;
+ protected:
+ Uint32 m_currentSection;
+ public:
+ ConstIterator(const ConfigValues&c) : m_cfg(c) { m_currentSection = 0;}
+
+ bool openSection(Uint32 key, Uint32 no);
+ bool closeSection();
+
+ bool get(Uint32 key, Entry *) const;
+
+ bool get(Uint32 key, Uint32 * value) const;
+ bool get(Uint32 key, Uint64 * value) const;
+ bool get(Uint32 key, const char ** value) const;
+ bool getTypeOf(Uint32 key, ValueType * type) const;
+
+ Uint32 get(Uint32 key, Uint32 notFound) const;
+ Uint64 get64(Uint32 key, Uint64 notFound) const;
+ const char * get(Uint32 key, const char * notFound) const;
+ ValueType getTypeOf(Uint32 key) const;
+ };
+
+ class Iterator : public ConstIterator {
+ ConfigValues & m_cfg;
+ public:
+ Iterator(ConfigValues&c) : ConstIterator(c), m_cfg(c) {}
+
+ bool set(Uint32 key, Uint32 value);
+ bool set(Uint32 key, Uint64 value);
+ bool set(Uint32 key, const char * value);
+ };
+
+ Uint32 getPackedSize() const; // get size in bytes needed to pack
+ Uint32 pack(UtilBuffer&) const;
+ Uint32 pack(void * dst, Uint32 len) const;// pack into dst(of len %d);
+
+private:
+ friend class Iterator;
+ friend class ConstIterator;
+
+ bool getByPos(Uint32 pos, Entry *) const;
+ Uint64 & get64(Uint32 index) const;
+ char * & getString(Uint32 index) const;
+
+ Uint32 m_size;
+ Uint32 m_dataSize;
+ Uint32 m_stringCount;
+ Uint32 m_int64Count;
+
+ Uint32 m_values[1];
+ void * m_data[1];
+};
+
+class ConfigValuesFactory {
+ Uint32 m_currentSection;
+public:
+ Uint32 m_sectionCounter;
+ Uint32 m_freeKeys;
+ Uint32 m_freeData;
+
+public:
+ ConfigValuesFactory(Uint32 keys = 50, Uint32 data = 10); // Initial
+ ConfigValuesFactory(ConfigValues * m_cfg); //
+
+ ConfigValues * m_cfg;
+ ConfigValues * getConfigValues();
+
+ bool openSection(Uint32 key, Uint32 no);
+ bool put(const ConfigValues::Entry & );
+ bool put(Uint32 key, Uint32 value);
+ bool put64(Uint32 key, Uint64 value);
+ bool put(Uint32 key, const char * value);
+ bool closeSection();
+
+ void expand(Uint32 freeKeys, Uint32 freeData);
+ void shrink();
+
+ bool unpack(const UtilBuffer&);
+ bool unpack(const void * src, Uint32 len);
+
+ static ConfigValues * extractCurrentSection(const ConfigValues::ConstIterator &);
+
+private:
+ static ConfigValues * create(Uint32 keys, Uint32 data);
+ void put(const ConfigValues & src);
+};
+
+inline
+bool
+ConfigValues::ConstIterator::get(Uint32 key, Uint32 * value) const {
+ Entry tmp;
+ if(get(key, &tmp) && tmp.m_type == IntType){
+ * value = tmp.m_int;
+ return true;
+ }
+ return false;
+}
+
+inline
+bool
+ConfigValues::ConstIterator::get(Uint32 key, Uint64 * value) const {
+ Entry tmp;
+ if(get(key, &tmp) && tmp.m_type == Int64Type){
+ * value = tmp.m_int64;
+ return true;
+ }
+ return false;
+}
+
+inline
+bool
+ConfigValues::ConstIterator::get(Uint32 key, const char ** value) const {
+ Entry tmp;
+ if(get(key, &tmp) && tmp.m_type == StringType){
+ * value = tmp.m_string;
+ return true;
+ }
+ return false;
+}
+
+inline
+bool
+ConfigValues::ConstIterator::getTypeOf(Uint32 key, ValueType * type) const{
+ Entry tmp;
+ if(get(key, &tmp)){
+ * type = tmp.m_type;
+ return true;
+ }
+ return false;
+}
+
+inline
+Uint32
+ConfigValues::ConstIterator::get(Uint32 key, Uint32 notFound) const {
+ Entry tmp;
+ if(get(key, &tmp) && tmp.m_type == IntType){
+ return tmp.m_int;
+ }
+ return notFound;
+}
+
+inline
+Uint64
+ConfigValues::ConstIterator::get64(Uint32 key, Uint64 notFound) const {
+ Entry tmp;
+ if(get(key, &tmp) && tmp.m_type == Int64Type){
+ return tmp.m_int64;
+ }
+ return notFound;
+}
+
+inline
+const char *
+ConfigValues::ConstIterator::get(Uint32 key, const char * notFound) const {
+ Entry tmp;
+ if(get(key, &tmp) && tmp.m_type == StringType){
+ return tmp.m_string;
+ }
+ return notFound;
+}
+
+inline
+ConfigValues::ValueType
+ConfigValues::ConstIterator::getTypeOf(Uint32 key) const{
+ Entry tmp;
+ if(get(key, &tmp)){
+ return tmp.m_type;
+ }
+ return ConfigValues::InvalidType;
+}
+
+inline
+bool
+ConfigValuesFactory::put(Uint32 key, Uint32 val){
+ ConfigValues::Entry tmp;
+ tmp.m_key = key;
+ tmp.m_type = ConfigValues::IntType;
+ tmp.m_int = val;
+ return put(tmp);
+}
+
+inline
+bool
+ConfigValuesFactory::put64(Uint32 key, Uint64 val){
+ ConfigValues::Entry tmp;
+ tmp.m_key = key;
+ tmp.m_type = ConfigValues::Int64Type;
+ tmp.m_int64 = val;
+ return put(tmp);
+}
+
+inline
+bool
+ConfigValuesFactory::put(Uint32 key, const char * val){
+ ConfigValues::Entry tmp;
+ tmp.m_key = key;
+ tmp.m_type = ConfigValues::StringType;
+ tmp.m_string = val;
+ return put(tmp);
+}
+
+inline
+Uint32
+ConfigValues::pack(UtilBuffer& buf) const {
+ Uint32 len = getPackedSize();
+ void * tmp = buf.append(len);
+ if(tmp == 0){
+ return 0;
+ }
+ return pack(tmp, len);
+}
+
+inline
+bool
+ConfigValuesFactory::unpack(const UtilBuffer& buf){
+ return unpack(buf.get_data(), buf.length());
+}
+
+#endif
diff --git a/ndb/include/util/NdbSqlUtil.hpp b/ndb/include/util/NdbSqlUtil.hpp
index bb573eea17b..841da513d4a 100644
--- a/ndb/include/util/NdbSqlUtil.hpp
+++ b/ndb/include/util/NdbSqlUtil.hpp
@@ -19,6 +19,7 @@
#include <string.h>
#include <ndb_types.h>
+#include <kernel/ndb_limits.h>
class NdbSqlUtil {
public:
@@ -77,7 +78,9 @@ public:
Binary, // Len
Varbinary, // Max len
Datetime, // Precision down to 1 sec (size 8 bytes)
- Timespec // Precision down to 1 nsec (size 12 bytes)
+ Timespec, // Precision down to 1 nsec (size 12 bytes)
+ Blob, // Blob
+ Clob // Text blob
};
Enum m_typeId;
Cmp* m_cmp; // set to NULL if cmp not implemented
@@ -121,6 +124,8 @@ private:
static Cmp cmpVarbinary;
static Cmp cmpDatetime;
static Cmp cmpTimespec;
+ static Cmp cmpBlob;
+ static Cmp cmpClob;
};
inline int
@@ -145,7 +150,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Tinyunsigned:
{
if (size >= 1) {
@@ -160,7 +164,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Smallint:
{
if (size >= 1) {
@@ -175,7 +178,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Smallunsigned:
{
if (size >= 1) {
@@ -190,7 +192,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Mediumint: // XXX fix these
break;
case Type::Mediumunsigned:
@@ -209,7 +210,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Unsigned:
{
if (size >= 1) {
@@ -224,7 +224,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Bigint:
{
if (size >= 2) {
@@ -241,7 +240,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Bigunsigned:
{
if (size >= 2) {
@@ -258,7 +256,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Float:
{
if (size >= 1) {
@@ -273,7 +270,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Double:
{
if (size >= 2) {
@@ -290,7 +286,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Decimal:
break;
case Type::Char:
@@ -305,7 +300,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
int k = memcmp(u1.v, u2.v, size << 2);
return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
}
- break;
case Type::Varchar:
{
/*
@@ -323,7 +317,6 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Binary: // XXX fix these
break;
case Type::Varbinary:
@@ -347,9 +340,24 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- break;
case Type::Timespec: // XXX fix this
break;
+ case Type::Blob: // XXX fix
+ break;
+ case Type::Clob:
+ {
+ // skip blob head, the rest is varchar
+ const unsigned skip = NDB_BLOB_HEAD_SIZE;
+ if (size >= skip + 1) {
+ union { const Uint32* p; const char* v; } u1, u2;
+ u1.p = p1 + skip;
+ u2.p = p2 + skip;
+ // length in first 2 bytes
+ int k = strncmp(u1.v + 2, u2.v + 2, ((size - skip) << 2) - 2);
+ return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+ }
+ return CmpUnknown;
+ }
}
return CmpError;
}
diff --git a/ndb/include/util/Parser.hpp b/ndb/include/util/Parser.hpp
index 9c2f02b6024..65cf24db633 100644
--- a/ndb/include/util/Parser.hpp
+++ b/ndb/include/util/Parser.hpp
@@ -165,6 +165,7 @@ Parser<T>::Parser(const ParserRow<T> rows[], class InputStream & in,
template<class T>
inline
Parser<T>::~Parser(){
+ delete impl;
}
template<class T>
diff --git a/ndb/include/util/Properties.hpp b/ndb/include/util/Properties.hpp
index ff5d1338c79..2c30f7f7e3c 100644
--- a/ndb/include/util/Properties.hpp
+++ b/ndb/include/util/Properties.hpp
@@ -22,9 +22,10 @@
#include <UtilBuffer.hpp>
enum PropertiesType {
- PropertiesType_Uint32,
- PropertiesType_char,
- PropertiesType_Properties
+ PropertiesType_Uint32 = 0,
+ PropertiesType_char = 1,
+ PropertiesType_Properties = 2,
+ PropertiesType_Uint64 = 3
};
/**
@@ -36,6 +37,7 @@ enum PropertiesType {
*/
struct Property {
Property(const char* name, Uint32 val);
+ Property(const char* name, Uint64 val);
Property(const char* name, const char * value);
Property(const char* name, const class Properties * value);
~Property();
@@ -75,6 +77,7 @@ public:
void put(const Property *, int len);
bool put(const char * name, Uint32 value, bool replace = false);
+ bool put64(const char * name, Uint64 value, bool replace = false);
bool put(const char * name, const char * value, bool replace = false);
bool put(const char * name, const Properties * value, bool replace = false);
@@ -84,6 +87,7 @@ public:
* Compare get(name, no)
*/
bool put(const char *, Uint32 no, Uint32, bool replace = false);
+ bool put64(const char *, Uint32 no, Uint64, bool replace = false);
bool put(const char *, Uint32 no, const char *, bool replace = false);
bool put(const char *, Uint32 no, const Properties *, bool replace = false);
@@ -94,6 +98,7 @@ public:
bool contains(const char * name) const;
bool get(const char * name, Uint32 * value) const;
+ bool get(const char * name, Uint64 * value) const;
bool get(const char * name, const char ** value) const;
bool get(const char * name, BaseString & value) const;
bool get(const char * name, const Properties ** value) const;
@@ -109,6 +114,7 @@ public:
bool contains(const char * name, Uint32 no) const;
bool get(const char * name, Uint32 no, Uint32 * value) const;
+ bool get(const char * name, Uint32 no, Uint64 * value) const;
bool get(const char * name, Uint32 no, const char ** value) const;
bool get(const char * name, Uint32 no, const Properties ** value) const;
@@ -230,11 +236,12 @@ Properties::unpack(UtilBuffer &buf) {
inline bool
Properties::pack(UtilBuffer &buf) const {
Uint32 size = getPackedSize();
- char *tmp_buf = new char[size];
+ void *tmp_buf = buf.append(size);
+ if(tmp_buf == 0)
+ return false;
bool ret = pack((Uint32 *)tmp_buf);
if(ret == false)
return false;
- buf.append(tmp_buf, size);
return true;
}
diff --git a/ndb/include/util/UtilBuffer.hpp b/ndb/include/util/UtilBuffer.hpp
index b357fa0fdf2..f43fc960a16 100644
--- a/ndb/include/util/UtilBuffer.hpp
+++ b/ndb/include/util/UtilBuffer.hpp
@@ -63,6 +63,15 @@ public:
return 0;
};
+ void * append(size_t l){
+ if(grow(len+l) != 0)
+ return 0;
+
+ void * ret = (char*)data+len;
+ len += l;
+ return ret;
+ }
+
int assign(const void * d, size_t l) {
if (data) free(data);
data = NULL;
diff --git a/ndb/mysqlclusterenv.sh b/ndb/mysqlclusterenv.sh
deleted file mode 100644
index e151186d01e..00000000000
--- a/ndb/mysqlclusterenv.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-# Sets necessary environment variables for mysqlcluster install scripts
-mytop=
-if [ -f bin/mysql ]; then
- mytop=`/bin/pwd`
-elif [ -f bin/ndb ]; then
- mytop=`dirname \`/bin/pwd\``
-fi
-if [ "$mytop" ]; then
- MYSQLCLUSTER_TOP=$mytop
- PATH=$MYSQLCLUSTER_TOP/bin:$MYSQLCLUSTER_TOP/ndb/bin:$PATH
- LD_LIBRARY_PATH=$MYSQLCLUSTER_TOP/lib:$LD_LIBRARY_PATH
- LD_LIBRARY_PATH=$MYSQLCLUSTER_TOP/ndb/lib:$LD_LIBRARY_PATH
- export MYSQLCLUSTER_TOP PATH LD_LIBRARY_PATH
-else
-if [ -d SCCS ]; then
-if [ -f ndb/mysqlclusterenv.sh ]; then
- mytop=`/bin/pwd`
-elif [ -f mysqlclusterenv.sh ]; then
- mytop=`dirname \`/bin/pwd\``
-fi
-fi
-if [ "$mytop" ]; then
-# we're in the development tree
- if [ "$REAL_EMAIL" ]; then :; else
-#Guessing REAL_EMAIL
- REAL_EMAIL=`whoami`@mysql.com
- export REAL_EMAIL
- echo Setting REAL_EMAIL=$REAL_EMAIL
- fi
-
- MYSQLCLUSTER_TOP=$mytop
-
- NDB_TOP=$MYSQLCLUSTER_TOP/ndb
- export NDB_TOP
-
- NDB_PROJ_HOME=$NDB_TOP/home
- export NDB_PROJ_HOME
-
- PATH=$MYSQLCLUSTER_TOP/ndb/bin:$MYSQLCLUSTER_TOP/ndb/home/bin:$PATH
- PATH=$MYSQLCLUSTER_TOP/client:$PATH
- PATH=$MYSQLCLUSTER_TOP/sql:$PATH
- LD_LIBRARY_PATH=$MYSQLCLUSTER_TOP/libmysql:$LD_LIBRARY_PATH
- LD_LIBRARY_PATH=$MYSQLCLUSTER_TOP/libmysqld:$LD_LIBRARY_PATH
- LD_LIBRARY_PATH=$MYSQLCLUSTER_TOP/ndb/lib:$LD_LIBRARY_PATH
- LD_LIBRARY_PATH=$MYSQLCLUSTER_TOP/libmysql_r/.libs:$LD_LIBRARY_PATH
- export MYSQLCLUSTER_TOP PATH LD_LIBRARY_PATH
-else
- echo "Please source this file (mysqlclusterenv.sh) from installation top directory"
-fi
-fi
-mytop=
diff --git a/ndb/src/Makefile b/ndb/src/Makefile
deleted file mode 100644
index 4f71eb46056..00000000000
--- a/ndb/src/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-include .defs.mk
-
-DIRS := \
- client \
- common \
- kernel \
- ndbapi \
- mgmsrv \
- mgmapi \
- rep \
- mgmclient \
- cw \
- newtonapi \
- ndbbaseclient
-ifneq ($(NDB_ODBC),N)
- DIRS += ndbclient
-endif
-ifeq ($(findstring OSE, $(NDB_OS)),)
- DIRS += scripts
-endif
-include $(NDB_TOP)/Epilogue.mk
-
-_bins_mgmsrv: _libs_ndbapi
-_bins_mgmsrv: _libs_mgmapi
-_bins_mgmclient: _libs_mgmapi
-_bins_mgmclient: _libs_common
-_bins_client: _bins_ndbapi
-_bins_common: _bins_mgmapi
-_bins_kernel: _bins_ndbapi
-_bins_newtonapi: _bins_ndbapi
-_bins_mgmapi : _libs_common
-_bins_rep: _libs_common
-_bins_rep: _libs_ndbapi
diff --git a/ndb/src/Makefile.am b/ndb/src/Makefile.am
new file mode 100644
index 00000000000..bed43438e91
--- /dev/null
+++ b/ndb/src/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = common mgmapi ndbapi . kernel mgmsrv mgmclient cw
+
+include $(top_srcdir)/ndb/config/common.mk.am
+
+ndblib_LTLIBRARIES = libndbclient.la
+
+libndbclient_la_SOURCES =
+
+libndbclient_la_LIBADD = \
+ ndbapi/libndbapi.la \
+ common/transporter/libtransporter.la \
+ common/debugger/libtrace.la \
+ common/debugger/signaldata/libsignaldataprint.la \
+ common/mgmcommon/libmgmsrvcommon.la \
+ mgmapi/libmgmapi.la \
+ common/logger/liblogger.la \
+ common/portlib/libportlib.la \
+ common/util/libgeneral.la
diff --git a/ndb/src/client/odbc/codegen/SimpleGram.ypp b/ndb/src/client/odbc/codegen/SimpleGram.ypp
deleted file mode 100644
index d49344849d2..00000000000
--- a/ndb/src/client/odbc/codegen/SimpleGram.ypp
+++ /dev/null
@@ -1,1629 +0,0 @@
-%{
-
-#include <NdbApi.hpp>
-#include <common/StmtArea.hpp>
-#include <common/DataRow.hpp>
-#include "CodeGen.hpp"
-#include <FlexLexer.h>
-#include "SimpleParser.hpp"
-
-/* redefine globals after headers */
-#define yyparse SimpleParser_yyparse
-#if YYDEBUG
-#define yydebug SimpleParser_yydebug
-#endif
-
-#define YYLEX_PARAM simpleParserPtr
-#define YYPARSE_PARAM simpleParserPtr
-#define simpleParser (*static_cast<SimpleParser*>(simpleParserPtr))
-
-static int yylex(YYSTYPE* lvalp, void* simpleParserPtr);
-
-#define yyerror(s) simpleParser.parseError(s)
-
-#if YYDEBUG
-// does not work in bison 1.75
-#undef stderr
-#define stderr 0
-#define YYFPRINTF simpleParser.ctx().print
-#endif
-
-// scanner states
-
-#define pushState(sc) simpleParser.pushState(sc)
-#define popState() simpleParser.popState()
-
-#define StateEval SimpleParser_stateEval
-#define StateType SimpleParser_stateType
-#define StatePhys SimpleParser_statePhys
-extern int SimpleParser_stateEval;
-extern int SimpleParser_stateType;
-extern int SimpleParser_statePhys;
-
-struct LimitPair { int off; int cnt; };
-
-struct PhysAttr { int storage; int logging; };
-
-%}
-
-%defines
-%pure-parser
-%verbose
-
-%union {
- Plan_root* m_root;
- Plan_stmt* m_stmt;
- Plan_select* m_select;
- Insert_op m_insert_op;
- Plan_insert* m_insert;
- Plan_update* m_update;
- Plan_delete* m_delete;
- Plan_create_table* m_create_table;
- Plan_create_index* m_create_index;
- NdbDictionary::Object::Type m_index_type;
- Plan_create_row* m_create_row;
- Plan_ddl_row* m_ddl_row;
- Plan_ddl_column* m_ddl_column;
- Plan_ddl_constr* m_ddl_constr;
- Plan_idx_column* m_idx_column;
- Plan_data_type* m_data_type;
- Plan_drop_table* m_drop_table;
- Plan_drop_index* m_drop_index;
- Plan_set_row* m_set_row;
- Plan_expr_row* m_expr_row;
- bool m_asc_desc;
- Plan_pred* m_pred;
- Pred_op::Opcode m_pred_opcode;
- Comp_op::Opcode m_comp_opcode;
- Plan_expr* m_expr;
- Expr_op::Opcode m_expr_opcode;
- Plan_dml_row* m_dml_row;
- Plan_dml_column* m_dml_column;
- Plan_table* m_table;
- Plan_table_list* m_table_list;
- const char* m_string;
- struct LimitPair* m_limit;
- int m_signed_integer;
- bool m_distinct;
- struct PhysAttr* m_phys_attr;
- NdbDictionary::Object::FragmentType m_storage_attr;
- bool m_logging_attr;
-}
-
-/* keywords */
-%token
- T_AND
- T_ASC
- T_AUTO_INCREMENT
- T_BIGINT
- T_BINARY
- T_BLOB
- T_BY
- T_CHAR
- T_CONSTRAINT
- T_CREATE
- T_DATETIME
- T_DEFAULT
- T_DELETE
- T_DESC
- T_DISTINCT
- T_DOUBLE
- T_DROP
- T_FLOAT
- T_FOREIGN
- T_FROM
- T_GROUP
- T_HASH
- T_HAVING
- T_IN
- T_INDEX
- T_INSERT
- T_INT
- T_INTEGER
- T_INTO
- T_IS
- T_KEY
- T_LARGE
- T_LIKE
- T_LIMIT
- T_LOGGING
- T_LONGBLOB
- T_MEDIUM
- T_NOLOGGING
- T_NOT
- T_NULL
- T_OFFSET
- T_ON
- T_OR
- T_ORDER
- T_PRECISION
- T_PRIMARY
- T_REAL
- T_REFERENCES
- T_ROWNUM
- T_SELECT
- T_SET
- T_SINGLE
- T_SMALL
- T_SMALLINT
- T_STORAGE
- T_SYSDATE
- T_TABLE
- T_UNIQUE
- T_UNSIGNED
- T_UPDATE
- T_VALUES
- T_VARBINARY
- T_VARCHAR
- T_WHERE
- T_WRITE
-
-/* identifiers and constants */
-%token
- <m_string> T_IDENTIFIER
- <m_string> T_LINTEGER
- <m_string> T_LDECIMAL
- <m_string> T_LREAL
- <m_string> T_STRING
-
-/* expressions and predicates */
-%token
- T_PLUS
- T_MINUS
- T_TIMES
- T_DIVIDE
- T_EQ
- T_NOTEQ
- T_LT
- T_LTEQ
- T_GT
- T_GTEQ
- T_QUES
-
-/* common special symbols */
-%token
- T_PERIOD
- T_COMMA
- T_PARENLEFT
- T_PARENRIGHT
- T_ASTERISK
- T_ASSIGN
-
-%type <m_root> root
-%type <m_stmt> stmt
-%type <m_select> stmt_select
-%type <m_insert> stmt_insert
-%type <m_insert_op> insert_op
-%type <m_update> stmt_update
-%type <m_delete> stmt_delete
-%type <m_create_table> create_table
-%type <m_create_index> create_index
-%type <m_index_type> index_type
-%type <m_create_row> create_row
-%type <m_ddl_column> create_column
-%type <m_ddl_constr> create_constr
-%type <m_idx_column> idx_column
-%type <m_data_type> data_type
-%type <m_ddl_row> ddl_row
-%type <m_ddl_column> ddl_column
-%type <m_drop_table> drop_table
-%type <m_drop_index> drop_index
-%type <m_asc_desc> asc_desc
-%type <m_set_row> set_row
-%type <m_expr_row> expr_row
-%type <m_expr_row> sort_row
-%type <m_pred> where_clause
-%type <m_expr_row> order_clause
-%type <m_pred> pred
-%type <m_pred> pred1
-%type <m_pred_opcode> pred1_op
-%type <m_pred> pred2
-%type <m_pred_opcode> pred2_op
-%type <m_pred> pred3
-%type <m_pred_opcode> pred3_op
-%type <m_pred> pred4
-%type <m_comp_opcode> comp_op
-%type <m_expr> expr
-%type <m_expr> expr1
-%type <m_expr_opcode> expr1_op
-%type <m_expr> expr2
-%type <m_expr_opcode> expr2_op
-%type <m_expr> expr3
-%type <m_expr_opcode> expr3_op
-%type <m_expr> expr4
-%type <m_expr> expr_column
-%type <m_dml_row> dml_row
-%type <m_dml_column> dml_column
-%type <m_expr_row> value_row
-%type <m_expr> value_expr
-%type <m_table> table
-%type <m_table_list> table_list
-%type <m_string> dot_identifier
-%type <m_limit> limit_clause
-%type <m_signed_integer> signed_integer
-%type <m_distinct> distinct_clause
-%type <m_expr_row> group_clause
-%type <m_pred> having_clause
-%type <m_phys_attr> phys_attr
-%type <m_phys_attr> phys_attr2
-%type <m_storage_attr> storage_attr
-%type <m_logging_attr> logging_attr
-
-%%
-
-root:
- stmt
- {
- Plan_root* root = simpleParser.root();
- root->setStmt($1);
- }
- ;
-stmt:
- stmt_select
- {
- $$ = $1;
- }
- |
- stmt_insert
- {
- $$ = $1;
- }
- |
- stmt_update
- {
- $$ = $1;
- }
- |
- stmt_delete
- {
- $$ = $1;
- }
- |
- create_table
- {
- $$ = $1;
- }
- |
- create_index
- {
- $$ = $1;
- }
- |
- drop_table
- {
- $$ = $1;
- }
- |
- drop_index
- {
- $$ = $1;
- }
- ;
-stmt_select:
- T_SELECT distinct_clause expr_row T_FROM table_list where_clause group_clause having_clause order_clause limit_clause
- {
- Plan_root* root = simpleParser.root();
- Plan_select* stmt = new Plan_select(root);
- root->saveNode(stmt);
- stmt->setDistinct($2);
- stmt->setRow($3);
- stmt->setList($5);
- if ($6 != 0)
- stmt->setPred($6);
- if ($7 != 0)
- stmt->setGroup($7);
- if ($8 != 0)
- stmt->setHaving($8);
- if ($9 != 0)
- stmt->setSort($9);
- if ($10 != 0) {
- stmt->setLimit($10->off, $10->cnt);
- delete $10;
- }
- $$ = stmt;
- }
- ;
-stmt_insert:
- insert_op T_INTO table T_VALUES T_PARENLEFT value_row T_PARENRIGHT
- {
- Plan_root* root = simpleParser.root();
- Plan_insert* stmt = new Plan_insert(root, $1);
- root->saveNode(stmt);
- stmt->setTable($3);
- stmt->setExprRow($6);
- $$ = stmt;
- }
- |
- insert_op T_INTO table T_PARENLEFT dml_row T_PARENRIGHT T_VALUES T_PARENLEFT value_row T_PARENRIGHT
- {
- Plan_root* root = simpleParser.root();
- Plan_insert* stmt = new Plan_insert(root, $1);
- root->saveNode(stmt);
- stmt->setTable($3);
- stmt->setDmlRow($5);
- stmt->setExprRow($9);
- $$ = stmt;
- }
- |
- insert_op T_INTO table stmt_select
- {
- Plan_root* root = simpleParser.root();
- Plan_insert* stmt = new Plan_insert(root, $1);
- root->saveNode(stmt);
- stmt->setTable($3);
- stmt->setSelect($4);
- $$ = stmt;
- }
- |
- insert_op T_INTO table T_PARENLEFT dml_row T_PARENRIGHT stmt_select
- {
- Plan_root* root = simpleParser.root();
- Plan_insert* stmt = new Plan_insert(root, $1);
- root->saveNode(stmt);
- stmt->setTable($3);
- stmt->setDmlRow($5);
- stmt->setSelect($7);
- $$ = stmt;
- }
- |
- insert_op T_INTO table T_SET set_row
- {
- Plan_root* root = simpleParser.root();
- Plan_insert* stmt = new Plan_insert(root, $1);
- root->saveNode(stmt);
- stmt->setTable($3);
- stmt->setMysqlRow($5);
- $$ = stmt;
- }
- ;
-insert_op:
- T_INSERT
- {
- $$ = Insert_op_insert;
- }
- |
- T_WRITE
- {
- $$ = Insert_op_write;
- }
- ;
-stmt_update:
- T_UPDATE table T_SET set_row where_clause
- {
- Plan_root* root = simpleParser.root();
- Plan_update* stmt = new Plan_update(root);
- root->saveNode(stmt);
- stmt->setTable($2);
- stmt->setRow($4);
- if ($5 != 0)
- stmt->setPred($5);
- $$ = stmt;
- }
- ;
-stmt_delete:
- T_DELETE T_FROM table where_clause
- {
- Plan_root* root = simpleParser.root();
- Plan_delete* stmt = new Plan_delete(root);
- root->saveNode(stmt);
- stmt->setTable($3);
- if ($4 != 0)
- stmt->setPred($4);
- $$ = stmt;
- }
- ;
-create_table:
- T_CREATE T_TABLE dot_identifier T_PARENLEFT create_row T_PARENRIGHT phys_attr
- {
- Plan_root* root = simpleParser.root();
- Plan_create_table* stmt = new Plan_create_table(root, $3);
- root->saveNode(stmt);
- delete[] $3;
- stmt->setCreateRow($5);
- if ($7->storage != -1)
- stmt->setFragmentType((NdbDictionary::Object::FragmentType)$7->storage);
- if ($7->logging != -1)
- stmt->setLogging($7->logging);
- delete $7;
- $$ = stmt;
- }
- ;
-create_row:
- create_column
- {
- Plan_root* root = simpleParser.root();
- Plan_create_row* createRow = new Plan_create_row(root);
- root->saveNode(createRow);
- createRow->addColumn($1);
- $$ = createRow;
- }
- |
- create_constr
- {
- Plan_root* root = simpleParser.root();
- Plan_create_row* createRow = new Plan_create_row(root);
- root->saveNode(createRow);
- createRow->addConstr($1);
- $$ = createRow;
- }
- |
- create_row T_COMMA create_column
- {
- Plan_create_row* createRow = $1;
- createRow->addColumn($3);
- $$ = createRow;
- }
- |
- create_row T_COMMA create_constr
- {
- Plan_create_row* createRow = $1;
- createRow->addConstr($3);
- $$ = createRow;
- }
- |
- create_row T_COMMA create_ignore
- {
- $$ = $1;
- }
- ;
-create_column:
- T_IDENTIFIER { pushState(StateType); } data_type { popState(); }
- {
- Plan_root* root = simpleParser.root();
- Plan_ddl_column* ddlColumn = new Plan_ddl_column(root, $1);
- root->saveNode(ddlColumn);
- delete[] $1;
- ddlColumn->setType($3);
- simpleParser.curr(ddlColumn);
- }
- create_column_rest
- {
- $$ = simpleParser.curr((Plan_ddl_column*)0);
- }
- ;
-data_type:
- T_CHAR T_PARENLEFT T_LINTEGER T_PARENRIGHT dummy_binary
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(simpleParser.ctx(), SqlType::Char, atoi($3), true);
- delete[] $3;
- if (! simpleParser.ctx().ok()) {
- YYABORT;
- }
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_BINARY T_PARENLEFT T_LINTEGER T_PARENRIGHT
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(simpleParser.ctx(), SqlType::Binary, atoi($3), true);
- delete[] $3;
- if (! simpleParser.ctx().ok()) {
- YYABORT;
- }
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_VARCHAR T_PARENLEFT T_LINTEGER T_PARENRIGHT dummy_binary
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(simpleParser.ctx(), SqlType::Varchar, atoi($3), true);
- delete[] $3;
- if (! simpleParser.ctx().ok()) {
- YYABORT;
- }
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_VARBINARY T_PARENLEFT T_LINTEGER T_PARENRIGHT
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(simpleParser.ctx(), SqlType::Varbinary, atoi($3), true);
- delete[] $3;
- if (! simpleParser.ctx().ok()) {
- YYABORT;
- }
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_SMALLINT
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(SqlType::Smallint, true);
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_INTEGER
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(SqlType::Integer, true);
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_INT
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(SqlType::Integer, true);
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_BIGINT
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(SqlType::Bigint, true);
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_REAL
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(SqlType::Real, true);
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_FLOAT
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(SqlType::Double, true);
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_DOUBLE T_PRECISION
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(SqlType::Double, true);
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- T_DATETIME
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(SqlType::Datetime, true);
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- |
- blob_keyword
- {
- Plan_root* root = simpleParser.root();
- SqlType sqlType(SqlType::Blob, true);
- Plan_data_type* dataType = new Plan_data_type(root, sqlType);
- root->saveNode(dataType);
- $$ = dataType;
- }
- ;
-dummy_binary:
- /* empty */
- |
- T_BINARY
- ;
-blob_keyword:
- T_BLOB
- |
- T_LONGBLOB
- ;
-create_column_rest:
- /* empty */
- |
- data_constr_list
- ;
-data_constr_list:
- data_constr
- |
- data_constr_list data_constr
- ;
-data_constr:
- T_NULL
- |
- T_NOT T_NULL
- {
- Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
- ddlColumn->setNotNull();
- }
- |
- T_UNSIGNED
- {
- Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
- ddlColumn->setUnSigned();
- }
- |
- T_PRIMARY T_KEY
- {
- Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
- ddlColumn->setPrimaryKey();
- }
- |
- T_AUTO_INCREMENT
- {
- Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
- ddlColumn->setAutoIncrement();
- }
- |
- T_DEFAULT expr
- {
- Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
- ddlColumn->setDefaultValue($2);
- }
- ;
-create_constr:
- T_PRIMARY T_KEY T_PARENLEFT ddl_row T_PARENRIGHT
- {
- Plan_root* root = simpleParser.root();
- Plan_ddl_constr* ddlConstr = new Plan_ddl_constr(root);
- root->saveNode(ddlConstr);
- ddlConstr->setRow($4);
- $$ = ddlConstr;
- }
- |
- T_CONSTRAINT dot_identifier T_PRIMARY T_KEY T_PARENLEFT ddl_row T_PARENRIGHT
- {
- Plan_root* root = simpleParser.root();
- Plan_ddl_constr* ddlConstr = new Plan_ddl_constr(root);
- root->saveNode(ddlConstr);
- ddlConstr->setRow($6);
- $$ = ddlConstr;
- }
- ;
-create_ignore:
- T_INDEX dot_identifier T_PARENLEFT ddl_row T_PARENRIGHT
- |
- T_FOREIGN T_KEY T_PARENLEFT ddl_row T_PARENRIGHT T_REFERENCES dot_identifier T_PARENLEFT ddl_row T_PARENRIGHT
- ;
-ddl_row:
- ddl_column
- {
- Plan_root* root = simpleParser.root();
- Plan_ddl_row* ddlRow = new Plan_ddl_row(root);
- root->saveNode(ddlRow);
- ddlRow->addColumn($1);
- $$ = ddlRow;
- }
- |
- ddl_row T_COMMA ddl_column
- {
- Plan_ddl_row* ddlRow = $1;
- ddlRow->addColumn($3);
- $$ = ddlRow;
- }
- ;
-ddl_column:
- T_IDENTIFIER
- {
- Plan_root* root = simpleParser.root();
- Plan_ddl_column* column = new Plan_ddl_column(root, $1);
- root->saveNode(column);
- delete[] $1;
- $$ = column;
- }
- ;
-create_index:
- T_CREATE index_type T_INDEX dot_identifier T_ON table
- {
- Plan_root* root = simpleParser.root();
- Plan_create_index* stmt = new Plan_create_index(root, $4);
- root->saveNode(stmt);
- delete[] $4;
- stmt->setType($2);
- stmt->setTable($6);
- simpleParser.curr(stmt);
- }
- T_PARENLEFT idx_row T_PARENRIGHT phys_attr
- {
- $$ = simpleParser.curr((Plan_create_index*)0);
- if ($11->storage != -1)
- $$->setFragmentType((NdbDictionary::Object::FragmentType)$11->storage);
- if ($11->logging != -1)
- $$->setLogging($11->logging);
- delete $11;
- }
- ;
-index_type:
- T_HASH
- {
- $$ = NdbDictionary::Object::HashIndex;
- }
- |
- T_UNIQUE T_HASH
- {
- $$ = NdbDictionary::Object::UniqueHashIndex;
- }
- |
- /* empty */
- {
- $$ = NdbDictionary::Object::OrderedIndex;
- }
- |
- T_UNIQUE
- {
- $$ = NdbDictionary::Object::UniqueOrderedIndex;
- }
- ;
-idx_row:
- idx_column
- {
- }
- |
- idx_row T_COMMA idx_column
- {
- }
- ;
-idx_column:
- T_IDENTIFIER
- {
- Plan_root* root = simpleParser.root();
- Plan_idx_column* column = new Plan_idx_column(root, $1);
- root->saveNode(column);
- delete[] $1;
- Plan_create_index* stmt = simpleParser.curr((Plan_create_index*)0);
- stmt->addColumn(column);
- }
- ;
-phys_attr:
- { pushState(StatePhys); } phys_attr2 { popState(); }
- {
- $$ = $2;
- }
- ;
-phys_attr2:
- /* empty */
- {
- $$ = new PhysAttr();
- $$->storage = $$->logging = -1;
- }
- |
- phys_attr2 storage_attr
- {
- if ($1->storage != -1 && $1->storage != $2) {
- simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "conflicting STORAGE clauses");
- YYABORT;
- }
- $$->storage = $2;
- }
- |
- phys_attr2 logging_attr
- {
- if ($1->logging != -1 && $1->logging != $2) {
- simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "conflicting LOGGING clauses");
- YYABORT;
- }
- $$->logging = $2;
- }
- ;
-logging_attr:
- T_LOGGING
- {
- $$ = true;
- }
- |
- T_NOLOGGING
- {
- $$ = false;
- }
- ;
-storage_attr:
- T_STORAGE T_PARENLEFT T_SINGLE T_PARENRIGHT
- {
- $$ = NdbDictionary::Object::FragSingle;
- }
- |
- T_STORAGE T_PARENLEFT T_SMALL T_PARENRIGHT
- {
- $$ = NdbDictionary::Object::FragAllSmall;
- }
- |
- T_STORAGE T_PARENLEFT T_MEDIUM T_PARENRIGHT
- {
- $$ = NdbDictionary::Object::FragAllMedium;
- }
- |
- T_STORAGE T_PARENLEFT T_LARGE T_PARENRIGHT
- {
- $$ = NdbDictionary::Object::FragAllLarge;
- }
- ;
-drop_table:
- T_DROP T_TABLE dot_identifier
- {
- Plan_root* root = simpleParser.root();
- Plan_drop_table* stmt = new Plan_drop_table(root, $3);
- root->saveNode(stmt);
- delete[] $3;
- $$ = stmt;
- }
- ;
-drop_index:
- T_DROP T_INDEX dot_identifier
- {
- Plan_root* root = simpleParser.root();
- Plan_drop_index* stmt = new Plan_drop_index(root, $3);
- root->saveNode(stmt);
- delete[] $3;
- $$ = stmt;
- }
- |
- T_DROP T_INDEX dot_identifier T_ON dot_identifier
- {
- Plan_root* root = simpleParser.root();
- Plan_drop_index* stmt = new Plan_drop_index(root, $3, $5);
- root->saveNode(stmt);
- delete[] $3;
- delete[] $5;
- $$ = stmt;
- }
- ;
-distinct_clause:
- /* empty */
- {
- $$ = false;
- }
- |
- T_DISTINCT
- {
- $$ = true;
- }
- ;
-where_clause:
- /* empty */
- {
- $$ = 0;
- }
- |
- T_WHERE pred
- {
- $$ = $2;
- }
- ;
-group_clause:
- /* empty */
- {
- $$ = 0;
- }
- |
- T_GROUP T_BY value_row
- {
- $$ = $3;
- }
- ;
-having_clause:
- /* empty */
- {
- $$ = 0;
- }
- |
- T_HAVING pred
- {
- $$ = $2;
- }
- ;
-order_clause:
- /* empty */
- {
- $$ = 0;
- }
- |
- T_ORDER T_BY sort_row
- {
- $$ = $3;
- }
- ;
-limit_clause:
- /* empty */
- {
- $$ = 0;
- }
- |
- T_LIMIT signed_integer
- {
- LimitPair* p = new LimitPair;
- p->off = 0;
- p->cnt = $2;
- $$ = p;
- }
- |
- T_LIMIT signed_integer T_COMMA signed_integer
- {
- LimitPair* p = new LimitPair;
- p->off = $2,
- p->cnt = $4;
- $$ = p;
- }
- |
- T_LIMIT signed_integer T_OFFSET signed_integer
- {
- LimitPair* p = new LimitPair;
- p->off = $4;
- p->cnt = $2;
- $$ = p;
- }
- ;
-signed_integer:
- T_LINTEGER
- {
- $$ = atoi($1);
- delete[] $1;
- }
- |
- T_MINUS T_LINTEGER
- {
- $$ = (-1) * atoi($2);
- delete[] $2;
- }
- ;
-set_row:
- dml_column T_ASSIGN expr
- {
- Plan_root* root = simpleParser.root();
- Plan_set_row* row = new Plan_set_row(root);
- root->saveNode(row);
- row->addColumn($1);
- row->addExpr($3);
- $$ = row;
- }
- |
- set_row T_COMMA dml_column T_ASSIGN expr
- {
- Plan_set_row* row = $1;
- row->addColumn($3);
- row->addExpr($5);
- $$ = row;
- }
- ;
-dml_row:
- dml_column
- {
- Plan_root* root = simpleParser.root();
- Plan_dml_row* row = new Plan_dml_row(root);
- root->saveNode(row);
- row->addColumn($1);
- $$ = row;
- }
- |
- dml_row T_COMMA dml_column
- {
- Plan_dml_row* row = $1;
- row->addColumn($3);
- $$ = row;
- }
- ;
-dml_column:
- T_IDENTIFIER
- {
- Plan_root* root = simpleParser.root();
- Plan_dml_column* column = new Plan_dml_column(root, $1);
- root->saveNode(column);
- delete[] $1;
- $$ = column;
- }
- ;
-value_row:
- value_expr
- {
- Plan_root* root = simpleParser.root();
- Plan_expr_row* row = new Plan_expr_row(root);
- root->saveNode(row);
- row->addExpr($1);
- $$ = row;
- }
- |
- value_row T_COMMA value_expr
- {
- Plan_expr_row* row = $1;
- row->addExpr($3);
- $$ = row;
- }
- ;
-value_expr:
- expr
- {
- $$ = $1;
- }
- ;
-sort_row:
- expr asc_desc
- {
- Plan_root* root = simpleParser.root();
- Plan_expr_row* row = new Plan_expr_row(root);
- root->saveNode(row);
- row->addExpr($1, $2);
- $$ = row;
- }
- |
- sort_row T_COMMA expr asc_desc
- {
- Plan_expr_row* row = $1;
- row->addExpr($3, $4);
- $$ = row;
- }
- ;
-asc_desc:
- /* empty */
- {
- $$ = true;
- }
- |
- T_ASC
- {
- $$ = true;
- }
- |
- T_DESC
- {
- $$ = false;
- }
- ;
-expr_row:
- T_ASTERISK
- {
- Plan_root* root = simpleParser.root();
- Plan_expr_row* row = new Plan_expr_row(root);
- root->saveNode(row);
- row->setAsterisk();
- $$ = row;
- }
- |
- T_TIMES /* XXX fix scanner state */
- {
- Plan_root* root = simpleParser.root();
- Plan_expr_row* row = new Plan_expr_row(root);
- root->saveNode(row);
- row->setAsterisk();
- $$ = row;
- }
- |
- expr
- {
- Plan_root* root = simpleParser.root();
- Plan_expr_row* row = new Plan_expr_row(root);
- root->saveNode(row);
- row->addExpr($1);
- $$ = row;
- }
- |
- expr T_IDENTIFIER
- {
- Plan_root* root = simpleParser.root();
- Plan_expr_row* row = new Plan_expr_row(root);
- root->saveNode(row);
- row->addExpr($1, BaseString($2));
- $$ = row;
- }
- |
- expr_row T_COMMA expr
- {
- Plan_expr_row* row = $1;
- row->addExpr($3);
- $$ = row;
- }
- |
- expr_row T_COMMA expr T_IDENTIFIER
- {
- Plan_expr_row* row = $1;
- row->addExpr($3, BaseString($4));
- $$ = row;
- }
- ;
-pred:
- { pushState(StateEval); } pred1 { popState(); }
- {
- $$ = $2;
- }
- ;
-pred1:
- pred2
- {
- $$ = $1;
- }
- |
- pred1 pred1_op pred2
- {
- Plan_root* root = simpleParser.root();
- Pred_op op($2);
- Plan_pred_op* pred = new Plan_pred_op(root, op);
- root->saveNode(pred);
- pred->setPred(1, $1);
- pred->setPred(2, $3);
- $$ = pred;
- }
- ;
-pred1_op:
- T_OR
- {
- $$ = Pred_op::Or;
- }
- ;
-pred2:
- pred3
- {
- $$ = $1;
- }
- |
- pred2 pred2_op pred3
- {
- Plan_root* root = simpleParser.root();
- Pred_op op($2);
- Plan_pred_op* pred = new Plan_pred_op(root, op);
- root->saveNode(pred);
- pred->setPred(1, $1);
- pred->setPred(2, $3);
- $$ = pred;
- }
- ;
-pred2_op:
- T_AND
- {
- $$ = Pred_op::And;
- }
- ;
-pred3:
- pred4
- {
- $$ = $1;
- }
- |
- pred3_op pred3
- {
- Plan_root* root = simpleParser.root();
- Pred_op op($1);
- Plan_pred_op* pred = new Plan_pred_op(root, op);
- root->saveNode(pred);
- pred->setPred(1, $2);
- $$ = pred;
- }
- ;
-pred3_op:
- T_NOT
- {
- $$ = Pred_op::Not;
- }
- ;
-pred4:
- T_PARENLEFT pred1 T_PARENRIGHT
- {
- $$ = $2;
- }
- |
- expr1 comp_op expr1
- {
- Plan_root* root = simpleParser.root();
- Comp_op op($2);
- Plan_comp_op* comp = new Plan_comp_op(root, op);
- root->saveNode(comp);
- comp->setExpr(1, $1);
- comp->setExpr(2, $3);
- $$ = comp;
- }
- |
- expr1 T_IS T_NULL
- {
- Plan_root* root = simpleParser.root();
- Comp_op op(Comp_op::Isnull);
- Plan_comp_op* comp = new Plan_comp_op(root, op);
- root->saveNode(comp);
- comp->setExpr(1, $1);
- $$ = comp;
- }
- |
- expr1 T_IS T_NOT T_NULL
- {
- Plan_root* root = simpleParser.root();
- Comp_op op(Comp_op::Isnotnull);
- Plan_comp_op* comp = new Plan_comp_op(root, op);
- root->saveNode(comp);
- comp->setExpr(1, $1);
- $$ = comp;
- }
- |
- expr1 T_IN T_PARENLEFT value_row T_PARENRIGHT
- {
- Plan_root* root = simpleParser.root();
- Plan_pred* predOut = 0; // hack directly into Or of Eq
- Plan_expr* exprLeft = $1;
- Plan_expr_row* row = $4;
- for (unsigned i = row->getSize(); i >= 1; i--) {
- Plan_expr* exprRight = row->getExpr(i);
- Plan_comp_op* comp = new Plan_comp_op(root, Comp_op::Eq);
- root->saveNode(comp);
- comp->setExpr(1, exprLeft);
- comp->setExpr(2, exprRight);
- if (predOut == 0) {
- predOut = comp;
- } else {
- Plan_pred_op* pred = new Plan_pred_op(root, Pred_op::Or);
- root->saveNode(pred);
- pred->setPred(1, predOut);
- pred->setPred(2, comp);
- predOut = pred;
- }
- }
- $$ = predOut;
- }
- |
- expr1 T_NOT T_IN T_PARENLEFT value_row T_PARENRIGHT
- {
- Plan_root* root = simpleParser.root();
- Plan_pred* predOut = 0; // hack directly into And of Noteq
- Plan_expr* exprLeft = $1;
- Plan_expr_row* row = $5;
- for (unsigned i = row->getSize(); i >= 1; i--) {
- Plan_expr* exprRight = row->getExpr(i);
- Plan_comp_op* comp = new Plan_comp_op(root, Comp_op::Noteq);
- root->saveNode(comp);
- comp->setExpr(1, exprLeft);
- comp->setExpr(2, exprRight);
- if (predOut == 0) {
- predOut = comp;
- } else {
- Plan_pred_op* pred = new Plan_pred_op(root, Pred_op::And);
- root->saveNode(pred);
- pred->setPred(1, predOut);
- pred->setPred(2, comp);
- predOut = pred;
- }
- }
- $$ = predOut;
- }
- ;
-comp_op:
- T_EQ
- {
- $$ = Comp_op::Eq;
- }
- |
- T_NOTEQ
- {
- $$ = Comp_op::Noteq;
- }
- |
- T_LT
- {
- $$ = Comp_op::Lt;
- }
- |
- T_LTEQ
- {
- $$ = Comp_op::Lteq;
- }
- |
- T_GT
- {
- $$ = Comp_op::Gt;
- }
- |
- T_GTEQ
- {
- $$ = Comp_op::Gteq;
- }
- |
- T_LIKE
- {
- $$ = Comp_op::Like;
- }
- |
- T_NOT T_LIKE
- {
- $$ = Comp_op::Notlike;
- }
- ;
-expr:
- { pushState(StateEval); } expr1 { popState(); }
- {
- $$ = $2;
- }
- ;
-expr1:
- expr2
- {
- $$ = $1;
- }
- |
- expr1 expr1_op expr2
- {
- Plan_root* root = simpleParser.root();
- Expr_op op($2);
- Plan_expr_op* expr = new Plan_expr_op(root, op);
- root->saveNode(expr);
- expr->setExpr(1, $1);
- expr->setExpr(2, $3);
- $$ = expr;
- }
- ;
-expr1_op:
- T_PLUS
- {
- $$ = Expr_op::Add;
- }
- |
- T_MINUS
- {
- $$ = Expr_op::Subtract;
- }
- ;
-expr2:
- expr3
- {
- $$ = $1;
- }
- |
- expr2 expr2_op expr3
- {
- Plan_root* root = simpleParser.root();
- Expr_op op($2);
- Plan_expr_op* expr = new Plan_expr_op(root, op);
- root->saveNode(expr);
- expr->setExpr(1, $1);
- expr->setExpr(2, $3);
- $$ = expr;
- }
- ;
-expr2_op:
- T_TIMES
- {
- $$ = Expr_op::Multiply;
- }
- |
- T_DIVIDE
- {
- $$ = Expr_op::Divide;
- }
- ;
-expr3:
- expr4
- {
- $$ = $1;
- }
- |
- expr3_op expr3
- {
- Plan_root* root = simpleParser.root();
- Expr_op op($1);
- Plan_expr_op* expr = new Plan_expr_op(root, op);
- root->saveNode(expr);
- expr->setExpr(1, $2);
- $$ = expr;
- }
- ;
-expr3_op:
- T_PLUS
- {
- $$ = Expr_op::Plus;
- }
- |
- T_MINUS
- {
- $$ = Expr_op::Minus;
- }
- ;
-expr4:
- T_PARENLEFT expr1 T_PARENRIGHT
- {
- $$ = $2;
- }
- |
- T_IDENTIFIER T_PARENLEFT expr_row T_PARENRIGHT
- {
- Plan_root* root = simpleParser.root();
- const Expr_func& spec = Expr_func::find($1);
- if (spec.m_name == 0) {
- simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "unknown function %s", $1);
- delete[] $1;
- YYABORT;
- }
- Plan_expr_func* func = new Plan_expr_func(root, spec);
- root->saveNode(func);
- delete[] $1;
- func->setArgs($3);
- $$ = func;
- }
- |
- T_ROWNUM
- {
- Plan_root* root = simpleParser.root();
- const Expr_func& spec = Expr_func::find("ROWNUM");
- ctx_assert(spec.m_name != 0);
- Plan_expr_func* func = new Plan_expr_func(root, spec);
- root->saveNode(func);
- func->setArgs(0);
- $$ = func;
- }
- |
- T_SYSDATE
- {
- Plan_root* root = simpleParser.root();
- const Expr_func& spec = Expr_func::find("SYSDATE");
- ctx_assert(spec.m_name != 0);
- Plan_expr_func* func = new Plan_expr_func(root, spec);
- root->saveNode(func);
- func->setArgs(0);
- $$ = func;
- }
- |
- expr_column
- {
- $$ = $1;
- }
- |
- T_STRING
- {
- Plan_root* root = simpleParser.root();
- LexType lexType(LexType::Char);
- Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
- root->saveNode(expr);
- delete[] $1;
- $$ = expr;
- }
- |
- T_LINTEGER
- {
- Plan_root* root = simpleParser.root();
- LexType lexType(LexType::Integer);
- Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
- root->saveNode(expr);
- delete[] $1;
- $$ = expr;
- }
- |
- T_LDECIMAL
- {
- Plan_root* root = simpleParser.root();
- LexType lexType(LexType::Float);
- Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
- root->saveNode(expr);
- delete[] $1;
- $$ = expr;
- }
- |
- T_LREAL
- {
- Plan_root* root = simpleParser.root();
- LexType lexType(LexType::Float);
- Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
- root->saveNode(expr);
- delete[] $1;
- $$ = expr;
- }
- |
- T_NULL
- {
- Plan_root* root = simpleParser.root();
- LexType lexType(LexType::Null);
- Plan_expr_const* expr = new Plan_expr_const(root, lexType, "");
- root->saveNode(expr);
- $$ = expr;
- }
- |
- T_QUES
- {
- Plan_root* root = simpleParser.root();
- unsigned paramNumber = simpleParser.paramNumber();
- ctx_assert(paramNumber != 0);
- Plan_expr_param* expr = new Plan_expr_param(root, paramNumber);
- root->saveNode(expr);
- $$ = expr;
- }
- ;
-expr_column:
- T_IDENTIFIER
- {
- Plan_root* root = simpleParser.root();
- Plan_expr_column* column = new Plan_expr_column(root, $1);
- root->saveNode(column);
- delete[] $1;
- $$ = column;
- }
- |
- T_IDENTIFIER T_PERIOD T_IDENTIFIER
- {
- Plan_root* root = simpleParser.root();
- Plan_expr_column* column = new Plan_expr_column(root, $3);
- root->saveNode(column);
- delete[] $3;
- column->setCname($1);
- $$ = column;
- }
- |
- T_IDENTIFIER T_PERIOD T_IDENTIFIER T_PERIOD T_IDENTIFIER
- {
- Plan_root* root = simpleParser.root();
- BaseString str;
- str.append($1);
- str.append(".");
- str.append($3);
- delete[] $1;
- delete[] $3;
- Plan_expr_column* column = new Plan_expr_column(root, $5);
- root->saveNode(column);
- delete[] $5;
- column->setCname(str);
- $$ = column;
- }
- ;
-table_list:
- table
- {
- Plan_root* root = simpleParser.root();
- Plan_table_list* tableList = new Plan_table_list(root);
- root->saveNode(tableList);
- tableList->addTable($1);
- $$ = tableList;
- }
- |
- table_list T_COMMA table
- {
- Plan_table_list* tableList = $1;
- tableList->addTable($3);
- $$ = tableList;
- }
- ;
-table:
- dot_identifier
- {
- Plan_root* root = simpleParser.root();
- Plan_table* table = new Plan_table(root, $1);
- root->saveNode(table);
- delete[] $1;
- $$ = table;
- }
- |
- dot_identifier T_IDENTIFIER
- {
- Plan_root* root = simpleParser.root();
- Plan_table* table = new Plan_table(root, $1);
- root->saveNode(table);
- delete[] $1;
- table->setCname($2);
- delete[] $2;
- $$ = table;
- }
- ;
-dot_identifier:
- T_IDENTIFIER
- {
- $$ = $1;
- }
- |
- T_IDENTIFIER T_PERIOD T_IDENTIFIER
- {
- char* s = new char[strlen($1) + 1 + strlen($3) + 1];
- strcpy(s, $1);
- strcat(s, ".");
- strcat(s, $3);
- delete[] $1;
- delete[] $3;
- $$ = s;
- }
- ;
-
-%%
-
-static int
-yylex(YYSTYPE* lvalp, void* simpleParserPtr)
-{
- int ret = simpleParser.yylex();
- *lvalp = simpleParser.yylval();
- return ret;
-}
-
-/* vim: set filetype=yacc: */
diff --git a/ndb/src/client/odbc/codegen/SimpleParser.cpp b/ndb/src/client/odbc/codegen/SimpleParser.cpp
deleted file mode 100644
index 62162172bc8..00000000000
--- a/ndb/src/client/odbc/codegen/SimpleParser.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NdbMutex.h>
-#include <common/StmtArea.hpp>
-#include <FlexLexer.h>
-#include "SimpleParser.hpp"
-
-SimpleParser::~SimpleParser()
-{
-}
-
-#ifdef NDB_WIN32
-static NdbMutex & parse_mutex = * NdbMutex_Create();
-#else
-static NdbMutex parse_mutex = NDB_MUTEX_INITIALIZER;
-#endif
-
-void
-SimpleParser::yyparse()
-{
- Ctx& ctx = this->ctx();
- NdbMutex_Lock(&parse_mutex);
- ctx_log2(("parse: %s", stmtArea().sqlText().c_str()));
-#if YYDEBUG
- SimpleParser_yydebug = (m_ctx.logLevel() >= 5);
-#endif
- SimpleParser_yyparse((void*)this);
- NdbMutex_Unlock(&parse_mutex);
-}
-
-void
-SimpleParser::pushState(int sc)
-{
- yy_push_state(sc);
- m_stacksize++;
-}
-
-void
-SimpleParser::popState()
-{
- ctx_assert(m_stacksize > 0);
- yy_pop_state();
- m_stacksize--;
-}
-
-void
-SimpleParser::parseError(const char* msg)
-{
- ctx().pushStatus(Sqlstate::_42000, Error::Gen, "%s at '%*s' position %u", msg, yyleng, yytext, m_parsePos - yyleng);
-}
-
-int
-SimpleParser::LexerInput(char* buf, int max_size)
-{
- const BaseString& text = stmtArea().sqlText();
- int n = 0;
- const char* const t = text.c_str();
- const unsigned m = text.length();
- while (n < max_size && m_textPos < m) {
- buf[n++] = t[m_textPos++];
- m_parsePos++; // XXX simple hack
- break;
- }
- return n;
-}
-
-// XXX just a catch-all (scanner should match all input)
-void
-SimpleParser::LexerOutput(const char* buf, int size)
-{
- if (! ctx().ok())
- return;
- const char* msg = "unrecognized input";
- ctx().pushStatus(Sqlstate::_42000, Error::Gen, "%s at '%*s' position %u", msg, size, buf, m_parsePos);
-}
-
-void
-SimpleParser::LexerError(const char* msg)
-{
- ctx().pushStatus(Sqlstate::_42000, Error::Gen, "%s at '%*s' position %u", msg, yyleng, yytext, m_parsePos);
-}
diff --git a/ndb/src/client/odbc/codegen/SimpleScan.lpp b/ndb/src/client/odbc/codegen/SimpleScan.lpp
deleted file mode 100644
index bd930c08cfa..00000000000
--- a/ndb/src/client/odbc/codegen/SimpleScan.lpp
+++ /dev/null
@@ -1,241 +0,0 @@
-%{
-#include <ctype.h>
-#include "SimpleParser.hpp"
-
-struct SqlKeyword {
- const char* m_name;
- int m_value;
- int m_state;
- static const SqlKeyword* find(Ctx& ctx, const char* name, int state);
-};
-
-%}
-
-%option c++
-%option yyclass="SimpleParser"
-%option stack
-%option noyywrap
-
-space [\040\t\n\r\f]
-digit [0-9]
-letter [A-Za-z_]
-special ("$")
-identifier ({letter}({letter}|{digit}|{special})*)
-integer {digit}++
-decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))
-real ((({digit}*\.{digit}+)|({digit}+\.{digit}*)|({digit}+))([Ee][-+]?{digit}+))
-
-%s StateEval
-%s StateType
-%s StatePhys
-%x StateString
-%x StateQuoted
-
-%%
-
-{space} {
- }
-{identifier} {
- const SqlKeyword* key = SqlKeyword::find(m_ctx, (char*)yytext, YYSTATE);
- if (key != 0)
- return key->m_value;
- for (unsigned char* a = (unsigned char*)yytext; *a != 0; a++) {
- if (islower(*a))
- *a = toupper(*a);
- }
- m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
- return T_IDENTIFIER;
- }
-{integer} {
- m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
- return T_LINTEGER;
- }
-{decimal} {
- m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
- return T_LDECIMAL;
- }
-{real} {
- m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
- return T_LREAL;
- }
-"--".* {
- }
-"/*" {
- int c = 0, d;
- while (1) {
- d = c;
- if ((c = yyinput()) == EOF) {
- parseError("unterminated comment");
- yyterminate();
- }
- if (d == '*' && c == '/')
- break;
- }
- }
-<StateEval>{
-"+" return T_PLUS;
-"-" return T_MINUS;
-"*" return T_TIMES;
-"/" return T_DIVIDE;
-"=" return T_EQ;
-"!=" return T_NOTEQ;
-"^=" return T_NOTEQ;
-"<>" return T_NOTEQ;
-"<" return T_LT;
-"<=" return T_LTEQ;
-">" return T_GT;
-">=" return T_GTEQ;
-"?" m_paramNumber++; return T_QUES;
-}
-
-"." return T_PERIOD;
-"," return T_COMMA;
-"(" return T_PARENLEFT;
-")" return T_PARENRIGHT;
-"*" return T_ASTERISK;
-"=" return T_ASSIGN;
-
-"'" {
- pushState(StateString);
- m_string.assign("");
- }
-<StateString>{
-[^']* {
- m_string.append(yytext);
- }
-"''" {
- m_string.append("'");
- }
-"'" {
- m_yylval.m_string = strcpy(new char[m_string.length() + 1], m_string.c_str());
- popState();
- return T_STRING;
- }
-}
-
-\" {
- pushState(StateQuoted);
- m_string.assign("");
- }
-<StateQuoted>{
-[^"]* {
- m_string.append(yytext);
- }
-\\\" {
- m_string.append("\"");
- }
-\" {
- m_yylval.m_string = strcpy(new char[m_string.length() + 1], m_string.c_str());
- popState();
- return T_IDENTIFIER;
- }
-}
-
-%%
-
-// scan states
-int SimpleParser_stateEval = StateEval;
-int SimpleParser_stateType = StateType;
-int SimpleParser_statePhys = StatePhys;
-
-// keep sorted
-
-static const SqlKeyword sqlKeyword[] = {
- { "AND", T_AND, -1 },
- { "ASC", T_ASC, -1 },
- { "AUTO_INCREMENT", T_AUTO_INCREMENT, -1 },
- { "BIGINT", T_BIGINT, StateType },
- { "BINARY", T_BINARY, StateType },
- { "BLOB", T_BLOB, StateType },
- { "BY", T_BY, -1 },
- { "CHAR", T_CHAR, StateType },
- { "CONSTRAINT", T_CONSTRAINT, -1 },
- { "CREATE", T_CREATE, -1 },
- { "DATETIME", T_DATETIME, StateType },
- { "DEFAULT", T_DEFAULT, -1 },
- { "DELETE", T_DELETE, -1 },
- { "DESC", T_DESC, -1 },
- { "DISTINCT", T_DISTINCT, -1 },
- { "DOUBLE", T_DOUBLE, StateType },
- { "DROP", T_DROP, -1 },
- { "FLOAT", T_FLOAT, StateType },
- { "FOREIGN", T_FOREIGN, -1 },
- { "FROM", T_FROM, -1 },
- { "GROUP", T_GROUP, -1 },
- { "HASH", T_HASH, -1 },
- { "HAVING", T_HAVING, -1 },
- { "IN", T_IN, -1 },
- { "INDEX", T_INDEX, -1 },
- { "INSERT", T_INSERT, -1 },
- { "INT", T_INT, StateType },
- { "INTEGER", T_INTEGER, StateType },
- { "INTO", T_INTO, -1 },
- { "IS", T_IS, -1 },
- { "KEY", T_KEY, -1 },
- { "LARGE", T_LARGE, StatePhys },
- { "LIKE", T_LIKE, -1 },
- { "LIMIT", T_LIMIT, -1 },
- { "LOGGING", T_LOGGING, StatePhys },
- { "LONGBLOB", T_LONGBLOB, StateType },
- { "MEDIUM", T_MEDIUM, StatePhys },
- { "NOLOGGING", T_NOLOGGING, StatePhys },
- { "NOT", T_NOT, -1 },
- { "NULL", T_NULL, -1 },
- { "OFFSET", T_OFFSET, -1 },
- { "ON", T_ON, -1 },
- { "OR", T_OR, -1 },
- { "ORDER", T_ORDER, -1 },
- { "PRECISION", T_PRECISION, StateType },
- { "PRIMARY", T_PRIMARY, -1 },
- { "REAL", T_REAL, StateType },
- { "REFERENCES", T_REFERENCES, -1 },
- { "ROWNUM", T_ROWNUM, -1 },
- { "SELECT", T_SELECT, -1 },
- { "SET", T_SET, -1 },
- { "SINGLE", T_SINGLE, StatePhys },
- { "SMALL", T_SMALL, StatePhys },
- { "SMALLINT", T_SMALLINT, StateType },
- { "STORAGE", T_STORAGE, StatePhys },
- { "SYSDATE", T_SYSDATE, -1 },
- { "TABLE", T_TABLE, -1 },
- { "UNIQUE", T_UNIQUE, -1 },
- { "UNSIGNED", T_UNSIGNED, -1 },
- { "UPDATE", T_UPDATE, -1 },
- { "VALUES", T_VALUES, -1 },
- { "VARBINARY", T_VARBINARY, StateType },
- { "VARCHAR", T_VARCHAR, StateType },
- { "WHERE", T_WHERE, -1 },
- { "WRITE", T_WRITE, -1 }
-};
-
-static const unsigned sqlKeywordCount = sizeof(sqlKeyword) / sizeof(sqlKeyword[0]);
-
-const SqlKeyword*
-SqlKeyword::find(Ctx& ctx, const char* name, int state)
-{
- ctx_log4(("find keyword '%s' lex state = %d", name, state));
- const unsigned maxlen = 99;
- char buf[maxlen + 1];
- char* a = buf;
- const char* b = name;
- while (*b != 0) {
- if (a >= buf + maxlen) // will not be found
- break;
- char c = *b++;
- if ('a' <= c && c <= 'z') // locale independent
- c -= 'a' - 'A';
- *a++ = c;
- }
- *a = 0;
- for (unsigned i = 0; i < sqlKeywordCount; i++) {
- const SqlKeyword* key = &sqlKeyword[i];
- if (strcmp(key->m_name, buf) == 0) {
- if (key->m_state != -1 && key->m_state != state)
- return 0;
- return key;
- }
- }
- return 0;
-}
-
-/* vim: set filetype=lex: */
diff --git a/ndb/src/client/odbc/common/Ctx.cpp b/ndb/src/client/odbc/common/Ctx.cpp
deleted file mode 100644
index 44689657788..00000000000
--- a/ndb/src/client/odbc/common/Ctx.cpp
+++ /dev/null
@@ -1,356 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <ndb_global.h>
-#include <NdbApi.hpp>
-#include <common/common.hpp>
-#include "DiagArea.hpp"
-
-// ctor
-
-Ctx::Ctx() :
- m_diagArea(0) // create on demand
-{
- const char* p;
- if ((p = getenv("NDB_ODBC_TRACE")) != 0)
- m_logLevel = atoi(p);
- if ((p = getenv("NDB_ODBC_TRACE_FILE")) != 0 && *p != 0)
- strcpy(m_szTraceFile, p);
-}
-
-Ctx::~Ctx()
-{
- delete m_diagArea;
- m_diagArea = 0;
-}
-
-// handle exceptions
-
-CtxAssert::CtxAssert(const char* file, int line) :
- m_file(file),
- m_line(line)
-{
- const char* p;
- if ((p = getenv("NDB_ODBC_DEBUG")) != 0 && atoi(p) != 0) {
- char buf[200];
- snprintf(buf, sizeof(buf), "%s, line %d: assert failed\n", m_file, m_line);
- if ((p = getenv("NDB_ODBC_TRACE_FILE")) != 0 && *p != 0) {
- FILE* pFile = fopen(p, "a");
- fprintf(pFile, buf);
- fflush(pFile);
- fclose(pFile);
- } else {
- fprintf(stderr, buf);
- fflush(stderr);
- }
- abort();
- exit(1);
- }
-}
-
-void
-Ctx::handleEx(CtxAssert& ctxAssert)
-{
- pushStatus(Sqlstate::_IM001, Error::Gen, "exception at %s line %d", ctxAssert.m_file, ctxAssert.m_line);
-}
-
-// logging methods
-
-int Ctx::m_logLevel = 0;
-char Ctx::m_szTraceFile[MAX_PATH];
-
-void
-Ctx::log(const char* fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- if (m_szTraceFile[0]) {
- FILE* pFile = fopen(m_szTraceFile, "a");
- fprintf(pFile, "[NdbOdbc] ");
- vfprintf(pFile, fmt, ap);
- fprintf(pFile, "\n");
- fflush(pFile);
- fclose(pFile);
- } else {
- printf("[NdbOdbc] ");
- vprintf(fmt, ap);
- printf("\n");
- fflush(stdout);
- }
- va_end(ap);
-}
-
-void
-Ctx::logSqlEnter(const char* sqlFunction)
-{
- Ctx& ctx = *this;
- snprintf(m_sqlFunction, sizeof(m_sqlFunction), "%s", sqlFunction);
- ctx_log3(("%s", m_sqlFunction));
-}
-
-void
-Ctx::logSqlExit()
-{
- Ctx& ctx = *this;
- if (m_diagArea == 0) {
- ctx_log3(("%s ret=%d", m_sqlFunction, getCode()));
- return;
- }
- int logLevel = diagArea().numStatus() != 0 ? 2 : 3;
- ctx_logN(logLevel, ("%s ret=%d diag=%d", m_sqlFunction, diagArea().getCode(), diagArea().numStatus()));
- for (unsigned i = 1; i <= diagArea().numStatus(); i++) {
- OdbcData state;
- OdbcData message;
- diagArea().getRecord(ctx, i, SQL_DIAG_SQLSTATE, state);
- diagArea().getRecord(ctx, i, SQL_DIAG_MESSAGE_TEXT, message);
- ctx_logN(logLevel, ("diag %u: %s - %s", i, state.sqlstate().state(), message.sqlchar()));
- }
-}
-
-void
-Ctx::print(const char* fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- if (m_szTraceFile[0]) {
- FILE* pFile = fopen(m_szTraceFile, "a");
- vfprintf(pFile, fmt, ap);
- unsigned n = strlen(fmt);
- if (n > 0 && fmt[n-1] == '\n')
- fflush(pFile);
- fclose(pFile);
- } else {
- vprintf(fmt, ap);
- unsigned n = strlen(fmt);
- if (n > 0 && fmt[n-1] == '\n')
- fflush(stdout);
- }
- va_end(ap);
-}
-
-void
-Ctx::print(int level, const char* fmt, ...)
-{
- if (level > m_logLevel)
- return;
- va_list ap;
- va_start(ap, fmt);
- if (m_szTraceFile[0]) {
- FILE* pFile = fopen(m_szTraceFile, "a");
- vfprintf(pFile, fmt, ap);
- unsigned n = strlen(fmt);
- if (n > 0 && fmt[n-1] == '\n')
- fflush(pFile);
- fclose(pFile);
- } else {
- vprintf(fmt, ap);
- unsigned n = strlen(fmt);
- if (n > 0 && fmt[n-1] == '\n')
- fflush(stdout);
- }
- va_end(ap);
-}
-
-// diagnostics
-
-static const unsigned MessageSize = 512;
-
-DiagArea&
-Ctx::diagArea() const
-{
- ctx_assert(m_diagArea != 0);
- return *m_diagArea;
-}
-
-DiagArea&
-Ctx::diagArea()
-{
- if (m_diagArea == 0)
- m_diagArea = new DiagArea;
- return *m_diagArea;
-}
-
-SQLRETURN
-Ctx::getCode() const
-{
- if (m_diagArea == 0)
- return SQL_SUCCESS;
- return diagArea().getCode();
-}
-
-void
-Ctx::setCode(SQLRETURN ret)
-{
- diagArea().setCode(ret);
-}
-
-void
-Ctx::pushStatus(const Sqlstate& state, SQLINTEGER code, const char* fmt, ...)
-{
- char message[MessageSize];
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(message, sizeof(message), fmt, ap);
- va_end(ap);
- Error error(state);
- error.m_status = NdbError::PermanentError;
- error.m_classification = NdbError::ApplicationError;
- error.m_code = code;
- error.m_message = message;
- error.m_sqlFunction = m_sqlFunction;
- diagArea().pushStatus(error);
-}
-
-void
-Ctx::pushStatus(SQLINTEGER code, const char* fmt, ...)
-{
- char message[MessageSize];
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(message, sizeof(message), fmt, ap);
- va_end(ap);
- Error error(Sqlstate::_IM000);
- error.m_status = NdbError::PermanentError;
- error.m_classification = NdbError::ApplicationError;
- error.m_code = code;
- error.m_message = message;
- error.m_sqlFunction = m_sqlFunction;
- diagArea().pushStatus(error);
-}
-
-void
-Ctx::pushStatus(const NdbError& ndbError, const char* fmt, ...)
-{
- char message[MessageSize];
- va_list ap;
- va_start(ap, fmt);
- snprintf(message, sizeof(message), "%s", ndbError.message);
- snprintf(message + strlen(message), sizeof(message) - strlen(message), "%s", " - at ");
- vsnprintf(message + strlen(message), sizeof(message) - strlen(message), fmt, ap);
- va_end(ap);
- Error error(Sqlstate::_IM000);
- error.m_status = ndbError.status;
- error.m_classification = ndbError.classification;
- error.m_code = ndbError.code;
- error.m_message = message;
- error.m_sqlFunction = m_sqlFunction;
- diagArea().pushStatus(error);
-}
-
-void
-Ctx::pushStatus(const Ndb* ndb, const char* fmt, ...)
-{
- char message[MessageSize];
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(message, sizeof(message), fmt, ap);
- va_end(ap);
- bool found = false;
- if (ndb != 0) {
- const NdbError& ndbError = ndb->getNdbError();
- if (ndbError.code != 0) {
- pushStatus(ndbError, "%s", message);
- found = true;
- }
- }
- if (! found) {
- pushStatus(Error::Gen, "unknown NDB error");
- }
-}
-
-void
-Ctx::pushStatus(const Ndb* ndb, const NdbConnection* tcon, const NdbOperation* op, const char* fmt, ...)
-{
- char message[MessageSize];
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(message, sizeof(message), fmt, ap);
- va_end(ap);
- bool found = false;
- if (op != 0) {
- const NdbError& ndbError = op->getNdbError();
- if (ndbError.code != 0) {
- pushStatus(ndbError, "%s", message);
- found = true;
- }
- }
- if (tcon != 0) {
- const NdbError& ndbError = tcon->getNdbError();
- if (ndbError.code != 0) {
- pushStatus(ndbError, "%s", message);
- found = true;
- }
- }
- if (ndb != 0) {
- const NdbError& ndbError = ndb->getNdbError();
- if (ndbError.code != 0) {
- pushStatus(ndbError, "%s", message);
- found = true;
- }
- }
- if (! found) {
- pushStatus(Error::Gen, "unknown NDB error");
- }
-}
-
-void
-Ctx::pushStatus(const Ndb* ndb, const NdbSchemaCon* scon, const NdbSchemaOp* op, const char* fmt, ...)
-{
- char message[MessageSize];
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(message, sizeof(message), fmt, ap);
- va_end(ap);
- bool found = false;
- if (op != 0) {
- const NdbError& ndbError = op->getNdbError();
- if (ndbError.code != 0) {
- pushStatus(ndbError, "%s", message);
- found = true;
- }
- }
- if (scon != 0) {
- const NdbError& ndbError = scon->getNdbError();
- if (ndbError.code != 0) {
- pushStatus(ndbError, "%s", message);
- found = true;
- }
- }
- if (ndb != 0) {
- const NdbError& ndbError = ndb->getNdbError();
- if (ndbError.code != 0) {
- pushStatus(ndbError, "%s", message);
- found = true;
- }
- }
- if (! found) {
- pushStatus(Error::Gen, "unknown NDB error");
- }
-}
-
-// check for error
-
-bool
-Ctx::ok()
-{
- if (m_diagArea == 0)
- return true;
- if (diagArea().getCode() == SQL_SUCCESS)
- return true;
- if (diagArea().getCode() == SQL_SUCCESS_WITH_INFO)
- return true;
- return false;
-}
diff --git a/ndb/src/client/odbc/common/DataField.cpp b/ndb/src/client/odbc/common/DataField.cpp
deleted file mode 100644
index dfd4137ffd9..00000000000
--- a/ndb/src/client/odbc/common/DataField.cpp
+++ /dev/null
@@ -1,3024 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <ndb_global.h>
-#include "DataField.hpp"
-
-#ifndef INT_MAX
-#define INT_MAX (2147483647)
-#endif
-
-#ifndef INT_MIN
-#define INT_MIN (-INT_MAX - 1)
-#endif
-
-#ifndef UINT_MAX
-#define UINT_MAX 4294967295U
-#endif
-
-#ifndef FLT_MAX
-#define FLT_MAX (3.402823466E+38F)
-#endif
-#ifndef FLT_MIN
-#define FLT_MIN (1.175494351E-38F)
-#endif
-
-#ifdef NDB_WIN32
-#define FMT_I64 "%I64d"
-#define FMT_U64 "%I64u"
-#else
-#define FMT_I64 "%lld"
-#define FMT_U64 "%llu"
-#endif
-
-#ifdef NDB_WIN32
-#define strtoll(str, endptr, base) strtoint64(str, endptr, base)
-#define strtoull(str, endptr, base) strtouint64(str, endptr, base)
-
-static Int64
-strtoint64(const char *str, char **endptr, int base)
-{
- Int64 x = 0;
- while (*str == ' ')
- str++;
- const char* p = str;
- while ('0' <= *p && *p <= '9')
- x = 10 * x + *p++ - '0';
- if (p == str) {
- *endptr = 0;
- return 0;
- }
- *endptr = (char*)p;
- return x;
-}
-
-static Uint64
-strtouint64(const char *str, char **endptr, int base)
-{
- Uint64 x = 0;
- while (*str == ' ')
- str++;
- const char* p = str;
- while ('0' <= *p && *p <= '9')
- x = 10 * x + *p++ - '0';
- if (p == str) {
- *endptr = 0;
- return 0;
- }
- *endptr = (char*)p;
- return x;
-}
-#endif
-
-// LexSpec
-
-void
-LexSpec::convert(Ctx& ctx, const BaseString& value, SqlField& out)
-{
- const SqlSpec& sqlSpec = out.sqlSpec();
- const SqlType& sqlType = sqlSpec.sqlType();
- out.alloc();
- if (sqlType.type() == SqlType::Char) {
- const SqlChar* s = (const SqlChar*)value.c_str();
- out.sqlChar(s, SQL_NTS);
- return;
- }
- if (sqlType.type() == SqlType::Bigint) {
- char* endptr = 0;
- SqlBigint n = static_cast<SqlBigint>(strtoll(value.c_str(), &endptr, 10));
- if (endptr == 0 || *endptr != 0) {
- ctx.pushStatus(Error::Gen, "cannot convert '%s' to integer", value.c_str());
- return;
- }
- out.sqlBigint(n);
- return;
- }
- if (sqlType.type() == SqlType::Double) {
- char* endptr = 0;
- SqlDouble x = static_cast<SqlDouble>(strtod(value.c_str(), &endptr));
- if (endptr == 0 || *endptr != 0) {
- ctx.pushStatus(Error::Gen, "cannot convert '%s' to number", value.c_str());
- return;
- }
- out.sqlDouble(x);
- return;
- }
- if (sqlType.type() == SqlType::Null) {
- out.u_null.m_nullFlag = true;
- return;
- }
- ctx_assert(false);
-}
-
-// SqlField
-
-void
-SqlField::alloc()
-{
- ctx_assert(sqlSpec().store() == SqlSpec::Physical);
- const SqlType& sqlType = sqlSpec().sqlType();
- if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varchar)
- n += 2;
- if (n > SqlField_CharSmall) {
- u_data.m_sqlChar = new SqlChar[n];
- }
- }
- if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varbinary)
- n += 2;
- if (n > SqlField_CharSmall) {
- u_data.m_sqlChar = new SqlChar[n];
- }
- }
-}
-
-void
-SqlField::alloc(const SqlField& sqlField)
-{
- alloc();
- const SqlType& sqlType = sqlSpec().sqlType();
- if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varchar)
- n += 2;
- if (n > SqlField_CharSmall) {
- memcpy(u_data.m_sqlChar, sqlField.u_data.m_sqlChar, n);
- }
- }
- if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varbinary)
- n += 2;
- if (n > SqlField_CharSmall) {
- memcpy(u_data.m_sqlChar, sqlField.u_data.m_sqlChar, n);
- }
- }
-}
-
-const void*
-SqlField::addr() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->addr();
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varchar)
- n += 2;
- if (n > SqlField_CharSmall) {
- return static_cast<const void*>(u_data.m_sqlChar);
- }
- return static_cast<const void*>(u_data.m_sqlCharSmall);
- }
- if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varbinary)
- n += 2;
- if (n > SqlField_CharSmall) {
- return static_cast<const void*>(u_data.m_sqlChar);
- }
- return static_cast<const void*>(u_data.m_sqlCharSmall);
- }
- if (sqlType.type() == SqlType::Smallint) {
- return static_cast<const void*>(&u_data.m_sqlSmallint);
- }
- if (sqlType.type() == SqlType::Integer) {
- return static_cast<const void*>(&u_data.m_sqlInteger);
- }
- if (sqlType.type() == SqlType::Bigint) {
- return static_cast<const void*>(&u_data.m_sqlBigint);
- }
- if (sqlType.type() == SqlType::Real) {
- return static_cast<const void*>(&u_data.m_sqlReal);
- }
- if (sqlType.type() == SqlType::Double) {
- return static_cast<const void*>(&u_data.m_sqlDouble);
- }
- if (sqlType.type() == SqlType::Datetime) {
- return static_cast<const void*>(&u_data.m_sqlDatetime);
- }
- ctx_assert(false); // SqlType::Null has no address
- return 0;
-}
-
-void*
-SqlField::addr()
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varchar)
- n += 2;
- if (n > SqlField_CharSmall) {
- return static_cast<void*>(u_data.m_sqlChar);
- }
- return static_cast<void*>(u_data.m_sqlCharSmall);
- }
- if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varbinary)
- n += 2;
- if (n > SqlField_CharSmall) {
- return static_cast<void*>(u_data.m_sqlChar);
- }
- return static_cast<void*>(u_data.m_sqlCharSmall);
- }
- if (sqlType.type() == SqlType::Smallint) {
- return static_cast<void*>(&u_data.m_sqlSmallint);
- }
- if (sqlType.type() == SqlType::Integer) {
- return static_cast<void*>(&u_data.m_sqlInteger);
- }
- if (sqlType.type() == SqlType::Bigint) {
- return static_cast<void*>(&u_data.m_sqlBigint);
- }
- if (sqlType.type() == SqlType::Real) {
- return static_cast<void*>(&u_data.m_sqlReal);
- }
- if (sqlType.type() == SqlType::Double) {
- return static_cast<void*>(&u_data.m_sqlDouble);
- }
- if (sqlType.type() == SqlType::Datetime) {
- return static_cast<void*>(&u_data.m_sqlDatetime);
- }
- ctx_assert(false); // SqlType::Null has no address
- return 0;
-}
-
-unsigned
-SqlField::allocSize() const
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- unsigned n = sqlType.size();
- if (sqlType.type() == SqlType::Varchar || sqlType.type() == SqlType::Varbinary) {
- n += 2;
- }
- return n;
-}
-
-void
-SqlField::free()
-{
- ctx_assert(sqlSpec().store() == SqlSpec::Physical);
- const SqlType& sqlType = sqlSpec().sqlType();
- if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varchar)
- n += 2;
- if (n > SqlField_CharSmall) {
- delete[] u_data.m_sqlChar;
- u_data.m_sqlChar = 0; // safety since dtor used explicitly
- }
- }
- if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
- unsigned n = sqlType.length();
- if (sqlType.type() == SqlType::Varbinary)
- n += 2;
- if (n > SqlField_CharSmall) {
- delete[] u_data.m_sqlChar;
- u_data.m_sqlChar = 0; // safety since dtor used explicitly
- }
- }
-}
-
-// get
-
-const SqlChar*
-SqlField::sqlChar() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlChar();
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Char);
- if (sqlType.length() > SqlField_CharSmall)
- return u_data.m_sqlChar;
- return u_data.m_sqlCharSmall;
-}
-
-const SqlChar*
-SqlField::sqlVarchar(unsigned* length) const
-{
-#if NDB_VERSION_MAJOR >= 3
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlVarchar(length);
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Varchar);
- const SqlChar* sqlChar;
- unsigned n = sqlType.length();
- if (2 + n > SqlField_CharSmall)
- sqlChar = u_data.m_sqlChar;
- else
- sqlChar = u_data.m_sqlCharSmall;
- if (length != 0)
- *length = (sqlChar[0] << 8) | sqlChar[1]; // big-endian
- return sqlChar + 2;
-#else
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlVarchar(length);
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Varchar);
- const SqlChar* sqlChar;
- unsigned n = sqlType.length();
- if (n + 2 > SqlField_CharSmall)
- sqlChar = u_data.m_sqlChar;
- else
- sqlChar = u_data.m_sqlCharSmall;
- if (length != 0)
- *length = (sqlChar[n + 0] << 8) | sqlChar[n + 1]; // big-endian
- return sqlChar;
-#endif
-}
-
-const SqlChar*
-SqlField::sqlBinary() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlChar();
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Binary);
- if (sqlType.length() > SqlField_CharSmall)
- return u_data.m_sqlChar;
- return u_data.m_sqlCharSmall;
-}
-
-const SqlChar*
-SqlField::sqlVarbinary(unsigned* length) const
-{
-#if NDB_VERSION_MAJOR >= 3
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlVarchar(length);
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Varbinary);
- const SqlChar* sqlChar;
- unsigned n = sqlType.length();
- if (2 + n > SqlField_CharSmall)
- sqlChar = u_data.m_sqlChar;
- else
- sqlChar = u_data.m_sqlCharSmall;
- if (length != 0)
- *length = (sqlChar[0] << 8) | sqlChar[1]; // big-endian
- return sqlChar + 2;
-#else
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlVarchar(length);
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Varbinary);
- const SqlChar* sqlChar;
- unsigned n = sqlType.length();
- if (n + 2 > SqlField_CharSmall)
- sqlChar = u_data.m_sqlChar;
- else
- sqlChar = u_data.m_sqlCharSmall;
- if (length != 0)
- *length = (sqlChar[n + 0] << 8) | sqlChar[n + 1]; // big-endian
- return sqlChar;
-#endif
-}
-
-SqlSmallint
-SqlField::sqlSmallint() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlSmallint();
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Smallint);
- return u_data.m_sqlSmallint;
-}
-
-SqlInteger
-SqlField::sqlInteger() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlInteger();
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Integer);
- return u_data.m_sqlInteger;
-}
-
-SqlBigint
-SqlField::sqlBigint() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlBigint();
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Bigint);
- return u_data.m_sqlBigint;
-}
-
-SqlReal
-SqlField::sqlReal() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlReal();
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Real);
- return u_data.m_sqlReal;
-}
-
-SqlDouble
-SqlField::sqlDouble() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlDouble();
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Double);
- return u_data.m_sqlDouble;
-}
-
-SqlDatetime
-SqlField::sqlDatetime() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlDatetime();
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Datetime);
- return u_data.m_sqlDatetime;
-}
-
-// set
-
-void
-SqlField::sqlChar(const SqlChar* value, int length)
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Char);
- unsigned n = sqlType.length();
- SqlChar* p = n > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
- const SqlChar* q = value;
- unsigned m = length == SQL_NTS ? strlen((const char*)q) : length;
- ctx_assert(m <= n);
- for (unsigned i = 0; i < m; i++)
- *p++ = *q++;
- for (unsigned i = m; i < n; i++)
- *p++ = 0x20; // space
- u_null.m_nullFlag = false;
-}
-
-void
-SqlField::sqlVarchar(const SqlChar* value, int length)
-{
-#if NDB_VERSION_MAJOR >= 3
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Varchar);
- unsigned n = sqlType.length();
- SqlChar* p = 2 + n > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
- const SqlChar* q = value;
- unsigned m = length == SQL_NTS ? strlen((const char*)q) : length;
- ctx_assert(m <= n);
- *p++ = (m >> 8) & 0xff; // big-endian
- *p++ = (m & 0xff);
- for (unsigned i = 0; i < m; i++)
- *p++ = *q++;
- for (unsigned i = m; i < n; i++)
- *p++ = 0x0; // null
- u_null.m_nullFlag = false;
-#else
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Varchar);
- unsigned n = sqlType.length();
- SqlChar* p = n + 2 > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
- const SqlChar* q = value;
- unsigned m = length == SQL_NTS ? strlen((const char*)q) : length;
- ctx_assert(m <= n);
- for (unsigned i = 0; i < m; i++)
- *p++ = *q++;
- for (unsigned i = m; i < n; i++)
- *p++ = 0x0; // null
- *p++ = (m >> 8) & 0xff; // big-endian
- *p++ = (m & 0xff);
- u_null.m_nullFlag = false;
-#endif
-}
-
-void
-SqlField::sqlBinary(const SqlChar* value, int length)
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Binary);
- unsigned n = sqlType.length();
- SqlChar* p = n > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
- const SqlChar* q = value;
- unsigned m = length;
- ctx_assert(m <= n);
- for (unsigned i = 0; i < m; i++)
- *p++ = *q++;
- for (unsigned i = m; i < n; i++)
- *p++ = 0x0; // null
- u_null.m_nullFlag = false;
-}
-
-void
-SqlField::sqlVarbinary(const SqlChar* value, int length)
-{
-#if NDB_VERSION_MAJOR >= 3
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Varbinary);
- unsigned n = sqlType.length();
- SqlChar* p = 2 + n > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
- const SqlChar* q = value;
- unsigned m = length;
- ctx_assert(m <= n);
- *p++ = (m >> 8) & 0xff; // big-endian
- *p++ = (m & 0xff);
- for (unsigned i = 0; i < m; i++)
- *p++ = *q++;
- for (unsigned i = m; i < n; i++)
- *p++ = 0x0; // null
- u_null.m_nullFlag = false;
-#else
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Varbinary);
- unsigned n = sqlType.length();
- SqlChar* p = n + 2 > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
- const SqlChar* q = value;
- unsigned m = length;
- ctx_assert(m <= n);
- for (unsigned i = 0; i < m; i++)
- *p++ = *q++;
- for (unsigned i = m; i < n; i++)
- *p++ = 0x0; // null
- *p++ = (m >> 8) & 0xff; // big-endian
- *p++ = (m & 0xff);
- u_null.m_nullFlag = false;
-#endif
-}
-
-void
-SqlField::sqlSmallint(SqlSmallint value)
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Smallint);
- u_data.m_sqlSmallint = value;
- u_null.m_nullFlag = false;
-}
-
-void
-SqlField::sqlInteger(SqlInteger value)
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Integer);
- u_data.m_sqlInteger = value;
- u_null.m_nullFlag = false;
-}
-
-void
-SqlField::sqlBigint(SqlBigint value)
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Bigint);
- u_data.m_sqlBigint = value;
- u_null.m_nullFlag = false;
-}
-
-void
-SqlField::sqlReal(SqlReal value)
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Real);
- u_data.m_sqlReal = value;
- u_null.m_nullFlag = false;
-}
-
-void
-SqlField::sqlDouble(SqlDouble value)
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Double);
- u_data.m_sqlDouble = value;
- u_null.m_nullFlag = false;
-}
-
-void
-SqlField::sqlDatetime(SqlDatetime value)
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- ctx_assert(sqlType.type() == SqlType::Datetime);
- u_data.m_sqlDatetime = value;
- u_null.m_nullFlag = false;
-}
-
-// get and and set null
-
-bool
-SqlField::sqlNull() const
-{
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- return u_data.m_sqlField->sqlNull();
- }
- return u_null.m_nullFlag;
-}
-
-void
-SqlField::sqlNull(bool value)
-{
- u_null.m_nullFlag = value;
-}
-
-unsigned
-SqlField::trim() const
-{
- const SqlType& sqlType = sqlSpec().sqlType();
- unsigned n = 0;
- const SqlChar* s = 0;
- if (sqlType.type() == SqlType::Char) {
- n = sqlType.length();
- s = sqlChar();
- } else if (sqlType.type() == SqlType::Varchar) {
- s = sqlVarchar(&n);
- } else {
- ctx_assert(false);
- return 0;
- }
- while (n > 0 && s[n - 1] == 0x20)
- n--;
- return n;
-}
-
-void
-SqlField::copy(Ctx& ctx, SqlField& out) const
-{
- const SqlField& f1 = *this;
- SqlField& f2 = out;
- const SqlType& t1 = f1.sqlSpec().sqlType();
- const SqlType& t2 = f2.sqlSpec().sqlType();
- ctx_assert(t1.type() == t2.type());
- if (f1.sqlNull()) {
- f2.sqlNull(true);
- return;
- }
- if (t1.type() == SqlType::Char) {
- f2.sqlChar(f1.sqlChar(), t1.length());
- return;
- }
- if (t1.type() == SqlType::Varchar) {
- unsigned length;
- const SqlChar* s1 = f1.sqlVarchar(&length);
- f2.sqlVarchar(s1, length);
- return;
- }
- if (t1.type() == SqlType::Binary) {
- f2.sqlBinary(f1.sqlBinary(), t1.length());
- return;
- }
- if (t1.type() == SqlType::Varbinary) {
- unsigned length;
- const SqlChar* s1 = f1.sqlVarbinary(&length);
- f2.sqlVarbinary(s1, length);
- return;
- }
- if (t1.type() == SqlType::Smallint) {
- f2.sqlSmallint(f1.sqlSmallint());
- return;
- }
- if (t1.type() == SqlType::Integer) {
- f2.sqlInteger(f1.sqlInteger());
- return;
- }
- if (t1.type() == SqlType::Bigint) {
- f2.sqlBigint(f1.sqlBigint());
- return;
- }
- if (t1.type() == SqlType::Real) {
- f2.sqlReal(f1.sqlReal());
- return;
- }
- if (t1.type() == SqlType::Double) {
- f2.sqlDouble(f1.sqlDouble());
- return;
- }
- if (t1.type() == SqlType::Datetime) {
- f2.sqlDatetime(f1.sqlDatetime());
- return;
- }
- ctx_assert(false);
-}
-
-bool
-SqlField::cast(Ctx& ctx, SqlField& out) const
-{
- const SqlField& f1 = *this;
- SqlField& f2 = out;
- if (f1.sqlNull()) {
- f2.sqlNull(true);
- return true;
- }
- const SqlType& t1 = f1.sqlSpec().sqlType();
- const SqlType& t2 = f2.sqlSpec().sqlType();
- if (t1.type() == SqlType::Char) {
- if (t2.type() == SqlType::Char) {
- unsigned n1 = f1.trim();
- if (n1 > t2.length())
- return false;
- f2.sqlChar(f1.sqlChar(), n1);
- return true;
- }
- if (t2.type() == SqlType::Varchar) {
- unsigned n1 = t1.length();
- if (n1 > t2.length())
- return false;
- f2.sqlVarchar(f1.sqlChar(), n1);
- return true;
- }
- if (t2.type() == SqlType::Binary) {
- unsigned n1 = t1.length();
- if (n1 > t2.length())
- return false;
- f2.sqlBinary(f1.sqlChar(), n1);
- return true;
- }
- if (t2.type() == SqlType::Varbinary) {
- unsigned n1 = t1.length();
- if (n1 > t2.length())
- return false;
- f2.sqlVarbinary(f1.sqlChar(), n1);
- return true;
- }
- ctx_assert(false);
- return false;
- }
- if (t1.type() == SqlType::Varchar) {
- if (t2.type() == SqlType::Char) {
- unsigned n1 = f1.trim();
- if (n1 > t2.length())
- return false;
- f2.sqlChar(f1.sqlVarchar(0), n1);
- return true;
- }
- if (t2.type() == SqlType::Varchar) {
- unsigned n1 = f1.trim();
- if (n1 > t2.length())
- return false;
- f2.sqlVarchar(f1.sqlVarchar(0), n1);
- return true;
- }
- if (t2.type() == SqlType::Binary) {
- unsigned n1 = t1.length();
- if (n1 > t2.length())
- return false;
- f2.sqlBinary(f1.sqlVarchar(0), n1);
- return true;
- }
- if (t2.type() == SqlType::Varbinary) {
- unsigned n1 = t1.length();
- if (n1 > t2.length())
- return false;
- f2.sqlVarbinary(f1.sqlVarchar(0), n1);
- return true;
- }
- ctx_assert(false);
- return false;
- }
- if (t1.type() == SqlType::Binary) {
- if (t2.type() == SqlType::Binary) {
- unsigned n1 = t1.length();
- if (n1 > t2.length())
- return false;
- f2.sqlBinary(f1.sqlBinary(), n1);
- return true;
- }
- if (t2.type() == SqlType::Varbinary) {
- unsigned n1 = t1.length();
- if (n1 > t2.length())
- return false;
- f2.sqlVarbinary(f1.sqlBinary(), n1);
- return true;
- }
- ctx_assert(false);
- return false;
- }
- if (t1.type() == SqlType::Varbinary) {
- if (t2.type() == SqlType::Binary) {
- unsigned n1 = t1.length();
- if (n1 > t2.length())
- return false;
- f2.sqlBinary(f1.sqlVarbinary(0), n1);
- return true;
- }
- if (t2.type() == SqlType::Varbinary) {
- unsigned n1 = t1.length();
- if (n1 > t2.length())
- return false;
- f2.sqlVarbinary(f1.sqlVarbinary(0), n1);
- return true;
- }
- ctx_assert(false);
- return false;
- }
- if (t1.type() == SqlType::Smallint) {
- if (! t2.unSigned()) {
- SqlSmallint x1 = f1.sqlSmallint();
- if (t2.type() == SqlType::Smallint) {
- f2.sqlSmallint(x1);
- return true;
- }
- if (t2.type() == SqlType::Integer) {
- SqlInteger x2 = static_cast<SqlInteger>(x1);
- f2.sqlInteger(x2);
- return true;
- }
- if (t2.type() == SqlType::Bigint) {
- SqlBigint x2 = static_cast<SqlBigint>(x1);
- f2.sqlBigint(x2);
- return true;
- }
- if (t2.type() == SqlType::Real) {
- SqlReal x2 = static_cast<SqlReal>(x1);
- f2.sqlReal(x2);
- return true;
- }
- if (t2.type() == SqlType::Double) {
- SqlDouble x2 = static_cast<SqlDouble>(x1);
- f2.sqlDouble(x2);
- return true;
- }
- } else {
- SqlUsmallint x1 = f1.sqlSmallint();
- if (t2.type() == SqlType::Smallint) {
- f2.sqlSmallint(x1);
- return true;
- }
- if (t2.type() == SqlType::Integer) {
- SqlUinteger x2 = static_cast<SqlUinteger>(x1);
- f2.sqlInteger(x2);
- return true;
- }
- if (t2.type() == SqlType::Bigint) {
- SqlUbigint x2 = static_cast<SqlUbigint>(x1);
- f2.sqlBigint(x2);
- return true;
- }
- }
- ctx_assert(false);
- return false;
- }
- if (t1.type() == SqlType::Integer) {
- if (! t2.unSigned()) {
- SqlInteger x1 = f1.sqlInteger();
- if (t2.type() == SqlType::Smallint) {
- SqlSmallint x2 = static_cast<SqlSmallint>(x1);
- if (x1 != static_cast<SqlInteger>(x2))
- return false;
- f2.sqlSmallint(x2);
- return true;
- }
- if (t2.type() == SqlType::Integer) {
- f2.sqlInteger(x1);
- return true;
- }
- if (t2.type() == SqlType::Bigint) {
- SqlBigint x2 = static_cast<SqlBigint>(x1);
- f2.sqlBigint(x2);
- return true;
- }
- if (t2.type() == SqlType::Real) {
- SqlReal x2 = static_cast<SqlReal>(x1);
- f2.sqlReal(x2);
- return true;
- }
- if (t2.type() == SqlType::Double) {
- SqlDouble x2 = static_cast<SqlDouble>(x1);
- f2.sqlDouble(x2);
- return true;
- }
- } else {
- SqlUinteger x1 = f1.sqlInteger();
- if (t2.type() == SqlType::Smallint) {
- SqlUsmallint x2 = static_cast<SqlUsmallint>(x1);
- if (x1 != static_cast<SqlUinteger>(x2))
- return false;
- f2.sqlSmallint(x2);
- return true;
- }
- if (t2.type() == SqlType::Integer) {
- f2.sqlInteger(x1);
- return true;
- }
- if (t2.type() == SqlType::Bigint) {
- SqlUbigint x2 = static_cast<SqlUbigint>(x1);
- f2.sqlBigint(x2);
- return true;
- }
- }
- ctx_assert(false);
- return false;
- }
- if (t1.type() == SqlType::Bigint) {
- if (! t2.unSigned()) {
- SqlBigint x1 = f1.sqlBigint();
- if (t2.type() == SqlType::Smallint) {
- SqlSmallint x2 = static_cast<SqlSmallint>(x1);
- if (x1 != static_cast<SqlBigint>(x2))
- return false;
- f2.sqlSmallint(x2);
- return true;
- }
- if (t2.type() == SqlType::Integer) {
- SqlInteger x2 = static_cast<SqlInteger>(x1);
- if (x1 != static_cast<SqlBigint>(x2))
- return false;
- f2.sqlInteger(x2);
- return true;
- }
- if (t2.type() == SqlType::Bigint) {
- f2.sqlBigint(x1);
- return true;
- }
- if (t2.type() == SqlType::Real) {
- SqlReal x2 = static_cast<SqlReal>(x1);
- f2.sqlReal(x2);
- return true;
- }
- if (t2.type() == SqlType::Double) {
- SqlDouble x2 = static_cast<SqlDouble>(x1);
- f2.sqlDouble(x2);
- return true;
- }
- } else {
- SqlUbigint x1 = f1.sqlBigint();
- if (t2.type() == SqlType::Smallint) {
- SqlUsmallint x2 = static_cast<SqlUsmallint>(x1);
- if (x1 != static_cast<SqlUbigint>(x2))
- return false;
- f2.sqlSmallint(x2);
- return true;
- }
- if (t2.type() == SqlType::Integer) {
- SqlUinteger x2 = static_cast<SqlUinteger>(x1);
- if (x1 != static_cast<SqlUbigint>(x2))
- return false;
- f2.sqlInteger(x2);
- return true;
- }
- if (t2.type() == SqlType::Bigint) {
- f2.sqlBigint(x1);
- return true;
- }
- }
- ctx_assert(false);
- return false;
- }
- if (t1.type() == SqlType::Real) {
- SqlReal x1 = f1.sqlReal();
- int off = 0;
- if (x1 > 0.0 && x1 - floor(x1) >= 0.5)
- off = 1;
- if (x1 < 0.0 && x1 - floor(x1) <= 0.5)
- off = -1;
- bool b = (x1 - floor(x1) < 0.5);
- if (t2.type() == SqlType::Smallint) {
- SqlSmallint x2 = static_cast<SqlSmallint>(x1) + off;
- if (fabs(x1 - static_cast<SqlReal>(x2)) >= 1.0)
- return false;
- f2.sqlSmallint(x2);
- return true;
- }
- if (t2.type() == SqlType::Integer) {
- SqlInteger x2 = static_cast<SqlInteger>(x1) + off;
- if (fabs(x1 - static_cast<SqlReal>(x2)) >= 1.0)
- return false;
- f2.sqlInteger(x2);
- return true;
- }
- if (t2.type() == SqlType::Bigint) {
- SqlBigint x2 = static_cast<SqlBigint>(x1) + off;
- if (fabs(x1 - static_cast<SqlReal>(x2)) >= 1.0)
- return false;
- f2.sqlBigint(x2);
- return true;
- }
- if (t2.type() == SqlType::Real) {
- f2.sqlReal(x1);
- return true;
- }
- if (t2.type() == SqlType::Double) {
- SqlDouble x2 = static_cast<SqlDouble>(x1);
- f2.sqlDouble(x2);
- return true;
- }
- ctx_assert(false);
- return false;
- }
- if (t1.type() == SqlType::Double) {
- SqlDouble x1 = f1.sqlDouble();
- int off = 0;
- if (x1 > 0.0 && x1 - floor(x1) >= 0.5)
- off = 1;
- if (x1 < 0.0 && x1 - floor(x1) <= 0.5)
- off = -1;
- bool b = (x1 - floor(x1) < 0.5);
- if (t2.type() == SqlType::Smallint) {
- SqlSmallint x2 = static_cast<SqlSmallint>(x1) + off;
- if (fabs(x1 - static_cast<SqlDouble>(x2)) >= 1.0)
- return false;
- f2.sqlSmallint(x2);
- return true;
- }
- if (t2.type() == SqlType::Integer) {
- SqlInteger x2 = static_cast<SqlInteger>(x1) + off;
- if (fabs(x1 - static_cast<SqlDouble>(x2)) >= 1.0)
- return false;
- f2.sqlInteger(x2);
- return true;
- }
- if (t2.type() == SqlType::Bigint) {
- SqlBigint x2 = static_cast<SqlBigint>(x1) + off;
- if (fabs(x1 - static_cast<SqlDouble>(x2)) >= 1.0)
- return false;
- f2.sqlBigint(x2);
- return true;
- }
- if (t2.type() == SqlType::Real) {
- SqlReal x2 = static_cast<SqlReal>(x1);
- if (fabs(x1 - static_cast<SqlDouble>(x2)) >= 1.0) // XXX
- return false;
- f2.sqlReal(x1);
- return true;
- }
- if (t2.type() == SqlType::Double) {
- f2.sqlDouble(x1);
- return true;
- }
- ctx_assert(false);
- return false;
- }
- ctx_assert(false);
- return false;
-}
-
-bool
-SqlField::less(const SqlField& sqlField) const
-{
- const SqlField& f1 = *this;
- const SqlField& f2 = sqlField;
- const SqlType& t1 = f1.sqlSpec().sqlType();
- const SqlType& t2 = f2.sqlSpec().sqlType();
- ctx_assert(t1.type() == t2.type());
- if (t1.type() == SqlType::Char) {
- const SqlChar* s1 = f1.sqlChar();
- const SqlChar* s2 = f2.sqlChar();
- unsigned n1 = t1.length();
- unsigned n2 = t2.length();
- SqlChar c1 = 0;
- SqlChar c2 = 0;
- unsigned i = 0;
- while (i < n1 || i < n2) {
- c1 = i < n1 ? s1[i] : 0x20;
- c2 = i < n2 ? s2[i] : 0x20;
- if (c1 != c2)
- break;
- i++;
- }
- return (c1 < c2);
- }
- if (t1.type() == SqlType::Varchar) {
- unsigned n1, n2;
- const SqlChar* s1 = f1.sqlVarchar(&n1);
- const SqlChar* s2 = f2.sqlVarchar(&n2);
- SqlChar c1 = 0;
- SqlChar c2 = 0;
- unsigned i = 0;
- while (i < n1 || i < n2) {
- c1 = i < n1 ? s1[i] : 0x0;
- c2 = i < n2 ? s2[i] : 0x0;
- if (c1 != c2)
- break;
- i++;
- }
- return (c1 < c2);
- }
- if (t1.type() == SqlType::Smallint) {
- ctx_assert(t1.unSigned() == t2.unSigned());
- if (! t1.unSigned()) {
- SqlSmallint x1 = f1.sqlSmallint();
- SqlSmallint x2 = f2.sqlSmallint();
- return (x1 < x2);
- } else {
- SqlUsmallint x1 = f1.sqlSmallint();
- SqlUsmallint x2 = f2.sqlSmallint();
- return (x1 < x2);
- }
- }
- if (t1.type() == SqlType::Integer) {
- ctx_assert(t1.unSigned() == t2.unSigned());
- if (! t1.unSigned()) {
- SqlInteger x1 = f1.sqlInteger();
- SqlInteger x2 = f2.sqlInteger();
- return (x1 < x2);
- } else {
- SqlUinteger x1 = f1.sqlInteger();
- SqlUinteger x2 = f2.sqlInteger();
- return (x1 < x2);
- }
- }
- if (t1.type() == SqlType::Bigint) {
- ctx_assert(t1.unSigned() == t2.unSigned());
- if (! t1.unSigned()) {
- SqlBigint x1 = f1.sqlBigint();
- SqlBigint x2 = f2.sqlBigint();
- return (x1 < x2);
- } else {
- SqlUbigint x1 = f1.sqlBigint();
- SqlUbigint x2 = f2.sqlBigint();
- return (x1 < x2);
- }
- }
- if (t1.type() == SqlType::Real) {
- SqlReal x1 = f1.sqlReal();
- SqlReal x2 = f2.sqlReal();
- return (x1 < x2);
- }
- if (t1.type() == SqlType::Double) {
- SqlDouble x1 = f1.sqlDouble();
- SqlDouble x2 = f2.sqlDouble();
- return (x1 < x2);
- }
- if (t1.type() == SqlType::Datetime) {
- SqlDatetime x1 = f1.sqlDatetime();
- SqlDatetime x2 = f2.sqlDatetime();
- return x1.less(x2);
- }
- ctx_assert(false);
-}
-
-// copy from external
-
-static bool
-copyin_char_char(Ctx& ctx, char* value, unsigned n, const char* ptr, const SQLINTEGER* ind, int* off, SqlChar* addr, int fieldId)
-{
- if (off != 0 && *off >= 0) {
- if ((unsigned)*off > n) {
- ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d truncated (%u > %u)", fieldId, (unsigned)*off, n);
- return false;
- }
- value += *off;
- n -= *off;
- }
- unsigned m;
- if (ind == 0 || *ind == SQL_NTS)
- m = strlen(ptr);
- else
- m = *ind;
- if (m > n) {
- ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d truncated (%u > %u)", fieldId, m, n);
- return false;
- }
- for (unsigned i = 0; i < m; i++)
- value[i] = ptr[i];
- if (off != 0 && *off >= 0)
- *off += m;
- for (unsigned i = m; i < n; i++)
- value[i] = addr == 0 ? 0x20 : 0x0;
- if (addr != 0) {
- if (off != 0 && *off >= 0)
- m = *off;
- addr[0] = (m >> 8) & 0xff;
- addr[1] = (m & 0xff);
- }
- return true;
-}
-
-static bool
-copyin_binary_binary(Ctx& ctx, char* value, unsigned n, const char* ptr, const SQLINTEGER* ind, int* off, SqlChar* addr, int fieldId)
-{
- if (off != 0 && *off >= 0) {
- if ((unsigned)*off > n) {
- ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d truncated (%u > %u)", fieldId, (unsigned)*off, n);
- return false;
- }
- value += *off;
- n -= *off;
- }
- if (ind == 0) {
- ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d missing length", fieldId);
- return false;
- }
- if (*ind < 0) {
- ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d invalid length %d", fieldId, (int)*ind);
- return false;
- }
- unsigned m;
- m = *ind;
- if (m > n) {
- ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d truncated (%u > %u)", fieldId, m, n);
- return false;
- }
- for (unsigned i = 0; i < m; i++)
- value[i] = ptr[i];
- if (off != 0 && *off >= 0)
- *off += m;
- for (unsigned i = m; i < n; i++)
- value[i] = addr == 0 ? 0x0 : 0x0; // just null
- if (addr != 0) {
- if (off != 0 && *off >= 0)
- m = *off;
- addr[0] = (m >> 8) & 0xff;
- addr[1] = (m & 0xff);
- }
- return true;
-}
-
-static bool
-copyin_signed_char(Ctx& ctx, SqlBigint* value, const char* ptr, int fieldId)
-{
- errno = 0;
- char* endptr = 0;
- SqlBigint x = strtoll(ptr, &endptr, 10);
- if (endptr == 0 || *endptr != 0) {
- errno = 0;
- endptr = 0;
- double y = strtod(ptr, &endptr);
- if (endptr == 0 || *endptr != 0) {
- ctx.pushStatus(Sqlstate::_22005, Error::Gen, "input parameter %d value %s not numeric", fieldId, ptr);
- return false;
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "input parameter %d value %s overflow", fieldId, ptr);
- return false;
- }
- // XXX should handle 123.000
- ctx.pushStatus(Sqlstate::_01004, Error::Gen, "input parameter %d value %s truncated", fieldId, ptr);
- x = static_cast<SqlBigint>(y);
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "input parameter %d value %s overflow", fieldId, ptr);
- return false;
- }
- *value = x;
- return true;
-}
-
-static bool
-copyin_double_char(Ctx& ctx, SqlDouble* value, const char* ptr, int fieldId)
-{
- errno = 0;
- char* endptr = 0;
- double x = strtod(ptr, &endptr);
- if (endptr == 0 || *endptr != 0) {
- ctx.pushStatus(Sqlstate::_22005, Error::Gen, "input parameter %d value %s not numeric", fieldId, ptr);
- return false;
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "input parameter %d value %s overflow", fieldId, ptr);
- return false;
- }
- *value = x;
- return true;
-}
-
-void
-SqlField::copyin(Ctx& ctx, ExtField& extField)
-{
- ctx_assert(extField.extSpec().extType().type() != ExtType::Unbound);
- ctx_assert(sqlSpec().store() == SqlSpec::Physical);
- SQLINTEGER* indPtr = extField.m_indPtr;
- const int fieldId = extField.fieldId();
- if (indPtr != 0 && *indPtr == SQL_NULL_DATA) {
- sqlNull(true);
- return;
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- const ExtType& extType = extField.extSpec().extType();
- if (extField.m_pos > 0) {
- if (sqlType.type() == SqlType::Char && extType.type() == ExtType::Char)
- ;
- else if (sqlType.type() == SqlType::Varchar && extType.type() == ExtType::Char)
- ;
- else {
- char buf[40];
- sqlType.print(buf, sizeof(buf));
- ctx.pushStatus(Sqlstate::_HY019, Error::Gen, "cannot send %s data in pieces", buf);
- return;
- }
- }
- if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
- unsigned length = 0;
- char* value = 0;
- SqlChar* laddr = 0; // Varchar length address
- if (sqlType.type() == SqlType::Char) {
- length = sqlType.length();
- if (length > SqlField_CharSmall)
- value = reinterpret_cast<char *>(u_data.m_sqlChar);
- else
- value = reinterpret_cast<char *>(u_data.m_sqlCharSmall);
- laddr = 0;
- } else {
-#if NDB_VERSION_MAJOR >= 3
- length = sqlType.length();
- if (2 + length > SqlField_CharSmall)
- value = reinterpret_cast<char *>(u_data.m_sqlChar + 2);
- else
- value = reinterpret_cast<char *>(u_data.m_sqlCharSmall + 2);
- laddr = (SqlChar*)value - 2;
-#else
- length = sqlType.length();
- if (length + 2 > SqlField_CharSmall)
- value = reinterpret_cast<char *>(u_data.m_sqlChar);
- else
- value = reinterpret_cast<char *>(u_data.m_sqlCharSmall);
- laddr = (SqlChar*)value + length;
-#endif
- }
- if (extType.type() == ExtType::Char) {
- const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- int* off = 0;
- if (extField.m_pos >= 0)
- off = &extField.m_pos;
- if (! copyin_char_char(ctx, value, length, dataPtr, indPtr, off, laddr, fieldId))
- return;
- sqlNull(false);
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- const short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- char buf[100];
- sprintf(buf, "%hd", *dataPtr);
- if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
- return;
- sqlNull(false);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- const unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- char buf[100];
- sprintf(buf, "%hu", *dataPtr);
- if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
- return;
- sqlNull(false);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- const long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- char buf[100];
- sprintf(buf, "%ld", *dataPtr);
- if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
- return;
- sqlNull(false);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- const unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- char buf[100];
- sprintf(buf, "%lu", *dataPtr);
- if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
- return;
- sqlNull(false);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- const SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- char buf[100];
- sprintf(buf, FMT_I64, *dataPtr);
- if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
- return;
- sqlNull(false);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- const SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- char buf[100];
- sprintf(buf, FMT_U64, *dataPtr);
- if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
- return;
- sqlNull(false);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- const float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- char buf[100];
- sprintf(buf, "%.7f", (double)*dataPtr);
- if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
- return;
- sqlNull(false);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- const double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- char buf[100];
- sprintf(buf, "%.14f", *dataPtr);
- if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
- return;
- sqlNull(false);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
- unsigned length = 0;
- char* value = 0;
- SqlChar* laddr = 0; // Varbinary length address
- if (sqlType.type() == SqlType::Binary) {
- length = sqlType.length();
- if (length > SqlField_CharSmall)
- value = reinterpret_cast<char *>(u_data.m_sqlChar);
- else
- value = reinterpret_cast<char *>(u_data.m_sqlCharSmall);
- laddr = 0;
- } else {
-#if NDB_VERSION_MAJOR >= 3
- length = sqlType.length();
- if (2 + length > SqlField_CharSmall)
- value = reinterpret_cast<char *>(u_data.m_sqlChar + 2);
- else
- value = reinterpret_cast<char *>(u_data.m_sqlCharSmall + 2);
- laddr = (SqlChar*)value - 2;
-#else
- length = sqlType.length();
- if (length + 2 > SqlField_CharSmall)
- value = reinterpret_cast<char *>(u_data.m_sqlChar);
- else
- value = reinterpret_cast<char *>(u_data.m_sqlCharSmall);
- laddr = (SqlChar*)value + length;
-#endif
- }
- if (extType.type() == ExtType::Binary) {
- const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- int* off = 0;
- if (extField.m_pos >= 0)
- off = &extField.m_pos;
- if (! copyin_binary_binary(ctx, value, length, dataPtr, indPtr, off, laddr, fieldId))
- return;
- sqlNull(false);
- return;
- }
- }
- if (sqlType.type() == SqlType::Smallint) {
- SqlSmallint value;
- if (extType.type() == ExtType::Char) {
- const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- SqlBigint x;
- if (! copyin_signed_char(ctx, &x, dataPtr, fieldId))
- return;
- value = x;
- sqlSmallint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlSmallint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlSmallint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlSmallint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlSmallint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlSmallint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlSmallint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- value = (SqlSmallint)*dataPtr;
- sqlSmallint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- value = (SqlSmallint)*dataPtr;
- sqlSmallint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Integer) {
- SqlInteger value;
- if (extType.type() == ExtType::Char) {
- const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- SqlBigint x;
- if (! copyin_signed_char(ctx, &x, dataPtr, fieldId))
- return;
- value = x;
- sqlInteger(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlInteger(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlInteger(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlInteger(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlInteger(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlInteger(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlInteger(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- value = (SqlInteger)*dataPtr;
- sqlInteger(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- value = (SqlInteger)*dataPtr;
- sqlInteger(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Bigint) {
- SqlBigint value;
- if (extType.type() == ExtType::Char) {
- const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- SqlBigint x;
- if (! copyin_signed_char(ctx, &x, dataPtr, fieldId))
- return;
- value = x;
- sqlBigint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlBigint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlBigint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlBigint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlBigint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlBigint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlBigint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- value = (SqlBigint)*dataPtr;
- sqlBigint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- value = (SqlBigint)*dataPtr;
- sqlBigint(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Real) {
- SqlReal value;
- if (extType.type() == ExtType::Char) {
- const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- SqlDouble x;
- if (! copyin_double_char(ctx, &x, dataPtr, fieldId))
- return;
- value = x;
- sqlReal(x);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlReal(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlReal(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlReal(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlReal(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlReal(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlReal(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlReal(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlReal(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Double) {
- SqlDouble value;
- if (extType.type() == ExtType::Char) {
- const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- SqlDouble x;
- if (! copyin_double_char(ctx, &x, dataPtr, fieldId))
- return;
- value = x;
- sqlDouble(x);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlDouble(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlDouble(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlDouble(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlDouble(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlDouble(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlDouble(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlDouble(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- value = *dataPtr;
- sqlDouble(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Datetime) {
- SqlDatetime value;
- if (extType.type() == ExtType::Char) {
- // XXX replace sscanf by manual scan or regex
- const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- int cc = 0;
- unsigned yy = 0, mm = 0, dd = 0, HH = 0, MM = 0, SS = 0, ff = 0;
- bool setdate = false;
- char dummy[10];
- if (sscanf(dataPtr, "%2d%2u-%2u-%2u %2u:%2u:%2u.%4u%1s", &cc, &yy, &mm, &dd, &HH, &MM, &SS, &ff, dummy) == 8) {
- ;
- } else if (sscanf(dataPtr, "%2d%2u-%2u-%2u %2u:%2u:%2u%1s", &cc, &yy, &mm, &dd, &HH, &MM, &SS, dummy) == 7) {
- ;
- } else if (sscanf(dataPtr, "%2d%2u-%2u-%2u%1s", &cc, &yy, &mm, &dd, dummy) == 4) {
- ;
- } else if (sscanf(dataPtr, "%2u:%2u:%2u.%4u%1s", &HH, &MM, &SS, &ff, dummy) == 4) {
- setdate = true;
- } else if (sscanf(dataPtr, "%2u:%2u:%2u%1s", &HH, &MM, &SS, dummy) == 3) {
- setdate = true;
- } else {
- ctx.pushStatus(Sqlstate::_22008, Error::Gen, "invalid timestamp format '%s'", dataPtr);
- return;
- }
- if (setdate) {
- time_t clock = time(0);
- struct tm* t = localtime(&clock);
- cc = (1900 + t->tm_year) / 100;
- yy = (1900 + t->tm_year) % 100;
- mm = 1 + t->tm_mon;
- dd = t->tm_mday;
- }
- value.cc(cc);
- value.yy(yy);
- value.mm(mm);
- value.dd(dd);
- value.HH(HH);
- value.MM(MM);
- value.SS(SS);
- value.ff(ff);
- // XXX write date routines later
- if (! value.valid()) {
- ctx.pushStatus(Sqlstate::_22008, Error::Gen, "invalid timestamp values '%s'", dataPtr);
- return;
- }
- sqlDatetime(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Timestamp) {
- SQL_TIMESTAMP_STRUCT* dataPtr = static_cast<SQL_TIMESTAMP_STRUCT*>(extField.m_dataPtr);
- // XXX assume same datatype
- value.cc(dataPtr->year / 100);
- value.yy(dataPtr->year / 100);
- value.mm(dataPtr->month);
- value.dd(dataPtr->day);
- value.HH(dataPtr->hour);
- value.MM(dataPtr->minute);
- value.SS(dataPtr->second);
- value.ff(dataPtr->fraction);
- if (! value.valid()) {
- ctx.pushStatus(Sqlstate::_22008, Error::Gen, "invalid timestamp struct");
- return;
- }
- sqlDatetime(value);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- ctx_assert(false); // SqlType::Null not applicable
-}
-
-// copy to external
-
-static bool
-copyout_char_char(Ctx& ctx, const char* value, unsigned n, char* ptr, unsigned len, SQLINTEGER* ind, int* off)
-{
- unsigned n2 = n;
- if (off != 0 && *off >= 0) {
- ctx_assert((unsigned)*off <= n2);
- value += *off;
- n2 -= *off;
- if (len < n2 + 1) {
- ctx.pushStatus(Sqlstate::_01004, Error::Gen, "more data at offset %d, current fetch %u, available %u", *off, len, n2);
- n2 = len - 1;
- }
- } else {
- if (len < n + 1) { // room for null byte
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "char value '%.*s' overflow (%u < %u)", (int)n, value, (unsigned)len, (unsigned)(len + 1));
- return false;
- }
- }
- memcpy(ptr, value, n2);
- ptr[n2] = 0;
- if (off != 0 && *off >= 0) {
- if (ind != 0)
- *ind = n - *off;
- *off += n2;
- } else {
- if (ind != 0)
- *ind = n;
- }
- return true;
-}
-
-static bool
-copyout_binary_binary(Ctx& ctx, const char* value, unsigned n, char* ptr, unsigned len, SQLINTEGER* ind, int* off)
-{
- unsigned n2 = n;
- if (off != 0 && *off >= 0) {
- ctx_assert((unsigned)*off <= n2);
- value += *off;
- n2 -= *off;
- if (len < n2 + 1) {
- ctx.pushStatus(Sqlstate::_01004, Error::Gen, "more data at offset %d, current fetch %u, available %u", *off, len, n2);
- n2 = len - 1;
- }
- } else {
- if (len < n) { // no room for null byte
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "binary value '%.*s' overflow (%u < %u)", (int)n, value, (unsigned)len, (unsigned)n);
- return false;
- }
- }
- memcpy(ptr, value, n2);
- ptr[n2] = 0;
- if (off != 0 && *off >= 0) {
- if (ind != 0)
- *ind = n - *off;
- *off += n2;
- } else {
- if (ind != 0)
- *ind = n;
- }
- return true;
-}
-
-static bool
-copyout_char_signed(Ctx& ctx, const char* value, unsigned n, long* ptr)
-{
- while (n > 0 && value[0] == 0x20) {
- value++;
- n--;
- }
- char buf[200];
- if (n >= 200)
- n = 200 - 1;
- memcpy(buf, value, n);
- buf[n] = 0;
- errno = 0;
- char* endptr = 0;
- long x = strtol(buf, &endptr, 10);
- if (endptr == 0 || *endptr != 0) {
- errno = 0;
- endptr = 0;
- double y = strtod(buf, &endptr);
- if (endptr == 0 || *endptr != 0) {
- ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", buf);
- return false;
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- // XXX should handle 123.000
- ctx.pushStatus(Sqlstate::_01004, Error::Gen, "value %s truncated", buf);
- x = static_cast<long>(y);
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- *ptr = x;
- return true;
-}
-
-static bool
-copyout_char_bigsigned(Ctx& ctx, const char* value, unsigned n, SQLBIGINT* ptr)
-{
- while (n > 0 && value[0] == 0x20) {
- value++;
- n--;
- }
- char buf[200];
- if (n >= 200)
- n = 200 - 1;
- memcpy(buf, value, n);
- buf[n] = 0;
- errno = 0;
- char* endptr = 0;
- SQLBIGINT x = strtoll(buf, &endptr, 10);
- if (endptr == 0 || *endptr != 0) {
- errno = 0;
- endptr = 0;
- double y = strtod(buf, &endptr);
- if (endptr == 0 || *endptr != 0) {
- ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", buf);
- return false;
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- // XXX should handle 123.000
- ctx.pushStatus(Sqlstate::_01004, Error::Gen, "value %s truncated", buf);
- x = static_cast<long>(y);
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- *ptr = x;
- return true;
-}
-
-static bool
-copyout_char_unsigned(Ctx& ctx, const char* value, unsigned n, unsigned long* ptr)
-{
- while (n > 0 && value[0] == 0x20) {
- value++;
- n--;
- }
- char buf[200];
- if (n >= 200)
- n = 200 - 1;
- memcpy(buf, value, n);
- buf[n] = 0;
- errno = 0;
- char* endptr = 0;
- unsigned long x = strtoul(buf, &endptr, 10);
- if (endptr == 0 || *endptr != 0) {
- errno = 0;
- endptr = 0;
- double y = strtod(buf, &endptr);
- if (endptr == 0 || *endptr != 0) {
- ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", buf);
- return false;
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- // XXX should handle 123.000
- ctx.pushStatus(Sqlstate::_01004, Error::Gen, "value %s truncated", buf);
- x = static_cast<unsigned long>(y);
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- *ptr = x;
- return true;
-}
-
-static bool
-copyout_char_bigunsigned(Ctx& ctx, const char* value, unsigned n, SQLUBIGINT* ptr)
-{
- while (n > 0 && value[0] == 0x20) {
- value++;
- n--;
- }
- char buf[200];
- if (n >= 200)
- n = 200 - 1;
- memcpy(buf, value, n);
- buf[n] = 0;
- errno = 0;
- char* endptr = 0;
- SQLUBIGINT x = strtoull(buf, &endptr, 10);
- if (endptr == 0 || *endptr != 0) {
- errno = 0;
- endptr = 0;
- double y = strtod(buf, &endptr);
- if (endptr == 0 || *endptr != 0) {
- ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", buf);
- return false;
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- // XXX should handle 123.000
- ctx.pushStatus(Sqlstate::_01004, Error::Gen, "value %s truncated", buf);
- x = static_cast<unsigned long>(y);
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- *ptr = x;
- return true;
-}
-
-static bool
-copyout_char_double(Ctx& ctx, const char* value, unsigned n, double* ptr)
-{
- while (n > 0 && value[0] == 0x20) {
- value++;
- n--;
- }
- char buf[200];
- if (n >= 200)
- n = 200 - 1;
- memcpy(buf, value, n);
- buf[n] = 0;
- errno = 0;
- char* endptr = 0;
- double x = strtod(value, &endptr);
- if (endptr == 0 || *endptr != 0) {
- ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", value);
- return false;
- } else if (errno != 0) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", value);
- return false;
- }
- *ptr = x;
- return true;
-}
-
-static bool
-copyout_signed_char(Ctx& ctx, Int64 value, char* ptr, int len, SQLINTEGER* ind)
-{
- char buf[100];
- sprintf(buf, FMT_I64, value);
- unsigned n = strlen(buf);
- if (len <= 0) {
- ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", len);
- return false;
- }
- if ((unsigned)len < n + 1) { // room for null byte
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- strcpy(ptr, buf);
- if (ind != 0)
- *ind = n;
- return true;
-}
-
-static bool
-copyout_unsigned_char(Ctx& ctx, Uint64 uvalue, char* ptr, int len, SQLINTEGER* ind)
-{
- char buf[100];
- sprintf(buf, FMT_U64, uvalue);
- unsigned n = strlen(buf);
- if (len <= 0) {
- ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", len);
- return false;
- }
- if ((unsigned)len < n + 1) { // room for null byte
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- strcpy(ptr, buf);
- if (ind != 0)
- *ind = n;
- return true;
-}
-
-static bool
-copyout_double_char(Ctx& ctx, double value, unsigned prec, char* ptr, int len, SQLINTEGER* ind)
-{
- char buf[100];
- sprintf(buf, "%.*f", (int)prec, value);
- char* p = buf + strlen(buf);
- while (p > buf + prec)
- *--p = 0;
- while (p > buf && *(p - 1) == '0')
- *--p = 0;
- if (p > buf && *(p - 1) == '.') {
- *p++ = '0';
- *p = 0;
- }
- unsigned n = strlen(buf);
- if (len <= 0) {
- ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", len);
- return false;
- }
- if ((unsigned)len < n + 1) { // room for null byte
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
- return false;
- }
- strcpy(ptr, buf);
- if (ind != 0)
- *ind = n;
- return true;
-}
-
-void
-SqlField::copyout(Ctx& ctx, ExtField& extField) const
-{
- if (extField.extSpec().extType().type() == ExtType::Unbound) {
- return; // output buffer may be unbound
- }
- if (sqlSpec().store() == SqlSpec::Reference) {
- ctx_assert(u_data.m_sqlField != 0);
- u_data.m_sqlField->copyout(ctx, extField);
- return;
- }
- SQLINTEGER* indPtr = extField.m_indPtr;
- if (u_null.m_nullFlag) {
- if (extField.m_pos > 0) { // second time from SQLGetData
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- if (indPtr == 0) {
- ctx.pushStatus(Sqlstate::_22002, Error::Gen, "indicator variable required");
- return;
- }
- *indPtr = SQL_NULL_DATA;
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- const SqlType& sqlType = sqlSpec().sqlType();
- const ExtType& extType = extField.extSpec().extType();
- if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
- unsigned n = 0;
- const char* value = 0;
- if (sqlType.type() == SqlType::Char) {
- n = sqlType.length();
- value = reinterpret_cast<const char*>(sqlChar());
- } else {
- value = reinterpret_cast<const char*>(sqlVarchar(&n));
- }
- if (extType.type() == ExtType::Char) {
- char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- if (extField.m_dataLen <= 0) {
- ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", (int)extField.m_dataLen);
- return;
- }
- int* off = 0;
- if (extField.m_pos >= 0) {
- off = &extField.m_pos;
- if ((unsigned)*off >= n) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- }
- if (! copyout_char_char(ctx, value, n, dataPtr, extField.m_dataLen, indPtr, off))
- return;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- long x;
- if (! copyout_char_signed(ctx, value, n, &x))
- return;
- if (x < SHRT_MIN || x > SHRT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", value);
- return;
- }
- *dataPtr = static_cast<short>(x);
- if (indPtr != 0)
- *indPtr = sizeof(short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- unsigned long x;
- if (! copyout_char_unsigned(ctx, value, n, &x))
- return;
- if (x > USHRT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", value);
- return;
- }
- *dataPtr = static_cast<unsigned short>(x);
- if (indPtr != 0)
- *indPtr = sizeof(unsigned short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- if (! copyout_char_signed(ctx, value, n, dataPtr))
- return;
- if (indPtr != 0)
- *indPtr = sizeof(long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- if (! copyout_char_unsigned(ctx, value, n, dataPtr))
- return;
- if (indPtr != 0)
- *indPtr = sizeof(unsigned long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- if (! copyout_char_bigsigned(ctx, value, n, dataPtr))
- return;
- if (indPtr != 0)
- *indPtr = sizeof(SQLBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- if (! copyout_char_bigunsigned(ctx, value, n, dataPtr))
- return;
- if (indPtr != 0)
- *indPtr = sizeof(SQLUBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- double x;
- if (! copyout_char_double(ctx, value, n, &x))
- return;
- if (fabs(x) < FLT_MIN || fabs(x) > FLT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", value);
- return;
- }
- *dataPtr = static_cast<float>(x);
- if (indPtr != 0)
- *indPtr = sizeof(float);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- double x;
- if (! copyout_char_double(ctx, value, n, &x))
- return;
- *dataPtr = static_cast<double>(x);
- if (indPtr != 0)
- *indPtr = sizeof(double);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
- unsigned n = 0;
- const char* value = 0;
- if (sqlType.type() == SqlType::Binary) {
- n = sqlType.length();
- value = reinterpret_cast<const char*>(sqlBinary());
- } else {
- value = reinterpret_cast<const char*>(sqlVarbinary(&n));
- }
- if (extType.type() == ExtType::Binary) {
- char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- if (extField.m_dataLen <= 0) {
- ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", (int)extField.m_dataLen);
- return;
- }
- int* off = 0;
- if (extField.m_pos >= 0) {
- off = &extField.m_pos;
- if ((unsigned)*off >= n) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- }
- if (! copyout_binary_binary(ctx, value, n, dataPtr, extField.m_dataLen, indPtr, off))
- return;
- return;
- }
- }
- if (sqlType.type() == SqlType::Smallint) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- const SqlSmallint value = sqlSmallint();
- const SqlUsmallint uvalue = value;
- if (extType.type() == ExtType::Char) {
- char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- if (! sqlType.unSigned()) {
- if (! copyout_signed_char(ctx, value, dataPtr, extField.m_dataLen, indPtr))
- return;
- } else {
- if (! copyout_unsigned_char(ctx, uvalue, dataPtr, extField.m_dataLen, indPtr))
- return;
- }
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- *dataPtr = static_cast<short>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- *dataPtr = static_cast<unsigned short>(uvalue);
- if (indPtr != 0)
- *indPtr = sizeof(unsigned short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- *dataPtr = static_cast<long>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- *dataPtr = static_cast<unsigned long>(uvalue);
- if (indPtr != 0)
- *indPtr = sizeof(unsigned long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLBIGINT>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(SQLBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLUBIGINT>(uvalue);
- if (indPtr != 0)
- *indPtr = sizeof(SQLUBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- *dataPtr = static_cast<float>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(float);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- *dataPtr = static_cast<double>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(double);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Integer) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- const SqlInteger value = sqlInteger();
- const SqlUinteger uvalue = value;
- if (extType.type() == ExtType::Char) {
- char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- if (! sqlType.unSigned()) {
- if (! copyout_signed_char(ctx, value, dataPtr, extField.m_dataLen, indPtr))
- return;
- } else {
- if (! copyout_unsigned_char(ctx, uvalue, dataPtr, extField.m_dataLen, indPtr))
- return;
- }
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- if (value < SHRT_MIN || value > SHRT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %d overflow", (int)value);
- return;
- }
- *dataPtr = static_cast<short>(value);
- if (indPtr != 0)
- *indPtr = sizeof(short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- if (uvalue > USHRT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %u overflow", uvalue);
- return;
- }
- *dataPtr = static_cast<unsigned short>(value);
- if (indPtr != 0)
- *indPtr = sizeof(unsigned short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- *dataPtr = static_cast<long>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- *dataPtr = static_cast<unsigned long>(uvalue);
- if (indPtr != 0)
- *indPtr = sizeof(unsigned long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLBIGINT>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(SQLBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLUBIGINT>(uvalue);
- if (indPtr != 0)
- *indPtr = sizeof(SQLUBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- *dataPtr = static_cast<float>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(float);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- *dataPtr = static_cast<double>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(double);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Bigint) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- const SqlBigint value = sqlBigint();
- const SqlUbigint uvalue = value;
- if (extType.type() == ExtType::Char) {
- char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- if (! sqlType.unSigned()) {
- if (! copyout_signed_char(ctx, value, dataPtr, extField.m_dataLen, indPtr))
- return;
- } else {
- if (! copyout_unsigned_char(ctx, uvalue, dataPtr, extField.m_dataLen, indPtr))
- return;
- }
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- if (value < SHRT_MIN || value > SHRT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value " FMT_I64 " overflow", (Int64)value);
- return;
- }
- *dataPtr = static_cast<short>(value);
- if (indPtr != 0)
- *indPtr = sizeof(short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- if (uvalue > USHRT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value " FMT_U64 " overflow", (Uint64)uvalue);
- return;
- }
- *dataPtr = static_cast<short>(value);
- if (indPtr != 0)
- *indPtr = sizeof(unsigned short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- if (value < INT_MIN || value > INT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value " FMT_I64 " overflow", (Int64)value);
- return;
- }
- *dataPtr = static_cast<long>(value);
- if (indPtr != 0)
- *indPtr = sizeof(long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- if (uvalue > UINT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value " FMT_U64 " overflow", (Uint64)uvalue);
- return;
- }
- *dataPtr = static_cast<unsigned long>(uvalue);
- if (indPtr != 0)
- *indPtr = sizeof(unsigned long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLBIGINT>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(SQLBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLUBIGINT>(uvalue);
- if (indPtr != 0)
- *indPtr = sizeof(SQLUBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- *dataPtr = static_cast<float>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(float);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- *dataPtr = static_cast<double>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(double);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Real) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- const SqlReal value = sqlReal();
- if (extType.type() == ExtType::Char) {
- char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- if (! copyout_double_char(ctx, value, 7, dataPtr, extField.m_dataLen, indPtr))
- return;
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- *dataPtr = static_cast<short>(value); // XXX todo
- if (indPtr != 0)
- *indPtr = sizeof(short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- if (value < 0 || value > USHRT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %g overflow", (double)value);
- return;
- }
- *dataPtr = static_cast<short>(value);
- if (indPtr != 0)
- *indPtr = sizeof(unsigned short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- *dataPtr = static_cast<long>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- *dataPtr = static_cast<unsigned long>(value); // XXX todo
- if (indPtr != 0)
- *indPtr = sizeof(unsigned long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLBIGINT>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(SQLBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLUBIGINT>(value);
- if (indPtr != 0)
- *indPtr = sizeof(SQLUBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- *dataPtr = static_cast<float>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(float);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- *dataPtr = static_cast<double>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(double);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Double) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- SqlDouble value = sqlDouble();
- if (extType.type() == ExtType::Char) {
- char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- if (! copyout_double_char(ctx, value, 14, dataPtr, extField.m_dataLen, indPtr))
- return;
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
- short* dataPtr = static_cast<short*>(extField.m_dataPtr);
- *dataPtr = static_cast<short>(value); // XXX todo
- if (indPtr != 0)
- *indPtr = sizeof(short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ushort) {
- unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
- if (value < 0 || value > USHRT_MAX) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %g overflow", (double)value);
- return;
- }
- *dataPtr = static_cast<short>(value);
- if (indPtr != 0)
- *indPtr = sizeof(unsigned short);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
- long* dataPtr = static_cast<long*>(extField.m_dataPtr);
- *dataPtr = static_cast<long>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ulong) {
- unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
- *dataPtr = static_cast<unsigned long>(value); // XXX todo
- if (indPtr != 0)
- *indPtr = sizeof(unsigned long);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Sbigint) {
- SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLBIGINT>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(SQLBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Ubigint) {
- SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
- *dataPtr = static_cast<SQLUBIGINT>(value);
- if (indPtr != 0)
- *indPtr = sizeof(SQLUBIGINT);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Float) {
- float* dataPtr = static_cast<float*>(extField.m_dataPtr);
- *dataPtr = static_cast<float>(value); // big enough
- if (indPtr != 0)
- *indPtr = sizeof(float);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Double) {
- double* dataPtr = static_cast<double*>(extField.m_dataPtr);
- *dataPtr = static_cast<double>(value);
- if (indPtr != 0)
- *indPtr = sizeof(double);
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- }
- if (sqlType.type() == SqlType::Datetime) {
- if (extField.m_pos > 0) {
- ctx.setCode(SQL_NO_DATA);
- return;
- }
- SqlDatetime value = sqlDatetime();
- if (extType.type() == ExtType::Char) {
- char* dataPtr = static_cast<char*>(extField.m_dataPtr);
- char buf[100];
- sprintf(buf, "%02d%02u-%02u-%02u\040%02u:%02u:%02u.%09u", value.cc(), value.yy(), value.mm(), value.dd(), value.HH(), value.MM(), value.SS(), value.ff());
- int n = strlen(buf);
- if (extField.m_dataLen < 20) {
- ctx.pushStatus(Sqlstate::_22003, Error::Gen, "buffer too small for timestamp %s", buf);
- return;
- }
- if (extField.m_dataLen < n) {
- ctx.pushStatus(Sqlstate::_01004, Error::Gen, "truncating fractional part of timestamp %s", buf);
- n = extField.m_dataLen;
- }
- if (! copyout_char_char(ctx, buf, n, dataPtr, extField.m_dataLen, indPtr, 0))
- return;
- if (extField.m_pos >= 0)
- extField.m_pos = 1;
- return;
- }
- if (extType.type() == ExtType::Timestamp) {
- SQL_TIMESTAMP_STRUCT* dataPtr = static_cast<SQL_TIMESTAMP_STRUCT*>(extField.m_dataPtr);
- // XXX assume same datatype
- dataPtr->year = value.cc() * 100 + value.yy();
- dataPtr->month = value.mm();
- dataPtr->day = value.dd();
- dataPtr->hour = value.HH();
- dataPtr->minute = value.MM();
- dataPtr->second = value.SS();
- dataPtr->fraction = value.ff();
- return;
- }
- }
- ctx_assert(false); // SqlType::Null not applicable
-}
-
-void
-SqlField::print(char* buf, unsigned size) const
-{
- Ctx ctx;
- unsigned n = sqlSpec().sqlType().displaySize();
- SQLINTEGER ind = 0;
- ExtType extType(ExtType::Char);
- ExtSpec extSpec(extType);
- ExtField extField(extSpec, (SQLPOINTER)buf, size, &ind);
- buf[0] = 0;
- copyout(ctx, extField);
- if (ind == SQL_NULL_DATA)
- snprintf(buf, size, "NULL");
-}
diff --git a/ndb/src/client/odbc/common/DataType.cpp b/ndb/src/client/odbc/common/DataType.cpp
deleted file mode 100644
index 9c9629f1d24..00000000000
--- a/ndb/src/client/odbc/common/DataType.cpp
+++ /dev/null
@@ -1,545 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "DataType.hpp"
-
-// SqlType
-
-SqlType::SqlType() :
- m_type(Undef)
-{
-}
-
-SqlType::SqlType(Type type, bool nullable)
-{
- Ctx ctx;
- setType(ctx, type, nullable);
- ctx_assert(ctx.ok());
-}
-
-SqlType::SqlType(Type type, unsigned length, bool nullable)
-{
- Ctx ctx;
- setType(ctx, type, length, nullable);
- ctx_assert(ctx.ok());
-}
-
-SqlType::SqlType(Type type, unsigned precision, unsigned scale, bool nullable)
-{
- Ctx ctx;
- setType(ctx, type, precision, scale, nullable);
- ctx_assert(ctx.ok());
-}
-
-SqlType::SqlType(Ctx& ctx, Type type, bool nullable)
-{
- setType(ctx, type, nullable);
-}
-
-SqlType::SqlType(Ctx& ctx, Type type, unsigned length, bool nullable)
-{
- setType(ctx, type, length, nullable);
-}
-
-SqlType::SqlType(Ctx& ctx, Type type, unsigned precision, unsigned scale, bool nullable)
-{
- setType(ctx, type, precision, scale, nullable);
-}
-
-SqlType::SqlType(Ctx& ctx, const NdbDictionary::Column* ndbColumn)
-{
- setType(ctx, ndbColumn);
-}
-
-void
-SqlType::setType(Ctx& ctx, Type type, bool nullable)
-{
- switch (type) {
- case Smallint:
- case Integer:
- case Bigint:
- case Real:
- case Double:
- case Datetime:
- break;
- case Blob:
- setType(ctx, Varbinary, FAKE_BLOB_SIZE, nullable); // XXX BLOB hack
- return;
- case Null:
- case Unbound:
- break;
- default:
- ctx_assert(false);
- break;
- }
- m_type = type;
- m_precision = 0;
- m_scale = 0;
- m_length = 0;
- m_nullable = nullable;
- m_unSigned = false;
-}
-
-void
-SqlType::setType(Ctx& ctx, Type type, unsigned length, bool nullable)
-{
- switch (type) {
- case Char:
- case Varchar:
- case Binary:
- case Varbinary:
- break;
- default:
- ctx_assert(false);
- break;
- }
- m_type = type;
- m_precision = 0;
- m_scale = 0;
- m_length = length;
- m_nullable = nullable;
- m_unSigned = false;
-}
-
-void
-SqlType::setType(Ctx& ctx, Type type, unsigned precision, unsigned scale, bool nullable)
-{
- ctx_assert(false); // not yet
-}
-
-void
-SqlType::setType(Ctx& ctx, const NdbDictionary::Column* ndbColumn)
-{
- NdbDictionary::Column::Type type = ndbColumn->getType();
- unsigned length = ndbColumn->getLength();
- unsigned precision = ndbColumn->getPrecision();
- unsigned scale = ndbColumn->getScale();
- bool nullable = ndbColumn->getNullable();
- switch (type) {
- case NdbDictionary::Column::Undefined:
- break;
- case NdbDictionary::Column::Int:
- if (length == 1)
- setType(ctx, Integer, nullable);
- else
- setType(ctx, Binary, length * sizeof(SqlInteger), nullable);
- return;
- case NdbDictionary::Column::Unsigned:
- if (length == 1) {
- setType(ctx, Integer, nullable);
- unSigned(true);
- } else
- setType(ctx, Binary, length * sizeof(SqlUinteger), nullable);
- return;
- case NdbDictionary::Column::Bigint:
- if (length == 1)
- setType(ctx, Bigint, nullable);
- else
- setType(ctx, Binary, length * sizeof(SqlBigint), nullable);
- return;
- case NdbDictionary::Column::Bigunsigned:
- if (length == 1) {
- setType(ctx, Bigint, nullable);
- unSigned(true);
- } else
- setType(ctx, Binary, length * sizeof(SqlBigint), nullable);
- return;
- case NdbDictionary::Column::Float:
- if (length == 1)
- setType(ctx, Real, nullable);
- else
- setType(ctx, Binary, length * sizeof(SqlReal), nullable);
- return;
- case NdbDictionary::Column::Double:
- if (length == 1)
- setType(ctx, Double, nullable);
- else
- setType(ctx, Binary, length * sizeof(SqlDouble), nullable);
- return;
- case NdbDictionary::Column::Decimal:
- setType(ctx, Decimal, precision, scale, nullable);
- return;
- case NdbDictionary::Column::Char:
- setType(ctx, Char, length, nullable);
- return;
- case NdbDictionary::Column::Varchar:
- setType(ctx, Varchar, length, nullable);
- return;
- case NdbDictionary::Column::Binary:
- setType(ctx, Binary, length, nullable);
- return;
- case NdbDictionary::Column::Varbinary:
- setType(ctx, Varbinary, length, nullable);
- return;
- case NdbDictionary::Column::Datetime:
- // XXX not yet
- break;
- case NdbDictionary::Column::Timespec:
- setType(ctx, Datetime, nullable);
- return;
- case NdbDictionary::Column::Blob:
- setType(ctx, Blob, nullable);
- return;
- default:
- break;
- }
- ctx.pushStatus(Error::Gen, "unsupported NDB type %d", (signed)type);
-}
-
-bool
-SqlType::equal(const SqlType& sqlType) const
-{
- return
- m_type == sqlType.m_type &&
- m_precision == sqlType.m_precision &&
- m_scale == sqlType.m_scale &&
- m_length == sqlType.m_length;
-}
-
-unsigned
-SqlType::size() const
-{
- switch (m_type) {
- case Char:
- case Varchar:
- case Binary:
- case Varbinary:
- return m_length;
- case Smallint:
- return sizeof(SqlSmallint);
- case Integer:
- return sizeof(SqlInteger);
- case Bigint:
- return sizeof(SqlBigint);
- case Real:
- return sizeof(SqlReal);
- case Double:
- return sizeof(SqlDouble);
- case Datetime:
- return sizeof(SqlDatetime);
- case Null:
- return 0;
- default:
- break;
- }
- ctx_assert(false);
- return 0;
-}
-
-unsigned
-SqlType::displaySize() const
-{
- switch (m_type) {
- case Char:
- case Varchar:
- return m_length;
- case Binary:
- case Varbinary:
- return m_length;
- case Smallint:
- return m_unSigned ? 5 : 6;
- case Integer:
- return m_unSigned ? 10 : 11;
- case Bigint:
- return m_unSigned ? 20 : 21;
- case Real:
- return 10;
- case Double:
- return 20;
- case Datetime:
- return 30;
- case Null:
- return 0;
- default:
- break;
- }
- ctx_assert(false);
- return 0;
-}
-
-void
-SqlType::getType(Ctx& ctx, NdbDictionary::Column* ndbColumn) const
-{
- switch (m_type) {
- case Char:
- ndbColumn->setType(NdbDictionary::Column::Char);
- ndbColumn->setLength(m_length);
- break;
- case Varchar:
- ndbColumn->setType(NdbDictionary::Column::Varchar);
- ndbColumn->setLength(m_length);
- break;
- case Binary:
- ndbColumn->setType(NdbDictionary::Column::Binary);
- ndbColumn->setLength(m_length);
- break;
- case Varbinary:
- ndbColumn->setType(NdbDictionary::Column::Varbinary);
- ndbColumn->setLength(m_length);
- break;
- case Smallint:
- break; // XXX
- case Integer:
- if (! m_unSigned)
- ndbColumn->setType(NdbDictionary::Column::Int);
- else
- ndbColumn->setType(NdbDictionary::Column::Unsigned);
- ndbColumn->setLength(1);
- break;
- case Bigint:
- if (! m_unSigned)
- ndbColumn->setType(NdbDictionary::Column::Bigint);
- else
- ndbColumn->setType(NdbDictionary::Column::Bigunsigned);
- ndbColumn->setLength(1);
- break;
- case Real:
- ndbColumn->setType(NdbDictionary::Column::Float);
- ndbColumn->setLength(1);
- break;
- case Double:
- ndbColumn->setType(NdbDictionary::Column::Double);
- ndbColumn->setLength(1);
- break;
- case Datetime:
- ndbColumn->setType(NdbDictionary::Column::Timespec);
- ndbColumn->setLength(1);
- break;
- default:
- ctx_assert(false);
- break;
- }
- ndbColumn->setNullable(m_nullable);
-}
-
-const char*
-SqlType::typeName() const
-{
- switch (m_type) {
- case Char:
- return "CHAR";
- case Varchar:
- return "VARCHAR";
- case Binary:
- return "BINARY";
- case Varbinary:
- return "VARBINARY";
- case Smallint:
- return "SMALLINT";
- case Integer:
- return "INTEGER";
- case Bigint:
- return "BIGINT";
- case Real:
- return "REAL";
- case Double:
- return "FLOAT";
- case Datetime:
- return "DATETIME";
- default:
- break;
- }
- return "UNKNOWN";
-}
-
-void
-SqlType::print(char* buf, unsigned size) const
-{
- switch (m_type) {
- case Char:
- snprintf(buf, size, "char(%d)", m_length);
- break;
- case Varchar:
- snprintf(buf, size, "varchar(%d)", m_length);
- break;
- case Binary:
- snprintf(buf, size, "binary(%d)", m_length);
- break;
- case Varbinary:
- snprintf(buf, size, "varbinary(%d)", m_length);
- break;
- case Smallint:
- snprintf(buf, size, "smallint%s", m_unSigned ? " unsigned" : "");
- break;
- case Integer:
- snprintf(buf, size, "integer%s", m_unSigned ? " unsigned" : "");
- break;
- case Bigint:
- snprintf(buf, size, "bigint%s", m_unSigned ? " unsigned" : "");
- break;
- case Real:
- snprintf(buf, size, "real");
- break;
- case Double:
- snprintf(buf, size, "double");
- break;
- case Datetime:
- snprintf(buf, size, "datetime");
- break;
- case Null:
- snprintf(buf, size, "null");
- break;
- case Unbound:
- snprintf(buf, size, "unbound");
- break;
- default:
- snprintf(buf, size, "sqltype(%d)", (int)m_type);
- break;
- }
-}
-
-// ExtType
-
-ExtType::ExtType() :
- m_type(Undef)
-{
-}
-
-ExtType::ExtType(Type type)
-{
- Ctx ctx;
- setType(ctx, type);
- ctx_assert(ctx.ok());
-}
-
-ExtType::ExtType(Ctx& ctx, Type type)
-{
- setType(ctx, type);
-}
-
-void
-ExtType::setType(Ctx& ctx, Type type)
-{
- switch (type) {
- case Char:
- case Short:
- case Sshort:
- case Ushort:
- case Long:
- case Slong:
- case Ulong:
- case Sbigint:
- case Ubigint:
- case Float:
- case Double:
- case Timestamp:
- case Binary: // XXX BLOB hack
- case Unbound:
- break;
- default:
- ctx.pushStatus(Error::Gen, "unsupported external type %d", (int)type);
- return;
- }
- m_type = type;
-}
-
-unsigned
-ExtType::size() const
-{
- ctx_assert(false);
- return 0;
-}
-
-// LexType
-
-LexType::LexType() :
- m_type(Undef)
-{
-}
-
-LexType::LexType(Type type)
-{
- Ctx ctx;
- setType(ctx, type);
- ctx_assert(ctx.ok());
-}
-
-LexType::LexType(Ctx& ctx, Type type)
-{
- setType(ctx, type);
-}
-
-void
-LexType::setType(Ctx& ctx, Type type)
-{
- switch (type) {
- case Char:
- case Integer:
- case Float:
- case Null:
- break;
- default:
- ctx_assert(false);
- break;
- }
- m_type = type;
-}
-
-// convert types
-
-SQLSMALLINT
-SqlType::sqlcdefault(Ctx& ctx) const
-{
- switch (m_type) {
- case Char:
- return SQL_C_CHAR;
- case Varchar:
- return SQL_C_CHAR;
- case Binary:
- return SQL_C_BINARY;
- case Varbinary:
- return SQL_C_BINARY;
- case Smallint:
- return m_unSigned ? SQL_C_USHORT : SQL_C_SSHORT;
- case Integer:
- return m_unSigned ? SQL_C_ULONG : SQL_C_SLONG;
- case Bigint:
- return SQL_C_CHAR;
- // or maybe this
- return m_unSigned ? SQL_C_UBIGINT : SQL_C_SBIGINT;
- case Real:
- return SQL_C_FLOAT;
- case Double:
- return SQL_C_DOUBLE;
- case Datetime:
- return SQL_C_TYPE_TIMESTAMP;
- default:
- break;
- }
- return SQL_C_DEFAULT; // no default
-}
-
-void
-LexType::convert(Ctx& ctx, SqlType& out, unsigned length) const
-{
- switch (m_type) {
- case Char:
- out.setType(ctx, SqlType::Char, length, true);
- return;
- case Integer:
- out.setType(ctx, SqlType::Bigint, false);
- return;
- case Float:
- out.setType(ctx, SqlType::Double, false);
- return;
- case Null:
- out.setType(ctx, SqlType::Null, true);
- return;
- default:
- break;
- }
- ctx.pushStatus(Error::Gen, "unsupported lexical to SQL type conversion");
-}
diff --git a/ndb/src/client/odbc/common/DataType.hpp b/ndb/src/client/odbc/common/DataType.hpp
deleted file mode 100644
index ac2ca337e22..00000000000
--- a/ndb/src/client/odbc/common/DataType.hpp
+++ /dev/null
@@ -1,292 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef ODBC_COMMON_DataType_hpp
-#define ODBC_COMMON_DataType_hpp
-
-#include <map>
-#include <ndb_types.h>
-#include <AttrType.hpp>
-#include <NdbDictionary.hpp>
-#include <common/common.hpp>
-
-/**
- * Sql data exists in several formats:
- *
- * - as NDB data at the bottom
- * - as SQL data during intermediary processing
- * - as external data in user input and output buffers
- * - as lexical constants in SQL statement text
- *
- * Each data format has specific types (e.g. number) and each
- * type has specific attributes (e.g. precision).
- */
-enum DataFormat {
- Undef_format = 0,
- Ndb_format = 1, // not used in NDB version >= v2.10
- Sql_format = 2,
- Ext_format = 3,
- Lex_format = 4
-};
-
-#define UndefDataType 990
-#define NullDataType 991
-#define UnboundDataType 992
-
-class SqlType;
-class ExtType;
-class LexType;
-
-/**
- * @class SqlType
- * @brief Sql data type
- */
-class SqlType {
-public:
- enum Type {
- Undef = UndefDataType,
- Char = SQL_CHAR,
- Varchar = SQL_VARCHAR,
- Longvarchar = SQL_LONGVARCHAR,
- Binary = SQL_BINARY,
- Varbinary = SQL_VARBINARY,
- Longvarbinary = SQL_LONGVARBINARY,
- Decimal = SQL_DECIMAL,
- Tinyint = SQL_TINYINT,
- Smallint = SQL_SMALLINT,
- Integer = SQL_INTEGER,
- Bigint = SQL_BIGINT,
- Real = SQL_REAL,
- Double = SQL_DOUBLE,
- Date = SQL_DATE,
- Datetime = SQL_TYPE_TIMESTAMP,
- Blob = SQL_BLOB,
- Null = NullDataType, // not an ODBC SQL type
- Unbound = UnboundDataType // special for placeholders
- };
- SqlType();
- SqlType(Type type, bool nullable = true);
- SqlType(Type type, unsigned length, bool nullable = true);
- SqlType(Type type, unsigned precision, unsigned scale, bool nullable = true);
- SqlType(Ctx& ctx, Type type, bool nullable = true);
- SqlType(Ctx& ctx, Type type, unsigned length, bool nullable = true);
- SqlType(Ctx& ctx, Type type, unsigned precision, unsigned scale, bool nullable = true);
- SqlType(Ctx& ctx, const NdbDictionary::Column* ndbColumn);
- Type type() const;
- void setType(Ctx& ctx, Type type, bool nullable = true);
- void setType(Ctx& ctx, Type type, unsigned length, bool nullable = true);
- void setType(Ctx& ctx, Type type, unsigned precision, unsigned scale, bool nullable = true);
- void setType(Ctx& ctx, const NdbDictionary::Column* ndbColumn);
- bool equal(const SqlType& sqlType) const;
- unsigned size() const;
- unsigned displaySize() const;
- const char* typeName() const;
- unsigned length() const;
- bool nullable() const;
- void nullable(bool value);
- bool unSigned() const;
- void unSigned(bool value);
- // forwards compatible
- void getType(Ctx& ctx, NdbDictionary::Column* ndbColumn) const;
- // type conversion
- SQLSMALLINT sqlcdefault(Ctx& ctx) const;
- // print for debugging
- void print(char* buf, unsigned size) const;
-private:
- friend class LexType;
- Type m_type;
- unsigned m_precision;
- unsigned m_scale;
- unsigned m_length;
- bool m_nullable;
- bool m_unSigned; // qualifier instead of separate types
-};
-
-inline SqlType::Type
-SqlType::type() const
-{
- return m_type;
-}
-
-inline unsigned
-SqlType::length() const
-{
- return m_length;
-}
-
-inline bool
-SqlType::nullable() const
-{
- return m_nullable;
-}
-
-inline void
-SqlType::nullable(bool value)
-{
- m_nullable = value;
-}
-
-inline bool
-SqlType::unSigned() const
-{
- return m_unSigned;
-}
-
-inline void
-SqlType::unSigned(bool value)
-{
- ctx_assert(m_type == Smallint || m_type == Integer || m_type == Bigint);
- m_unSigned = value;
-}
-
-/**
- * Actual SQL datatypes.
- */
-typedef unsigned char SqlChar; // Char and Varchar via pointer
-typedef Int16 SqlSmallint;
-typedef Int32 SqlInteger;
-typedef Int64 SqlBigint;
-typedef Uint16 SqlUsmallint;
-typedef Uint32 SqlUinteger;
-typedef Uint64 SqlUbigint;
-typedef float SqlReal;
-typedef double SqlDouble;
-
-// datetime cc yy mm dd HH MM SS 00 ff ff ff ff stored as String(12)
-struct SqlDatetime {
- int cc() const { return *(signed char*)&m_data[0]; }
- void cc(int x) { *(signed char*)&m_data[0] = x; }
- unsigned yy() const { return *(unsigned char*)&m_data[1]; }
- void yy(unsigned x) { *(unsigned char*)&m_data[1] = x; }
- unsigned mm() const { return *(unsigned char*)&m_data[2]; }
- void mm(unsigned x) { *(unsigned char*)&m_data[2] = x; }
- unsigned dd() const { return *(unsigned char*)&m_data[3]; }
- void dd(unsigned x) { *(unsigned char*)&m_data[3] = x; }
- unsigned HH() const { return *(unsigned char*)&m_data[4]; }
- void HH(unsigned x) { *(unsigned char*)&m_data[4] = x; }
- unsigned MM() const { return *(unsigned char*)&m_data[5]; }
- void MM(unsigned x) { *(unsigned char*)&m_data[5] = x; }
- unsigned SS() const { return *(unsigned char*)&m_data[6]; }
- void SS(unsigned x) { *(unsigned char*)&m_data[6] = x; }
- unsigned ff() const {
- const unsigned char* p = (unsigned char*)&m_data[8];
- unsigned x = 0;
- x += *p++ << 24;
- x += *p++ << 16;
- x += *p++ << 8;
- x += *p++;
- return x;
- }
- void ff(unsigned x) {
- unsigned char* p = (unsigned char*)&m_data[8];
- *p++ = (x >> 24) & 0xff;
- *p++ = (x >> 16) & 0xff;
- *p++ = (x >> 8) & 0xff;
- *p++ = x & 0xff;
- }
- bool valid() { return true; } // XXX later
- bool less(const SqlDatetime t) const {
- if (cc() != t.cc())
- return cc() < t.cc();
- if (yy() != t.yy())
- return yy() < t.yy();
- if (mm() != t.mm())
- return mm() < t.mm();
- if (dd() != t.dd())
- return dd() < t.dd();
- if (HH() != t.HH())
- return HH() < t.HH();
- if (MM() != t.MM())
- return MM() < t.MM();
- if (SS() != t.SS())
- return SS() < t.SS();
- if (ff() != t.ff())
- return ff() < t.ff();
- return false;
- }
-private:
- char m_data[12]; // use array to avoid gaps
-};
-
-/**
- * @class ExtType
- * @brief External data type
- */
-class ExtType {
-public:
- enum Type {
- Undef = UndefDataType,
- Char = SQL_C_CHAR,
- Short = SQL_C_SHORT,
- Sshort = SQL_C_SSHORT,
- Ushort = SQL_C_USHORT,
- Long = SQL_C_LONG, // for sun.jdbc.odbc
- Slong = SQL_C_SLONG,
- Ulong = SQL_C_ULONG,
- Sbigint = SQL_C_SBIGINT,
- Ubigint = SQL_C_UBIGINT,
- Float = SQL_C_FLOAT,
- Double = SQL_C_DOUBLE,
- Timestamp = SQL_C_TYPE_TIMESTAMP,
- Binary = SQL_C_BINARY, // XXX BLOB hack
- Unbound = UnboundDataType
- };
- ExtType();
- ExtType(Type type);
- ExtType(Ctx& ctx, Type type);
- Type type() const;
- void setType(Ctx& ctx, Type type);
- unsigned size() const;
-private:
- Type m_type;
-};
-
-inline ExtType::Type
-ExtType::type() const
-{
- return m_type;
-}
-
-/**
- * @class LexType
- * @class Lexical data type
- */
-class LexType {
-public:
- enum Type {
- Undef = UndefDataType,
- Char = 1,
- Integer = 2,
- Float = 3,
- Null = 4
- };
- LexType();
- LexType(Type type);
- LexType(Ctx& ctx, Type type);
- Type type() const;
- void setType(Ctx& ctx, Type type);
- void convert(Ctx& ctx, SqlType& out, unsigned length = 0) const;
-private:
- Type m_type;
-};
-
-inline LexType::Type
-LexType::type() const
-{
- return m_type;
-}
-
-#endif
diff --git a/ndb/src/client/odbc/common/OdbcData.cpp b/ndb/src/client/odbc/common/OdbcData.cpp
deleted file mode 100644
index 2e1bd768aec..00000000000
--- a/ndb/src/client/odbc/common/OdbcData.cpp
+++ /dev/null
@@ -1,561 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <ndb_global.h>
-#include "OdbcData.hpp"
-
-OdbcData::OdbcData() :
- m_type(Undef)
-{
-}
-
-OdbcData::OdbcData(Type type) :
- m_type(type)
-{
- switch (m_type) {
- case Smallint:
- m_smallint = 0;
- break;
- case Usmallint:
- m_usmallint = 0;
- break;
- case Integer:
- m_integer = 0;
- break;
- case Uinteger:
- m_uinteger = 0;
- break;
- case Pointer:
- m_pointer = 0;
- break;
- case SmallintPtr:
- m_smallintPtr = 0;
- break;
- case UsmallintPtr:
- m_usmallintPtr = 0;
- break;
- case IntegerPtr:
- m_integerPtr = 0;
- break;
- case UintegerPtr:
- m_uintegerPtr = 0;
- break;
- case PointerPtr:
- m_pointerPtr = 0;
- break;
- case Sqlchar:
- m_sqlchar = 0;
- break;
- case Sqlstate:
- m_sqlstate = 0;
- break;
- default:
- ctx_assert(false);
- break;
- };
-}
-
-OdbcData::OdbcData(const OdbcData& odbcData) :
- m_type(odbcData.m_type)
-{
- switch (m_type) {
- case Smallint:
- m_smallint = odbcData.m_smallint;
- break;
- case Usmallint:
- m_usmallint = odbcData.m_usmallint;
- break;
- case Integer:
- m_integer = odbcData.m_integer;
- break;
- case Uinteger:
- m_uinteger = odbcData.m_uinteger;
- break;
- case Pointer:
- m_pointer = odbcData.m_pointer;
- break;
- case SmallintPtr:
- m_smallintPtr = odbcData.m_smallintPtr;
- break;
- case UsmallintPtr:
- m_usmallintPtr = odbcData.m_usmallintPtr;
- break;
- case IntegerPtr:
- m_integerPtr = odbcData.m_integerPtr;
- break;
- case UintegerPtr:
- m_uintegerPtr = odbcData.m_uintegerPtr;
- break;
- case PointerPtr:
- m_pointerPtr = odbcData.m_pointerPtr;
- break;
- case Sqlchar: {
- unsigned n = strlen(odbcData.m_sqlchar);
- m_sqlchar = new char[n + 1];
- memcpy(m_sqlchar, odbcData.m_sqlchar, n + 1);
- break;
- }
- case Sqlstate:
- m_sqlstate = odbcData.m_sqlstate;
- break;
- default:
- ctx_assert(false);
- break;
- };
-}
-
-OdbcData::~OdbcData()
-{
- switch (m_type) {
- case Sqlchar:
- delete[] m_sqlchar;
- break;
- default:
- break;
- }
-}
-
-void
-OdbcData::setValue()
-{
- m_type = Undef;
-}
-
-void
-OdbcData::setValue(Type type)
-{
- if (m_type == Sqlchar) {
- delete[] m_sqlchar;
- m_sqlchar = 0;
- }
- switch (m_type) {
- case Smallint:
- m_smallint = 0;
- break;
- case Usmallint:
- m_usmallint = 0;
- break;
- case Integer:
- m_integer = 0;
- break;
- case Uinteger:
- m_uinteger = 0;
- break;
- case Pointer:
- m_pointer = 0;
- break;
- case SmallintPtr:
- m_smallintPtr = 0;
- break;
- case UsmallintPtr:
- m_usmallintPtr = 0;
- break;
- case IntegerPtr:
- m_integerPtr = 0;
- break;
- case UintegerPtr:
- m_uintegerPtr = 0;
- break;
- case PointerPtr:
- m_pointerPtr = 0;
- break;
- case Sqlchar:
- m_sqlchar = 0;
- break;
- case Sqlstate:
- m_sqlstate = 0;
- break;
- default:
- ctx_assert(false);
- break;
- };
-}
-
-void
-OdbcData::setValue(const OdbcData odbcData)
-{
- if (m_type == Sqlchar) {
- delete[] m_sqlchar;
- m_sqlchar = 0;
- }
- m_type = odbcData.m_type;
- switch (m_type) {
- case Smallint:
- m_smallint = odbcData.m_smallint;
- break;
- case Usmallint:
- m_usmallint = odbcData.m_usmallint;
- break;
- case Integer:
- m_integer = odbcData.m_integer;
- break;
- case Uinteger:
- m_uinteger = odbcData.m_uinteger;
- break;
- case Pointer:
- m_pointer = odbcData.m_pointer;
- break;
- case SmallintPtr:
- m_smallintPtr = odbcData.m_smallintPtr;
- break;
- case UsmallintPtr:
- m_usmallintPtr = odbcData.m_usmallintPtr;
- break;
- case IntegerPtr:
- m_integerPtr = odbcData.m_integerPtr;
- break;
- case UintegerPtr:
- m_uintegerPtr = odbcData.m_uintegerPtr;
- break;
- case PointerPtr:
- m_pointerPtr = odbcData.m_pointerPtr;
- break;
- case Sqlchar: {
- unsigned n = strlen(odbcData.m_sqlchar);
- m_sqlchar = new char[n + 1];
- memcpy(m_sqlchar, odbcData.m_sqlchar, n + 1);
- break;
- }
- case Sqlstate:
- m_sqlstate = odbcData.m_sqlstate;
- break;
- default:
- ctx_assert(false);
- break;
- };
-}
-
-// copy in from user buffer
-
-void
-OdbcData::copyin(Ctx& ctx, Type type, SQLPOINTER buf, SQLINTEGER length)
-{
- if (m_type == Sqlchar) {
- delete[] m_sqlchar;
- m_sqlchar = 0;
- }
- m_type = type;
- switch (m_type) {
- case Smallint: {
- SQLSMALLINT val = 0;
- switch (length) {
- case 0:
- case SQL_IS_SMALLINT:
- val = (SQLSMALLINT)(SQLINTEGER)buf;
- break;
- case SQL_IS_USMALLINT:
- val = (SQLUSMALLINT)(SQLUINTEGER)buf;
- break;
- case SQL_IS_INTEGER:
- val = (SQLINTEGER)buf;
- break;
- case SQL_IS_UINTEGER:
- val = (SQLUINTEGER)buf;
- break;
- default:
- ctx.pushStatus(Error::Gen, "smallint input - invalid length %d", (int)length);
- return;
- }
- m_smallint = val;
- break;
- }
- case Usmallint: {
- SQLUSMALLINT val = 0;
- switch (length) {
- case SQL_IS_SMALLINT:
- val = (SQLSMALLINT)(SQLINTEGER)buf;
- break;
- case 0:
- case SQL_IS_USMALLINT:
- val = (SQLUSMALLINT)(SQLUINTEGER)buf;
- break;
- case SQL_IS_INTEGER:
- val = (SQLINTEGER)buf;
- break;
- case SQL_IS_UINTEGER:
- val = (SQLUINTEGER)buf;
- break;
- default:
- ctx.pushStatus(Error::Gen, "unsigned smallint input - invalid length %d", (int)length);
- return;
- }
- m_usmallint = val;
- break;
- }
- case Integer: {
- SQLINTEGER val = 0;
- switch (length) {
- case SQL_IS_SMALLINT:
- val = (SQLSMALLINT)(SQLINTEGER)buf;
- break;
- case SQL_IS_USMALLINT:
- val = (SQLUSMALLINT)(SQLUINTEGER)buf;
- break;
- case 0:
- case SQL_IS_INTEGER:
- val = (SQLINTEGER)buf;
- break;
- case SQL_IS_UINTEGER:
- val = (SQLUINTEGER)buf;
- break;
- default:
- ctx.pushStatus(Error::Gen, "integer input - invalid length %d", (int)length);
- return;
- }
- m_integer = val;
- break;
- }
- case Uinteger: {
- SQLUINTEGER val = 0;
- switch (length) {
- case SQL_IS_SMALLINT:
- val = (SQLSMALLINT)(SQLINTEGER)buf;
- break;
- case SQL_IS_USMALLINT:
- val = (SQLUSMALLINT)(SQLUINTEGER)buf;
- break;
- case SQL_IS_INTEGER:
- val = (SQLINTEGER)buf;
- break;
- case 0:
- case SQL_IS_UINTEGER:
- val = (SQLUINTEGER)buf;
- break;
- default:
- ctx.pushStatus(Error::Gen, "unsigned integer input - invalid length %d", (int)length);
- return;
- }
- m_uinteger = val;
- break;
- }
- case Pointer: {
- SQLPOINTER val = 0;
- switch (length) {
- case 0:
- case SQL_IS_POINTER:
- val = (SQLPOINTER)buf;
- break;
- default:
- ctx.pushStatus(Error::Gen, "pointer input - invalid length %d", (int)length);
- return;
- }
- m_pointer = val;
- break;
- }
- case SmallintPtr: {
- SQLSMALLINT* val = 0;
- switch (length) {
- case 0:
- case SQL_IS_POINTER:
- val = (SQLSMALLINT*)buf;
- break;
- default:
- ctx.pushStatus(Error::Gen, "smallint pointer input - invalid length %d", (int)length);
- return;
- }
- m_smallintPtr = val;
- break;
- }
- case UsmallintPtr: {
- SQLUSMALLINT* val = 0;
- switch (length) {
- case 0:
- case SQL_IS_POINTER:
- val = (SQLUSMALLINT*)buf;
- break;
- default:
- ctx.pushStatus(Error::Gen, "unsigned smallint pointer input - invalid length %d", (int)length);
- return;
- }
- m_usmallintPtr = val;
- break;
- }
- case IntegerPtr: {
- SQLINTEGER* val = 0;
- switch (length) {
- case 0:
- case SQL_IS_POINTER:
- val = (SQLINTEGER*)buf;
- break;
- default:
- ctx.pushStatus(Error::Gen, "integer pointer input - invalid length %d", (int)length);
- return;
- }
- m_integerPtr = val;
- break;
- }
- case UintegerPtr: {
- SQLUINTEGER* val = 0;
- switch (length) {
- case 0:
- case SQL_IS_POINTER:
- val = (SQLUINTEGER*)buf;
- break;
- default:
- ctx.pushStatus(Error::Gen, "unsigned integer pointer input - invalid length %d", (int)length);
- return;
- }
- m_uintegerPtr = val;
- break;
- }
- case Sqlchar: {
- const char* val = (char*)buf;
- if (val == 0) {
- ctx.pushStatus(Sqlstate::_HY009, Error::Gen, "null string input");
- return;
- }
- if (length < 0 && length != SQL_NTS) {
- ctx.pushStatus(Error::Gen, "string input - invalid length %d", (int)length);
- return;
- }
- if (length == SQL_NTS) {
- m_sqlchar = strcpy(new char[strlen(val) + 1], val);
- } else {
- m_sqlchar = (char*)memcpy(new char[length + 1], val, length);
- m_sqlchar[length] = 0;
- }
- break;
- }
- default:
- ctx_assert(false);
- break;
- }
-}
-
-// copy out to user buffer
-
-void
-OdbcData::copyout(Ctx& ctx, SQLPOINTER buf, SQLINTEGER length, SQLINTEGER* total, SQLSMALLINT* total2)
-{
- if (buf == 0) {
- ctx.setCode(SQL_ERROR);
- return;
- }
- switch (m_type) {
- case Smallint: {
- SQLSMALLINT* ptr = static_cast<SQLSMALLINT*>(buf);
- *ptr = m_smallint;
- break;
- }
- case Usmallint: {
- SQLUSMALLINT* ptr = static_cast<SQLUSMALLINT*>(buf);
- *ptr = m_usmallint;
- break;
- }
- case Integer: {
- SQLINTEGER* ptr = static_cast<SQLINTEGER*>(buf);
- *ptr = m_integer;
- break;
- }
- case Uinteger: {
- SQLUINTEGER* ptr = static_cast<SQLUINTEGER*>(buf);
- *ptr = m_uinteger;
- break;
- }
- case Pointer: {
- SQLPOINTER* ptr = static_cast<SQLPOINTER*>(buf);
- *ptr = m_pointer;
- break;
- }
- case Sqlchar: {
- char* ptr = static_cast<char*>(buf);
- if (length < 0 && length != SQL_NTS) {
- ctx.setCode(SQL_ERROR);
- return;
- }
- if (length == SQL_NTS) {
- strcpy(ptr, m_sqlchar);
- } else {
- strncpy(ptr, m_sqlchar, length);
- }
- if (total != 0)
- *total = strlen(m_sqlchar);
- if (total2 != 0)
- *total2 = strlen(m_sqlchar);
- break;
- }
- case Sqlstate: {
- char* ptr = static_cast<char*>(buf);
- const char* state = m_sqlstate->state();
- if (length < 0 && length != SQL_NTS) {
- ctx.setCode(SQL_ERROR);
- return;
- }
- if (length == SQL_NTS) {
- strcpy(ptr, state);
- } else {
- strncpy(ptr, state, length);
- }
- if (total != 0)
- *total = strlen(state);
- if (total2 != 0)
- *total2 = strlen(state);
- break;
- }
- default:
- ctx_assert(false);
- break;
- }
-}
-
-void
-OdbcData::print(char* buf, unsigned size) const
-{
- switch (m_type) {
- case Undef:
- snprintf(buf, size, "undef");
- break;
- case Smallint:
- snprintf(buf, size, "%d", (int)m_smallint);
- break;
- case Usmallint:
- snprintf(buf, size, "%u", (unsigned)m_usmallint);
- break;
- case Integer:
- snprintf(buf, size, "%ld", (long)m_integer);
- break;
- case Uinteger:
- snprintf(buf, size, "%lu", (unsigned long)m_uinteger);
- break;
- case Pointer:
- snprintf(buf, size, "0x%lx", (unsigned long)m_pointer);
- break;
- case SmallintPtr:
- snprintf(buf, size, "0x%lx", (unsigned long)m_smallintPtr);
- break;
- case UsmallintPtr:
- snprintf(buf, size, "0x%lx", (unsigned long)m_usmallintPtr);
- break;
- case IntegerPtr:
- snprintf(buf, size, "0x%lx", (unsigned long)m_integerPtr);
- break;
- case UintegerPtr:
- snprintf(buf, size, "0x%lx", (unsigned long)m_uintegerPtr);
- break;
- case PointerPtr:
- snprintf(buf, size, "0x%lx", (unsigned long)m_pointerPtr);
- break;
- case Sqlchar:
- snprintf(buf, size, "%s", m_sqlchar);
- break;
- case Sqlstate:
- snprintf(buf, size, "%s", m_sqlstate->state());
- break;
- default:
- snprintf(buf, size, "data(%d)", (int)m_type);
- break;
- };
-}
diff --git a/ndb/src/client/odbc/common/common.hpp b/ndb/src/client/odbc/common/common.hpp
deleted file mode 100644
index e90950df9c5..00000000000
--- a/ndb/src/client/odbc/common/common.hpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef ODBC_COMMON_common_hpp
-#define ODBC_COMMON_common_hpp
-
-// misc defs
-
-#ifdef NDB_GCC
-#define PRINTFLIKE(i,j) __attribute__ ((format (printf, i, j)))
-#else
-#define PRINTFLIKE(i,j)
-#endif
-
-// odbc defs
-
-#define ODBCVER 0x0351
-
-#ifdef NDB_WIN32
-#include <windows.h>
-#endif
-
-extern "C" {
-#include <sqlext.h>
-}
-// some types which may be missing
-#ifndef SQL_BLOB
-#define SQL_BLOB 30
-#endif
-#ifndef SQL_BLOB_LOCATOR
-#define SQL_BLOB_LOCATOR 31
-#endif
-#ifndef SQL_CLOB
-#define SQL_CLOB 40
-#endif
-#ifndef SQL_CLOB_LOCATOR
-#define SQL_CLOB_LOCATOR 41
-#endif
-
-// until real blobs use Varchar of this size
-#define FAKE_BLOB_SIZE 2000
-
-#define SQL_HANDLE_ROOT 0 // assume real handles != 0
-
-enum OdbcHandle {
- Odbc_handle_root = 0, // not an odbc handle
- Odbc_handle_env = 1,
- Odbc_handle_dbc = 2,
- Odbc_handle_stmt = 4,
- Odbc_handle_desc = 8,
- Odbc_handle_all = (1|2|4|8)
-};
-
-// ndb defs
-
-#undef BOOL
-#include <ndb_types.h>
-// this info not yet on api side
-#include <kernel/ndb_limits.h>
-#include <ndb_version.h>
-
-#ifndef MAX_TAB_NAME_SIZE
-#define MAX_TAB_NAME_SIZE 128
-#endif
-
-#ifndef MAX_ATTR_NAME_SIZE
-#define MAX_ATTR_NAME_SIZE 32
-#endif
-
-#ifndef MAX_ATTR_DEFAULT_VALUE_SIZE
-#define MAX_ATTR_DEFAULT_VALUE_SIZE 128
-#endif
-
-typedef Uint32 NdbAttrId;
-typedef Uint64 CountType;
-
-// ndb odbc defs
-
-#define NDB_ODBC_COMPONENT_VENDOR "[MySQL]"
-#define NDB_ODBC_COMPONENT_DRIVER "[ODBC driver]"
-#define NDB_ODBC_COMPONENT_DATABASE "[NDB Cluster]"
-
-#define NDB_ODBC_VERSION_MAJOR 0
-#define NDB_ODBC_VERSION_MINOR 22
-#define NDB_ODBC_VERSION_STRING "0.22"
-
-// reserved error codes for non-NDB errors
-#define NDB_ODBC_ERROR_MIN 5000
-#define NDB_ODBC_ERROR_MAX 5100
-
-// maximum log level compiled in
-#ifdef VM_TRACE
-#define NDB_ODBC_MAX_LOG_LEVEL 5
-#else
-#define NDB_ODBC_MAX_LOG_LEVEL 3
-#endif
-
-// driver specific statement attribute for number of NDB tuples fetched
-#define SQL_ATTR_NDB_TUPLES_FETCHED 66601
-
-#include <BaseString.hpp>
-#include <common/Sqlstate.hpp>
-#include <common/Ctx.hpp>
-
-#undef assert
-
-#endif
diff --git a/ndb/src/client/odbc/driver/driver.cpp b/ndb/src/client/odbc/driver/driver.cpp
deleted file mode 100644
index dabfd5f855b..00000000000
--- a/ndb/src/client/odbc/driver/driver.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NdbMutex.h>
-#include "driver.hpp"
-
-#undef NDB_ODBC_SIG_DFL
-#ifdef NDB_ODBC_SIG_DFL
-#include <signal.h>
-#endif
-
-// The big mutex (just in case).
-
-#ifdef NDB_WIN32
-static NdbMutex & driver_mutex = * NdbMutex_Create();
-#else
-static NdbMutex driver_mutex = NDB_MUTEX_INITIALIZER;
-#endif
-
-static void
-driver_lock()
-{
- NdbMutex_Lock(&driver_mutex);
-}
-
-static void
-driver_unlock()
-{
- NdbMutex_Unlock(&driver_mutex);
-}
-
-// Hooks for function entry and exit.
-
-static inline void
-driver_enter(SQLUSMALLINT functionId)
-{
- switch (functionId) {
- default:
- break;
- }
-#ifdef NDB_ODBC_SIG_DFL
- // XXX need to restore old sig
- for (int i = 1; i <= 30; i++)
- signal(i, SIG_DFL);
-#endif
-}
-
-static inline void
-driver_exit(SQLUSMALLINT functionId)
-{
- switch (functionId) {
- default:
- break;
- }
-}
-
-// Some C++ compilers (like gcc) cannot merge template code
-// in different files. So compile all in one file.
-
-#include "SQLAllocConnect.cpp"
-#include "SQLAllocEnv.cpp"
-#include "SQLAllocHandle.cpp"
-#include "SQLAllocHandleStd.cpp"
-#include "SQLAllocStmt.cpp"
-#include "SQLBindCol.cpp"
-#include "SQLBindParam.cpp"
-#include "SQLBindParameter.cpp"
-#include "SQLBrowseConnect.cpp"
-#include "SQLBulkOperations.cpp"
-#include "SQLCancel.cpp"
-#include "SQLCloseCursor.cpp"
-#include "SQLColAttribute.cpp"
-#include "SQLColAttributes.cpp"
-#include "SQLColumnPrivileges.cpp"
-#include "SQLColumns.cpp"
-#include "SQLConnect.cpp"
-#include "SQLCopyDesc.cpp"
-#include "SQLDataSources.cpp"
-#include "SQLDescribeCol.cpp"
-#include "SQLDescribeParam.cpp"
-#include "SQLDisconnect.cpp"
-#include "SQLDriverConnect.cpp"
-#include "SQLDrivers.cpp"
-#include "SQLEndTran.cpp"
-#include "SQLError.cpp"
-#include "SQLExecDirect.cpp"
-#include "SQLExecute.cpp"
-#include "SQLExtendedFetch.cpp"
-#include "SQLFetch.cpp"
-#include "SQLFetchScroll.cpp"
-#include "SQLForeignKeys.cpp"
-#include "SQLFreeConnect.cpp"
-#include "SQLFreeEnv.cpp"
-#include "SQLFreeHandle.cpp"
-#include "SQLFreeStmt.cpp"
-#include "SQLGetConnectAttr.cpp"
-#include "SQLGetConnectOption.cpp"
-#include "SQLGetCursorName.cpp"
-#include "SQLGetData.cpp"
-#include "SQLGetDescField.cpp"
-#include "SQLGetDescRec.cpp"
-#include "SQLGetDiagField.cpp"
-#include "SQLGetDiagRec.cpp"
-#include "SQLGetEnvAttr.cpp"
-#include "SQLGetFunctions.cpp"
-#include "SQLGetInfo.cpp"
-#include "SQLGetStmtAttr.cpp"
-#include "SQLGetStmtOption.cpp"
-#include "SQLGetTypeInfo.cpp"
-#include "SQLMoreResults.cpp"
-#include "SQLNativeSql.cpp"
-#include "SQLNumParams.cpp"
-#include "SQLNumResultCols.cpp"
-#include "SQLParamData.cpp"
-#include "SQLParamOptions.cpp"
-#include "SQLPrepare.cpp"
-#include "SQLPrimaryKeys.cpp"
-#include "SQLProcedureColumns.cpp"
-#include "SQLProcedures.cpp"
-#include "SQLPutData.cpp"
-#include "SQLRowCount.cpp"
-#include "SQLSetConnectAttr.cpp"
-#include "SQLSetConnectOption.cpp"
-#include "SQLSetCursorName.cpp"
-#include "SQLSetDescField.cpp"
-#include "SQLSetDescRec.cpp"
-#include "SQLSetEnvAttr.cpp"
-#include "SQLSetParam.cpp"
-#include "SQLSetPos.cpp"
-#include "SQLSetScrollOptions.cpp"
-#include "SQLSetStmtAttr.cpp"
-#include "SQLSetStmtOption.cpp"
-#include "SQLSpecialColumns.cpp"
-#include "SQLStatistics.cpp"
-#include "SQLTablePrivileges.cpp"
-#include "SQLTables.cpp"
-#include "SQLTransact.cpp"
diff --git a/ndb/src/client/odbc/handles/HandleRoot.cpp b/ndb/src/client/odbc/handles/HandleRoot.cpp
deleted file mode 100644
index d901cb5cb7f..00000000000
--- a/ndb/src/client/odbc/handles/HandleRoot.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NdbMutex.h>
-#include <common/DiagArea.hpp>
-#include "HandleRoot.hpp"
-#include "HandleEnv.hpp"
-#include "HandleDbc.hpp"
-#include "HandleStmt.hpp"
-#include "HandleDesc.hpp"
-#include "PoolNdb.hpp"
-
-HandleRoot::HandleRoot() :
- m_attrArea(m_attrSpec)
-{
- m_attrArea.setHandle(this);
- m_poolNdb = new PoolNdb();
-}
-
-HandleRoot::~HandleRoot()
-{
-}
-
-#ifdef NDB_WIN32
-static NdbMutex & root_mutex = * NdbMutex_Create();
-#else
-static NdbMutex root_mutex = NDB_MUTEX_INITIALIZER;
-#endif
-
-HandleRoot*
-HandleRoot::instance()
-{
- NdbMutex_Lock(&root_mutex);
- if (m_instance == 0)
- m_instance = new HandleRoot();
- NdbMutex_Unlock(&root_mutex);
- return m_instance;
-}
-
-void
-HandleRoot::lockHandle()
-{
- NdbMutex_Lock(&root_mutex);
-}
-
-void
-HandleRoot::unlockHandle()
-{
- NdbMutex_Unlock(&root_mutex);
-}
-
-// check and find handle types and handles
-
-SQLSMALLINT
-HandleRoot::findParentType(SQLSMALLINT childType)
-{
- switch (childType) {
- case SQL_HANDLE_ENV:
- return SQL_HANDLE_ROOT;
- case SQL_HANDLE_DBC:
- return SQL_HANDLE_ENV;
- case SQL_HANDLE_STMT:
- return SQL_HANDLE_DBC;
- case SQL_HANDLE_DESC:
- return SQL_HANDLE_DBC;
- }
- return -1;
-}
-
-HandleBase*
-HandleRoot::findBase(SQLSMALLINT handleType, void* pHandle)
-{
- switch (handleType) {
- case SQL_HANDLE_ROOT:
- return getRoot();
- case SQL_HANDLE_ENV:
- return findEnv(pHandle);
- case SQL_HANDLE_DBC:
- return findDbc(pHandle);
- case SQL_HANDLE_STMT:
- return findStmt(pHandle);
- case SQL_HANDLE_DESC:
- return findDesc(pHandle);
- }
- return 0;
-}
-
-HandleEnv*
-HandleRoot::findEnv(void* pHandle)
-{
- lockHandle();
- ValidList::iterator i = m_validList.find(pHandle);
- if (i == m_validList.end() || (*i).second != SQL_HANDLE_ENV) {
- unlockHandle();
- return 0;
- }
- unlockHandle();
- ctx_assert(pHandle != 0);
- return static_cast<HandleEnv*>(pHandle);
-}
-
-HandleDbc*
-HandleRoot::findDbc(void* pHandle)
-{
- lockHandle();
- ValidList::iterator i = m_validList.find(pHandle);
- if (i == m_validList.end() || (*i).second != SQL_HANDLE_DBC) {
- unlockHandle();
- return 0;
- }
- unlockHandle();
- ctx_assert(pHandle != 0);
- return static_cast<HandleDbc*>(pHandle);
-}
-
-HandleStmt*
-HandleRoot::findStmt(void* pHandle)
-{
- lockHandle();
- ValidList::iterator i = m_validList.find(pHandle);
- if (i == m_validList.end() || (*i).second != SQL_HANDLE_STMT) {
- unlockHandle();
- return 0;
- }
- unlockHandle();
- ctx_assert(pHandle != 0);
- return static_cast<HandleStmt*>(pHandle);
-}
-
-HandleDesc*
-HandleRoot::findDesc(void* pHandle)
-{
- lockHandle();
- ValidList::iterator i = m_validList.find(pHandle);
- if (i == m_validList.end() || (*i).second != SQL_HANDLE_DESC) {
- unlockHandle();
- return 0;
- }
- unlockHandle();
- ctx_assert(pHandle != 0);
- return static_cast<HandleDesc*>(pHandle);
-}
-
-// add or remove handle from validation list
-
-void
-HandleRoot::record(SQLSMALLINT handleType, HandleBase* pHandle, bool add)
-{
- switch (handleType) {
- case SQL_HANDLE_ENV:
- case SQL_HANDLE_DBC:
- case SQL_HANDLE_STMT:
- case SQL_HANDLE_DESC:
- break;
- default:
- ctx_assert(false);
- break;
- }
- ctx_assert(pHandle != 0);
- lockHandle();
- ValidList::iterator i = m_validList.find(pHandle);
- if (add) {
- if (i != m_validList.end()) {
- unlockHandle();
- ctx_assert(false);
- }
- m_validList.insert(ValidList::value_type(pHandle, handleType));
- } else {
- if (i == m_validList.end() || (*i).second != handleType) {
- unlockHandle();
- ctx_assert(false);
- }
- m_validList.erase(i);
- }
- unlockHandle();
-}
-
-// allocate and free handles
-
-void
-HandleRoot::sqlAllocEnv(Ctx& ctx, HandleEnv** ppEnv)
-{
- if (ppEnv == 0) {
- ctx.pushStatus(Sqlstate::_HY009, Error::Gen, "cannot allocate environment handle - null return address");
- return;
- }
- HandleEnv* pEnv = new HandleEnv(this);
- pEnv->ctor(ctx);
- if (! ctx.ok()) {
- pEnv->dtor(ctx);
- delete pEnv;
- return;
- }
- lockHandle();
- m_listEnv.push_back(pEnv);
- unlockHandle();
- getRoot()->record(SQL_HANDLE_ENV, pEnv, true);
- *ppEnv = pEnv;
-}
-
-void
-HandleRoot::sqlAllocHandle(Ctx& ctx, SQLSMALLINT childType, HandleBase** ppChild)
-{
- switch (childType) {
- case SQL_HANDLE_ENV:
- sqlAllocEnv(ctx, (HandleEnv**)ppChild);
- return;
- }
- ctx.pushStatus(Sqlstate::_HY092, Error::Gen, "invalid child handle type %d", (int)childType);
-}
-
-void
-HandleRoot::sqlFreeEnv(Ctx& ctx, HandleEnv* pEnv)
-{
- pEnv->dtor(ctx);
- if (! ctx.ok()) {
- return;
- }
- lockHandle();
- m_listEnv.remove(pEnv);
- unlockHandle();
- getRoot()->record(SQL_HANDLE_ENV, pEnv, false);
- delete pEnv;
-}
-
-void
-HandleRoot::sqlFreeHandle(Ctx& ctx, SQLSMALLINT childType, HandleBase* pChild)
-{
- switch (childType) {
- case SQL_HANDLE_ENV:
- sqlFreeEnv(ctx, (HandleEnv*)pChild);
- return;
- }
- ctx.pushStatus(Sqlstate::_HY092, Error::Gen, "invalid child handle type %d", (int)childType);
-}
-
-// process-level attributes
-
-void
-HandleRoot::sqlSetRootAttr(Ctx& ctx, SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER stringLength)
-{
- lockHandle();
- baseSetHandleAttr(ctx, m_attrArea, attribute, value, stringLength);
- unlockHandle();
-}
-
-void
-HandleRoot::sqlGetRootAttr(Ctx& ctx, SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* stringLength)
-{
- lockHandle();
- baseGetHandleAttr(ctx, m_attrArea, attribute, value, bufferLength, stringLength);
- unlockHandle();
-}
-
-// the instance
-
-HandleRoot* HandleRoot::m_instance = 0;
diff --git a/ndb/src/client/odbc/handles/PoolNdb.cpp b/ndb/src/client/odbc/handles/PoolNdb.cpp
deleted file mode 100644
index c487ca2b976..00000000000
--- a/ndb/src/client/odbc/handles/PoolNdb.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NdbMutex.h>
-#include <NdbApi.hpp>
-#include "PoolNdb.hpp"
-
-#ifdef NDB_WIN32
-static NdbMutex & ndb_mutex = * NdbMutex_Create();
-#else
-static NdbMutex ndb_mutex = NDB_MUTEX_INITIALIZER;
-#endif
-
-PoolNdb::PoolNdb() :
- m_cntUsed(0),
- m_cntFree(0)
-{
-}
-
-PoolNdb::~PoolNdb()
-{
-}
-
-Ndb*
-PoolNdb::allocate(Ctx& ctx, int timeout)
-{
- NdbMutex_Lock(&ndb_mutex);
- Ndb* pNdb;
- if (m_cntFree == 0) {
- pNdb = new Ndb("TEST_DB");
- pNdb->useFullyQualifiedNames(true);
- if (pNdb->init(64) < 0) {
- ctx.pushStatus(pNdb, "init");
- delete pNdb;
- NdbMutex_Unlock(&ndb_mutex);
- return 0;
- }
- if (pNdb->waitUntilReady(timeout) < 0) {
- ctx.pushStatus(Sqlstate::_HYT00, Error::Gen, "connection timeout after %d seconds", timeout);
- ctx.pushStatus(pNdb, "waitUntilReady");
- delete pNdb;
- NdbMutex_Unlock(&ndb_mutex);
- return 0;
- }
- m_listFree.push_back(pNdb);
- m_cntFree++;
- }
- pNdb = m_listFree.front();
- m_listFree.pop_front();
- m_cntFree--;
- m_cntUsed++;
- ctx_log1(("alloc Ndb: used=%u free=%u", m_cntUsed, m_cntFree));
- NdbMutex_Unlock(&ndb_mutex);
- return pNdb;
-}
-
-void
-PoolNdb::release(Ctx& ctx, Ndb* pNdb)
-{
- NdbMutex_Lock(&ndb_mutex);
- m_listUsed.remove(pNdb);
- m_listFree.push_back(pNdb);
- m_cntFree++;
- m_cntUsed--;
- ctx_log1(("free Ndb: used=%u free=%u", m_cntUsed, m_cntFree));
- NdbMutex_Unlock(&ndb_mutex);
-}
diff --git a/ndb/src/client/odbc/handles/PoolNdb.hpp b/ndb/src/client/odbc/handles/PoolNdb.hpp
deleted file mode 100644
index bea7e72a59f..00000000000
--- a/ndb/src/client/odbc/handles/PoolNdb.hpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef ODBC_HANDLES_PoolNdb_hpp
-#define ODBC_HANDLES_PoolNdb_hpp
-
-#include <list>
-#include <common/common.hpp>
-
-class Ndb;
-
-/**
- * @class PoolNdb
- * @brief Pool of Ndb objects.
- *
- * A class implementing pool of Ndb objects.
- */
-class PoolNdb {
-public:
- PoolNdb();
- ~PoolNdb();
- Ndb* allocate(Ctx& ctx, int timeout);
- void release(Ctx& ctx, Ndb* pNdb);
-private:
- std::list<Ndb*> m_listUsed;
- std::list<Ndb*> m_listFree;
- unsigned m_cntUsed;
- unsigned m_cntFree;
-};
-
-#endif
diff --git a/ndb/src/common/Makefile.am b/ndb/src/common/Makefile.am
new file mode 100644
index 00000000000..7fcf2cab636
--- /dev/null
+++ b/ndb/src/common/Makefile.am
@@ -0,0 +1,13 @@
+SUBDIRS = portlib debugger util logger transporter mgmcommon editline
+
+noinst_LTLIBRARIES = libcommon.la
+
+libcommon_la_SOURCES =
+libcommon_la_LIBADD = \
+ transporter/libtransporter.la \
+ debugger/libtrace.la \
+ debugger/signaldata/libsignaldataprint.la \
+ mgmcommon/libmgmsrvcommon.la \
+ portlib/libportlib.la \
+ logger/liblogger.la \
+ util/libgeneral.la
diff --git a/ndb/src/common/Makefile b/ndb/src/common/Makefile_old
index ebde75bf3ec..ebde75bf3ec 100644
--- a/ndb/src/common/Makefile
+++ b/ndb/src/common/Makefile_old
diff --git a/ndb/src/common/debugger/LogLevel.cpp b/ndb/src/common/debugger/LogLevel.cpp
index 5348924bbbb..f9e2f318432 100644
--- a/ndb/src/common/debugger/LogLevel.cpp
+++ b/ndb/src/common/debugger/LogLevel.cpp
@@ -17,13 +17,14 @@
#include <LogLevel.hpp>
const LogLevel::LogLevelCategoryName LogLevel::LOGLEVEL_CATEGORY_NAME[] = {
- {"LogLevelStartup"},
- {"LogLevelShutdown"},
- {"LogLevelStatistic"},
- {"LogLevelCheckpoint"},
- {"LogLevelNodeRestart"},
- {"LogLevelConnection"},
- {"LogLevelError"},
- {"LogLevelInfo"},
- {"LogLevelGrep"}
+ { "LogLevelStartup" },
+ { "LogLevelShutdown" },
+ { "LogLevelStatistic" },
+ { "LogLevelCheckpoint" },
+ { "LogLevelNodeRestart" },
+ { "LogLevelConnection" },
+ { "LogLevelError" },
+ { "LogLevelWarning" },
+ { "LogLevelInfo" },
+ { "LogLevelGrep" }
};
diff --git a/ndb/src/common/debugger/Makefile.am b/ndb/src/common/debugger/Makefile.am
new file mode 100644
index 00000000000..0278d0d2ba0
--- /dev/null
+++ b/ndb/src/common/debugger/Makefile.am
@@ -0,0 +1,11 @@
+SUBDIRS = signaldata
+
+noinst_LTLIBRARIES = libtrace.la
+
+libtrace_la_SOURCES = SignalLoggerManager.cpp DebuggerNames.cpp BlockNames.cpp LogLevel.cpp EventLogger.cpp GrepError.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/common/debugger/Makefile b/ndb/src/common/debugger/Makefile_old
index ac3a4475a54..ac3a4475a54 100644
--- a/ndb/src/common/debugger/Makefile
+++ b/ndb/src/common/debugger/Makefile_old
diff --git a/ndb/src/common/debugger/signaldata/BackupImpl.cpp b/ndb/src/common/debugger/signaldata/BackupImpl.cpp
index be9e43e3df1..bdc34d614cf 100644
--- a/ndb/src/common/debugger/signaldata/BackupImpl.cpp
+++ b/ndb/src/common/debugger/signaldata/BackupImpl.cpp
@@ -24,7 +24,7 @@ printDEFINE_BACKUP_REQ(FILE * out, const Uint32 * data, Uint32 len, Uint16 bno){
sig->backupPtr, sig->backupId, sig->clientRef, sig->clientData);
fprintf(out, " backupKey: [ %08x%08x ] DataLength: %d\n",
sig->backupKey[0], sig->backupKey[1], sig->backupDataLen);
- char buf[sig->nodes.TextLength + 1];
+ char buf[_NDB_NODE_BITMASK_SIZE * 8 + 1];
fprintf(out, " Nodes: %s\n", sig->nodes.getText(buf));
return true;
}
diff --git a/ndb/src/common/debugger/signaldata/CntrStart.cpp b/ndb/src/common/debugger/signaldata/CntrStart.cpp
new file mode 100644
index 00000000000..154013f40b0
--- /dev/null
+++ b/ndb/src/common/debugger/signaldata/CntrStart.cpp
@@ -0,0 +1,37 @@
+#include <signaldata/CntrStart.hpp>
+
+bool
+printCNTR_START_REQ(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const CntrStartReq * const sig = (CntrStartReq *)theData;
+ fprintf(output, " nodeId: %x\n", sig->nodeId);
+ fprintf(output, " startType: %x\n", sig->startType);
+ fprintf(output, " lastGci: %x\n", sig->lastGci);
+ return true;
+}
+
+bool
+printCNTR_START_REF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const CntrStartRef * const sig = (CntrStartRef *)theData;
+ fprintf(output, " errorCode: %x\n", sig->errorCode);
+ fprintf(output, " masterNodeId: %x\n", sig->masterNodeId);
+ return true;
+}
+
+bool
+printCNTR_START_CONF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const CntrStartConf * const sig = (CntrStartConf *)theData;
+ fprintf(output, " startType: %x\n", sig->startType);
+ fprintf(output, " startGci: %x\n", sig->startGci);
+ fprintf(output, " masterNodeId: %x\n", sig->masterNodeId);
+ fprintf(output, " noStartNodes: %x\n", sig->noStartNodes);
+
+ char buf[32*NdbNodeBitmask::Size+1];
+ fprintf(output, " startedNodes: %s\n",
+ BitmaskImpl::getText(NdbNodeBitmask::Size, sig->startedNodes, buf));
+ fprintf(output, " startingNodes: %s\n",
+ BitmaskImpl::getText(NdbNodeBitmask::Size, sig->startingNodes, buf));
+ return true;
+}
diff --git a/ndb/src/common/debugger/signaldata/CreateTrig.cpp b/ndb/src/common/debugger/signaldata/CreateTrig.cpp
index d8360dec4d5..ddd45080cba 100644
--- a/ndb/src/common/debugger/signaldata/CreateTrig.cpp
+++ b/ndb/src/common/debugger/signaldata/CreateTrig.cpp
@@ -87,7 +87,7 @@ bool printCREATE_TRIG_REQ(FILE * output, const Uint32 * theData, Uint32 len, Uin
fprintf(output, "Monitor all attributes: %s ", (sig->getMonitorAllAttributes())?"true":"false");
const AttributeMask& attributeMask = sig->getAttributeMask();
- char buf[attributeMask.TextLength + 1];
+ char buf[MAXNROFATTRIBUTESINWORDS * 8 + 1];
fprintf(output, "Attribute mask: %s", attributeMask.getText(buf));
fprintf(output, "\n");
diff --git a/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp b/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp
index ad9cb623c17..9b32fab87ba 100644
--- a/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp
+++ b/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp
@@ -59,10 +59,10 @@ printFSREADWRITEREQ(FILE * output, const Uint32 * theData,
sig->numberOfPages);
fprintf(output, " pageData: ");
-
+ unsigned int i;
switch(sig->getFormatFlag(sig->operationFlag)){
case FsReadWriteReq::fsFormatListOfPairs:
- for (unsigned int i = 0; i < sig->numberOfPages*2; i += 2){
+ for (i= 0; i < sig->numberOfPages*2; i += 2){
fprintf(output, " H\'%.8x, H\'%.8x\n", sig->data.pageData[i],
sig->data.pageData[i + 1]);
}
@@ -72,7 +72,7 @@ printFSREADWRITEREQ(FILE * output, const Uint32 * theData,
sig->data.pageData[1]);
break;
case FsReadWriteReq::fsFormatListOfMemPages:
- for (unsigned int i = 0; i < (sig->numberOfPages + 1); i++){
+ for (i= 0; i < (sig->numberOfPages + 1); i++){
fprintf(output, " H\'%.8x, ", sig->data.pageData[i]);
}
break;
diff --git a/ndb/src/common/debugger/signaldata/Makefile b/ndb/src/common/debugger/signaldata/Makefile
deleted file mode 100644
index 5e86aaf97c0..00000000000
--- a/ndb/src/common/debugger/signaldata/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := signaldataprint
-
-SOURCES = TcKeyReq.cpp TcKeyConf.cpp TcKeyRef.cpp \
- TcRollbackRep.cpp \
- TupKey.cpp TupCommit.cpp LqhKey.cpp \
- FsOpenReq.cpp FsCloseReq.cpp FsRef.cpp FsConf.cpp FsReadWriteReq.cpp\
- SignalDataPrint.cpp SignalNames.cpp \
- ContinueB.cpp DihContinueB.cpp NdbfsContinueB.cpp \
- CloseComReqConf.cpp PackedSignal.cpp PrepFailReqRef.cpp \
- GCPSave.cpp DictTabInfo.cpp \
- AlterTable.cpp AlterTab.cpp \
- CreateTrig.cpp AlterTrig.cpp DropTrig.cpp \
- FireTrigOrd.cpp TrigAttrInfo.cpp \
- CreateIndx.cpp AlterIndx.cpp DropIndx.cpp TcIndx.cpp \
- IndxKeyInfo.cpp IndxAttrInfo.cpp \
- FsAppendReq.cpp ScanTab.cpp \
- BackupImpl.cpp BackupSignalData.cpp \
- UtilSequence.cpp UtilPrepare.cpp UtilDelete.cpp UtilExecute.cpp \
- LqhFrag.cpp DropTab.cpp PrepDropTab.cpp LCP.cpp MasterLCP.cpp \
- CopyGCI.cpp SystemError.cpp StartRec.cpp NFCompleteRep.cpp \
- FailRep.cpp DisconnectRep.cpp SignalDroppedRep.cpp \
- SumaImpl.cpp NdbSttor.cpp CreateFragmentation.cpp \
- UtilLock.cpp TuxMaint.cpp TupAccess.cpp AccLock.cpp \
- LqhTrans.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/src/common/debugger/signaldata/Makefile.am b/ndb/src/common/debugger/signaldata/Makefile.am
new file mode 100644
index 00000000000..0d6ed45dcef
--- /dev/null
+++ b/ndb/src/common/debugger/signaldata/Makefile.am
@@ -0,0 +1,32 @@
+
+noinst_LTLIBRARIES = libsignaldataprint.la
+
+libsignaldataprint_la_SOURCES = \
+ TcKeyReq.cpp TcKeyConf.cpp TcKeyRef.cpp \
+ TcRollbackRep.cpp \
+ TupKey.cpp TupCommit.cpp LqhKey.cpp \
+ FsOpenReq.cpp FsCloseReq.cpp FsRef.cpp FsConf.cpp FsReadWriteReq.cpp\
+ SignalDataPrint.cpp SignalNames.cpp \
+ ContinueB.cpp DihContinueB.cpp NdbfsContinueB.cpp \
+ CloseComReqConf.cpp PackedSignal.cpp PrepFailReqRef.cpp \
+ GCPSave.cpp DictTabInfo.cpp \
+ AlterTable.cpp AlterTab.cpp \
+ CreateTrig.cpp AlterTrig.cpp DropTrig.cpp \
+ FireTrigOrd.cpp TrigAttrInfo.cpp \
+ CreateIndx.cpp AlterIndx.cpp DropIndx.cpp TcIndx.cpp \
+ IndxKeyInfo.cpp IndxAttrInfo.cpp \
+ FsAppendReq.cpp ScanTab.cpp \
+ BackupImpl.cpp BackupSignalData.cpp \
+ UtilSequence.cpp UtilPrepare.cpp UtilDelete.cpp UtilExecute.cpp \
+ LqhFrag.cpp DropTab.cpp PrepDropTab.cpp LCP.cpp MasterLCP.cpp \
+ CopyGCI.cpp SystemError.cpp StartRec.cpp NFCompleteRep.cpp \
+ FailRep.cpp DisconnectRep.cpp SignalDroppedRep.cpp \
+ SumaImpl.cpp NdbSttor.cpp CreateFragmentation.cpp \
+ UtilLock.cpp TuxMaint.cpp TupAccess.cpp AccLock.cpp \
+ LqhTrans.cpp ReadNodesConf.cpp CntrStart.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/common/debugger/signaldata/Makefile_old b/ndb/src/common/debugger/signaldata/Makefile_old
new file mode 100644
index 00000000000..bd00667b482
--- /dev/null
+++ b/ndb/src/common/debugger/signaldata/Makefile_old
@@ -0,0 +1,33 @@
+include .defs.mk
+
+TYPE := ndbapi
+
+PIC_ARCHIVE := Y
+ARCHIVE_TARGET := signaldataprint
+
+SOURCES = TcKeyReq.cpp TcKeyConf.cpp TcKeyRef.cpp \
+ TcRollbackRep.cpp \
+ TupKey.cpp TupCommit.cpp LqhKey.cpp \
+ FsOpenReq.cpp FsCloseReq.cpp FsRef.cpp FsConf.cpp FsReadWriteReq.cpp\
+ SignalDataPrint.cpp SignalNames.cpp \
+ ContinueB.cpp DihContinueB.cpp NdbfsContinueB.cpp \
+ CloseComReqConf.cpp PackedSignal.cpp PrepFailReqRef.cpp \
+ GCPSave.cpp DictTabInfo.cpp \
+ AlterTable.cpp AlterTab.cpp \
+ CreateTrig.cpp AlterTrig.cpp DropTrig.cpp \
+ FireTrigOrd.cpp TrigAttrInfo.cpp \
+ CreateIndx.cpp AlterIndx.cpp DropIndx.cpp TcIndx.cpp \
+ IndxKeyInfo.cpp IndxAttrInfo.cpp \
+ FsAppendReq.cpp ScanTab.cpp \
+ BackupImpl.cpp BackupSignalData.cpp \
+ UtilSequence.cpp UtilPrepare.cpp UtilDelete.cpp UtilExecute.cpp \
+ LqhFrag.cpp DropTab.cpp PrepDropTab.cpp LCP.cpp MasterLCP.cpp \
+ CopyGCI.cpp SystemError.cpp StartRec.cpp NFCompleteRep.cpp \
+ FailRep.cpp DisconnectRep.cpp SignalDroppedRep.cpp \
+ SumaImpl.cpp NdbSttor.cpp CreateFragmentation.cpp \
+ CntrStart.cpp ReadNodesConf.cpp \
+ UtilLock.cpp TuxMaint.cpp TupAccess.cpp AccLock.cpp \
+ LqhTrans.cpp
+
+include $(NDB_TOP)/Epilogue.mk
+
diff --git a/ndb/src/common/debugger/signaldata/ReadNodesConf.cpp b/ndb/src/common/debugger/signaldata/ReadNodesConf.cpp
new file mode 100644
index 00000000000..103f4a884f1
--- /dev/null
+++ b/ndb/src/common/debugger/signaldata/ReadNodesConf.cpp
@@ -0,0 +1,24 @@
+#include <signaldata/ReadNodesConf.hpp>
+
+bool
+printREAD_NODES_CONF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const ReadNodesConf * const sig = (ReadNodesConf *)theData;
+ fprintf(output, " noOfNodes: %x\n", sig->noOfNodes);
+ fprintf(output, " ndynamicId: %x\n", sig->ndynamicId);
+ fprintf(output, " masterNodeId: %x\n", sig->masterNodeId);
+
+ char buf[32*NdbNodeBitmask::Size+1];
+ fprintf(output, " allNodes(defined): %s\n",
+ BitmaskImpl::getText(NdbNodeBitmask::Size, sig->allNodes, buf));
+ fprintf(output, " inactiveNodes: %s\n",
+ BitmaskImpl::getText(NdbNodeBitmask::Size, sig->inactiveNodes, buf));
+ fprintf(output, " clusterNodes: %s\n",
+ BitmaskImpl::getText(NdbNodeBitmask::Size, sig->clusterNodes, buf));
+ fprintf(output, " startedNodes: %s\n",
+ BitmaskImpl::getText(NdbNodeBitmask::Size, sig->startedNodes, buf));
+ fprintf(output, " startingNodes: %s\n",
+ BitmaskImpl::getText(NdbNodeBitmask::Size, sig->startingNodes, buf));
+ return true;
+}
+
diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
index 2236d0c0af1..d49e316ad38 100644
--- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
@@ -70,6 +70,8 @@
#include <signaldata/NdbSttor.hpp>
#include <signaldata/CreateFragmentation.hpp>
#include <signaldata/UtilLock.hpp>
+#include <signaldata/CntrStart.hpp>
+#include <signaldata/ReadNodesConf.hpp>
#include <signaldata/TuxMaint.hpp>
#include <signaldata/TupAccess.hpp>
#include <signaldata/AccLock.hpp>
@@ -240,6 +242,12 @@ SignalDataPrintFunctions[] = {
,{ GSN_UTIL_UNLOCK_REQ, printUTIL_UNLOCK_REQ }
,{ GSN_UTIL_UNLOCK_REF, printUTIL_UNLOCK_REF }
,{ GSN_UTIL_UNLOCK_CONF, printUTIL_UNLOCK_CONF }
+ ,{ GSN_CNTR_START_REQ, printCNTR_START_REQ }
+ ,{ GSN_CNTR_START_REF, printCNTR_START_REF }
+ ,{ GSN_CNTR_START_CONF, printCNTR_START_CONF }
+
+ ,{ GSN_READ_NODESCONF, printREAD_NODES_CONF }
+
,{ GSN_TUX_MAINT_REQ, printTUX_MAINT_REQ }
,{ GSN_TUP_READ_ATTRS, printTUP_READ_ATTRS }
,{ GSN_TUP_QUERY_TH, printTUP_QUERY_TH }
diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp
index 4e5c8603db1..377a588dbb0 100644
--- a/ndb/src/common/debugger/signaldata/SignalNames.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp
@@ -101,40 +101,23 @@ const GsnName SignalNames [] = {
,{ GSN_ADD_FRAGREQ, "ADD_FRAGREQ" }
,{ GSN_API_FAILCONF, "API_FAILCONF" }
,{ GSN_API_FAILREQ, "API_FAILREQ" }
- ,{ GSN_APPL_CHANGEREP, "APPL_CHANGEREP" }
- // ,{ GSN_APPL_ERROR, "APPL_ERROR" }
- ,{ GSN_APPL_HB, "APPL_HB" }
- ,{ GSN_APPL_HBREQ, "APPL_HBREQ" }
- ,{ GSN_APPL_REGCONF, "APPL_REGCONF" }
- ,{ GSN_APPL_REGREF, "APPL_REGREF" }
- ,{ GSN_APPL_REGREQ, "APPL_REGREQ" }
- ,{ GSN_APPL_RUN, "APPL_RUN" }
- ,{ GSN_APPL_STARTCONF, "APPL_STARTCONF" }
- ,{ GSN_APPL_STARTREG, "APPL_STARTREG" }
,{ GSN_CHECK_LCP_STOP, "CHECK_LCP_STOP" }
,{ GSN_CLOSE_COMCONF, "CLOSE_COMCONF" }
,{ GSN_CLOSE_COMREQ, "CLOSE_COMREQ" }
,{ GSN_CM_ACKADD, "CM_ACKADD" }
- ,{ GSN_CM_ACKALARM, "CM_ACKALARM" }
,{ GSN_CM_ADD, "CM_ADD" }
- ,{ GSN_CM_APPCHG, "CM_APPCHG" }
+ ,{ GSN_CM_ADD_REP, "CM_ADD_REP" }
,{ GSN_CM_HEARTBEAT, "CM_HEARTBEAT" }
- ,{ GSN_CM_INFOCONF, "CM_INFOCONF" }
- ,{ GSN_CM_INFOREQ, "CM_INFOREQ" }
- ,{ GSN_CM_INIT, "CM_INIT" }
,{ GSN_CM_NODEINFOCONF, "CM_NODEINFOCONF" }
,{ GSN_CM_NODEINFOREF, "CM_NODEINFOREF" }
,{ GSN_CM_NODEINFOREQ, "CM_NODEINFOREQ" }
,{ GSN_CM_REGCONF, "CM_REGCONF" }
,{ GSN_CM_REGREF, "CM_REGREF" }
,{ GSN_CM_REGREQ, "CM_REGREQ" }
- ,{ GSN_CM_RUN, "CM_RUN" }
- ,{ GSN_CMVMI_CFGCONF, "CMVMI_CFGCONF" }
- ,{ GSN_CMVMI_CFGREQ, "CMVMI_CFGREQ" }
- ,{ GSN_CNTR_CHANGEREP, "CNTR_CHANGEREP" }
- ,{ GSN_CNTR_MASTERCONF, "CNTR_MASTERCONF" }
- ,{ GSN_CNTR_MASTERREF, "CNTR_MASTERREF" }
- ,{ GSN_CNTR_MASTERREQ, "CNTR_MASTERREQ" }
+ ,{ GSN_CNTR_START_REQ, "CNTR_START_REQ" }
+ ,{ GSN_CNTR_START_REF, "CNTR_START_REF" }
+ ,{ GSN_CNTR_START_CONF, "CNTR_START_CONF" }
+ ,{ GSN_CNTR_START_REP, "CNTR_START_REP" }
,{ GSN_CNTR_WAITREP, "CNTR_WAITREP" }
,{ GSN_COMMIT, "COMMIT" }
,{ GSN_COMMIT_FAILCONF, "COMMIT_FAILCONF" }
@@ -294,9 +277,6 @@ const GsnName SignalNames [] = {
,{ GSN_NEXT_SCANREQ, "NEXT_SCANREQ" }
,{ GSN_NEXTOPERATION, "NEXTOPERATION" }
,{ GSN_NF_COMPLETEREP, "NF_COMPLETEREP" }
- ,{ GSN_NODE_STATESCONF, "NODE_STATESCONF" }
- ,{ GSN_NODE_STATESREF, "NODE_STATESREF" }
- ,{ GSN_NODE_STATESREQ, "NODE_STATESREQ" }
,{ GSN_OPEN_COMCONF, "OPEN_COMCONF" }
,{ GSN_OPEN_COMREF, "OPEN_COMREF" }
,{ GSN_OPEN_COMREQ, "OPEN_COMREQ" }
@@ -318,8 +298,8 @@ const GsnName SignalNames [] = {
,{ GSN_SEND_PACKED, "SEND_PACKED" }
,{ GSN_SET_LOGLEVELORD, "SET_LOGLEVELORD" }
,{ GSN_SHRINKCHECK2, "SHRINKCHECK2" }
- ,{ GSN_SIZEALT_ACK, "SIZEALT_ACK" }
- ,{ GSN_SIZEALT_REP, "SIZEALT_REP" }
+ ,{ GSN_READ_CONFIG_REQ, "READ_CONFIG_REQ" }
+ ,{ GSN_READ_CONFIG_CONF, "READ_CONFIG_CONF" }
,{ GSN_SR_FRAGIDCONF, "SR_FRAGIDCONF" }
,{ GSN_SR_FRAGIDREF, "SR_FRAGIDREF" }
,{ GSN_SR_FRAGIDREQ, "SR_FRAGIDREQ" }
@@ -396,7 +376,6 @@ const GsnName SignalNames [] = {
,{ GSN_UPDATE_TOCONF, "UPDATE_TOCONF" }
,{ GSN_UPDATE_TOREF, "UPDATE_TOREF" }
,{ GSN_UPDATE_TOREQ, "UPDATE_TOREQ" }
- ,{ GSN_VOTE_MASTERORD, "VOTE_MASTERORD" }
,{ GSN_TUP_ALLOCREQ, "TUP_ALLOCREQ" }
,{ GSN_LQH_ALLOCREQ, "LQH_ALLOCREQ" }
,{ GSN_TUP_DEALLOCREQ, "TUP_DEALLOCREQ" }
@@ -428,7 +407,6 @@ const GsnName SignalNames [] = {
,{ GSN_CHECKNODEGROUPSREQ, "CHECKNODEGROUPSREQ" }
,{ GSN_CHECKNODEGROUPSCONF, "CHECKNODEGROUPSCONF" }
- ,{ GSN_ARBIT_CFG, "ARBIT_CFG" }
,{ GSN_ARBIT_PREPREQ, "ARBIT_PREPREQ" }
,{ GSN_ARBIT_PREPCONF, "ARBIT_PREPCONF" }
,{ GSN_ARBIT_PREPREF, "ARBIT_PREPREF" }
diff --git a/ndb/src/common/debugger/signaldata/TuxMaint.cpp b/ndb/src/common/debugger/signaldata/TuxMaint.cpp
index 06ac475382c..ba6a299b77d 100644
--- a/ndb/src/common/debugger/signaldata/TuxMaint.cpp
+++ b/ndb/src/common/debugger/signaldata/TuxMaint.cpp
@@ -24,10 +24,10 @@ printTUX_MAINT_REQ(FILE* output, const Uint32* theData, Uint32 len, Uint16 rbn)
//const bool inOut = rbn & (1 << 15);
const TuxMaintReq* const sig = (const TuxMaintReq*)theData;
fprintf(output, " errorCode=%d\n", sig->errorCode);
- fprintf(output, " table: id=%d", sig->tableId);
- fprintf(output, " index: id=%d", sig->indexId);
- fprintf(output, " fragment: id=%d\n", sig->fragId);
- fprintf(output, " tuple: addr=0x%x version=%d\n", sig->tupAddr, sig->tupVersion);
+ fprintf(output, " table: id=%u", sig->tableId);
+ fprintf(output, " index: id=%u", sig->indexId);
+ fprintf(output, " fragment: id=%u\n", sig->fragId);
+ fprintf(output, " tuple: loc=%u.%u version=%u\n", sig->pageId, sig->pageOffset, sig->tupVersion);
const Uint32 opCode = sig->opInfo & 0xFF;
const Uint32 opFlag = sig->opInfo >> 8;
switch (opCode ) {
diff --git a/ndb/src/common/editline/Makefile.am b/ndb/src/common/editline/Makefile.am
new file mode 100644
index 00000000000..4f53bdc6326
--- /dev/null
+++ b/ndb/src/common/editline/Makefile.am
@@ -0,0 +1,10 @@
+
+noinst_LIBRARIES = libeditline.a
+
+libeditline_a_SOURCES = complete.c editline.c sysunix.c
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/ndb/include
+DEFS = -DANSI_ARROWS -DHAVE_TCGETATTR -DSYS_UNIX
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/common/editline/Makefile b/ndb/src/common/editline/Makefile_old
index 800df8f0f31..800df8f0f31 100644
--- a/ndb/src/common/editline/Makefile
+++ b/ndb/src/common/editline/Makefile_old
diff --git a/ndb/src/common/logger/Makefile.am b/ndb/src/common/logger/Makefile.am
new file mode 100644
index 00000000000..0a48214c37c
--- /dev/null
+++ b/ndb/src/common/logger/Makefile.am
@@ -0,0 +1,11 @@
+
+noinst_LTLIBRARIES = liblogger.la
+
+liblogger_la_SOURCES = Logger.cpp LogHandlerList.cpp LogHandler.cpp \
+ ConsoleLogHandler.cpp FileLogHandler.cpp SysLogHandler.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/common/logger/Makefile b/ndb/src/common/logger/Makefile_old
index 994eb86ba35..994eb86ba35 100644
--- a/ndb/src/common/logger/Makefile
+++ b/ndb/src/common/logger/Makefile_old
diff --git a/ndb/src/common/mgmcommon/Config.cpp b/ndb/src/common/mgmcommon/Config.cpp
index 5492394ee4a..c0819b9f463 100644
--- a/ndb/src/common/mgmcommon/Config.cpp
+++ b/ndb/src/common/mgmcommon/Config.cpp
@@ -26,23 +26,17 @@
//*****************************************************************************
Config::Config() {
- m_info = new ConfigInfo();
-}
-
-Config::Config(const Config & org) :
- Properties(org) {
-
- m_info = new ConfigInfo();
-}
-
-Config::Config(const Properties & org) :
- Properties(org) {
-
- m_info = new ConfigInfo();
+ m_oldConfig = 0;
+ m_configValues = 0;
}
Config::~Config() {
- delete m_info;
+ if(m_configValues != 0){
+ free(m_configValues);
+ }
+
+ if(m_oldConfig != 0)
+ delete m_oldConfig;
}
/*****************************************************************************/
@@ -52,25 +46,33 @@ Config::printAllNameValuePairs(NdbOut &out,
const Properties *prop,
const char* s) const {
Properties::Iterator it(prop);
- const Properties * section = m_info->getInfo(s);
+ const Properties * section = m_info.getInfo(s);
for (const char* n = it.first(); n != NULL; n = it.next()) {
Uint32 int_value;
const char* str_value;
+ Uint64 int_64;
- if (m_info->getStatus(section, n) == ConfigInfo::INTERNAL)
+ if(!section->contains(n))
continue;
- if (m_info->getStatus(section, n) == ConfigInfo::DEPRICATED)
+ if (m_info.getStatus(section, n) == ConfigInfo::INTERNAL)
continue;
- if (m_info->getStatus(section, n) == ConfigInfo::NOTIMPLEMENTED)
+ if (m_info.getStatus(section, n) == ConfigInfo::DEPRICATED)
+ continue;
+ if (m_info.getStatus(section, n) == ConfigInfo::NOTIMPLEMENTED)
continue;
out << n << ": ";
- switch (m_info->getType(section, n)) {
+ switch (m_info.getType(section, n)) {
case ConfigInfo::INT:
MGM_REQUIRE(prop->get(n, &int_value));
out << int_value;
break;
+
+ case ConfigInfo::INT64:
+ MGM_REQUIRE(prop->get(n, &int_64));
+ out << int_64;
+ break;
case ConfigInfo::BOOL:
MGM_REQUIRE(prop->get(n, &int_value));
@@ -92,6 +94,7 @@ Config::printAllNameValuePairs(NdbOut &out,
/*****************************************************************************/
void Config::printConfigFile(NdbOut &out) const {
+#if 0
Uint32 noOfNodes, noOfConnections, noOfComputers;
MGM_REQUIRE(get("NoOfNodes", &noOfNodes));
MGM_REQUIRE(get("NoOfConnections", &noOfConnections));
@@ -172,15 +175,12 @@ void Config::printConfigFile(NdbOut &out) const {
endl;
}
}
-}
-
-const
-ConfigInfo* Config::getConfigInfo() const {
- return m_info;
+#endif
}
Uint32
Config::getGenerationNumber() const {
+#if 0
Uint32 ret;
const Properties *prop = NULL;
@@ -191,10 +191,14 @@ Config::getGenerationNumber() const {
return ret;
return 0;
+#else
+ return 0;
+#endif
}
int
Config::setGenerationNumber(Uint32 gen) {
+#if 0
Properties *prop = NULL;
getCopy("SYSTEM", &prop);
@@ -205,12 +209,16 @@ Config::setGenerationNumber(Uint32 gen) {
return 0;
}
return -1;
+#else
+ return -1;
+#endif
}
bool
Config::change(const BaseString &section,
const BaseString &param,
const BaseString &value) {
+#if 0
const char *name;
Properties::Iterator it(this);
@@ -252,4 +260,7 @@ Config::change(const BaseString &section,
}
}
return true;
+#else
+ return false;
+#endif
}
diff --git a/ndb/src/common/mgmcommon/Config.hpp b/ndb/src/common/mgmcommon/Config.hpp
index 284256d9ed6..26fd53dbed2 100644
--- a/ndb/src/common/mgmcommon/Config.hpp
+++ b/ndb/src/common/mgmcommon/Config.hpp
@@ -17,7 +17,6 @@
#ifndef Config_H
#define Config_H
-#include <signaldata/ConfigParamId.hpp>
#include <LogLevel.hpp>
#include <kernel_types.h>
@@ -25,6 +24,9 @@
#include <NdbOut.hpp>
#include <ndb_limits.h>
#include <Properties.hpp>
+#include "ConfigInfo.hpp"
+
+class ConfigInfo;
/**
* @class Config
@@ -38,14 +40,14 @@
*
* The following categories (sections) of configuration parameters exists:
* - COMPUTER, DB, MGM, API, TCP, SCI, SHM, OSE
+ *
*/
-class Config : public Properties {
+
+class Config {
public:
/**
* Constructor which loads the object with an Properties object
*/
- Config(const Config & org);
- Config(const Properties & org);
Config();
virtual ~Config();
@@ -58,8 +60,6 @@ public:
printConfigFile(ndb);
}
- const class ConfigInfo* getConfigInfo() const;
-
Uint32 getGenerationNumber() const;
int setGenerationNumber(Uint32);
@@ -69,7 +69,13 @@ public:
const BaseString &param,
const BaseString &value);
+
+ /**
+ * Info
+ */
+ const ConfigInfo * getConfigInfo() const { return &m_info;}
private:
+ ConfigInfo m_info;
void printAllNameValuePairs(NdbOut &out,
const Properties *prop,
@@ -78,7 +84,9 @@ private:
/**
* Information about parameters (min, max values etc)
*/
- const class ConfigInfo* m_info;
+public:
+ Properties * m_oldConfig;
+ struct ndb_mgm_configuration * m_configValues;
};
#endif // Config_H
diff --git a/ndb/src/common/mgmcommon/ConfigInfo.cpp b/ndb/src/common/mgmcommon/ConfigInfo.cpp
index da6024d946f..c2b5fdabf01 100644
--- a/ndb/src/common/mgmcommon/ConfigInfo.cpp
+++ b/ndb/src/common/mgmcommon/ConfigInfo.cpp
@@ -15,7 +15,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "ConfigInfo.hpp"
+#include <mgmapi_config_parameters.h>
+
#define MAX_LINE_LENGTH 255
+#define KEY_INTERNAL 0
/****************************************************************************
* Section names
@@ -56,9 +59,12 @@ bool fixPortNumber(InitConfigFileParser::Context & ctx, const char *);
bool fixShmkey(InitConfigFileParser::Context & ctx, const char *);
bool checkDbConstraints(InitConfigFileParser::Context & ctx, const char *);
bool checkConnectionConstraints(InitConfigFileParser::Context &, const char *);
+bool fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data);
bool fixHostname(InitConfigFileParser::Context & ctx, const char * data);
bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data);
bool fixExtConnection(InitConfigFileParser::Context & ctx, const char * data);
+bool fixDepricated(InitConfigFileParser::Context & ctx, const char *);
+bool saveInConfigValues(InitConfigFileParser::Context & ctx, const char *);
const ConfigInfo::SectionRule
ConfigInfo::m_SectionRules[] = {
@@ -79,21 +85,12 @@ ConfigInfo::m_SectionRules[] = {
{ "TCP", fixPortNumber, 0 },
//{ "SHM", fixShmKey, 0 },
-
- { "COMPUTER", applyDefaultValues, 0 },
-
- { "DB", applyDefaultValues, 0 },
- { "API", applyDefaultValues, 0 },
- { "MGM", applyDefaultValues, 0 },
- { "REP", applyDefaultValues, 0 },
- { "EXTERNAL REP", applyDefaultValues, 0 },
-
- { "TCP", applyDefaultValues, 0 },
- { "SHM", applyDefaultValues, 0 },
- { "SCI", applyDefaultValues, 0 },
- { "OSE", applyDefaultValues, 0 },
- { "DB", checkDbConstraints, 0 },
+ { "DB", fixNodeHostname, 0 },
+ { "API", fixNodeHostname, 0 },
+ { "MGM", fixNodeHostname, 0 },
+ { "REP", fixNodeHostname, 0 },
+ //{ "EXTERNAL REP", fixNodeHostname, 0 },
{ "TCP", fixNodeId, "NodeId1" },
{ "TCP", fixNodeId, "NodeId2" },
@@ -103,6 +100,11 @@ ConfigInfo::m_SectionRules[] = {
{ "SCI", fixNodeId, "NodeId2" },
{ "OSE", fixNodeId, "NodeId1" },
{ "OSE", fixNodeId, "NodeId2" },
+
+ { "TCP", fixHostname, "HostName1" },
+ { "TCP", fixHostname, "HostName2" },
+ { "OSE", fixHostname, "HostName1" },
+ { "OSE", fixHostname, "HostName2" },
/**
* fixExtConnection must be after fixNodeId
@@ -112,6 +114,12 @@ ConfigInfo::m_SectionRules[] = {
{ "SCI", fixExtConnection, 0 },
{ "OSE", fixExtConnection, 0 },
+ { "*", applyDefaultValues, "user" },
+ { "*", fixDepricated, 0 },
+ { "*", applyDefaultValues, "system" },
+
+ { "DB", checkDbConstraints, 0 },
+
/**
* checkConnectionConstraints must be after fixExtConnection
*/
@@ -120,24 +128,63 @@ ConfigInfo::m_SectionRules[] = {
{ "SCI", checkConnectionConstraints, 0 },
{ "OSE", checkConnectionConstraints, 0 },
- { "COMPUTER", checkMandatory, 0 },
- { "DB", checkMandatory, 0 },
- { "API", checkMandatory, 0 },
- { "MGM", checkMandatory, 0 },
- { "REP", checkMandatory, 0 },
+ { "*", checkMandatory, 0 },
+
+ { "DB", saveInConfigValues, 0 },
+ { "API", saveInConfigValues, 0 },
+ { "MGM", saveInConfigValues, 0 },
+ { "REP", saveInConfigValues, 0 },
+
+ { "TCP", saveInConfigValues, 0 },
+ { "SHM", saveInConfigValues, 0 },
+ { "SCI", saveInConfigValues, 0 },
+ { "OSE", saveInConfigValues, 0 }
+};
+const int ConfigInfo::m_NoOfRules = sizeof(m_SectionRules)/sizeof(SectionRule);
- { "TCP", checkMandatory, 0 },
- { "SHM", checkMandatory, 0 },
- { "SCI", checkMandatory, 0 },
- { "OSE", checkMandatory, 0 },
+/****************************************************************************
+ * Config Rules declarations
+ ****************************************************************************/
+bool addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>&sections,
+ struct InitConfigFileParser::Context &ctx,
+ const char * ruleData);
+
+const ConfigInfo::ConfigRule
+ConfigInfo::m_ConfigRules[] = {
+ { addNodeConnections, 0 },
+ { 0, 0 }
+};
+
+struct DepricationTransform {
+ const char * m_section;
+ const char * m_oldName;
+ const char * m_newName;
+ double m_add;
+ double m_mul;
+};
- { "TCP", fixHostname, "HostName1" },
- { "TCP", fixHostname, "HostName2" },
- { "OSE", fixHostname, "HostName1" },
- { "OSE", fixHostname, "HostName2" },
+static
+const DepricationTransform f_deprication[] = {
+ { "DB", "NoOfIndexPages", "IndexMemory", 0, 8192 }
+ ,{ "DB", "MemorySpaceIndexes", "IndexMemory", 0, 8192 }
+ ,{ "DB", "NoOfDataPages", "DataMemory", 0, 8192 }
+ ,{ "DB", "MemorySpaceTuples", "DataMemory", 0, 8192 }
+ ,{ "DB", "TransactionInactiveTimeBeforeAbort", "TransactionInactiveTimeout",
+ 0, 1 }
+ ,{ "TCP", "ProcessId1", "NodeId1", 0, 1}
+ ,{ "TCP", "ProcessId2", "NodeId2", 0, 1}
+ ,{ "TCP", "SendBufferSize", "SendBufferMemory", 0, 16384 }
+ ,{ "TCP", "MaxReceiveSize", "ReceiveBufferMemory", 0, 16384 }
+
+ ,{ "SHM", "ProcessId1", "NodeId1", 0, 1}
+ ,{ "SHM", "ProcessId2", "NodeId2", 0, 1}
+ ,{ "SCI", "ProcessId1", "NodeId1", 0, 1}
+ ,{ "SCI", "ProcessId2", "NodeId2", 0, 1}
+ ,{ "OSE", "ProcessId1", "NodeId1", 0, 1}
+ ,{ "OSE", "ProcessId2", "NodeId2", 0, 1}
+ ,{ 0, 0, 0, 0, 0}
};
-const int ConfigInfo::m_NoOfRules = sizeof(m_SectionRules)/sizeof(SectionRule);
/**
* The default constructors create objects with suitable values for the
@@ -166,224 +213,340 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
/****************************************************************************
* COMPUTER
- ****************************************************************************/
-
- {"Id",
- "Id",
- "COMPUTER",
- "Name of computer",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0},
-
- {"HostName",
- "HostName",
- "COMPUTER",
- "Hostname of computer (e.g. mysql.com)",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"ByteOrder",
- "ByteOrder",
- "COMPUTER",
- "Not yet implemented",
- ConfigInfo::USED, // Actually not used, but since it is MANDATORY,
- // we don't want any warning message
- false,
- ConfigInfo::STRING,
- MANDATORY, // Big == 0, Little == 1, NotSet == 2 (?)
- 0,
- 0x7FFFFFFF},
+ ***************************************************************************/
+ {
+ KEY_INTERNAL,
+ "COMPUTER",
+ "COMPUTER",
+ "Computer section",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::SECTION,
+ 0,
+ 0, 0 },
+
+ {
+ KEY_INTERNAL,
+ "Id",
+ "COMPUTER",
+ "Name of computer",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0 },
+
+ {
+ KEY_INTERNAL,
+ "HostName",
+ "COMPUTER",
+ "Hostname of computer (e.g. alzato.com)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_BYTE_ORDER,
+ "ByteOrder",
+ "COMPUTER",
+ "Not yet implemented",
+ ConfigInfo::USED, // Actually not used, but since it is MANDATORY,
+ // we don't want any warning message
+ false,
+ ConfigInfo::STRING,
+ MANDATORY, // Big == 0, Little == 1, NotSet == 2 (?)
+ 0,
+ 1 },
/****************************************************************************
- * DB
- ****************************************************************************/
-
- {"Id",
- "Id",
- "DB",
- "Number identifying the database node (DB)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 1,
- (MAX_NODES - 1)},
-
- {"Type",
- "Type",
- "DB",
- "Type of node (Should have value DB)",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0},
-
- {"NoOfReplicas",
- "NoOfReplicas",
- "DB",
- "Number of copies of all data in the database (1-4)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 1,
- 4},
-
- {"MaxNoOfAttributes",
- "MaxNoOfAttributes",
- "DB",
- "Total number of attributes stored in database. I.e. sum over all tables",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 1000,
- 32,
- 4096},
+ * SYSTEM
+ ***************************************************************************/
+ {
+ CFG_SECTION_SYSTEM,
+ "SYSTEM",
+ "SYSTEM",
+ "System section",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::SECTION,
+ CFG_SECTION_SYSTEM,
+ 0,
+ 0 },
+
+ {
+ CFG_SYS_NAME,
+ "Name",
+ "SYSTEM",
+ "Name of system (NDB Cluster)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0 },
- {"MaxNoOfTables",
- "MaxNoOfTables",
- "DB",
- "Total number of tables stored in the database",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 32,
- 8,
- 128},
+ {
+ CFG_SYS_REPLICATION_ROLE,
+ "ReplicationRole",
+ "SYSTEM",
+ "Role in Global Replication (None, Primary, or Standby)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0 },
- {"MaxNoOfIndexes",
- "MaxNoOfIndexes",
- "DB",
- "Total number of indexes that can be defined in the system",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 128,
- 0,
- 2048},
-
- {"MaxNoOfConcurrentIndexOperations",
- "MaxNoOfConcurrentIndexOperations",
- "DB",
- "Total number of index operations that can execute simultaneously on one DB node",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 8192,
- 0,
- 1000000
+ {
+ CFG_SYS_PRIMARY_MGM_NODE,
+ "PrimaryMGMNode",
+ "SYSTEM",
+ "Node id of Primary MGM node",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_SYS_CONFIG_GENERATION,
+ "ConfigGenerationNumber",
+ "SYSTEM",
+ "Configuration generation number",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 0x7FFFFFFF },
+
+ /***************************************************************************
+ * DB
+ ***************************************************************************/
+ {
+ CFG_SECTION_NODE,
+ "DB",
+ "DB",
+ "Node section",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::SECTION,
+ NODE_TYPE_DB,
+ 0, 0
},
- {"MaxNoOfTriggers",
- "MaxNoOfTriggers",
- "DB",
- "Total number of triggers that can be defined in the system",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 768,
- 0,
- 2432},
-
- {"MaxNoOfFiredTriggers",
- "MaxNoOfFiredTriggers",
- "DB",
- "Total number of triggers that can fire simultaneously in one DB node",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 1000,
- 0,
- 1000000},
-
- {"ExecuteOnComputer",
- "ExecuteOnComputer",
- "DB",
- "String referencing an earlier defined COMPUTER",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
+ {
+ CFG_NODE_HOST,
+ "HostName",
+ "DB",
+ "Name of computer for this node",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_SYSTEM,
+ "System",
+ "DB",
+ "Name of system for this node",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_ID,
+ "Id",
+ "DB",
+ "Number identifying the database node (DB)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 1,
+ (MAX_NODES - 1) },
+
+ {
+ CFG_DB_NO_REPLICAS,
+ "NoOfReplicas",
+ "DB",
+ "Number of copies of all data in the database (1-4)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 1,
+ 2 },
+
+ {
+ CFG_DB_NO_ATTRIBUTES,
+ "MaxNoOfAttributes",
+ "DB",
+ "Total number of attributes stored in database. I.e. sum over all tables",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 1000,
+ 32,
+ 4096 },
- {"MaxNoOfSavedMessages",
- "MaxNoOfSavedMessages",
- "DB",
- "Max number of error messages in error log and max number of trace files",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 25,
- 0,
- 0x7FFFFFFF},
-
- {"LockPagesInMainMemory",
- "LockPagesInMainMemory",
- "DB",
- "If set to yes, then NDB Cluster data will not be swapped out to disk",
- ConfigInfo::USED,
- true,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF},
-
- {"SleepWhenIdle",
- "SleepWhenIdle",
- "DB",
- "?",
- ConfigInfo::DEPRICATED,
- true,
- ConfigInfo::BOOL,
- true,
- 0,
- 0x7FFFFFFF},
-
- {"NoOfSignalsToExecuteBetweenCommunicationInterfacePoll",
- "NoOfSignalsToExecuteBetweenCommunicationInterfacePoll",
- "DB",
- "?",
- ConfigInfo::DEPRICATED,
- true,
- ConfigInfo::INT,
- 20,
- 1,
- 0x7FFFFFFF},
+ {
+ CFG_DB_NO_TABLES,
+ "MaxNoOfTables",
+ "DB",
+ "Total number of tables stored in the database",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 32,
+ 8,
+ 128 },
- {"TimeBetweenWatchDogCheck",
- "TimeBetweenWatchDogCheck",
- "DB",
- "Time between execution checks inside a database node",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 4000,
- 70,
- 0x7FFFFFFF},
-
- {"StopOnError",
- "StopOnError",
- "DB",
- "If set to N, the DB automatically restarts/recovers in case of node failure",
- ConfigInfo::USED,
- true,
- ConfigInfo::BOOL,
- true,
- 0,
- 0x7FFFFFFF},
-
- { "RestartOnErrorInsert",
+ {
+ CFG_DB_NO_INDEXES,
+ "MaxNoOfIndexes",
+ "DB",
+ "Total number of indexes that can be defined in the system",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 128,
+ 0,
+ 2048 },
+
+ {
+ CFG_DB_NO_INDEX_OPS,
+ "MaxNoOfConcurrentIndexOperations",
+ "DB",
+ "Total number of index operations that can execute simultaneously on one DB node",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 8192,
+ 0,
+ 1000000
+ },
+
+ {
+ CFG_DB_NO_TRIGGERS,
+ "MaxNoOfTriggers",
+ "DB",
+ "Total number of triggers that can be defined in the system",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 768,
+ 0,
+ 2432 },
+
+ {
+ CFG_DB_NO_TRIGGER_OPS,
+ "MaxNoOfFiredTriggers",
+ "DB",
+ "Total number of triggers that can fire simultaneously in one DB node",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 1000,
+ 0,
+ 1000000 },
+
+ {
+ KEY_INTERNAL,
+ "ExecuteOnComputer",
+ "DB",
+ "String referencing an earlier defined COMPUTER",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_DB_NO_SAVE_MSGS,
+ "MaxNoOfSavedMessages",
+ "DB",
+ "Max number of error messages in error log and max number of trace files",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 25,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_DB_MEMLOCK,
+ "LockPagesInMainMemory",
+ "DB",
+ "If set to yes, then NDB Cluster data will not be swapped out to disk",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::BOOL,
+ false,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "SleepWhenIdle",
+ "DB",
+ 0,
+ ConfigInfo::DEPRICATED,
+ true,
+ ConfigInfo::BOOL,
+ true,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "NoOfSignalsToExecuteBetweenCommunicationInterfacePoll",
+ "DB",
+ 0,
+ ConfigInfo::DEPRICATED,
+ true,
+ ConfigInfo::INT,
+ 20,
+ 1,
+ 0x7FFFFFFF },
+
+ {
+ CFG_DB_WATCHDOG_INTERVAL,
+ "TimeBetweenWatchDogCheck",
+ "DB",
+ "Time between execution checks inside a database node",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 4000,
+ 70,
+ 0x7FFFFFFF },
+
+ {
+ CFG_DB_STOP_ON_ERROR,
+ "StopOnError",
+ "DB",
+ "If set to N, the DB automatically restarts/recovers in case of node failure",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::BOOL,
+ true,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_DB_STOP_ON_ERROR_INSERT,
"RestartOnErrorInsert",
"DB",
"See src/kernel/vm/Emulator.hpp NdbRestartType for details",
@@ -394,41 +557,45 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0,
4 },
- {"MaxNoOfConcurrentOperations",
- "MaxNoOfConcurrentOperations",
- "DB",
- "Max no of op:s on DB (op:s within a transaction are concurrently executed)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 8192,
- 32,
- 1000000},
-
- {"MaxNoOfConcurrentTransactions",
- "MaxNoOfConcurrentTransactions",
- "DB",
- "Max number of transaction executing concurrently on the DB node",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 4096,
- 32,
- 1000000},
-
- {"MaxNoOfConcurrentScans",
- "MaxNoOfConcurrentScans",
- "DB",
- "Max number of scans executing concurrently on the DB node",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 25,
- 2,
- 500},
-
- {"TransactionBufferMemory",
- "TransactionBufferMemory",
+ {
+ CFG_DB_NO_OPS,
+ "MaxNoOfConcurrentOperations",
+ "DB",
+ "Max no of op:s on DB (op:s within a transaction are concurrently executed)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 8192,
+ 32,
+ 1000000 },
+
+ {
+ CFG_DB_NO_TRANSACTIONS,
+ "MaxNoOfConcurrentTransactions",
+ "DB",
+ "Max number of transaction executing concurrently on the DB node",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 4096,
+ 32,
+ 1000000 },
+
+ {
+ CFG_DB_NO_SCANS,
+ "MaxNoOfConcurrentScans",
+ "DB",
+ "Max number of scans executing concurrently on the DB node",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 25,
+ 2,
+ 500 },
+
+ {
+ CFG_DB_TRANS_BUFFER_MEM,
+ "TransactionBufferMemory",
"DB",
"Dynamic buffer space (in bytes) for key and attribute data allocated for each DB node",
ConfigInfo::USED,
@@ -436,437 +603,442 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
1024000,
1024,
- 0x7FFFFFFF},
+ 0x7FFFFFFF },
- {"NoOfIndexPages",
- "NoOfIndexPages",
- "DB",
- "Number of 8k byte pages on each DB node for storing indexes",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 3000,
- 128,
- 192000},
-
- {"MemorySpaceIndexes",
- "NoOfIndexPages",
- "DB",
- "Depricated",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 128,
- 192000},
-
- {"NoOfDataPages",
- "NoOfDataPages",
- "DB",
- "Number of 8k byte pages on each DB node for storing data",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 10000,
- 128,
- 400000},
-
- {"MemorySpaceTuples",
- "NoOfDataPages",
- "DB",
- "Depricated",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 128,
- 400000},
-
- {"NoOfDiskBufferPages",
- "NoOfDiskBufferPages",
- "DB",
- "?",
- ConfigInfo::NOTIMPLEMENTED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 0},
-
- {"MemoryDiskPages",
- "NoOfDiskBufferPages",
- "DB",
- "?",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0},
-
- {"NoOfFreeDiskClusters",
- "NoOfFreeDiskClusters",
- "DB",
- "?",
- ConfigInfo::NOTIMPLEMENTED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 0},
-
- {"NoOfDiskClusters",
- "NoOfDiskClusters",
- "DB",
- "?",
- ConfigInfo::NOTIMPLEMENTED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 0x7FFFFFFF},
+ {
+ CFG_DB_INDEX_MEM,
+ "IndexMemory",
+ "DB",
+ "Number bytes on each DB node allocated for storing indexes",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT64,
+ 3000 * 8192,
+ 128 * 8192,
+ ((Uint64)192000) * ((Uint64)8192) },
+
+ {
+ KEY_INTERNAL,
+ "NoOfIndexPages",
+ "DB",
+ "IndexMemory",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ 3000,
+ 128,
+ 192000 },
+
+ {
+ KEY_INTERNAL,
+ "MemorySpaceIndexes",
+ "DB",
+ "IndexMemory",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 128,
+ 192000 },
+
+ {
+ CFG_DB_DATA_MEM,
+ "DataMemory",
+ "DB",
+ "Number bytes on each DB node allocated for storing data",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT64,
+ 10000 * 8192,
+ 128 * 8192,
+ ((Uint64)400000) * ((Uint64)8192) },
+
+ {
+ KEY_INTERNAL,
+ "NoOfDataPages",
+ "DB",
+ "DataMemory",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ 10000,
+ 128,
+ 400000 },
+
+ {
+ KEY_INTERNAL,
+ "MemorySpaceTuples",
+ "DB",
+ "DataMemory",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 128,
+ 400000 },
- {"TimeToWaitAlive",
- "TimeToWaitAlive",
- "DB",
- "Time to wait for other nodes to become alive during initial system start",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 25,
- 2,
- 4000},
-
- {"HeartbeatIntervalDbDb",
- "HeartbeatIntervalDbDb",
- "DB",
- "Time between DB-to-DB heartbeats. DB considered dead after 3 missed HBs",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 1500,
- 10,
- 0x7FFFFFFF},
-
- {"HeartbeatIntervalDbApi",
- "HeartbeatIntervalDbApi",
- "DB",
- "Time between API-to-DB heartbeats. API connection closed after 3 missed HBs",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 1500,
- 100,
- 0x7FFFFFFF},
-
- {"TimeBetweenLocalCheckpoints",
- "TimeBetweenLocalCheckpoints",
- "DB",
- "Time between taking snapshots of the database (expressed in 2log of bytes)",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 20,
- 0,
- 31},
-
- {"TimeBetweenGlobalCheckpoints",
- "TimeBetweenGlobalCheckpoints",
- "DB",
- "Time between doing group commit of transactions to disk",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 2000,
- 10,
- 32000},
-
- {"NoOfFragmentLogFiles",
- "NoOfFragmentLogFiles",
- "DB",
- "No of 16 Mbyte Redo log files in each of 4 file sets belonging to DB node",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 8,
- 1,
- 0x7FFFFFFF},
-
- {"MaxNoOfOpenFiles",
- "MaxNoOfOpenFiles",
- "DB",
- "Max number of files open per DB node.(One thread is created per file)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 40,
- 20,
- 256},
-
- {"NoOfConcurrentCheckpointsDuringRestart",
- "NoOfConcurrentCheckpointsDuringRestart",
- "DB",
- "?",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 1,
- 1,
- 4},
+ {
+ CFG_DB_START_PARTIAL_TIMEOUT,
+ "StartPartialTimeout",
+ "DB",
+ "Time to wait before trying to start wo/ all nodes. 0=Wait forever",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 30000,
+ 0,
+ ~0 },
+
+ {
+ CFG_DB_START_PARTITION_TIMEOUT,
+ "StartPartitionedTimeout",
+ "DB",
+ "Time to wait before trying to start partitioned. 0=Wait forever",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 60000,
+ 0,
+ ~0 },
- {"TimeBetweenInactiveTransactionAbortCheck",
- "TimeBetweenInactiveTransactionAbortCheck",
- "DB",
- "Time between inactive transaction checks",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 1000,
- 1000,
- 0x7FFFFFFF},
+ {
+ CFG_DB_START_FAILURE_TIMEOUT,
+ "StartFailureTimeout",
+ "DB",
+ "Time to wait before terminating. 0=Wait forever",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 5*60000,
+ 0,
+ ~0 },
+
+ {
+ KEY_INTERNAL,
+ "TimeToWaitAlive",
+ "DB",
+ "Start{Partial/Partitioned/Failure}Time",
+ ConfigInfo::DEPRICATED,
+ true,
+ ConfigInfo::INT,
+ 25,
+ 2,
+ 4000 },
+
+ {
+ CFG_DB_HEARTBEAT_INTERVAL,
+ "HeartbeatIntervalDbDb",
+ "DB",
+ "Time between DB-DB heartbeats. DB considered dead after 3 missed HBs",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 1500,
+ 10,
+ 0x7FFFFFFF },
+
+ {
+ CFG_DB_API_HEARTBEAT_INTERVAL,
+ "HeartbeatIntervalDbApi",
+ "DB",
+ "Time between API-DB heartbeats. API connection closed after 3 missed HBs",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 1500,
+ 100,
+ 0x7FFFFFFF },
+
+ {
+ CFG_DB_LCP_INTERVAL,
+ "TimeBetweenLocalCheckpoints",
+ "DB",
+ "Time between taking snapshots of the database (expressed in 2log of bytes)",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 20,
+ 0,
+ 31 },
+
+ {
+ CFG_DB_GCP_INTERVAL,
+ "TimeBetweenGlobalCheckpoints",
+ "DB",
+ "Time between doing group commit of transactions to disk",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 2000,
+ 10,
+ 32000 },
+
+ {
+ CFG_DB_NO_REDOLOG_FILES,
+ "NoOfFragmentLogFiles",
+ "DB",
+ "No of 16 Mbyte Redo log files in each of 4 file sets belonging to DB node",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 8,
+ 1,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "MaxNoOfOpenFiles",
+ "DB",
+ "Max number of files open per DB node.(One thread is created per file)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 40,
+ 20,
+ 256 },
+
- {"TransactionInactiveTimeout",
- "TransactionInactiveTimeout",
- "DB",
- "Time application can wait before executing another transaction part (ms).\n"
- "This is the time the transaction coordinator waits for the application\n"
- "to execute or send another part (query, statement) of the transaction.\n"
- "If the application takes too long time, the transaction gets aborted.\n"
- "Timeout set to 0 means that we don't timeout at all on application wait.",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 3000,
- 0,
- 0x7FFFFFFF},
-
- {"TransactionDeadlockDetectionTimeout",
- "TransactionDeadlockDetectionTimeout",
- "DB",
- "Time transaction can be executing in a DB node (ms).\n"
- "This is the time the transaction coordinator waits for each database node\n"
- "of the transaction to execute a request. If the database node takes too\n"
- "long time, the transaction gets aborted.",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 3000,
- 50,
- 0x7FFFFFFF},
-
- {"TransactionInactiveTimeBeforeAbort",
- "TransactionInactiveTimeBeforeAbort",
- "DB",
- "Time a transaction can be inactive before getting aborted (ms)",
- ConfigInfo::DEPRICATED,
- true,
- ConfigInfo::INT,
- 3000,
- 20,
- 0x7FFFFFFF},
-
- {"NoOfConcurrentProcessesHandleTakeover",
- "NoOfConcurrentProcessesHandleTakeover",
- "DB",
- "?",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 1,
- 1,
- 15},
+ {
+ CFG_DB_TRANSACTION_CHECK_INTERVAL,
+ "TimeBetweenInactiveTransactionAbortCheck",
+ "DB",
+ "Time between inactive transaction checks",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 1000,
+ 1000,
+ 0x7FFFFFFF },
- {"NoOfConcurrentCheckpointsAfterRestart",
- "NoOfConcurrentCheckpointsAfterRestart",
- "DB",
- "?",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 1,
- 1,
- 4},
+ {
+ CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
+ "TransactionInactiveTimeout",
+ "DB",
+ "Time application can wait before executing another transaction part (ms).\n"
+ "This is the time the transaction coordinator waits for the application\n"
+ "to execute or send another part (query, statement) of the transaction.\n"
+ "If the application takes too long time, the transaction gets aborted.\n"
+ "Timeout set to 0 means that we don't timeout at all on application wait.",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 3000,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
+ "TransactionDeadlockDetectionTimeout",
+ "DB",
+ "Time transaction can be executing in a DB node (ms).\n"
+ "This is the time the transaction coordinator waits for each database node\n"
+ "of the transaction to execute a request. If the database node takes too\n"
+ "long time, the transaction gets aborted.",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 3000,
+ 50,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "TransactionInactiveTimeBeforeAbort",
+ "DB",
+ "TransactionInactiveTimeout",
+ ConfigInfo::DEPRICATED,
+ true,
+ ConfigInfo::INT,
+ 3000,
+ 20,
+ 0x7FFFFFFF },
- {"NoOfDiskPagesToDiskDuringRestartTUP",
- "NoOfDiskPagesToDiskDuringRestartTUP",
- "DB",
- "?",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 50,
- 1,
- 0x7FFFFFFF},
-
- {"NoOfDiskPagesToDiskAfterRestartTUP",
- "NoOfDiskPagesToDiskAfterRestartTUP",
- "DB",
- "?",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 10,
- 1,
- 0x7FFFFFFF},
-
- {"NoOfDiskPagesToDiskDuringRestartACC",
- "NoOfDiskPagesToDiskDuringRestartACC",
- "DB",
- "?",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 25,
- 1,
- 0x7FFFFFFF},
-
- {"NoOfDiskPagesToDiskAfterRestartACC",
- "NoOfDiskPagesToDiskAfterRestartACC",
- "DB",
- "?",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 5,
- 1,
- 0x7FFFFFFF},
+ {
+ KEY_INTERNAL,
+ "NoOfDiskPagesToDiskDuringRestartTUP",
+ "DB",
+ "?",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 50,
+ 1,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "NoOfDiskPagesToDiskAfterRestartTUP",
+ "DB",
+ "?",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 10,
+ 1,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "NoOfDiskPagesToDiskDuringRestartACC",
+ "DB",
+ "?",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 25,
+ 1,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "NoOfDiskPagesToDiskAfterRestartACC",
+ "DB",
+ "?",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 5,
+ 1,
+ 0x7FFFFFFF },
- {"NoOfDiskClustersPerDiskFile",
- "NoOfDiskClustersPerDiskFile",
- "DB",
- "?",
- ConfigInfo::NOTIMPLEMENTED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 0x7FFFFFFF},
+
+ {
+ CFG_DB_DISCLESS,
+ "Discless",
+ "DB",
+ "Run wo/ disk",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::BOOL,
+ 0,
+ 0,
+ 1},
- {"NoOfDiskFiles",
- "NoOfDiskFiles",
- "DB",
- "?",
- ConfigInfo::NOTIMPLEMENTED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 0x7FFFFFFF},
-
- {"ArbitrationTimeout",
- "ArbitrationTimeout",
- "DB",
- "Max time (milliseconds) database partion waits for arbitration signal",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 1000,
- 10,
- 0x7FFFFFFF},
-
- {"FileSystemPath",
- "FileSystemPath",
- "DB",
- "Path to directory where the DB node stores its data (directory must exist)",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"LogLevelStartup",
- "LogLevelStartup",
- "DB",
- "Node startup info printed on stdout",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 1,
- 0,
- 15},
+ {
+ CFG_DB_ARBIT_TIMEOUT,
+ "ArbitrationTimeout",
+ "DB",
+ "Max time (milliseconds) database partion waits for arbitration signal",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 1000,
+ 10,
+ 0x7FFFFFFF },
+
+ {
+ CFG_DB_FILESYSTEM_PATH,
+ "FileSystemPath",
+ "DB",
+ "Path to directory where the DB node stores its data (directory must exist)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_LOGLEVEL_STARTUP,
+ "LogLevelStartup",
+ "DB",
+ "Node startup info printed on stdout",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 1,
+ 0,
+ 15 },
- {"LogLevelShutdown",
- "LogLevelShutdown",
- "DB",
- "Node shutdown info printed on stdout",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 15},
-
- {"LogLevelStatistic",
- "LogLevelStatistic",
- "DB",
- "Transaction, operation, transporter info printed on stdout",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 15},
-
- {"LogLevelCheckpoint",
- "LogLevelCheckpoint",
- "DB",
- "Local and Global checkpoint info printed on stdout",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 15},
-
- {"LogLevelNodeRestart",
- "LogLevelNodeRestart",
- "DB",
- "Node restart, node failure info printed on stdout",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 15},
-
- {"LogLevelConnection",
- "LogLevelConnection",
- "DB",
- "Node connect/disconnect info printed on stdout",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 15},
-
- {"LogLevelError",
- "LogLevelError",
- "DB",
- "Transporter, heartbeat errors printed on stdout",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 15},
-
- {"LogLevelInfo",
- "LogLevelInfo",
- "DB",
- "Heartbeat and log info printed on stdout",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 15},
+ {
+ CFG_LOGLEVEL_SHUTDOWN,
+ "LogLevelShutdown",
+ "DB",
+ "Node shutdown info printed on stdout",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 15 },
+
+ {
+ CFG_LOGLEVEL_STATISTICS,
+ "LogLevelStatistic",
+ "DB",
+ "Transaction, operation, transporter info printed on stdout",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 15 },
+
+ {
+ CFG_LOGLEVEL_CHECKPOINT,
+ "LogLevelCheckpoint",
+ "DB",
+ "Local and Global checkpoint info printed on stdout",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 15 },
+
+ {
+ CFG_LOGLEVEL_NODERESTART,
+ "LogLevelNodeRestart",
+ "DB",
+ "Node restart, node failure info printed on stdout",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 15 },
+
+ {
+ CFG_LOGLEVEL_CONNECTION,
+ "LogLevelConnection",
+ "DB",
+ "Node connect/disconnect info printed on stdout",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 15 },
+
+ {
+ CFG_LOGLEVEL_ERROR,
+ "LogLevelError",
+ "DB",
+ "Transporter, heartbeat errors printed on stdout",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 15 },
+
+ {
+ CFG_LOGLEVEL_INFO,
+ "LogLevelInfo",
+ "DB",
+ "Heartbeat and log info printed on stdout",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 15 },
/**
* Backup
*/
- { "ParallelBackups",
+ {
+ CFG_DB_PARALLEL_BACKUPS,
"ParallelBackups",
"DB",
"Maximum number of parallel backups",
@@ -877,7 +1049,8 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
1,
1 },
- { "BackupMemory",
+ {
+ CFG_DB_BACKUP_MEM,
"BackupMemory",
"DB",
"Total memory allocated for backups per node (in bytes)",
@@ -888,7 +1061,8 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0,
0x7FFFFFFF },
- { "BackupDataBufferSize",
+ {
+ CFG_DB_BACKUP_DATA_BUFFER_MEM,
"BackupDataBufferSize",
"DB",
"Default size of databuffer for a backup (in bytes)",
@@ -899,7 +1073,8 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0,
0x7FFFFFFF },
- { "BackupLogBufferSize",
+ {
+ CFG_DB_BACKUP_LOG_BUFFER_MEM,
"BackupLogBufferSize",
"DB",
"Default size of logbuffer for a backup (in bytes)",
@@ -910,7 +1085,8 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0,
0x7FFFFFFF },
- { "BackupWriteSize",
+ {
+ CFG_DB_BACKUP_WRITE_SIZE,
"BackupWriteSize",
"DB",
"Default size of filesystem writes made by backup (in bytes)",
@@ -921,967 +1097,1098 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0,
0x7FFFFFFF },
- /****************************************************************************
+ /***************************************************************************
* REP
- ****************************************************************************/
-
- {"Id",
- "Id",
- "REP",
- "Number identifying replication node (REP)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 1,
- (MAX_NODES - 1)},
-
- {"Type",
- "Type",
- "REP",
- "Type of node (Should have value REP)",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0},
-
- {"ExecuteOnComputer",
- "ExecuteOnComputer",
- "REP",
- "String referencing an earlier defined COMPUTER",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
+ ***************************************************************************/
+ {
+ CFG_SECTION_NODE,
+ "REP",
+ "REP",
+ "Node section",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::SECTION,
+ NODE_TYPE_REP,
+ 0, 0
+ },
- /****************************************************************************
- * EXTERNAL REP
- ****************************************************************************/
-
- {"Id",
- "Id",
- "EXTERNAL REP",
- "Number identifying external (i.e. in another NDB Cluster) replication node (REP)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 1,
- (MAX_NODES - 1)},
-
- {"Type",
- "Type",
- "EXTERNAL REP",
- "Type of node (Should have value REP)",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0},
-
- {"System",
- "System",
- "EXTERNAL REP",
- "System name of system hosting node",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0},
-
- {"HeartbeatIntervalRepRep",
- "HeartbeatIntervalRepRep",
- "EXTERNAL REP",
- "Time between REP-REP heartbeats. Connection closed after 3 missed HBs",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 3000,
- 100,
- 0x7FFFFFFF},
+ {
+ CFG_NODE_HOST,
+ "HostName",
+ "REP",
+ "Name of computer for this node",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
- /****************************************************************************
+ {
+ CFG_NODE_SYSTEM,
+ "System",
+ "REP",
+ "Name of system for this node",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_ID,
+ "Id",
+ "REP",
+ "Number identifying replication node (REP)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 1,
+ (MAX_NODES - 1) },
+
+ {
+ KEY_INTERNAL,
+ "ExecuteOnComputer",
+ "REP",
+ "String referencing an earlier defined COMPUTER",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_REP_HEARTBEAT_INTERVAL,
+ "HeartbeatIntervalRepRep",
+ "REP",
+ "Time between REP-REP heartbeats. Connection closed after 3 missed HBs",
+ ConfigInfo::USED,
+ true,
+ ConfigInfo::INT,
+ 3000,
+ 100,
+ 0x7FFFFFFF },
+
+ /***************************************************************************
* API
- ****************************************************************************/
-
- {"Id",
- "Id",
- "API",
- "Number identifying application node (API)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 1,
- (MAX_NODES - 1)},
-
- {"Type",
- "Type",
- "API",
- "Type of node (Should have value API)",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0},
-
- {"ExecuteOnComputer",
- "ExecuteOnComputer",
- "API",
- "String referencing an earlier defined COMPUTER",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"MaxNoOfSavedMessages",
- "MaxNoOfSavedMessages",
- "API",
- "Max number of error messages in error log and max number of trace files",
- ConfigInfo::USED,
- true,
- ConfigInfo::INT,
- 25,
- 0,
- 0x7FFFFFFF},
-
- {"SleepWhenIdle",
- "SleepWhenIdle",
- "API",
- "?",
- ConfigInfo::DEPRICATED,
- true,
- ConfigInfo::BOOL,
- true,
- 0,
- 0x7FFFFFFF},
-
- {"ArbitrationRank",
- "ArbitrationRank",
- "API",
- "If 0, then API is not arbitrator. Kernel selects arbitrators in order 1, 2",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 2,
- 0,
- 2},
-
- {"ArbitrationDelay",
- "ArbitrationDelay",
- "API",
- "When asked to arbitrate, arbitrator waits this long before voting (msec)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 0x7FFFFFFF},
+ ***************************************************************************/
+ {
+ CFG_SECTION_NODE,
+ "API",
+ "API",
+ "Node section",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::SECTION,
+ NODE_TYPE_API,
+ 0, 0
+ },
+
+ {
+ CFG_NODE_HOST,
+ "HostName",
+ "API",
+ "Name of computer for this node",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_SYSTEM,
+ "System",
+ "API",
+ "Name of system for this node",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_ID,
+ "Id",
+ "API",
+ "Number identifying application node (API)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 1,
+ (MAX_NODES - 1) },
+
+ {
+ KEY_INTERNAL,
+ "ExecuteOnComputer",
+ "API",
+ "String referencing an earlier defined COMPUTER",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_ARBIT_RANK,
+ "ArbitrationRank",
+ "API",
+ "If 0, then API is not arbitrator. Kernel selects arbitrators in order 1, 2",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 2,
+ 0,
+ 2 },
+
+ {
+ CFG_NODE_ARBIT_DELAY,
+ "ArbitrationDelay",
+ "API",
+ "When asked to arbitrate, arbitrator waits this long before voting (msec)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 0x7FFFFFFF },
/****************************************************************************
* MGM
- ****************************************************************************/
-
- {"Id",
- "Id",
- "MGM",
- "Number identifying the management server node (MGM)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 1,
- (MAX_NODES - 1)},
+ ***************************************************************************/
+ {
+ CFG_SECTION_NODE,
+ "MGM",
+ "MGM",
+ "Node section",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::SECTION,
+ NODE_TYPE_MGM,
+ 0, 0
+ },
+
+ {
+ CFG_NODE_HOST,
+ "HostName",
+ "MGM",
+ "Name of computer for this node",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_SYSTEM,
+ "System",
+ "MGM",
+ "Name of system for this node",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_ID,
+ "Id",
+ "MGM",
+ "Number identifying the management server node (MGM)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 1,
+ (MAX_NODES - 1) },
+
+ {
+ CFG_LOG_DESTINATION,
+ "LogDestination",
+ "MGM",
+ "String describing where logmessages are sent",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ 0,
+ 0,
+ 0x7FFFFFFF },
- {"Type",
- "Type",
- "MGM",
- "Type of node (Should have value MGM)",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0},
-
- {"ExecuteOnComputer",
- "ExecuteOnComputer",
- "MGM",
- "String referencing an earlier defined COMPUTER",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- // SHOULD THIS REALLY BE DEFINABLE FOR MGM ???
- {"MaxNoOfSavedMessages",
- "MaxNoOfSavedMessages",
- "MGM",
- "Max number of error messages in error log and max number of trace files",
- ConfigInfo::DEPRICATED,
- true,
- ConfigInfo::INT,
- 25,
- 0,
- 0x7FFFFFFF},
+ {
+ KEY_INTERNAL,
+ "ExecuteOnComputer",
+ "MGM",
+ "String referencing an earlier defined COMPUTER",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
- {"MaxNoOfSavedEvents",
- "MaxNoOfSavedEvents",
- "MGM",
- "",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 100,
- 0,
- 0x7FFFFFFF},
-
- {"PortNumber",
- "PortNumber",
- "MGM",
- "Port number to give commands to/fetch configurations from management server",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 2200,
- 0,
- 0x7FFFFFFF},
-
- {"PortNumberStats",
- "PortNumberStats",
- "MGM",
- "Port number used to get statistical information from a management server",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 2199,
- 0,
- 0x7FFFFFFF},
-
- {"ArbitrationRank",
- "ArbitrationRank",
- "MGM",
- "If 0, then MGM is not arbitrator. Kernel selects arbitrators in order 1, 2",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 2,
- 0,
- 2},
-
- {"ArbitrationDelay",
- "ArbitrationDelay",
- "MGM",
- "",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 0x7FFFFFFF},
-
- /*****************************************************************************
- * SYSTEM
- ****************************************************************************/
-
- {"Name",
- "Name",
- "SYSTEM",
- "Name of system (NDB Cluster)",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0},
-
- {"ReplicationRole",
- "ReplicationRole",
- "SYSTEM",
- "Role in Global Replication (None, Primary, or Standby)",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0},
-
- {"LogDestination",
- "LogDestination",
- "MGM",
- "String describing where logmessages are sent",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0x7FFFFFFF},
-
- {"PrimaryMGMNode",
- "PrimaryMGMNode",
- "SYSTEM",
- "Node id of Primary MGM node",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 0x7FFFFFFF},
-
- {"ConfigGenerationNumber",
- "ConfigGenerationNumber",
- "SYSTEM",
- "Configuration generation number",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 0,
- 0,
- 0x7FFFFFFF},
-
- {"Name",
- "Name",
- "EXTERNAL SYSTEM",
- "Name of external system (another NDB Cluster)",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0},
-
- /*****************************************************************************
+ {
+ KEY_INTERNAL,
+ "MaxNoOfSavedEvents",
+ "MGM",
+ "",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 100,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_MGM_PORT,
+ "PortNumber",
+ "MGM",
+ "Port number to give commands to/fetch configurations from management server",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 2200,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "PortNumberStats",
+ "MGM",
+ "Port number used to get statistical information from a management server",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 2199,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_NODE_ARBIT_RANK,
+ "ArbitrationRank",
+ "MGM",
+ "If 0, then MGM is not arbitrator. Kernel selects arbitrators in order 1, 2",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 2,
+ 0,
+ 2 },
+
+ {
+ CFG_NODE_ARBIT_DELAY,
+ "ArbitrationDelay",
+ "MGM",
+ "",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 0,
+ 0,
+ 0x7FFFFFFF },
+
+ /****************************************************************************
* TCP
- ****************************************************************************/
-
- {"Type",
- "Type",
- "TCP",
- "",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0x7FFFFFFF},
-
- {"HostName1",
- "HostName1",
- "TCP",
- "Name of computer on one side of the connection",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"HostName2",
- "HostName2",
- "TCP",
- "Name of computer on one side of the connection",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"NodeId1",
- "NodeId1",
- "TCP",
- "Id of node (DB, API or MGM) on one side of the connection",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"ProcessId1",
- "NodeId1",
- "TCP",
- "Depricated",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"NodeId2",
- "NodeId2",
- "TCP",
- "Id of node (DB, API or MGM) on one side of the connection",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"ProcessId2",
- "NodeId2",
- "TCP",
- "Depricated",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"IpAddress1",
- "HostName1",
- "TCP",
- "IP address of first node in connection.",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"IpAddress2",
- "HostName2",
- "TCP",
- "IP address of second node in connection.",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0},
-
- {"SendSignalId",
- "SendSignalId",
- "TCP",
- "Sends id in each signal. Used in trace files.",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- true,
- 0,
- 0x7FFFFFFF},
-
- {"Compression",
- "Compression",
- "TCP",
- "If compression is enabled, then all signals between nodes are compressed",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF},
-
- {"Checksum",
- "Checksum",
- "TCP",
- "If checksum is enabled, all signals between nodes are checked for errors",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF},
-
- {"PortNumber",
- "PortNumber",
- "TCP",
- "Port used for this transporter",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"SendBufferSize",
- "SendBufferSize",
- "TCP",
- "Size of buffer for signals sent from this node (in no of signals)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 16,
- 1,
- 0x7FFFFFFF},
+ ***************************************************************************/
+ {
+ CFG_SECTION_CONNECTION,
+ "TCP",
+ "TCP",
+ "Connection section",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::SECTION,
+ CONNECTION_TYPE_TCP,
+ 0, 0
+ },
+
+ {
+ CFG_TCP_HOSTNAME_1,
+ "HostName1",
+ "TCP",
+ "Name/IP of computer on one side of the connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_TCP_HOSTNAME_2,
+ "HostName2",
+ "TCP",
+ "Name/IP of computer on one side of the connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_1,
+ "NodeId1",
+ "TCP",
+ "Id of node (DB, API or MGM) on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "ProcessId1",
+ "TCP",
+ "NodeId1",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_2,
+ "NodeId2",
+ "TCP",
+ "Id of node (DB, API or MGM) on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "ProcessId2",
+ "TCP",
+ "NodeId2",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "IpAddress1",
+ "TCP",
+ "HostName1",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "IpAddress2",
+ "TCP",
+ "HostName2",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0 },
+
+ {
+ CFG_CONNECTION_SEND_SIGNAL_ID,
+ "SendSignalId",
+ "TCP",
+ "Sends id in each signal. Used in trace files.",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::BOOL,
+ true,
+ 0,
+ 0x7FFFFFFF },
+
+
+ {
+ CFG_CONNECTION_CHECKSUM,
+ "Checksum",
+ "TCP",
+ "If checksum is enabled, all signals between nodes are checked for errors",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::BOOL,
+ false,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_TCP_SERVER_PORT,
+ "PortNumber",
+ "TCP",
+ "Port used for this transporter",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 2202,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_TCP_SEND_BUFFER_SIZE,
+ "SendBufferMemory",
+ "TCP",
+ "Bytes of buffer for signals sent from this node",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 16 * 16384,
+ 1 * 16384,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "SendBufferSize",
+ "TCP",
+ "SendBufferMemory",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ 16,
+ 1,
+ 0x7FFFFFFF },
- {"MaxReceiveSize",
- "MaxReceiveSize",
- "TCP",
- "Size of buffer for signals received by this node (in no of signals)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 4,
- 1,
- 0x7FFFFFFF},
-
- {"Proxy",
- "Proxy",
- "TCP",
- "",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0},
-
- /*****************************************************************************
- * SHM
- ****************************************************************************/
-
- {"Type",
- "Type",
- "SHM",
- "",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0x7FFFFFFF},
+ {
+ CFG_TCP_RECEIVE_BUFFER_SIZE,
+ "ReceiveBufferMemory",
+ "TCP",
+ "Bytes of buffer for signals received by this node",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 4 * 16384,
+ 1 * 16384,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "MaxReceiveSize",
+ "TCP",
+ "ReceiveBufferMemory",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ 4,
+ 1,
+ 0x7FFFFFFF },
+
+ {
+ CFG_TCP_PROXY,
+ "Proxy",
+ "TCP",
+ "",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0 },
+
+ {
+ KEY_INTERNAL,
+ "Compression",
+ "TCP",
+ 0,
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::BOOL,
+ false,
+ 0,
+ 0x7FFFFFFF },
+
+
+ {
+ CFG_CONNECTION_NODE_1_SYSTEM,
+ "NodeId1_System",
+ "TCP",
+ "System for node 1 in connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_2_SYSTEM,
+ "NodeId2_System",
+ "TCP",
+ "System for node 2 in connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
- {"NodeId1",
- "NodeId1",
- "SHM",
- "Id of node (DB, API or MGM) on one side of the connection",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
+
+ /****************************************************************************
+ * SHM
+ ***************************************************************************/
+ {
+ CFG_SECTION_CONNECTION,
+ "SHM",
+ "SHM",
+ "Connection section",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::SECTION,
+ CONNECTION_TYPE_SHM,
+ 0, 0
+ },
+
+ {
+ CFG_CONNECTION_NODE_1,
+ "NodeId1",
+ "SHM",
+ "Id of node (DB, API or MGM) on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
- {"ProcessId1",
- "NodeId1",
- "SHM",
- "Depricated",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
+ {
+ KEY_INTERNAL,
+ "ProcessId1",
+ "SHM",
+ "NodeId1",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
- {"NodeId2",
- "NodeId2",
- "SHM",
- "Id of node (DB, API or MGM) on one side of the connection",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
+ {
+ CFG_CONNECTION_NODE_2,
+ "NodeId2",
+ "SHM",
+ "Id of node (DB, API or MGM) on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
- {"ProcessId2",
- "NodeId2",
- "SHM",
- "Depricated",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
+ {
+ KEY_INTERNAL,
+ "ProcessId2",
+ "SHM",
+ "NodeId1",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
- {"SendSignalId",
- "SendSignalId",
- "SHM",
- "Sends id in each signal. Used in trace files.",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF},
+ {
+ CFG_CONNECTION_SEND_SIGNAL_ID,
+ "SendSignalId",
+ "SHM",
+ "Sends id in each signal. Used in trace files.",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::BOOL,
+ false,
+ 0,
+ 0x7FFFFFFF },
- {"Compression",
- "Compression",
- "SHM",
- "If compression is enabled, then all signals between nodes are compressed",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF},
- {"Checksum",
- "Checksum",
- "SHM",
- "If checksum is enabled, all signals between nodes are checked for errors",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- true,
- 0,
- 0x7FFFFFFF},
+ {
+ CFG_CONNECTION_CHECKSUM,
+ "Checksum",
+ "SHM",
+ "If checksum is enabled, all signals between nodes are checked for errors",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::BOOL,
+ true,
+ 0,
+ 0x7FFFFFFF },
- {"ShmKey",
- "ShmKey",
- "SHM",
- "A shared memory key",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 0,
- 0x7FFFFFFF },
+ {
+ CFG_SHM_KEY,
+ "ShmKey",
+ "SHM",
+ "A shared memory key",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
- {"ShmSize",
- "ShmSize",
- "SHM",
- "Size of shared memory segment",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 1048576,
- 4096,
- 0x7FFFFFFF},
+ {
+ CFG_SHM_BUFFER_MEM,
+ "ShmSize",
+ "SHM",
+ "Size of shared memory segment",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 1048576,
+ 4096,
+ 0x7FFFFFFF },
- /*****************************************************************************
+ {
+ KEY_INTERNAL,
+ "Compression",
+ "SHM",
+ 0,
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::BOOL,
+ false,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_1_SYSTEM,
+ "NodeId1_System",
+ "SHM",
+ "System for node 1 in connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_2_SYSTEM,
+ "NodeId2_System",
+ "SHM",
+ "System for node 2 in connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ /****************************************************************************
* SCI
- ****************************************************************************/
-
- {"NodeId1",
- "NodeId1",
- "SCI",
- "Id of node (DB, API or MGM) on one side of the connection",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"ProcessId1",
- "NodeId1",
- "SCI",
- "Depricated",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"NodeId2",
- "NodeId2",
- "SCI",
- "Id of node (DB, API or MGM) on one side of the connection",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"ProcessId2",
- "NodeId2",
- "SCI",
- "Depricated",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"SciId0",
- "SciId0",
- "SCI",
- "Local SCI-node id for adapter 0 (a computer can have two adapters)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"SciId1",
- "SciId1",
- "SCI",
- "Local SCI-node id for adapter 1 (a computer can have two adapters)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"SendSignalId",
- "SendSignalId",
- "SCI",
- "Sends id in each signal. Used in trace files.",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- true,
- 0,
- 0x7FFFFFFF},
-
- {"Compression",
- "Compression",
- "SCI",
- "If compression is enabled, then all signals between nodes are compressed",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF},
-
- {"Checksum",
- "Checksum",
- "SCI",
- "If checksum is enabled, all signals between nodes are checked for errors",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF},
-
- {"SendLimit",
- "SendLimit",
- "SCI",
- "Transporter send buffer contents are sent when this no of bytes is buffered",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 2048,
- 512,
- 0x7FFFFFFF},
-
- {"SharedBufferSize",
- "SharedBufferSize",
- "SCI",
- "Size of shared memory segment",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 1048576,
- 262144,
- 0x7FFFFFFF},
-
- {"Node1_NoOfAdapters",
- "Node1_NoOfAdapters",
- "SCI",
- "",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"Node2_NoOfAdapters",
- "Node2_NoOfAdapters",
- "SCI",
- "",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"Node1_Adapter",
- "Node1_Adapter",
- "SCI",
- "",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"Node2_Adapter",
- "Node2_Adapter",
- "SCI",
- "",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- /*****************************************************************************
+ ***************************************************************************/
+ {
+ CFG_SECTION_CONNECTION,
+ "SCI",
+ "SCI",
+ "Connection section",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::SECTION,
+ CONNECTION_TYPE_SCI,
+ 0, 0
+ },
+
+ {
+ CFG_CONNECTION_NODE_1,
+ "NodeId1",
+ "SCI",
+ "Id of node (DB, API or MGM) on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "ProcessId1",
+ "SCI",
+ "NodeId1",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_2,
+ "NodeId2",
+ "SCI",
+ "Id of node (DB, API or MGM) on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "ProcessId2",
+ "SCI",
+ "NodeId2",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_SCI_ID_0,
+ "SciId0",
+ "SCI",
+ "Local SCI-node id for adapter 0 (a computer can have two adapters)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_SCI_ID_1,
+ "SciId1",
+ "SCI",
+ "Local SCI-node id for adapter 1 (a computer can have two adapters)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_SEND_SIGNAL_ID,
+ "SendSignalId",
+ "SCI",
+ "Sends id in each signal. Used in trace files.",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::BOOL,
+ true,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_CHECKSUM,
+ "Checksum",
+ "SCI",
+ "If checksum is enabled, all signals between nodes are checked for errors",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::BOOL,
+ false,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_SCI_SEND_LIMIT,
+ "SendLimit",
+ "SCI",
+ "Transporter send buffer contents are sent when this no of bytes is buffered",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 2048,
+ 512,
+ 0x7FFFFFFF },
+
+ {
+ CFG_SCI_BUFFER_MEM,
+ "SharedBufferSize",
+ "SCI",
+ "Size of shared memory segment",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 1048576,
+ 262144,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "Node1_NoOfAdapters",
+ "SCI",
+ 0,
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "Node2_NoOfAdapters",
+ "SCI",
+ 0,
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "Node1_Adapter",
+ "SCI",
+ 0,
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "Node2_Adapter",
+ "SCI",
+ 0,
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "Compression",
+ "SCI",
+ 0,
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::BOOL,
+ false,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_1_SYSTEM,
+ "NodeId1_System",
+ "SCI",
+ "System for node 1 in connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_2_SYSTEM,
+ "NodeId2_System",
+ "SCI",
+ "System for node 2 in connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ /****************************************************************************
* OSE
- ****************************************************************************/
-
- {"Type",
- "Type",
- "OSE",
- "",
- ConfigInfo::INTERNAL,
- false,
- ConfigInfo::STRING,
- 0,
- 0,
- 0x7FFFFFFF},
-
- {"HostName1",
- "HostName1",
- "OSE",
- "Name of computer on one side of the connection",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"HostName2",
- "HostName2",
- "OSE",
- "Name of computer on one side of the connection",
- ConfigInfo::USED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"NodeId1",
- "NodeId1",
- "OSE",
- "Id of node (DB, API or MGM) on one side of the connection",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"ProcessId1",
- "NodeId1",
- "OSE",
- "Depricated",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"NodeId2",
- "NodeId2",
- "OSE",
- "Id of node (DB, API or MGM) on one side of the connection",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF},
-
- {"ProcessId2",
- "NodeId2",
- "OSE",
- "Depricated",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 0,
- 0x7FFFFFFF},
-
- {"SendSignalId",
- "SendSignalId",
- "OSE",
- "Sends id in each signal. Used in trace files.",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- true,
- 0,
- 0x7FFFFFFF},
-
- {"Compression",
- "Compression",
- "OSE",
- "If compression is enabled, then all signals between nodes are compressed",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF},
-
- {"Checksum",
- "Checksum",
- "OSE",
- "If checksum is enabled, all signals between nodes are checked for errors",
- ConfigInfo::USED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF},
-
- // Should not be part of OSE ?
- {"SharedBufferSize",
- "SharedBufferSize",
- "OSE",
- "?",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 2000,
- 0x7FFFFFFF},
-
- {"PrioASignalSize",
- "PrioASignalSize",
- "OSE",
- "Size of priority A signals (in bytes)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 1000,
- 0,
- 0x7FFFFFFF},
-
- {"PrioBSignalSize",
- "PrioBSignalSize",
- "OSE",
- "Size of priority B signals (in bytes)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 1000,
- 0,
- 0x7FFFFFFF},
-
- {"ReceiveArraySize",
- "ReceiveArraySize",
- "OSE",
- "Number of OSE signals checked for correct ordering (in no of OSE signals)",
- ConfigInfo::USED,
- false,
- ConfigInfo::INT,
- 10,
- 0,
- 0x7FFFFFFF}
+ ***************************************************************************/
+ {
+ CFG_SECTION_CONNECTION,
+ "OSE",
+ "OSE",
+ "Connection section",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::SECTION,
+ CONNECTION_TYPE_OSE,
+ 0, 0
+ },
+
+ {
+ CFG_OSE_HOSTNAME_1,
+ "HostName1",
+ "OSE",
+ "Name of computer on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_OSE_HOSTNAME_2,
+ "HostName2",
+ "OSE",
+ "Name of computer on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_1,
+ "NodeId1",
+ "OSE",
+ "Id of node (DB, API or MGM) on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "ProcessId1",
+ "OSE",
+ "NodeId1",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_2,
+ "NodeId2",
+ "OSE",
+ "Id of node (DB, API or MGM) on one side of the connection",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "ProcessId2",
+ "OSE",
+ "NodeId2",
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::INT,
+ MANDATORY,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_SEND_SIGNAL_ID,
+ "SendSignalId",
+ "OSE",
+ "Sends id in each signal. Used in trace files.",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::BOOL,
+ true,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_CHECKSUM,
+ "Checksum",
+ "OSE",
+ "If checksum is enabled, all signals between nodes are checked for errors",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::BOOL,
+ false,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_OSE_PRIO_A_SIZE,
+ "PrioASignalSize",
+ "OSE",
+ "Size of priority A signals (in bytes)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 1000,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_OSE_PRIO_B_SIZE,
+ "PrioBSignalSize",
+ "OSE",
+ "Size of priority B signals (in bytes)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 1000,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_OSE_RECEIVE_ARRAY_SIZE,
+ "ReceiveArraySize",
+ "OSE",
+ "Number of OSE signals checked for correct ordering (in no of OSE signals)",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ 10,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ KEY_INTERNAL,
+ "Compression",
+ "OSE",
+ 0,
+ ConfigInfo::DEPRICATED,
+ false,
+ ConfigInfo::BOOL,
+ false,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_1_SYSTEM,
+ "NodeId1_System",
+ "OSE",
+ "System for node 1 in connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
+
+ {
+ CFG_CONNECTION_NODE_2_SYSTEM,
+ "NodeId2_System",
+ "OSE",
+ "System for node 2 in connection",
+ ConfigInfo::INTERNAL,
+ false,
+ ConfigInfo::STRING,
+ UNDEFINED,
+ 0,
+ 0x7FFFFFFF },
};
const int ConfigInfo::m_NoOfParams = sizeof(m_ParamInfo) / sizeof(ParamInfo);
@@ -1908,21 +2215,21 @@ ConfigInfo::ConfigInfo() {
newsection.setCaseInsensitiveNames(true);
m_info.put(param._section, &newsection);
}
-
+
// Get copy of section
m_info.getCopy(param._section, &section);
// Create pinfo (parameter info) entry
Properties pinfo;
+ pinfo.put("Id", param._paramId);
pinfo.put("Fname", param._fname);
- pinfo.put("Pname", param._pname);
pinfo.put("Description", param._description);
pinfo.put("Updateable", param._updateable);
pinfo.put("Type", param._type);
pinfo.put("Status", param._status);
- pinfo.put("Default", param._default);
- pinfo.put("Min", param._min);
- pinfo.put("Max", param._max);
+ pinfo.put64("Default", param._default);
+ pinfo.put64("Min", param._min);
+ pinfo.put64("Max", param._max);
// Check that pinfo is really new
if (section->get(param._fname, &oldpinfo)) {
@@ -1937,8 +2244,8 @@ ConfigInfo::ConfigInfo() {
// Replace section with modified section
m_info.put(param._section, section, true);
-
- {
+
+ if(param._type != ConfigInfo::SECTION){
Properties * p;
if(!m_systemDefaults.getCopy(param._section, &p)){
p = new Properties();
@@ -1947,26 +2254,28 @@ ConfigInfo::ConfigInfo() {
if(param._type != STRING &&
param._default != UNDEFINED &&
param._default != MANDATORY){
- require(p->put(param._pname, param._default));
+ require(p->put(param._fname, param._default));
}
require(m_systemDefaults.put(param._section, p, true));
delete p;
}
}
-
+
for (int i=0; i<m_NoOfParams; i++) {
if(m_ParamInfo[i]._section == NULL){
- ndbout << "Check that each pname has an fname failed." << endl;
- ndbout << "Parameter \"" << m_ParamInfo[i]._pname
- << "\" does not exist in section \""
- << m_ParamInfo[i]._section << "\"." << endl;
+ ndbout << "Check that each entry has a section failed." << endl;
+ ndbout << "Parameter \"" << m_ParamInfo[i]._fname << endl;
ndbout << "Edit file " << __FILE__ << "." << endl;
exit(-1);
}
+
+ if(m_ParamInfo[i]._type == ConfigInfo::SECTION)
+ continue;
+
const Properties * p = getInfo(m_ParamInfo[i]._section);
- if (!p || !p->contains(m_ParamInfo[i]._pname)) {
+ if (!p || !p->contains(m_ParamInfo[i]._fname)) {
ndbout << "Check that each pname has an fname failed." << endl;
- ndbout << "Parameter \"" << m_ParamInfo[i]._pname
+ ndbout << "Parameter \"" << m_ParamInfo[i]._fname
<< "\" does not exist in section \""
<< m_ParamInfo[i]._section << "\"." << endl;
ndbout << "Edit file " << __FILE__ << "." << endl;
@@ -2002,16 +2311,27 @@ ConfigInfo::getDefaults(const char * section) const {
}
static
-Uint32
+Uint64
getInfoInt(const Properties * section,
const char* fname, const char * type){
- Uint32 val;
+ Uint32 val32;
const Properties * p;
- if (section->get(fname, &p) && p->get(type, &val)) {
- return val;
+ if (section->get(fname, &p) && p->get(type, &val32)) {
+ return val32;
+ }
+
+ Uint64 val64;
+ if(p && p->get(type, &val64)){
+ return val64;
}
+
+ section->print();
+ if(section->get(fname, &p)){
+ p->print();
+ }
+
warning(type, fname);
- return val;
+ return 0;
}
static
@@ -2027,27 +2347,22 @@ getInfoString(const Properties * section,
return val;
}
-Uint32
+Uint64
ConfigInfo::getMax(const Properties * section, const char* fname) const {
return getInfoInt(section, fname, "Max");
}
-Uint32
+Uint64
ConfigInfo::getMin(const Properties * section, const char* fname) const {
return getInfoInt(section, fname, "Min");
}
-Uint32
+Uint64
ConfigInfo::getDefault(const Properties * section, const char* fname) const {
return getInfoInt(section, fname, "Default");
}
const char*
-ConfigInfo::getPName(const Properties * section, const char* fname) const {
- return getInfoString(section, fname, "Pname");
-}
-
-const char*
ConfigInfo::getDescription(const Properties * section,
const char* fname) const {
return getInfoString(section, fname, "Description");
@@ -2063,8 +2378,8 @@ ConfigInfo::isSection(const char * section) const {
bool
ConfigInfo::verify(const Properties * section, const char* fname,
- Uint32 value) const {
- Uint32 min, max; min = max + 1;
+ Uint64 value) const {
+ Uint64 min, max; min = max + 1;
min = getInfoInt(section, fname, "Min");
max = getInfoInt(section, fname, "Max");
@@ -2104,7 +2419,6 @@ void ConfigInfo::print(const char* section) const {
Properties::Iterator it(sec);
for (const char* n = it.first(); n != NULL; n = it.next()) {
// Skip entries with different F- and P-names
- if (strcmp(n, getPName(sec, n))) continue;
if (getStatus(sec, n) == ConfigInfo::INTERNAL) continue;
if (getStatus(sec, n) == ConfigInfo::DEPRICATED) continue;
if (getStatus(sec, n) == ConfigInfo::NOTIMPLEMENTED) continue;
@@ -2114,7 +2428,7 @@ void ConfigInfo::print(const char* section) const {
void ConfigInfo::print(const Properties * section,
const char* parameter) const {
- ndbout << getPName(section, parameter);
+ ndbout << parameter;
// ndbout << getDescription(section, parameter) << endl;
switch (getType(section, parameter)) {
case ConfigInfo::BOOL:
@@ -2133,6 +2447,7 @@ void ConfigInfo::print(const Properties * section,
break;
case ConfigInfo::INT:
+ case ConfigInfo::INT64:
ndbout << " (Non-negative Integer)" << endl;
ndbout << getDescription(section, parameter) << endl;
if (getDefault(section, parameter) == MANDATORY) {
@@ -2157,6 +2472,8 @@ void ConfigInfo::print(const Properties * section,
}
ndbout << endl;
break;
+ case ConfigInfo::SECTION:
+ break;
}
}
@@ -2189,6 +2506,39 @@ transformNode(InitConfigFileParser::Context & ctx, const char * data){
}
bool
+fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data){
+
+ const char * compId;
+ if(!ctx.m_currentSection->get("ExecuteOnComputer", &compId)){
+ ctx.reportError("Parameter \"ExecuteOnComputer\" missing from section "
+ "[%s] starting at line: %d",
+ ctx.fname, ctx.m_sectionLineno);
+ return false;
+ }
+
+ const Properties * computer;
+ char tmp[255];
+ snprintf(tmp, sizeof(tmp), "Computer_%s", compId);
+ if(!ctx.m_config->get(tmp, &computer)){
+ ctx.reportError("Computer \"%s\" not declared"
+ "- [%s] starting at line: %d",
+ compId, ctx.fname, ctx.m_sectionLineno);
+ return false;
+ }
+
+ const char * hostname;
+ if(!computer->get("HostName", &hostname)){
+ ctx.reportError("HostName missing in [COMPUTER] (Id: %d) "
+ " - [%s] starting at line: %d",
+ compId, ctx.fname, ctx.m_sectionLineno);
+ return false;
+ }
+
+ require(ctx.m_currentSection->put("HostName", hostname));
+ return true;
+}
+
+bool
transformExtNode(InitConfigFileParser::Context & ctx, const char * data){
Uint32 id;
@@ -2301,6 +2651,7 @@ applyDefaultValues(InitConfigFileParser::Context & ctx,
Properties::Iterator it(defaults);
for(const char * name = it.first(); name != NULL; name = it.next()){
+ ConfigInfo::Status st = ctx.m_info->getStatus(ctx.m_currentInfo, name);
if(!ctx.m_currentSection->contains(name)){
switch (ctx.m_info->getType(ctx.m_currentInfo, name)){
case ConfigInfo::INT:
@@ -2310,12 +2661,20 @@ applyDefaultValues(InitConfigFileParser::Context & ctx,
ctx.m_currentSection->put(name, val);
break;
}
+ case ConfigInfo::INT64:{
+ Uint64 val = 0;
+ ::require(defaults->get(name, &val));
+ ctx.m_currentSection->put64(name, val);
+ break;
+ }
case ConfigInfo::STRING:{
const char * val;
::require(defaults->get(name, &val));
ctx.m_currentSection->put(name, val);
break;
}
+ case ConfigInfo::SECTION:
+ break;
}
}
}
@@ -2325,9 +2684,13 @@ applyDefaultValues(InitConfigFileParser::Context & ctx,
bool
applyDefaultValues(InitConfigFileParser::Context & ctx, const char * data){
- applyDefaultValues(ctx, ctx.m_userDefaults);
- applyDefaultValues(ctx, ctx.m_systemDefaults);
-
+ if(strcmp(data, "user") == 0)
+ applyDefaultValues(ctx, ctx.m_userDefaults);
+ else if (strcmp(data, "system") == 0)
+ applyDefaultValues(ctx, ctx.m_systemDefaults);
+ else
+ return false;
+
return true;
}
@@ -2343,11 +2706,9 @@ checkMandatory(InitConfigFileParser::Context & ctx, const char * data){
::require(ctx.m_currentInfo->get(name, &info));
Uint32 val;
if(info->get("Default", &val) && val == MANDATORY){
- const char * pname;
const char * fname;
- ::require(info->get("Pname", &pname));
::require(info->get("Fname", &fname));
- if(!ctx.m_currentSection->contains(pname)){
+ if(!ctx.m_currentSection->contains(fname)){
ctx.reportError("Mandatory parameter %s missing from section "
"[%s] starting at line: %d",
fname, ctx.fname, ctx.m_sectionLineno);
@@ -2364,13 +2725,13 @@ checkMandatory(InitConfigFileParser::Context & ctx, const char * data){
* Transform a string "NodeidX" (e.g. "uppsala.32")
* into a Uint32 "NodeIdX" (e.g. 32) and a string "SystemX" (e.g. "uppsala").
*/
-bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data){
-
+bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data)
+{
char buf[] = "NodeIdX"; buf[6] = data[sizeof("NodeI")];
char sysbuf[] = "SystemX"; sysbuf[6] = data[sizeof("NodeI")];
const char* nodeId;
require(ctx.m_currentSection->get(buf, &nodeId));
-
+
char tmpLine[MAX_LINE_LENGTH];
strncpy(tmpLine, nodeId, MAX_LINE_LENGTH);
char* token1 = strtok(tmpLine, ".");
@@ -2391,7 +2752,6 @@ bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data){
require(ctx.m_currentSection->put(buf, id, true));
require(ctx.m_currentSection->put(sysbuf, token1));
}
-
return true;
}
@@ -2493,20 +2853,12 @@ fixHostname(InitConfigFileParser::Context & ctx, const char * data){
if(!ctx.m_currentSection->contains(data)){
Uint32 id = 0;
require(ctx.m_currentSection->get(buf, &id));
-
+
const Properties * node;
require(ctx.m_config->get("Node", id, &node));
- const char * compId;
- require(node->get("ExecuteOnComputer", &compId));
-
- const Properties * computer;
- char tmp[255];
- snprintf(tmp, sizeof(tmp), "Computer_%s", compId);
- require(ctx.m_config->get(tmp, &computer));
-
const char * hostname;
- require(computer->get("HostName", &hostname));
+ require(node->get("HostName", &hostname));
require(ctx.m_currentSection->put(data, hostname));
}
return true;
@@ -2522,9 +2874,9 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
Uint32 adder = 0;
ctx.m_userProperties.get("PortNumberAdder", &adder);
Uint32 base = 0;
- if(!ctx.m_userDefaults->get("PortNumber", &base) &&
+ if(!(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base)) &&
!ctx.m_systemDefaults->get("PortNumber", &base)){
- return true;
+ return false;
}
ctx.m_currentSection->put("PortNumber", base + adder);
adder++;
@@ -2627,3 +2979,265 @@ checkConnectionConstraints(InitConfigFileParser::Context & ctx, const char *){
}
return true;
}
+
+static
+bool
+transform(InitConfigFileParser::Context & ctx,
+ Properties & dst,
+ const char * oldName,
+ const char * newName,
+ double add, double mul){
+
+ if(ctx.m_currentSection->contains(newName)){
+ ctx.reportError("Both %s and %s specified"
+ " - [%s] starting at line: %d",
+ oldName, newName,
+ ctx.fname, ctx.m_sectionLineno);
+ return false;
+ }
+
+ PropertiesType oldType;
+ require(ctx.m_currentSection->getTypeOf(oldName, &oldType));
+ ConfigInfo::Type newType = ctx.m_info->getType(ctx.m_currentInfo, newName);
+ if(!((oldType == PropertiesType_Uint32 || oldType == PropertiesType_Uint64)
+ && (newType == ConfigInfo::INT || newType == ConfigInfo::INT64))){
+ ctx.reportError("Unable to handle type conversion w.r.t deprication %s %s"
+ "- [%s] starting at line: %d",
+ oldName, newName,
+ ctx.fname, ctx.m_sectionLineno);
+ return false;
+ }
+ Uint64 oldVal;
+ require(ctx.m_currentSection->get(oldName, &oldVal));
+
+ Uint64 newVal = (Uint64)(oldVal * mul + add);
+ if(!ctx.m_info->verify(ctx.m_currentInfo, newName, newVal)){
+ ctx.reportError("Unable to handle deprication, new value not within bounds"
+ "%s %s - [%s] starting at line: %d",
+ oldName, newName,
+ ctx.fname, ctx.m_sectionLineno);
+ return false;
+ }
+
+ if(newType == ConfigInfo::INT){
+ require(dst.put(newName, (Uint32)newVal));
+ } else {
+ require(dst.put64(newName, newVal));
+ }
+ return true;
+}
+
+bool
+fixDepricated(InitConfigFileParser::Context & ctx, const char * data){
+ /**
+ * Transform old values to new values
+ * Transform new values to old values (backward compatible)
+ */
+ Properties tmp;
+ Properties::Iterator it(ctx.m_currentSection);
+ for (const char* name = it.first(); name != NULL; name = it.next()) {
+ const DepricationTransform * p = &f_deprication[0];
+ while(p->m_section != 0){
+ if(strcmp(p->m_section, ctx.fname) == 0){
+ double mul = p->m_mul;
+ double add = p->m_add;
+ if(strcmp(name, p->m_oldName) == 0){
+ if(!transform(ctx, tmp, name, p->m_newName, add, mul)){
+ return false;
+ }
+ } else if(strcmp(name, p->m_newName) == 0) {
+ if(!transform(ctx, tmp, name, p->m_oldName, -add/mul,1.0/mul)){
+ return false;
+ }
+ }
+ }
+ p++;
+ }
+ }
+
+ Properties::Iterator it2(&tmp);
+ for (const char* name = it2.first(); name != NULL; name = it2.next()) {
+ PropertiesType type;
+ require(tmp.getTypeOf(name, &type));
+ switch(type){
+ case PropertiesType_Uint32:{
+ Uint32 val;
+ require(tmp.get(name, &val));
+ ::require(ctx.m_currentSection->put(name, val));
+ break;
+ }
+ case PropertiesType_char:{
+ const char * val;
+ require(tmp.get(name, &val));
+ ::require(ctx.m_currentSection->put(name, val));
+ break;
+ }
+ case PropertiesType_Uint64:{
+ Uint64 val;
+ require(tmp.get(name, &val));
+ ::require(ctx.m_currentSection->put64(name, val));
+ break;
+ }
+ case PropertiesType_Properties:
+ default:
+ abort();
+ }
+ }
+ return true;
+}
+
+bool
+saveInConfigValues(InitConfigFileParser::Context & ctx, const char * data){
+ const Properties * sec;
+ if(!ctx.m_currentInfo->get(ctx.fname, &sec)){
+ abort();
+ return false;
+ }
+
+ do {
+ const char *secName;
+ Uint32 id, status, typeVal;
+ require(sec->get("Fname", &secName));
+ require(sec->get("Id", &id));
+ require(sec->get("Status", &status));
+ require(sec->get("Default", &typeVal));
+
+ if(id == KEY_INTERNAL || status == ConfigInfo::INTERNAL){
+ ndbout_c("skipping section %s", ctx.fname);
+ break;
+ }
+
+ Uint32 no = 0;
+ ctx.m_userProperties.get("$Section", id, &no);
+ ctx.m_userProperties.put("$Section", id, no+1, true);
+
+ ctx.m_configValues.openSection(id, no);
+ ctx.m_configValues.put(CFG_TYPE_OF_SECTION, typeVal);
+
+ Properties::Iterator it(ctx.m_currentSection);
+ for (const char* n = it.first(); n != NULL; n = it.next()) {
+ const Properties * info;
+ if(!ctx.m_currentInfo->get(n, &info))
+ continue;
+
+ Uint32 id = 0;
+ info->get("Id", &id);
+
+ if(id == KEY_INTERNAL)
+ continue;
+
+ bool ok = true;
+ PropertiesType type;
+ require(ctx.m_currentSection->getTypeOf(n, &type));
+ switch(type){
+ case PropertiesType_Uint32:{
+ Uint32 val;
+ require(ctx.m_currentSection->get(n, &val));
+ ok = ctx.m_configValues.put(id, val);
+ break;
+ }
+ case PropertiesType_Uint64:{
+ Uint64 val;
+ require(ctx.m_currentSection->get(n, &val));
+ ok = ctx.m_configValues.put64(id, val);
+ break;
+ }
+ case PropertiesType_char:{
+ const char * val;
+ require(ctx.m_currentSection->get(n, &val));
+ ok = ctx.m_configValues.put(id, val);
+ break;
+ }
+ default:
+ abort();
+ }
+ }
+ ctx.m_configValues.closeSection();
+ } while(0);
+ return true;
+}
+
+bool
+addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>&sections,
+ struct InitConfigFileParser::Context &ctx,
+ const char * ruleData)
+{
+ Properties * props= ctx.m_config;
+ Properties p_connections;
+ Properties p_connections2;
+
+ for (Uint32 i = 0;; i++){
+ const Properties * tmp;
+ Uint32 nodeId1, nodeId2;
+
+ if(!props->get("Connection", i, &tmp)) break;
+
+ if(!tmp->get("NodeId1", &nodeId1)) continue;
+ p_connections.put("", nodeId1, nodeId1);
+ if(!tmp->get("NodeId2", &nodeId2)) continue;
+ p_connections.put("", nodeId2, nodeId2);
+
+ p_connections2.put("", nodeId1 + nodeId2<<16, nodeId1);
+ p_connections2.put("", nodeId2 + nodeId1<<16, nodeId2);
+ }
+
+ Uint32 nNodes;
+ ctx.m_userProperties.get("NoOfNodes", &nNodes);
+
+ Properties p_db_nodes;
+ Properties p_api_mgm_nodes;
+
+ Uint32 i_db= 0, i_api_mgm= 0;
+ for (Uint32 i= 0, n= 0; n < nNodes; i++){
+ const Properties * tmp;
+ if(!props->get("Node", i, &tmp)) continue;
+ n++;
+
+ const char * type;
+ if(!tmp->get("Type", &type)) continue;
+
+ if (strcmp(type,"DB") == 0)
+ p_db_nodes.put("", i_db++, i);
+ else if (strcmp(type,"API") == 0 ||
+ strcmp(type,"MGM") == 0)
+ p_api_mgm_nodes.put("", i_api_mgm++, i);
+ }
+
+ Uint32 nodeId1, nodeId2, dummy;
+
+ for (Uint32 i= 0; p_db_nodes.get("", i, &nodeId1); i++){
+ for (Uint32 j= i+1;; j++){
+ if(!p_db_nodes.get("", j, &nodeId2)) break;
+ if(!p_connections2.get("", nodeId1+nodeId2<<16, &dummy)) {
+ ConfigInfo::ConfigRuleSection s;
+ s.m_sectionType= BaseString("TCP");
+ s.m_sectionData= new Properties;
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%u", nodeId1);
+ s.m_sectionData->put("NodeId1", buf);
+ snprintf(buf, sizeof(buf), "%u", nodeId2);
+ s.m_sectionData->put("NodeId2", buf);
+ sections.push_back(s);
+ }
+ }
+ }
+
+ for (Uint32 i= 0; p_api_mgm_nodes.get("", i, &nodeId1); i++){
+ if(!p_connections.get("", nodeId1, &dummy)) {
+ for (Uint32 j= 0;; j++){
+ if(!p_db_nodes.get("", j, &nodeId2)) break;
+ ConfigInfo::ConfigRuleSection s;
+ s.m_sectionType= BaseString("TCP");
+ s.m_sectionData= new Properties;
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%u", nodeId1);
+ s.m_sectionData->put("NodeId1", buf);
+ snprintf(buf, sizeof(buf), "%u", nodeId2);
+ s.m_sectionData->put("NodeId2", buf);
+ sections.push_back(s);
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/ndb/src/common/mgmcommon/ConfigInfo.hpp b/ndb/src/common/mgmcommon/ConfigInfo.hpp
index 43041a3f772..79c17b436fe 100644
--- a/ndb/src/common/mgmcommon/ConfigInfo.hpp
+++ b/ndb/src/common/mgmcommon/ConfigInfo.hpp
@@ -27,8 +27,8 @@
* A MANDATORY parameters must be specified in the config file
* An UNDEFINED parameter may or may not be specified in the config file
*/
-static const Uint32 MANDATORY = ~0; // Default value for mandatory params.
-static const Uint32 UNDEFINED = (~0)-1; // Default value for undefined params.
+static const Uint64 MANDATORY = ~0; // Default value for mandatory params.
+static const Uint64 UNDEFINED = (~0)-1; // Default value for undefined params.
/**
* @class ConfigInfo
@@ -38,27 +38,27 @@ static const Uint32 UNDEFINED = (~0)-1; // Default value for undefined params.
*/
class ConfigInfo {
public:
- enum Type {BOOL, INT, STRING};
- enum Status {USED, ///< Active
- DEPRICATED, ///< Can be, but should not be used anymore
- NOTIMPLEMENTED, ///< Can not be used currently. Is ignored.
- INTERNAL ///< Not configurable by the user
+ enum Type { BOOL, INT, INT64, STRING, SECTION };
+ enum Status { USED, ///< Active
+ DEPRICATED, ///< Can be, but shouldn't
+ NOTIMPLEMENTED, ///< Is ignored.
+ INTERNAL ///< Not configurable by the user
};
/**
* Entry for one configuration parameter
*/
struct ParamInfo {
+ Uint32 _paramId;
const char* _fname;
- const char* _pname;
const char* _section;
const char* _description;
Status _status;
bool _updateable;
Type _type;
- Uint32 _default;
- Uint32 _min;
- Uint32 _max;
+ Uint64 _default;
+ Uint64 _min;
+ Uint64 _max;
};
/**
@@ -71,6 +71,21 @@ public:
const char * m_ruleData;
};
+ /**
+ * Entry for config rule
+ */
+ struct ConfigRuleSection {
+ BaseString m_sectionType;
+ Properties * m_sectionData;
+ };
+
+ struct ConfigRule {
+ bool (* m_configRule)(Vector<ConfigRuleSection>&,
+ struct InitConfigFileParser::Context &,
+ const char * m_ruleData);
+ const char * m_ruleData;
+ };
+
ConfigInfo();
/**
@@ -84,16 +99,15 @@ public:
*
* @note Result is not defined if section/name are wrong!
*/
- bool verify(const Properties* section, const char* fname, Uint32 value) const;
+ bool verify(const Properties* secti, const char* fname, Uint64 value) const;
bool isSection(const char*) const;
- const char* getPName(const Properties * section, const char* fname) const;
- const char* getDescription(const Properties * section, const char* fname) const;
+ const char* getDescription(const Properties * sec, const char* fname) const;
Type getType(const Properties * section, const char* fname) const;
Status getStatus(const Properties* section, const char* fname) const;
- Uint32 getMin(const Properties * section, const char* fname) const;
- Uint32 getMax(const Properties * section, const char* fname) const;
- Uint32 getDefault(const Properties * section, const char* fname) const;
+ Uint64 getMin(const Properties * section, const char* fname) const;
+ Uint64 getMax(const Properties * section, const char* fname) const;
+ Uint64 getDefault(const Properties * section, const char* fname) const;
const Properties * getInfo(const char * section) const;
const Properties * getDefaults(const char * section) const;
@@ -114,6 +128,7 @@ private:
public:
static const SectionRule m_SectionRules[];
+ static const ConfigRule m_ConfigRules[];
static const int m_NoOfRules;
};
diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
index 04dc5466bbc..d2c622593de 100644
--- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp
+++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
@@ -33,6 +33,12 @@
#include <socket_io.h>
#include <NdbConfig.h>
+#include <NdbAutoPtr.hpp>
+
+#include <mgmapi.h>
+#include <mgmapi_config_parameters.h>
+#include <ConfigValues.hpp>
+#include <NdbHost.h>
//****************************************************************************
//****************************************************************************
@@ -83,41 +89,10 @@ ConfigRetriever::init(bool onlyNodeId) {
//****************************************************************************
//****************************************************************************
-
-Properties *
-ConfigRetriever::getConfig(const char * nodeType, int versionId) {
- Properties * p = getConfig(versionId);
-
- if (p == 0) {
- char err_buf[255];
- snprintf(err_buf, sizeof(err_buf),
- "No configuration retrieved for this %s node ", nodeType);
- setError(CR_ERROR, err_buf);
- return 0;
- }
-
- const Uint32 nodeId = _ownNodeId;
-
- if (strcmp(nodeType, "DB") == 0) {
- if (!verifyProperties("DB", p, nodeId, versionId)) return 0;
- } else if (strcmp(nodeType, "API") == 0) {
- if (!verifyProperties("API", p, nodeId, versionId)) return 0;
- } else if (strcmp(nodeType, "REP") == 0) {
- if (!verifyProperties("REP", p, nodeId, versionId)) return 0;
- } else if (strcmp(nodeType, "MGM") == 0) {
- if (!verifyProperties("MGM", p, nodeId, versionId)) return 0;
- } else {
- return 0;
- }
-
- return p;
-}
-
-
//****************************************************************************
//****************************************************************************
-Properties *
-ConfigRetriever::getConfig(int verId) {
+struct ndb_mgm_configuration*
+ConfigRetriever::getConfig(int verId, int nodeType) {
int res = init();
if (res == -1) {
@@ -125,7 +100,7 @@ ConfigRetriever::getConfig(int verId) {
}
if (_localConfig->items == 0){
- setError(CR_ERROR, "No Management Servers configured in local config file");
+ setError(CR_ERROR,"No Management Servers configured in local config file");
return 0;
}
@@ -136,14 +111,13 @@ ConfigRetriever::getConfig(int verId) {
Uint32 type = CR_ERROR;
for (int i = 0; i<_localConfig->items; i++){
MgmtSrvrId * m = _localConfig->ids[i];
- Properties * p = 0;
- const Uint32 nodeId = _ownNodeId;
+ struct ndb_mgm_configuration * p = 0;
switch(m->type){
case MgmId_TCP:
- p = getConfig(m->data.tcp.remoteHost, m->data.tcp.port, nodeId, verId);
+ p = getConfig(m->data.tcp.remoteHost, m->data.tcp.port, verId);
break;
case MgmId_File:
- p = getConfig(m->data.file.filename, nodeId, verId);
+ p = getConfig(m->data.file.filename, verId);
break;
default:
setError(CR_ERROR, "Unknown error type");
@@ -151,6 +125,10 @@ ConfigRetriever::getConfig(int verId) {
}
if (p != 0) {
+ if(!verifyConfig(p, nodeType)){
+ free(p);
+ return 0;
+ }
return p;
}
if(latestErrorType == CR_RETRY)
@@ -161,110 +139,49 @@ ConfigRetriever::getConfig(int verId) {
REPORT_WARNING("Failed to retrieve cluster configuration");
ndbout << "(Cause of failure: " << getErrorString() << ")" << endl;
ndbout << "Attempt " << retry << " of " << retry_max << ". "
- << "Trying again in "<<retry_interval<<" seconds..." << endl << endl;
+ << "Trying again in "<< retry_interval <<" seconds..."
+ << endl << endl;
NdbSleep_SecSleep(retry_interval);
} else {
break;
}
retry++;
-
+
} while (retry <= retry_max);
return 0;
}
-int global_ndb_check = 0; // set to one in ndb main;
-Properties *
+ndb_mgm_configuration *
ConfigRetriever::getConfig(const char * mgmhost,
- unsigned int port,
- Uint32 nodeId,
+ short port,
int versionId){
- const int socketTimeout = 10000;
- int result;
- const NDB_SOCKET_TYPE sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd == NDB_INVALID_SOCKET) {
- setError(CR_RETRY, "Could not create socket to Management Server");
+
+ NdbMgmHandle h;
+ h = ndb_mgm_create_handle();
+ if (h == NULL) {
+ setError(CR_ERROR, "Unable to allocate mgm handle");
return 0;
}
- char err_buf[255];
- struct sockaddr_in servaddr;
- memset(&servaddr, 0, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(port);
- // Convert ip address presentation format to numeric format
- result = Ndb_getInAddr(&servaddr.sin_addr, mgmhost);
- if (result != 0) {
- snprintf(err_buf, sizeof(err_buf),
- "Name lookup failed: host \"%s\"", mgmhost);
- setError(CR_ERROR, err_buf);
+ BaseString tmp;
+ tmp.assfmt("%s:%d", mgmhost, port);
+ if (ndb_mgm_connect(h, tmp.c_str()) != 0) {
+ setError(CR_RETRY, ndb_mgm_get_latest_error_desc(h));
+ ndb_mgm_destroy_handle(&h);
return 0;
}
- result = connect(sockfd, (struct sockaddr*) &servaddr, sizeof(servaddr));
- if (result == -1) {
- snprintf(err_buf, sizeof(err_buf),
- "Failed to connect to \"%s:%d\"", mgmhost, port);
- setError(CR_RETRY, err_buf);
- NDB_CLOSE_SOCKET(sockfd);
- return 0;
+ ndb_mgm_configuration * conf = ndb_mgm_get_configuration(h, versionId);
+ if(conf == 0){
+ setError(CR_ERROR, ndb_mgm_get_latest_error_desc(h));
}
-
- if(println_socket(sockfd, 1000, "GET CONFIG %d %d" ,
- versionId, nodeId) != 0){
- NDB_CLOSE_SOCKET(sockfd);
- setError(CR_ERROR, "IO error, write");
- return 0;
- }
-
- char buf[255];
- {
- const int tmp = readln_socket(sockfd, socketTimeout, buf, 255);
- if(tmp == -1){
- NDB_CLOSE_SOCKET(sockfd);
- setError(CR_ERROR, "IO error, read");
- return 0;
- }
- if(tmp == 0){
- snprintf(err_buf, 256,
- "IO error, failed request: "
- "GET CONFIG %d %d", versionId, nodeId);
- NDB_CLOSE_SOCKET(sockfd);
- setError(CR_ERROR, err_buf);
- return 0;
- }
- }
+ ndb_mgm_disconnect(h);
+ ndb_mgm_destroy_handle(&h);
- int status, version, node, bytes, bytesUU;
- if(sscanf(buf, "GET CONFIG %d %d %d %d %d",
- &status, &version, &node, &bytes, &bytesUU) != 5){
- NDB_CLOSE_SOCKET(sockfd);
- snprintf(err_buf, sizeof(err_buf),
- "Invalid response: %s", buf);
- setError(CR_ERROR, err_buf);
- return 0;
- }
-
- if(status != 0){
- NDB_CLOSE_SOCKET(sockfd);
- if (status == 1){
- snprintf(err_buf, sizeof(err_buf),
- "Management Server: Requested version id is invalid");
- } else if (status == 2){
- snprintf(err_buf, sizeof(err_buf),
- "Management Server: Node with id %d has not been specified",
- nodeId);
- } else if (status == 3){
- snprintf(err_buf, sizeof(err_buf), "Management Server: Internal error");
- } else {
- snprintf(err_buf, sizeof(err_buf),
- "Management Server returned unknown error: %d", status);
- }
- setError(CR_ERROR, err_buf);
- return 0;
- }
-
+ return conf;
+#if 0
bool compatible;
if (global_ndb_check)
compatible = ndbCompatible_ndb_mgmt(versionId, version);
@@ -278,90 +195,11 @@ ConfigRetriever::getConfig(const char * mgmhost,
setError(CR_ERROR, err_buf);
return 0;
}
-
- if(node != (int)nodeId){
- NDB_CLOSE_SOCKET(sockfd);
- snprintf(err_buf, sizeof(err_buf), "Management Server: Invalid node id. "
- "Node id from server: %d Own node id: %d", node, nodeId);
- setError(CR_ERROR, err_buf);
- return 0;
- }
-
- if(readln_socket(sockfd, socketTimeout, buf, 255) == -1){
- NDB_CLOSE_SOCKET(sockfd);
- setError(CR_ERROR, "IO error, read");
- return 0;
- }
-
- if(strncmp("begin", buf, strlen("begin")) != 0){
- NDB_CLOSE_SOCKET(sockfd);
- snprintf(err_buf, sizeof(err_buf),
- "Invalid response: %s", buf);
- setError(CR_ERROR, err_buf);
- return 0;
- }
-
- char* bufUU = new char[bytesUU];
- int read = 0;
- int start = 0;
- do {
- if((read = read_socket(sockfd, socketTimeout, &bufUU[start], bytesUU-start)) == -1){
- delete[] bufUU;
- NDB_CLOSE_SOCKET(sockfd);
- setError(CR_ERROR, "IO error, read(bufUU)");
- return 0;
- }
- start += read;
- } while(start < bytesUU);
-
- Uint32 * buf2 = new Uint32[bytes/4+1]; // Properties byte size
- char * dst = (char *)buf2;
- int sz = 0;
- start = 0;
-
- for (int i = 0; i < bytesUU; i++) {
- if (bufUU[i] == '\n') {
- bufUU[i] = 0;
- if (bufUU[i-1] == '\r') {
- bufUU[i-1] = 0;
- }
- sz = uudecode_mem(dst, bytes, &bufUU[start]);
- dst += sz;
- start = i + 1; // Next row
- }
- }
-
- delete[] bufUU;
-
- if(sz < 0){
- delete []buf2;
- NDB_CLOSE_SOCKET(sockfd);
- setError(CR_ERROR, "IO error, sz < 0");
- return 0;
- }
-
- Properties * p = new Properties();
- if(!p->unpack(buf2, bytes+4)){
- snprintf(buf, sizeof(buf), "Error while unpacking %d,%d",
- p->getPropertiesErrno(),
- p->getOSErrno());
- setError(CR_ERROR, buf);
- delete []buf2;
- delete p;
- return 0;
- }
- delete []buf2;
-
- NDB_CLOSE_SOCKET(sockfd);
-
- return p;
-
+#endif
}
-Properties *
-ConfigRetriever::getConfig(const char * filename,
- Uint32 nodeId,
- int versionId){
+ndb_mgm_configuration *
+ConfigRetriever::getConfig(const char * filename, int versionId){
struct stat sbuf;
const int res = stat(filename, &sbuf);
@@ -389,74 +227,19 @@ ConfigRetriever::getConfig(const char * filename,
return 0;
}
- Properties * p = new Properties();
- if(!p->unpack(buf2, bytes+4)){
+ ConfigValuesFactory cvf;
+ if(!cvf.unpack(buf2, bytes)){
char buf[255];
- snprintf(buf, sizeof(buf), "Error while unpacking %d,%d",
- p->getPropertiesErrno(),
- p->getOSErrno());
+ snprintf(buf, sizeof(buf), "Error while unpacking");
setError(CR_ERROR, buf);
delete []buf2;
- delete p;
return 0;
}
delete [] buf2;
- return p;
+ return (ndb_mgm_configuration*)cvf.m_cfg;
}
-bool
-ConfigRetriever::verifyProperties(const char* nodeType, Properties * p,
- Uint32 nodeId, int versionId){
-
- Uint32 t = 0;
- const Properties *tmp;
- const char *type;
-
- if (p == 0) return false;
-
- bool compatible = false;
- if (p->get("Version", &t))
- if (global_ndb_check)
- compatible = ndbCompatible_ndb_mgmt(versionId, t);
- else
- compatible = ndbCompatible_api_mgmt(versionId, t);
-
- if(!compatible){ // if(!p->get("Version", &t) || versionId != (int)t){
- setError(CR_ERROR, "Invalid configuration version");
- delete p;
- return false;
- }
-
- if(!p->get("LocalNodeId", &t) || nodeId != t){
- setError(CR_ERROR, "Invalid node identity in configuration");
- delete p;
- return false;
- }
-
- if(!p->get("Node", nodeId, &tmp)){
- setError(CR_ERROR, "Internal error while processing configuration");
- ndbout_c("nodeId = %d", nodeId);
- p->print();
- delete p;
- return false;
- }
-
- if(!tmp->get("Type", &type) || strcmp(type, nodeType)) {
- if (!(!strcmp(type, "REP") && !strcmp(nodeType, "API"))) {
- char buf[1024];
- snprintf(buf, sizeof(buf),
- "Configuration error: Node with id %d is not of type %s.\n"
- "Check local config file: %s", nodeId, nodeType,
- _localConfigFileName);
- setError(CR_ERROR, buf);
- return false;
- }
- }
-
- return true;
-}
-
void
ConfigRetriever::setError(ErrorType et, const char * s){
if(errorString != 0){
@@ -509,3 +292,82 @@ ConfigRetriever::setDefaultConnectString(const char * defaultConnectString) {
m_defaultConnectString = 0;
}
}
+
+bool
+ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf,
+ int type){
+ char buf[255];
+ ndb_mgm_configuration_iterator * it;
+ it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, CFG_SECTION_NODE);
+
+ if(it == 0){
+ snprintf(buf, 255, "Unable to create config iterator");
+ setError(CR_ERROR, buf);
+ return false;
+
+ }
+ NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it);
+
+ if(ndb_mgm_find(it, CFG_NODE_ID, getOwnNodeId()) != 0){
+ snprintf(buf, 255, "Unable to find node with id: %d", getOwnNodeId());
+ setError(CR_ERROR, buf);
+ return false;
+ }
+
+ const char * hostname;
+ if(ndb_mgm_get_string_parameter(it, CFG_NODE_HOST, &hostname)){
+ snprintf(buf, 255, "Unable to get hostname(%d) from config",CFG_NODE_HOST);
+ setError(CR_ERROR, buf);
+ return false;
+ }
+
+ char localhost[MAXHOSTNAMELEN];
+ if(NdbHost_GetHostName(localhost) != 0){
+ snprintf(buf, 255, "Unable to own hostname");
+ setError(CR_ERROR, buf);
+ return false;
+ }
+
+ do {
+ if(strcasecmp(hostname, localhost) == 0)
+ break;
+
+ if(strcasecmp(hostname, "localhost") == 0)
+ break;
+
+ struct in_addr local, config;
+ bool b1 = false, b2 = false, b3 = false;
+ b1 = Ndb_getInAddr(&local, localhost) == 0;
+ b2 = Ndb_getInAddr(&config, hostname) == 0;
+ b3 = memcmp(&local, &config, sizeof(local)) == 0;
+
+ if(b1 && b2 && b3)
+ break;
+
+ b1 = Ndb_getInAddr(&local, "localhost") == 0;
+ b3 = memcmp(&local, &config, sizeof(local)) == 0;
+ if(b1 && b2 && b3)
+ break;
+
+ snprintf(buf, 255, "Local hostname(%s) and config hostname(%s) dont match",
+ localhost, hostname);
+ setError(CR_ERROR, buf);
+ return false;
+ } while(false);
+
+ unsigned int _type;
+ if(ndb_mgm_get_int_parameter(it, CFG_TYPE_OF_SECTION, &_type)){
+ snprintf(buf, 255, "Unable to get type of node(%d) from config",
+ CFG_TYPE_OF_SECTION);
+ setError(CR_ERROR, buf);
+ return false;
+ }
+
+ if(_type != type){
+ snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) "
+ " don't match", type, _type);
+ setError(CR_ERROR, buf);
+ return false;
+ }
+ return true;
+}
diff --git a/ndb/src/common/mgmcommon/IPCConfig.cpp b/ndb/src/common/mgmcommon/IPCConfig.cpp
index f75cf806cc0..ba5fe7ace80 100644
--- a/ndb/src/common/mgmcommon/IPCConfig.cpp
+++ b/ndb/src/common/mgmcommon/IPCConfig.cpp
@@ -17,10 +17,14 @@
#include "IPCConfig.hpp"
#include <NdbOut.hpp>
#include <NdbHost.h>
+
#include <TransporterDefinitions.hpp>
#include <TransporterRegistry.hpp>
#include <Properties.hpp>
+#include <mgmapi_configuration.hpp>
+#include <mgmapi_config_parameters.h>
+
#if defined DEBUG_TRANSPORTER
#define DEBUG(t) ndbout << __FILE__ << ":" << __LINE__ << ":" << t << endl;
#else
@@ -334,3 +338,158 @@ IPCConfig::getNodeType(NodeId id) const {
return out;
}
+
+Uint32
+IPCConfig::configureTransporters(Uint32 nodeId,
+ const class ndb_mgm_configuration & config,
+ class TransporterRegistry & tr){
+
+ Uint32 noOfTransportersCreated = 0;
+ ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);
+
+ for(iter.first(); iter.valid(); iter.next()){
+
+ Uint32 nodeId1, nodeId2, remoteNodeId;
+ if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
+ if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;
+
+ if(nodeId1 != nodeId && nodeId2 != nodeId) continue;
+ remoteNodeId = (nodeId == nodeId1 ? nodeId2 : nodeId1);
+
+ Uint32 sendSignalId = 1;
+ Uint32 checksum = 1;
+ if(iter.get(CFG_CONNECTION_SEND_SIGNAL_ID, &sendSignalId)) continue;
+ if(iter.get(CFG_CONNECTION_CHECKSUM, &checksum)) continue;
+
+ Uint32 type = ~0;
+ if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
+
+ switch(type){
+ case CONNECTION_TYPE_SHM:{
+ SHM_TransporterConfiguration conf;
+ conf.localNodeId = nodeId;
+ conf.remoteNodeId = remoteNodeId;
+ conf.byteOrder = 0;
+ conf.compression = 0;
+ conf.checksum = checksum;
+ conf.signalId = sendSignalId;
+
+ if(iter.get(CFG_SHM_KEY, &conf.shmKey)) break;
+ if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shmSize)) break;
+
+ if(!tr.createTransporter(&conf)){
+ ndbout << "Failed to create SHM Transporter from: "
+ << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
+ } else {
+ noOfTransportersCreated++;
+ }
+ break;
+ }
+ case CONNECTION_TYPE_SCI:{
+ SCI_TransporterConfiguration conf;
+ conf.localNodeId = nodeId;
+ conf.remoteNodeId = remoteNodeId;
+ conf.byteOrder = 0;
+ conf.compression = 0;
+ conf.checksum = checksum;
+ conf.signalId = sendSignalId;
+
+ if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sendLimit)) break;
+ if(iter.get(CFG_SCI_BUFFER_MEM, &conf.bufferSize)) break;
+
+ if(nodeId == nodeId1){
+ if(iter.get(CFG_SCI_NODE1_ADAPTERS, &conf.nLocalAdapters)) break;
+ if(iter.get(CFG_SCI_NODE2_ADAPTERS, &conf.nRemoteAdapters)) break;
+ if(iter.get(CFG_SCI_NODE2_ADAPTER0, &conf.remoteSciNodeId0)) break;
+ if(conf.nRemoteAdapters > 1){
+ if(iter.get(CFG_SCI_NODE2_ADAPTER1, &conf.remoteSciNodeId1)) break;
+ }
+ } else {
+ if(iter.get(CFG_SCI_NODE2_ADAPTERS, &conf.nLocalAdapters)) break;
+ if(iter.get(CFG_SCI_NODE1_ADAPTERS, &conf.nRemoteAdapters)) break;
+ if(iter.get(CFG_SCI_NODE1_ADAPTER0, &conf.remoteSciNodeId0)) break;
+ if(conf.nRemoteAdapters > 1){
+ if(iter.get(CFG_SCI_NODE1_ADAPTER1, &conf.remoteSciNodeId1)) break;
+ }
+ }
+
+ if(!tr.createTransporter(&conf)){
+ ndbout << "Failed to create SCI Transporter from: "
+ << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
+ } else {
+ noOfTransportersCreated++;
+ continue;
+ }
+ }
+ case CONNECTION_TYPE_TCP:{
+ TCP_TransporterConfiguration conf;
+
+ const char * host1, * host2;
+ if(iter.get(CFG_TCP_HOSTNAME_1, &host1)) break;
+ if(iter.get(CFG_TCP_HOSTNAME_2, &host2)) break;
+
+ if(iter.get(CFG_TCP_SERVER_PORT, &conf.port)) break;
+ if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.sendBufferSize)) break;
+ if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.maxReceiveSize)) break;
+
+ const char * proxy;
+ if (!iter.get(CFG_TCP_PROXY, &proxy)) {
+ if (strlen(proxy) > 0 && nodeId2 == nodeId) {
+ // TODO handle host:port
+ conf.port = atoi(proxy);
+ }
+ }
+
+ conf.localNodeId = nodeId;
+ conf.remoteNodeId = remoteNodeId;
+ conf.localHostName = (nodeId == nodeId1 ? host1 : host2);
+ conf.remoteHostName = (nodeId == nodeId1 ? host2 : host1);
+ conf.byteOrder = 0;
+ conf.compression = 0;
+ conf.checksum = checksum;
+ conf.signalId = sendSignalId;
+
+ if(!tr.createTransporter(&conf)){
+ ndbout << "Failed to create TCP Transporter from: "
+ << nodeId << " to: " << remoteNodeId << endl;
+ } else {
+ noOfTransportersCreated++;
+ }
+ case CONNECTION_TYPE_OSE:{
+ OSE_TransporterConfiguration conf;
+
+ const char * host1, * host2;
+ if(iter.get(CFG_OSE_HOSTNAME_1, &host1)) break;
+ if(iter.get(CFG_OSE_HOSTNAME_2, &host2)) break;
+
+ if(iter.get(CFG_OSE_PRIO_A_SIZE, &conf.prioASignalSize)) break;
+ if(iter.get(CFG_OSE_PRIO_B_SIZE, &conf.prioBSignalSize)) break;
+ if(iter.get(CFG_OSE_RECEIVE_ARRAY_SIZE, &conf.receiveBufferSize)) break;
+
+ conf.localNodeId = nodeId;
+ conf.remoteNodeId = remoteNodeId;
+ conf.localHostName = (nodeId == nodeId1 ? host1 : host2);
+ conf.remoteHostName = (nodeId == nodeId1 ? host2 : host1);
+ conf.byteOrder = 0;
+ conf.compression = 0;
+ conf.checksum = checksum;
+ conf.signalId = sendSignalId;
+
+ if(!tr.createTransporter(&conf)){
+ ndbout << "Failed to create OSE Transporter from: "
+ << nodeId << " to: " << remoteNodeId << endl;
+ } else {
+ noOfTransportersCreated++;
+ }
+ }
+ default:
+ ndbout << "Unknown transporter type from: " << nodeId <<
+ " to: " << remoteNodeId << endl;
+ break;
+ }
+ }
+ }
+
+ return noOfTransportersCreated;
+}
+
diff --git a/ndb/src/common/mgmcommon/InitConfigFileParser.cpp b/ndb/src/common/mgmcommon/InitConfigFileParser.cpp
index 62c4bd28857..d52bc54db52 100644
--- a/ndb/src/common/mgmcommon/InitConfigFileParser.cpp
+++ b/ndb/src/common/mgmcommon/InitConfigFileParser.cpp
@@ -22,7 +22,7 @@
#include <NdbOut.hpp>
#include "ConfigInfo.hpp"
-const int MAX_LINE_LENGTH = 120; // Max length of line of text in config file
+const int MAX_LINE_LENGTH = 1024; // Max length of line of text in config file
static void trim(char *);
static void require(bool v) { if(!v) abort();}
@@ -30,51 +30,66 @@ static void require(bool v) { if(!v) abort();}
//****************************************************************************
// Ctor / Dtor
//****************************************************************************
-InitConfigFileParser::InitConfigFileParser(const char* initialConfigFileName){
-
- m_initConfigStream = fopen(initialConfigFileName, "r");
+InitConfigFileParser::InitConfigFileParser(){
m_info = new ConfigInfo();
- m_config = new Config();
- m_defaults = new Properties();
- m_defaults->setCaseInsensitiveNames(true);
}
InitConfigFileParser::~InitConfigFileParser() {
- if (m_initConfigStream != NULL) fclose(m_initConfigStream);
-
delete m_info;
- delete m_config;
- delete m_defaults;
}
//****************************************************************************
// Read Config File
//****************************************************************************
-bool InitConfigFileParser::readConfigFile() {
+InitConfigFileParser::Context::Context(const ConfigInfo * info)
+ : m_configValues(1000, 20) {
+
+ m_config = new Properties();
+ m_defaults = new Properties();
+}
+
+InitConfigFileParser::Context::~Context(){
+ if(m_config != 0)
+ delete m_config;
+
+ if(m_defaults != 0)
+ delete m_defaults;
+}
+
+Config *
+InitConfigFileParser::parseConfig(const char * filename) {
+ FILE * file = fopen(filename, "r");
+ if(file == 0){
+ ndbout << "Error opening file: " << filename << endl;
+ return 0;
+ }
+
+ Config * ret = parseConfig(file);
+ fclose(file);
+ return ret;
+}
+
+Config *
+InitConfigFileParser::parseConfig(FILE * file) {
char line[MAX_LINE_LENGTH];
- Context ctx;
+ Context ctx(m_info);
ctx.m_lineno = 0;
ctx.m_currentSection = 0;
- ctx.m_info = m_info;
- ctx.m_config = m_config;
- ctx.m_defaults = m_defaults;
-
/*************
* Open file *
*************/
- if (m_initConfigStream == NULL) {
- ctx.reportError("Could not open file.");
- return false;
+ if (file == NULL) {
+ return 0;
}
/***********************
* While lines to read *
***********************/
- while (fgets(line, MAX_LINE_LENGTH, m_initConfigStream)) {
+ while (fgets(line, MAX_LINE_LENGTH, file)) {
ctx.m_lineno++;
trim(line);
@@ -94,7 +109,7 @@ bool InitConfigFileParser::readConfigFile() {
free(section);
ctx.reportError("Could not store previous default section "
"of configuration file.");
- return false;
+ return 0;
}
snprintf(ctx.fname, sizeof(ctx.fname), section); free(section);
@@ -115,7 +130,7 @@ bool InitConfigFileParser::readConfigFile() {
free(section);
ctx.reportError("Could not store previous section "
"of configuration file.");
- return false;
+ return 0;
}
snprintf(ctx.fname, sizeof(ctx.fname), section);
@@ -123,7 +138,7 @@ bool InitConfigFileParser::readConfigFile() {
ctx.type = InitConfigFileParser::Section;
ctx.m_sectionLineno = ctx.m_lineno;
ctx.m_currentSection = new Properties();
- ctx.m_userDefaults = getSection(ctx.fname, m_defaults);
+ ctx.m_userDefaults = getSection(ctx.fname, ctx.m_defaults);
ctx.m_currentInfo = m_info->getInfo(ctx.fname);
ctx.m_systemDefaults = m_info->getDefaults(ctx.fname);
continue;
@@ -134,15 +149,44 @@ bool InitConfigFileParser::readConfigFile() {
****************************/
if (!parseNameValuePair(ctx, line)) {
ctx.reportError("Could not parse name-value pair in config file.");
- return false;
+ return 0;
}
}
+ if (ferror(file)){
+ ctx.reportError("Failure in reading");
+ return 0;
+ }
+
if(!storeSection(ctx)) {
ctx.reportError("Could not store section of configuration file.");
- return false;
+ return 0;
}
+ for(size_t i = 0; ConfigInfo::m_ConfigRules[i].m_configRule != 0; i++){
+ ctx.type = InitConfigFileParser::Undefined;
+ ctx.m_currentSection = 0;
+ ctx.m_userDefaults = 0;
+ ctx.m_currentInfo = 0;
+ ctx.m_systemDefaults = 0;
+
+ Vector<ConfigInfo::ConfigRuleSection> tmp;
+ if(!(* ConfigInfo::m_ConfigRules[i].m_configRule)(tmp, ctx,
+ ConfigInfo::m_ConfigRules[i].m_ruleData))
+ return 0;
+
+ for(size_t j = 0; j<tmp.size(); j++){
+ snprintf(ctx.fname, sizeof(ctx.fname), tmp[j].m_sectionType.c_str());
+ ctx.type = InitConfigFileParser::Section;
+ ctx.m_currentSection = tmp[j].m_sectionData;
+ ctx.m_userDefaults = getSection(ctx.fname, ctx.m_defaults);
+ ctx.m_currentInfo = m_info->getInfo(ctx.fname);
+ ctx.m_systemDefaults = m_info->getDefaults(ctx.fname);
+ if(!storeSection(ctx))
+ return 0;
+ }
+ }
+
Uint32 nConnections = 0;
Uint32 nComputers = 0;
Uint32 nNodes = 0;
@@ -153,21 +197,20 @@ bool InitConfigFileParser::readConfigFile() {
ctx.m_userProperties.get("NoOfNodes", &nNodes);
ctx.m_userProperties.get("ExtNoOfConnections", &nExtConnections);
ctx.m_userProperties.get("ExtSystem", &system);
- m_config->put("NoOfConnections", nConnections);
- m_config->put("NoOfComputers", nComputers);
- m_config->put("NoOfNodes", nNodes);
+ ctx.m_config->put("NoOfConnections", nConnections);
+ ctx.m_config->put("NoOfComputers", nComputers);
+ ctx.m_config->put("NoOfNodes", nNodes);
char tmpLine[MAX_LINE_LENGTH];
snprintf(tmpLine, MAX_LINE_LENGTH, "EXTERNAL SYSTEM_");
strncat(tmpLine, system, MAX_LINE_LENGTH);
strncat(tmpLine, ":NoOfConnections", MAX_LINE_LENGTH);
- m_config->put(tmpLine, nExtConnections);
+ ctx.m_config->put(tmpLine, nExtConnections);
- if (ferror(m_initConfigStream)) {
- ctx.reportError("Failure in reading");
- return false;
- }
- return true;
+ Config * ret = new Config();
+ ret->m_configValues = (struct ndb_mgm_configuration*)ctx.m_configValues.getConfigValues();
+ ret->m_oldConfig = ctx.m_config; ctx.m_config = 0;
+ return ret;
}
//****************************************************************************
@@ -216,7 +259,13 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) {
ctx.reportWarning("[%s] %s not yet implemented", ctx.fname, fname);
}
if (status == ConfigInfo::DEPRICATED) {
- ctx.reportWarning("[%s] %s is depricated", ctx.fname, fname);
+ const char * desc = m_info->getDescription(ctx.m_currentInfo, fname);
+ if(desc){
+ ctx.reportWarning("[%s] %s is depricated, use %s instead",
+ ctx.fname, fname, desc);
+ } else {
+ ctx.reportWarning("[%s] %s is depricated", ctx.fname, fname);
+ }
}
// ******************************************
@@ -249,7 +298,7 @@ InitConfigFileParser::storeNameValuePair(Context& ctx,
const char* fname,
const char* value) {
- const char * pname = m_info->getPName(ctx.m_currentInfo, fname);
+ const char * pname = fname;
if (ctx.m_currentSection->contains(pname)) {
ctx.reportError("[%s] Parameter %s specified twice", ctx.fname, fname);
@@ -260,7 +309,8 @@ InitConfigFileParser::storeNameValuePair(Context& ctx,
// Store name-value pair
// ***********************
- switch(m_info->getType(ctx.m_currentInfo, fname)){
+ const ConfigInfo::Type type = m_info->getType(ctx.m_currentInfo, fname);
+ switch(type){
case ConfigInfo::BOOL: {
bool value_bool;
if (!convertStringToBool(value, value_bool)) {
@@ -270,20 +320,25 @@ InitConfigFileParser::storeNameValuePair(Context& ctx,
MGM_REQUIRE(ctx.m_currentSection->put(pname, value_bool));
break;
}
- case ConfigInfo::INT:{
- Uint32 value_int;
- if (!convertStringToUint32(value, value_int)) {
+ case ConfigInfo::INT:
+ case ConfigInfo::INT64:{
+ Uint64 value_int;
+ if (!convertStringToUint64(value, value_int)) {
ctx.reportError("Illegal integer value for parameter %s", fname);
return false;
}
if (!m_info->verify(ctx.m_currentInfo, fname, value_int)) {
ctx.reportError("Illegal value %s for parameter %s.\n"
- "Legal values are between %d and %d", value, fname,
+ "Legal values are between %Lu and %Lu", value, fname,
m_info->getMin(ctx.m_currentInfo, fname),
m_info->getMax(ctx.m_currentInfo, fname));
return false;
}
- MGM_REQUIRE(ctx.m_currentSection->put(pname, value_int));
+ if(type == ConfigInfo::INT){
+ MGM_REQUIRE(ctx.m_currentSection->put(pname, (Uint32)value_int));
+ } else {
+ MGM_REQUIRE(ctx.m_currentSection->put64(pname, value_int));
+ }
break;
}
case ConfigInfo::STRING:
@@ -313,8 +368,8 @@ bool InitConfigFileParser::isEmptyLine(const char* line) const {
//****************************************************************************
// Convert String to Int
//****************************************************************************
-bool InitConfigFileParser::convertStringToUint32(const char* s,
- Uint32& val,
+bool InitConfigFileParser::convertStringToUint64(const char* s,
+ Uint64& val,
Uint32 log10base) {
if (s == NULL)
return false;
@@ -323,7 +378,7 @@ bool InitConfigFileParser::convertStringToUint32(const char* s,
errno = 0;
char* p;
- long v = strtol(s, &p, 10);
+ long long v = strtoll(s, &p, 10);
if (errno != 0)
return false;
@@ -359,14 +414,16 @@ bool InitConfigFileParser::convertStringToBool(const char* s, bool& val) {
if (!strcmp(s, "Y") || !strcmp(s, "y") ||
!strcmp(s, "Yes") || !strcmp(s, "YES") || !strcmp(s, "yes") ||
- !strcmp(s, "True") || !strcmp(s, "TRUE") || !strcmp(s, "true")) {
+ !strcmp(s, "True") || !strcmp(s, "TRUE") || !strcmp(s, "true") ||
+ !strcmp(s, "1")) {
val = true;
return true;
}
if (!strcmp(s, "N") || !strcmp(s, "n") ||
!strcmp(s, "No") || !strcmp(s, "NO") || !strcmp(s, "no") ||
- !strcmp(s, "False") || !strcmp(s, "FALSE") || !strcmp(s, "false")) {
+ !strcmp(s, "False") || !strcmp(s, "FALSE") || !strcmp(s, "false") ||
+ !strcmp(s, "0")) {
val = false;
return true;
}
@@ -375,21 +432,6 @@ bool InitConfigFileParser::convertStringToBool(const char* s, bool& val) {
}
//****************************************************************************
-// Get Config
-//****************************************************************************
-const Config* InitConfigFileParser::getConfig() {
- Uint32 nConnections = 0;
- Uint32 nComputers = 0;
- Uint32 nNodes = 0;
- m_config->get("NoOfConnections", &nConnections);
- m_config->get("NoOfComputers", &nComputers);
- m_config->get("NoOfNodes", &nNodes);
-
- return m_config;
-}
-
-
-//****************************************************************************
// Parse Section Header
//****************************************************************************
static void
@@ -481,33 +523,30 @@ bool
InitConfigFileParser::storeSection(Context& ctx){
if(ctx.m_currentSection == NULL)
return true;
-
for(int i = strlen(ctx.fname) - 1; i>=0; i--){
ctx.fname[i] = toupper(ctx.fname[i]);
}
-
snprintf(ctx.pname, sizeof(ctx.pname), ctx.fname);
-
char buf[255];
if(ctx.type == InitConfigFileParser::Section)
snprintf(buf, sizeof(buf), "%s", ctx.fname);
if(ctx.type == InitConfigFileParser::DefaultSection)
snprintf(buf, sizeof(buf), "%s DEFAULT", ctx.fname);
-
snprintf(ctx.fname, sizeof(ctx.fname), buf);
- for(int i = 0; i<m_info->m_NoOfRules; i++){
- const ConfigInfo::SectionRule & rule = m_info->m_SectionRules[i];
- if(strcmp(rule.m_section, ctx.fname) == 0)
- if(!(* rule.m_sectionRule)(ctx, rule.m_ruleData)){
- return false;
- }
+ if(ctx.type == InitConfigFileParser::Section){
+ for(int i = 0; i<m_info->m_NoOfRules; i++){
+ const ConfigInfo::SectionRule & rule = m_info->m_SectionRules[i];
+ if(!strcmp(rule.m_section, "*") || !strcmp(rule.m_section, ctx.fname))
+ if(!(* rule.m_sectionRule)(ctx, rule.m_ruleData))
+ return false;
+ }
}
-
+
if(ctx.type == InitConfigFileParser::DefaultSection)
- require(m_defaults->put(ctx.pname, ctx.m_currentSection));
+ require(ctx.m_defaults->put(ctx.pname, ctx.m_currentSection));
if(ctx.type == InitConfigFileParser::Section)
- require(m_config->put(ctx.pname, ctx.m_currentSection));
+ require(ctx.m_config->put(ctx.pname, ctx.m_currentSection));
delete ctx.m_currentSection; ctx.m_currentSection = NULL;
diff --git a/ndb/src/common/mgmcommon/InitConfigFileParser.hpp b/ndb/src/common/mgmcommon/InitConfigFileParser.hpp
index f4f27abb055..6b7482c12ae 100644
--- a/ndb/src/common/mgmcommon/InitConfigFileParser.hpp
+++ b/ndb/src/common/mgmcommon/InitConfigFileParser.hpp
@@ -20,6 +20,7 @@
#include <ndb_global.h>
#include <Properties.hpp>
+#include <ConfigValues.hpp>
class Config;
class ConfigInfo;
@@ -28,18 +29,40 @@ class ConfigInfo;
* @class InitConfigFileParser
* @brief Reads initial config file and returns Config object
*
- * This class contains one public method InitConfigFileParser::getConfig,
+ * This class contains one public method InitConfigFileParser::parseConfig,
* which reads an initial configuration file and returns a Config
* object if the config file has correct syntax and semantic.
*/
class InitConfigFileParser {
public:
+ /**
+ * Constructor
+ */
+ InitConfigFileParser();
+ ~InitConfigFileParser();
+
+ /**
+ * Reads the initial configuration file, checks syntax and semantic
+ * and stores internally the values of all parameters.
+ *
+ * @returns Config or NULL on failure
+ * @note must be freed by caller
+ */
+ Config * parseConfig(FILE * file);
+ Config * parseConfig(const char * filename);
+
+ /**
+ * Parser context struct
+ */
enum ContextSectionType { Undefined, Section, DefaultSection };
/**
* Context = Which section in init config file we are currently parsing
*/
struct Context {
+ Context(const ConfigInfo *);
+ ~Context();
+
ContextSectionType type; ///< Section type (e.g. default section,section)
char fname[256]; ///< Section name occuring in init config file
char pname[256]; ///< Section name stored in properties object
@@ -47,8 +70,8 @@ public:
Uint32 m_sectionLineno; ///< Where did current section start
const ConfigInfo * m_info; // The config info
- const Properties * m_config; // The config object
- const Properties * m_defaults; // The user defaults
+ Properties * m_config; // The config object
+ Properties * m_defaults; // The user defaults
Properties * m_currentSection; // The current section I'm in
const Properties * m_userDefaults; // The defaults of this section
@@ -56,36 +79,13 @@ public:
const Properties * m_currentInfo; // The "info" for this section
Properties m_userProperties; // User properties (temporary values)
+ ConfigValuesFactory m_configValues; //
public:
void reportError(const char * msg, ...);
void reportWarning(const char * msg, ...);
};
-
- /**
- * Constructor
- * @param initialConfigFileName: Name of the initial configuration file
- */
- InitConfigFileParser(const char* initialConfigFileName);
- ~InitConfigFileParser();
-
- /**
- * Reads the initial configuration file, checks syntax and semantic
- * and stores internally the values of all parameters.
- *
- * @returns true if succeeded, o/w false (e.g. incorrect config file)
- */
- bool readConfigFile();
-
- /**
- * Get config. Must execute InitConfigFileParser::readConfigFile first.
- *
- * @returns Config if succeeded, o/w NULL
- */
- const Config* getConfig();
-
-
private:
/**
* Check if line only contains space/comments
@@ -111,33 +111,16 @@ private:
bool parseNameValuePair(Context&, const char* line);
bool storeNameValuePair(Context&, const char* fname, const char* value);
- bool convertStringToUint32(const char* s, Uint32& val, Uint32 log10base = 0);
+ bool convertStringToUint64(const char* s, Uint64& val, Uint32 log10base = 0);
bool convertStringToBool(const char* s, bool& val);
+ bool storeSection(Context&);
const Properties* getSection(const char * name, const Properties* src);
- /***************************************************************************
- * VARIABLES
- ***************************************************************************/
- FILE* m_initConfigStream;
-
/**
* Information about parameters (min, max values etc)
*/
- const ConfigInfo* m_info;
-
- /**
- * Configuration from initial configuration file
- * (returned by InitConfigFileParser::readConfigFile)
- */
- Config* m_config;
-
- /**
- * Default values specified in default sections
- */
- Properties* m_defaults;
-
- bool storeSection(Context&);
+ ConfigInfo* m_info;
};
#endif // InitConfigFileParser_H
diff --git a/ndb/src/common/mgmcommon/Makefile b/ndb/src/common/mgmcommon/Makefile
deleted file mode 100644
index 2db7be01d60..00000000000
--- a/ndb/src/common/mgmcommon/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi mgmapiclient
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := mgmsrvcommon
-
-DIRS := printConfig
-
-SOURCES = \
- LocalConfig.cpp \
- Config.cpp \
- ConfigInfo.cpp \
- ConfigRetriever.cpp \
- InitConfigFileParser.cpp \
- IPCConfig.cpp
-
-SOURCES.c = NdbConfig.c
-
-include $(NDB_TOP)/Epilogue.mk
-
-
-
-
-
-
diff --git a/ndb/src/common/mgmcommon/Makefile.am b/ndb/src/common/mgmcommon/Makefile.am
new file mode 100644
index 00000000000..8a34fa16ed1
--- /dev/null
+++ b/ndb/src/common/mgmcommon/Makefile.am
@@ -0,0 +1,18 @@
+noinst_LTLIBRARIES = libmgmsrvcommon.la
+
+libmgmsrvcommon_la_SOURCES = \
+ LocalConfig.cpp \
+ Config.cpp \
+ ConfigInfo.cpp \
+ ConfigRetriever.cpp \
+ InitConfigFileParser.cpp \
+ IPCConfig.cpp NdbConfig.c
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
+include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/common/mgmcommon/Makefile_old b/ndb/src/common/mgmcommon/Makefile_old
new file mode 100644
index 00000000000..c7bfda7e3bf
--- /dev/null
+++ b/ndb/src/common/mgmcommon/Makefile_old
@@ -0,0 +1,29 @@
+include .defs.mk
+
+TYPE := ndbapi mgmapiclient
+
+PIC_ARCHIVE := Y
+ARCHIVE_TARGET := mgmsrvcommon
+
+# Removed temporary
+DIRS := printConfig
+
+SOURCES = \
+ LocalConfig.cpp \
+ Config.cpp \
+ ConfigInfo.cpp \
+ ConfigRetriever.cpp \
+ InitConfigFileParser.cpp \
+ IPCConfig.cpp
+
+SOURCES.c = NdbConfig.c
+
+CFLAGS_IPCConfig.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
+
+include $(NDB_TOP)/Epilogue.mk
+
+
+
+
+
+
diff --git a/ndb/src/common/mgmcommon/printConfig/Makefile b/ndb/src/common/mgmcommon/printConfig/Makefile
index 9194316da87..77e8943e2c6 100644
--- a/ndb/src/common/mgmcommon/printConfig/Makefile
+++ b/ndb/src/common/mgmcommon/printConfig/Makefile
@@ -7,8 +7,10 @@ BIN_TARGET_ARCHIVES := general portlib
CCFLAGS_LOC += -I..
-SOURCES := printConfig.cpp
+SOURCES := printConfig.cpp ../ConfigRetriever.cpp
-SOURCES.c := ../ConfigRetriever.c ../NdbConfig.c ../LocalConfig.c
+SOURCES.c := ../NdbConfig.c ../LocalConfig.c
+
+CFLAGS_printConfig.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/common/mgmcommon/printConfig/printConfig.cpp b/ndb/src/common/mgmcommon/printConfig/printConfig.cpp
index daa287cc44d..7cedbb451e2 100644
--- a/ndb/src/common/mgmcommon/printConfig/printConfig.cpp
+++ b/ndb/src/common/mgmcommon/printConfig/printConfig.cpp
@@ -18,6 +18,7 @@
#include <ndb_global.h>
#include <NdbMain.h>
+#include <mgmapi.h>
#include <ConfigRetriever.hpp>
#include <Properties.hpp>
#include <NdbOut.hpp>
@@ -50,9 +51,9 @@ NDB_COMMAND(printConfig,
return 0;
}
- Properties * p = 0;
ConfigRetriever c;
-
+ struct ndb_mgm_configuration * p = 0;
+
if(strcmp("host", argv[1]) == 0){
int verId = 0;
if(argc > 5)
@@ -64,7 +65,6 @@ NDB_COMMAND(printConfig,
p = c.getConfig(argv[2],
atoi(argv[3]),
- atoi(argv[4]),
verId);
} else if (strcmp("file", argv[1]) == 0){
int verId = 0;
@@ -79,12 +79,11 @@ NDB_COMMAND(printConfig,
}
if(p != 0){
- p->print(stdout);
+ //
+ free(p);
} else {
ndbout << "Configuration not found: " << c.getErrorString() << endl;
}
- delete p;
-
return 0;
}
diff --git a/ndb/src/common/portlib/Makefile.am b/ndb/src/common/portlib/Makefile.am
new file mode 100644
index 00000000000..e6ecb30fe04
--- /dev/null
+++ b/ndb/src/common/portlib/Makefile.am
@@ -0,0 +1,18 @@
+noinst_HEADERS = gcc.cpp
+
+noinst_LTLIBRARIES = libportlib.la
+
+libportlib_la_SOURCES = \
+ NdbCondition.c NdbMutex.c NdbSleep.c NdbTick.c \
+ NdbEnv.c NdbThread.c NdbHost.c NdbTCP.c \
+ NdbDaemon.c NdbMem.c
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_util.mk.am
+
+EXTRA_PROGRAMS = memtest PortLibTest munmaptest
+
+PortLibTest_SOURCES = NdbPortLibTest.cpp
+munmaptest_SOURCES = munmaptest.cpp
+
+# Don't update the files from bitkeeper
diff --git a/ndb/src/common/portlib/Makefile b/ndb/src/common/portlib/Makefile_old
index 48f4929a839..48f4929a839 100644
--- a/ndb/src/common/portlib/Makefile
+++ b/ndb/src/common/portlib/Makefile_old
diff --git a/ndb/src/common/portlib/unix/NdbCondition.c b/ndb/src/common/portlib/NdbCondition.c
index 1d229bdcdef..1d229bdcdef 100644
--- a/ndb/src/common/portlib/unix/NdbCondition.c
+++ b/ndb/src/common/portlib/NdbCondition.c
diff --git a/ndb/src/common/portlib/NdbDaemon.c b/ndb/src/common/portlib/NdbDaemon.c
new file mode 100644
index 00000000000..d8d33595156
--- /dev/null
+++ b/ndb/src/common/portlib/NdbDaemon.c
@@ -0,0 +1,157 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+#include "NdbDaemon.h"
+
+#define NdbDaemon_ErrorSize 500
+long NdbDaemon_DaemonPid = 0;
+int NdbDaemon_ErrorCode = 0;
+char NdbDaemon_ErrorText[NdbDaemon_ErrorSize] = "";
+
+int
+NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
+{
+ int lockfd = -1, logfd = -1, n;
+ char buf[64];
+
+ /* Check that we have write access to lock file */
+ assert(lockfile != NULL);
+ lockfd = open(lockfile, O_CREAT|O_RDWR, 0644);
+ if (lockfd == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: open for write failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Read any old pid from lock file */
+ buf[0] = 0;
+ n = read(lockfd, buf, sizeof(buf));
+ if (n < 0) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: read failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ NdbDaemon_DaemonPid = atol(buf);
+ if (lseek(lockfd, 0, SEEK_SET) == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: lseek failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Test for lock before becoming daemon */
+ if (lockf(lockfd, F_TEST, 0) == -1) {
+ if (errno == EACCES || errno == EAGAIN) { /* results may vary */
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: already locked by pid=%ld", lockfile, NdbDaemon_DaemonPid);
+ return -1;
+ }
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: lock test failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Test open log file before becoming daemon */
+ if (logfile != NULL) {
+ logfd = open(logfile, O_CREAT|O_WRONLY|O_APPEND, 0644);
+ if (logfd == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: open for write failed: %s", logfile, strerror(errno));
+ return -1;
+ }
+ }
+ /* Fork */
+ n = fork();
+ if (n == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "fork failed: %s", strerror(errno));
+ return -1;
+ }
+ /* Exit if we are the parent */
+ if (n != 0) {
+ exit(0);
+ }
+ /* Running in child process */
+ NdbDaemon_DaemonPid = getpid();
+ /* Lock the lock file (likely to succeed due to test above) */
+ if (lockf(lockfd, F_LOCK, 0) == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: lock failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Become process group leader */
+ if (setsid() == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "setsid failed: %s", strerror(errno));
+ return -1;
+ }
+ /* Write pid to lock file */
+ if (ftruncate(lockfd, 0) == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: ftruncate failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ sprintf(buf, "%ld\n", NdbDaemon_DaemonPid);
+ n = strlen(buf);
+ if (write(lockfd, buf, n) != n) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: write failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Do input/output redirections (assume fd 0,1,2 not in use) */
+ close(0);
+ open("/dev/null", O_RDONLY);
+ if (logfile != 0) {
+ dup2(logfd, 1);
+ dup2(logfd, 2);
+ close(logfd);
+ }
+ /* Success */
+ return 0;
+}
+
+#if 0
+int
+NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
+{
+ /* Fail */
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "Daemon mode not implemented");
+ return -1;
+}
+#endif
+
+#ifdef NDB_DAEMON_TEST
+
+int
+main()
+{
+ if (NdbDaemon_Make("test.pid", "test.log", 0) == -1) {
+ fprintf(stderr, "NdbDaemon_Make: %s\n", NdbDaemon_ErrorText);
+ return 1;
+ }
+ sleep(10);
+ return 0;
+}
+
+#endif
diff --git a/ndb/src/common/portlib/unix/NdbEnv.c b/ndb/src/common/portlib/NdbEnv.c
index d294e0b52ca..d294e0b52ca 100644
--- a/ndb/src/common/portlib/unix/NdbEnv.c
+++ b/ndb/src/common/portlib/NdbEnv.c
diff --git a/ndb/src/common/portlib/unix/NdbHost.c b/ndb/src/common/portlib/NdbHost.c
index 4749bb39ea7..4749bb39ea7 100644
--- a/ndb/src/common/portlib/unix/NdbHost.c
+++ b/ndb/src/common/portlib/NdbHost.c
diff --git a/ndb/src/common/portlib/unix/NdbMem.c b/ndb/src/common/portlib/NdbMem.c
index 0b06e5b23f1..0b06e5b23f1 100644
--- a/ndb/src/common/portlib/unix/NdbMem.c
+++ b/ndb/src/common/portlib/NdbMem.c
diff --git a/ndb/src/common/portlib/unix/NdbMutex.c b/ndb/src/common/portlib/NdbMutex.c
index 50f314d2683..50f314d2683 100644
--- a/ndb/src/common/portlib/unix/NdbMutex.c
+++ b/ndb/src/common/portlib/NdbMutex.c
diff --git a/ndb/src/common/portlib/test/NdbPortLibTest.cpp b/ndb/src/common/portlib/NdbPortLibTest.cpp
index 55b9ccec5f2..55b9ccec5f2 100644
--- a/ndb/src/common/portlib/test/NdbPortLibTest.cpp
+++ b/ndb/src/common/portlib/NdbPortLibTest.cpp
diff --git a/ndb/src/common/portlib/unix/NdbSleep.c b/ndb/src/common/portlib/NdbSleep.c
index 8702a25d1b1..8702a25d1b1 100644
--- a/ndb/src/common/portlib/unix/NdbSleep.c
+++ b/ndb/src/common/portlib/NdbSleep.c
diff --git a/ndb/src/common/portlib/unix/NdbTCP.c b/ndb/src/common/portlib/NdbTCP.c
index 287dc6c2ecd..287dc6c2ecd 100644
--- a/ndb/src/common/portlib/unix/NdbTCP.c
+++ b/ndb/src/common/portlib/NdbTCP.c
diff --git a/ndb/src/common/portlib/NdbThread.c b/ndb/src/common/portlib/NdbThread.c
new file mode 100644
index 00000000000..8683a37edcb
--- /dev/null
+++ b/ndb/src/common/portlib/NdbThread.c
@@ -0,0 +1,113 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+#include <NdbThread.h>
+#include <pthread.h>
+
+#define MAX_THREAD_NAME 16
+
+/*#define USE_PTHREAD_EXTRAS*/
+
+struct NdbThread
+{
+ pthread_t thread;
+ char thread_name[MAX_THREAD_NAME];
+};
+
+
+
+struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
+ NDB_THREAD_ARG *p_thread_arg,
+ const NDB_THREAD_STACKSIZE thread_stack_size,
+ const char* p_thread_name,
+ NDB_THREAD_PRIO thread_prio)
+{
+ struct NdbThread* tmpThread;
+ int result;
+ pthread_attr_t thread_attr;
+
+ if (p_thread_func == NULL)
+ return 0;
+
+ tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread));
+ if (tmpThread == NULL)
+ return NULL;
+
+ snprintf(tmpThread->thread_name, sizeof(tmpThread->thread_name),
+ "%s", p_thread_name);
+
+ pthread_attr_init(&thread_attr);
+ pthread_attr_setstacksize(&thread_attr, thread_stack_size);
+#ifdef USE_PTHREAD_EXTRAS
+ /* Guard stack overflow with a 2k databuffer */
+ pthread_attr_setguardsize(&thread_attr, 2048);
+#endif
+
+#ifdef PTHREAD_CREATE_JOINABLE /* needed on SCO */
+ pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+#endif
+ result = pthread_create(&tmpThread->thread,
+ &thread_attr,
+ p_thread_func,
+ p_thread_arg);
+ assert(result==0);
+
+ pthread_attr_destroy(&thread_attr);
+ return tmpThread;
+}
+
+
+void NdbThread_Destroy(struct NdbThread** p_thread)
+{
+ if (*p_thread != NULL){
+ free(* p_thread);
+ * p_thread = 0;
+ }
+}
+
+
+int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status)
+{
+ int result;
+
+ if (p_wait_thread == NULL)
+ return 0;
+
+ if (p_wait_thread->thread == 0)
+ return 0;
+
+ result = pthread_join(p_wait_thread->thread, status);
+
+ return result;
+}
+
+
+void NdbThread_Exit(int status)
+{
+ pthread_exit(&status);
+}
+
+
+int NdbThread_SetConcurrencyLevel(int level)
+{
+#ifdef USE_PTHREAD_EXTRAS
+ return pthread_setconcurrency(level);
+#else
+ return 0;
+#endif
+}
diff --git a/ndb/src/common/portlib/unix/NdbTick.c b/ndb/src/common/portlib/NdbTick.c
index d8f0b6ec27a..d8f0b6ec27a 100644
--- a/ndb/src/common/portlib/unix/NdbTick.c
+++ b/ndb/src/common/portlib/NdbTick.c
diff --git a/ndb/src/common/portlib/gcc.cpp b/ndb/src/common/portlib/gcc.cpp
index 41b1373ee78..66aa4812dc6 100644
--- a/ndb/src/common/portlib/gcc.cpp
+++ b/ndb/src/common/portlib/gcc.cpp
@@ -2,6 +2,6 @@
/**
* GCC linking problem...
*/
-#if ( __GNUC__ == 3 )
+#ifdef DEFINE_CXA_PURE_VIRTUAL
extern "C" { int __cxa_pure_virtual() { return 0;} }
#endif
diff --git a/ndb/src/common/portlib/memtest/memtest.c b/ndb/src/common/portlib/memtest.c
index 059a4ec025e..059a4ec025e 100644
--- a/ndb/src/common/portlib/memtest/memtest.c
+++ b/ndb/src/common/portlib/memtest.c
diff --git a/ndb/src/common/portlib/mmstest/mmslist.cpp b/ndb/src/common/portlib/mmslist.cpp
index 05538785293..05538785293 100644
--- a/ndb/src/common/portlib/mmstest/mmslist.cpp
+++ b/ndb/src/common/portlib/mmslist.cpp
diff --git a/ndb/src/common/portlib/mmstest/mmstest.cpp b/ndb/src/common/portlib/mmstest.cpp
index 9cc7d810985..9cc7d810985 100644
--- a/ndb/src/common/portlib/mmstest/mmstest.cpp
+++ b/ndb/src/common/portlib/mmstest.cpp
diff --git a/ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp b/ndb/src/common/portlib/munmaptest.cpp
index b1d84131810..b1d84131810 100644
--- a/ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp
+++ b/ndb/src/common/portlib/munmaptest.cpp
diff --git a/ndb/src/common/portlib/memtest/Makefile b/ndb/src/common/portlib/old_dirs/memtest/Makefile
index 716cdbdea82..716cdbdea82 100644
--- a/ndb/src/common/portlib/memtest/Makefile
+++ b/ndb/src/common/portlib/old_dirs/memtest/Makefile
diff --git a/ndb/src/common/portlib/memtest/munmaptest/Makefile b/ndb/src/common/portlib/old_dirs/memtest/munmaptest/Makefile
index ea8c5238d1c..ea8c5238d1c 100644
--- a/ndb/src/common/portlib/memtest/munmaptest/Makefile
+++ b/ndb/src/common/portlib/old_dirs/memtest/munmaptest/Makefile
diff --git a/ndb/src/common/portlib/ose/Makefile b/ndb/src/common/portlib/old_dirs/ose/Makefile
index 4ef93b7824a..4ef93b7824a 100644
--- a/ndb/src/common/portlib/ose/Makefile
+++ b/ndb/src/common/portlib/old_dirs/ose/Makefile
diff --git a/ndb/src/common/portlib/ose/NdbCondition.c b/ndb/src/common/portlib/old_dirs/ose/NdbCondition.c
index 73a2dbc5d66..73a2dbc5d66 100644
--- a/ndb/src/common/portlib/ose/NdbCondition.c
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbCondition.c
diff --git a/ndb/src/common/portlib/ose/NdbConditionOSE.h b/ndb/src/common/portlib/old_dirs/ose/NdbConditionOSE.h
index bd0306261cc..bd0306261cc 100644
--- a/ndb/src/common/portlib/ose/NdbConditionOSE.h
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbConditionOSE.h
diff --git a/ndb/src/common/portlib/ose/NdbEnv.c b/ndb/src/common/portlib/old_dirs/ose/NdbEnv.c
index e2ac4d879d2..e2ac4d879d2 100644
--- a/ndb/src/common/portlib/ose/NdbEnv.c
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbEnv.c
diff --git a/ndb/src/common/portlib/ose/NdbHost.c b/ndb/src/common/portlib/old_dirs/ose/NdbHost.c
index f5e1e511c16..f5e1e511c16 100644
--- a/ndb/src/common/portlib/ose/NdbHost.c
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbHost.c
diff --git a/ndb/src/common/portlib/ose/NdbMem.c b/ndb/src/common/portlib/old_dirs/ose/NdbMem.c
index 0e38024bbb4..0e38024bbb4 100644
--- a/ndb/src/common/portlib/ose/NdbMem.c
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbMem.c
diff --git a/ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp b/ndb/src/common/portlib/old_dirs/ose/NdbMem_SoftOse.cpp
index cad22c0474b..cad22c0474b 100644
--- a/ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbMem_SoftOse.cpp
diff --git a/ndb/src/common/portlib/ose/NdbMutex.c b/ndb/src/common/portlib/old_dirs/ose/NdbMutex.c
index 253c0e412ff..253c0e412ff 100644
--- a/ndb/src/common/portlib/ose/NdbMutex.c
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbMutex.c
diff --git a/ndb/src/common/portlib/ose/NdbOut.cpp b/ndb/src/common/portlib/old_dirs/ose/NdbOut.cpp
index eb81bc9d971..eb81bc9d971 100644
--- a/ndb/src/common/portlib/ose/NdbOut.cpp
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbOut.cpp
diff --git a/ndb/src/common/portlib/ose/NdbSleep.c b/ndb/src/common/portlib/old_dirs/ose/NdbSleep.c
index 70fd83117ef..70fd83117ef 100644
--- a/ndb/src/common/portlib/ose/NdbSleep.c
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbSleep.c
diff --git a/ndb/src/common/portlib/ose/NdbTCP.c b/ndb/src/common/portlib/old_dirs/ose/NdbTCP.c
index 9994697b3f8..9994697b3f8 100644
--- a/ndb/src/common/portlib/ose/NdbTCP.c
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbTCP.c
diff --git a/ndb/src/common/portlib/ose/NdbThread.c b/ndb/src/common/portlib/old_dirs/ose/NdbThread.c
index e46903a5cce..e46903a5cce 100644
--- a/ndb/src/common/portlib/ose/NdbThread.c
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbThread.c
diff --git a/ndb/src/common/portlib/ose/NdbTick.c b/ndb/src/common/portlib/old_dirs/ose/NdbTick.c
index c3deae2bec3..c3deae2bec3 100644
--- a/ndb/src/common/portlib/ose/NdbTick.c
+++ b/ndb/src/common/portlib/old_dirs/ose/NdbTick.c
diff --git a/ndb/src/common/portlib/test/Makefile b/ndb/src/common/portlib/old_dirs/test/Makefile
index 4edc98ede75..4edc98ede75 100644
--- a/ndb/src/common/portlib/test/Makefile
+++ b/ndb/src/common/portlib/old_dirs/test/Makefile
diff --git a/ndb/src/common/portlib/unix/Makefile b/ndb/src/common/portlib/old_dirs/unix/Makefile_old
index 452196d9f08..452196d9f08 100644
--- a/ndb/src/common/portlib/unix/Makefile
+++ b/ndb/src/common/portlib/old_dirs/unix/Makefile_old
diff --git a/ndb/src/common/portlib/win32/Makefile b/ndb/src/common/portlib/old_dirs/win32/Makefile
index bb29ac5547e..bb29ac5547e 100644
--- a/ndb/src/common/portlib/win32/Makefile
+++ b/ndb/src/common/portlib/old_dirs/win32/Makefile
diff --git a/ndb/src/common/portlib/win32/NdbCondition.c b/ndb/src/common/portlib/old_dirs/win32/NdbCondition.c
index 77869b673de..77869b673de 100644
--- a/ndb/src/common/portlib/win32/NdbCondition.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbCondition.c
diff --git a/ndb/src/common/portlib/win32/NdbDaemon.c b/ndb/src/common/portlib/old_dirs/win32/NdbDaemon.c
index 972fb1b88d8..972fb1b88d8 100644
--- a/ndb/src/common/portlib/win32/NdbDaemon.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbDaemon.c
diff --git a/ndb/src/common/portlib/win32/NdbEnv.c b/ndb/src/common/portlib/old_dirs/win32/NdbEnv.c
index 0df703a5e97..0df703a5e97 100644
--- a/ndb/src/common/portlib/win32/NdbEnv.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbEnv.c
diff --git a/ndb/src/common/portlib/win32/NdbHost.c b/ndb/src/common/portlib/old_dirs/win32/NdbHost.c
index f91dd1a531c..f91dd1a531c 100644
--- a/ndb/src/common/portlib/win32/NdbHost.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbHost.c
diff --git a/ndb/src/common/portlib/win32/NdbMem.c b/ndb/src/common/portlib/old_dirs/win32/NdbMem.c
index ab7123b0a29..ab7123b0a29 100644
--- a/ndb/src/common/portlib/win32/NdbMem.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbMem.c
diff --git a/ndb/src/common/portlib/win32/NdbMutex.c b/ndb/src/common/portlib/old_dirs/win32/NdbMutex.c
index e797024d5bb..e797024d5bb 100644
--- a/ndb/src/common/portlib/win32/NdbMutex.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbMutex.c
diff --git a/ndb/src/common/portlib/win32/NdbSleep.c b/ndb/src/common/portlib/old_dirs/win32/NdbSleep.c
index ac0f44dd07f..ac0f44dd07f 100644
--- a/ndb/src/common/portlib/win32/NdbSleep.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbSleep.c
diff --git a/ndb/src/common/portlib/win32/NdbTCP.c b/ndb/src/common/portlib/old_dirs/win32/NdbTCP.c
index 483a53bd606..483a53bd606 100644
--- a/ndb/src/common/portlib/win32/NdbTCP.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbTCP.c
diff --git a/ndb/src/common/portlib/win32/NdbThread.c b/ndb/src/common/portlib/old_dirs/win32/NdbThread.c
index 1f052f034e8..1f052f034e8 100644
--- a/ndb/src/common/portlib/win32/NdbThread.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbThread.c
diff --git a/ndb/src/common/portlib/win32/NdbTick.c b/ndb/src/common/portlib/old_dirs/win32/NdbTick.c
index e3a67d8437d..e3a67d8437d 100644
--- a/ndb/src/common/portlib/win32/NdbTick.c
+++ b/ndb/src/common/portlib/old_dirs/win32/NdbTick.c
diff --git a/ndb/src/common/portlib/unix/NdbDaemon.c b/ndb/src/common/portlib/unix/NdbDaemon.c
deleted file mode 100644
index 186331a4dab..00000000000
--- a/ndb/src/common/portlib/unix/NdbDaemon.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <ndb_global.h>
-#include "NdbDaemon.h"
-
-#define NdbDaemon_ErrorSize 500
-long NdbDaemon_DaemonPid;
-int NdbDaemon_ErrorCode;
-char NdbDaemon_ErrorText[NdbDaemon_ErrorSize];
-
-int
-NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
-{
- int lockfd = -1, logfd = -1, n;
- char buf[64];
-
- /* Check that we have write access to lock file */
- assert(lockfile != NULL);
- lockfd = open(lockfile, O_CREAT|O_RDWR, 0644);
- if (lockfd == -1) {
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: open for write failed: %s", lockfile, strerror(errno));
- return -1;
- }
- /* Read any old pid from lock file */
- buf[0] = 0;
- n = read(lockfd, buf, sizeof(buf));
- if (n < 0) {
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: read failed: %s", lockfile, strerror(errno));
- return -1;
- }
- NdbDaemon_DaemonPid = atol(buf);
- if (lseek(lockfd, 0, SEEK_SET) == -1) {
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: lseek failed: %s", lockfile, strerror(errno));
- return -1;
- }
- /* Test for lock before becoming daemon */
- if (lockf(lockfd, F_TEST, 0) == -1) {
- if (errno == EACCES || errno == EAGAIN) { /* results may vary */
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: already locked by pid=%ld", lockfile, NdbDaemon_DaemonPid);
- return -1;
- }
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: lock test failed: %s", lockfile, strerror(errno));
- return -1;
- }
- /* Test open log file before becoming daemon */
- if (logfile != NULL) {
- logfd = open(logfile, O_CREAT|O_WRONLY|O_APPEND, 0644);
- if (logfd == -1) {
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: open for write failed: %s", logfile, strerror(errno));
- return -1;
- }
- }
- /* Fork */
- n = fork();
- if (n == -1) {
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "fork failed: %s", strerror(errno));
- return -1;
- }
- /* Exit if we are the parent */
- if (n != 0) {
- exit(0);
- }
- /* Running in child process */
- NdbDaemon_DaemonPid = getpid();
- /* Lock the lock file (likely to succeed due to test above) */
- if (lockf(lockfd, F_LOCK, 0) == -1) {
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: lock failed: %s", lockfile, strerror(errno));
- return -1;
- }
- /* Become process group leader */
- if (setsid() == -1) {
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "setsid failed: %s", strerror(errno));
- return -1;
- }
- /* Write pid to lock file */
- if (ftruncate(lockfd, 0) == -1) {
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: ftruncate failed: %s", lockfile, strerror(errno));
- return -1;
- }
- sprintf(buf, "%ld\n", NdbDaemon_DaemonPid);
- n = strlen(buf);
- if (write(lockfd, buf, n) != n) {
- NdbDaemon_ErrorCode = errno;
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: write failed: %s", lockfile, strerror(errno));
- return -1;
- }
- /* Do input/output redirections (assume fd 0,1,2 not in use) */
- close(0);
- open("/dev/null", O_RDONLY);
- if (logfile != 0) {
- dup2(logfd, 1);
- dup2(logfd, 2);
- close(logfd);
- }
- /* Success */
- return 0;
-}
-
-#if 0
-int
-NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
-{
- /* Fail */
- snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "Daemon mode not implemented");
- return -1;
-}
-#endif
-
-#ifdef NDB_DAEMON_TEST
-
-int
-main()
-{
- if (NdbDaemon_Make("test.pid", "test.log", 0) == -1) {
- fprintf(stderr, "NdbDaemon_Make: %s\n", NdbDaemon_ErrorText);
- return 1;
- }
- sleep(10);
- return 0;
-}
-
-#endif
diff --git a/ndb/src/common/portlib/unix/NdbThread.c b/ndb/src/common/portlib/unix/NdbThread.c
deleted file mode 100644
index a5c42f79be8..00000000000
--- a/ndb/src/common/portlib/unix/NdbThread.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include <ndb_global.h>
-#include <NdbThread.h>
-#include <pthread.h>
-
-#define MAX_THREAD_NAME 16
-
-
-struct NdbThread
-{
- pthread_t thread;
- char thread_name[MAX_THREAD_NAME];
-};
-
-
-
-struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
- NDB_THREAD_ARG *p_thread_arg,
- const NDB_THREAD_STACKSIZE thread_stack_size,
- const char* p_thread_name,
- NDB_THREAD_PRIO thread_prio)
-{
- struct NdbThread* tmpThread;
- int result;
- pthread_attr_t thread_attr;
-
- if (p_thread_func == NULL)
- return 0;
-
- tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread));
- if (tmpThread == NULL)
- return NULL;
-
- snprintf(tmpThread->thread_name, sizeof(tmpThread->thread_name),
- "%s", p_thread_name);
-
- pthread_attr_init(&thread_attr);
- pthread_attr_setstacksize(&thread_attr, thread_stack_size);
-#if defined NDB_SOLARIS
-#if !defined NDB_SOLARIS6
- /* Guard stack overflow with a 2k databuffer */
- pthread_attr_setguardsize(&thread_attr, 2048);
-#endif
-#endif
-
- pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
- result = pthread_create(&tmpThread->thread,
- &thread_attr,
- p_thread_func,
- p_thread_arg);
- assert(result==0);
-
- pthread_attr_destroy(&thread_attr);
- return tmpThread;
-}
-
-
-void NdbThread_Destroy(struct NdbThread** p_thread)
-{
- if (*p_thread != NULL){
- free(* p_thread);
- * p_thread = 0;
- }
-}
-
-
-int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status)
-{
- int result;
-
- if (p_wait_thread == NULL)
- return 0;
-
- if (p_wait_thread->thread == 0)
- return 0;
-
- result = pthread_join(p_wait_thread->thread, status);
-
- return result;
-}
-
-
-void NdbThread_Exit(int status)
-{
- pthread_exit(&status);
-}
-
-
-int NdbThread_SetConcurrencyLevel(int level)
-{
-#ifndef NDB_SOLARIS6
- return pthread_setconcurrency(level);
-#else
- return 0;
-#endif
-}
diff --git a/ndb/src/common/transporter/Makefile.am b/ndb/src/common/transporter/Makefile.am
new file mode 100644
index 00000000000..218b261606d
--- /dev/null
+++ b/ndb/src/common/transporter/Makefile.am
@@ -0,0 +1,22 @@
+
+noinst_LTLIBRARIES = libtransporter.la
+
+libtransporter_la_SOURCES = \
+ Transporter.cpp \
+ SendBuffer.cpp \
+ TCP_Transporter.cpp \
+ TransporterRegistry.cpp \
+ Packer.cpp
+
+EXTRA_libtransporter_la_SOURCES = SHM_Transporter.cpp SHM_Transporter.unix.cpp SCI_Transporter.cpp
+
+libtransporter_la_LIBADD = @ndb_transporter_opt_objs@
+libtransporter_la_DEPENDENCIES = @ndb_transporter_opt_objs@
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel -I$(top_srcdir)/ndb/include/transporter
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_util.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/common/transporter/Makefile b/ndb/src/common/transporter/Makefile_old
index 372bf640566..372bf640566 100644
--- a/ndb/src/common/transporter/Makefile
+++ b/ndb/src/common/transporter/Makefile_old
diff --git a/ndb/src/common/transporter/Transporter.hpp b/ndb/src/common/transporter/Transporter.hpp
index c562451a1b0..43b26d45899 100644
--- a/ndb/src/common/transporter/Transporter.hpp
+++ b/ndb/src/common/transporter/Transporter.hpp
@@ -17,6 +17,8 @@
#ifndef Transporter_H
#define Transporter_H
+#include <ndb_global.h>
+
#include <TransporterCallback.hpp>
#include "TransporterDefinitions.hpp"
#include "Packer.hpp"
diff --git a/ndb/src/common/util/Base64.cpp b/ndb/src/common/util/Base64.cpp
index 482d0b10ad2..f7a490d427d 100644
--- a/ndb/src/common/util/Base64.cpp
+++ b/ndb/src/common/util/Base64.cpp
@@ -22,89 +22,186 @@ static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789+/";
int
-base64_encode(UtilBuffer &src, BaseString &dst) {
- char *s = (char *)src.get_data();
- int i = 0;
+base64_encode(const UtilBuffer &src, BaseString &dst) {
+ const unsigned char *s = (const unsigned char *)src.get_data();
+ size_t i = 0;
+ size_t len = 0;
+ size_t src_len = src.length();
+ while(i < src_len) {
+ if(len == 76){
+ len = 0;
+ dst.append('\n');
+ }
- while(i < src.length()) {
- int c;
+ unsigned c;
c = s[i++];
c <<= 8;
- if(i < src.length())
+ if(i < src_len)
c += s[i];
c <<= 8;
i++;
- if(i < src.length())
+ if(i < src_len)
c += s[i];
i++;
-
+
dst.append(base64_table[(c >> 18) & 0x3f]);
dst.append(base64_table[(c >> 12) & 0x3f]);
- if(i > (src.length() + 1))
+ if(i > (src_len + 1))
dst.append('=');
else
dst.append(base64_table[(c >> 6) & 0x3f]);
- if(i > src.length())
+ if(i > src_len)
dst.append('=');
else
dst.append(base64_table[(c >> 0) & 0x3f]);
+
+ len += 4;
}
return 0;
}
-static inline int
-pos(char c) {
+static inline unsigned
+pos(unsigned char c) {
return strchr(base64_table, c) - base64_table;
}
int
-base64_decode(BaseString &src, UtilBuffer &dst) {
- size_t size;
- size = (src.length() * 3) / 4;
+base64_decode(const BaseString &src, UtilBuffer &dst) {
+ return base64_decode(src.c_str(), src.length(), dst);
+}
+
+#define SKIP_SPACE(src, i, size){ \
+ while(i < size && isspace(* src)){ \
+ i++; \
+ src++; \
+ } \
+ if(i == size){ \
+ i = size + 1; \
+ break; \
+ } \
+}
+
+int
+base64_decode(const char * src, size_t size, UtilBuffer &dst) {
size_t i = 0;
- const char *s = src.c_str();
- while(i < size) {
- int c = 0;
+ while(i < size){
+ unsigned c = 0;
int mark = 0;
- c += pos(*s++);
+
+ SKIP_SPACE(src, i, size);
+
+ c += pos(*src++);
c <<= 6;
i++;
- c += pos(*s++);
+ SKIP_SPACE(src, i, size);
+
+ c += pos(*src++);
c <<= 6;
i++;
- if(*s != '=')
- c += pos(*s++);
+ SKIP_SPACE(src, i, size);
+
+ if(* src != '=')
+ c += pos(*src++);
else {
- size--;
- mark++;
+ i = size;
+ mark = 2;
+ c <<= 6;
+ goto end;
}
c <<= 6;
i++;
- if(*s != '=')
- c += pos(*s++);
+ SKIP_SPACE(src, i, size);
+
+ if(*src != '=')
+ c += pos(*src++);
else {
- size--;
- mark++;
+ i = size;
+ mark = 1;
+ goto end;
}
- /* c <<= 6; */
i++;
+ end:
char b[3];
-
-
b[0] = (c >> 16) & 0xff;
b[1] = (c >> 8) & 0xff;
b[2] = (c >> 0) & 0xff;
-
+
dst.append((void *)b, 3-mark);
}
+
+ if(i != size){
+ abort();
+ return -1;
+ }
return 0;
}
+
+#ifdef __TEST__B64
+/**
+ * USER_FLAGS="-D__TEST__B64" make Base64.o && g++ Base64.o BaseString.o
+ */
+inline
+void
+require(bool b){
+ if(!b)
+ abort();
+}
+
+int
+main(void){
+ for(int i = 0; i < 500; i++){
+ const size_t len = rand() % 10000 + 1;
+ UtilBuffer src;
+ for(size_t j = 0; j<len; j++){
+ char c = rand();
+ src.append(&c, 1);
+ }
+ require(src.length() == len);
+
+ BaseString str;
+ require(base64_encode(src, str) == 0);
+
+ if(str.length() == 3850){
+ printf(">%s<\n", str.c_str());
+ }
+
+ UtilBuffer dst;
+ require(base64_decode(str, dst) == 0);
+ require(dst.length() == src.length());
+
+ const char * c_src = (char*)src.get_data();
+ const char * c_dst = (char*)dst.get_data();
+ if(memcmp(src.get_data(), dst.get_data(), src.length()) != 0){
+ printf("-- src --\n");
+ for(int i2 = 0; i2<len; i2++){
+ unsigned char c = c_src[i2];
+ printf("%.2x ", (unsigned)c);
+ if((i2 % 8) == 7)
+ printf("\n");
+ }
+ printf("\n");
+
+ printf("-- dst --\n");
+ for(int i2 = 0; i2<len; i2++){
+ unsigned char c = c_dst[i2];
+ printf("%.2x ", (unsigned)c);
+ if((i2 % 8) == 7)
+ printf("\n");
+ }
+ printf("\n");
+ abort();
+ }
+ }
+ return 0;
+}
+
+#endif
diff --git a/ndb/src/common/util/ConfigValues.cpp b/ndb/src/common/util/ConfigValues.cpp
new file mode 100644
index 00000000000..18ecf4bcdc4
--- /dev/null
+++ b/ndb/src/common/util/ConfigValues.cpp
@@ -0,0 +1,743 @@
+#include <ConfigValues.hpp>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <new>
+#include <NdbOut.hpp>
+#include <NdbTCP.h>
+
+static Uint32 hash(Uint32 key, Uint32 size);
+static Uint32 nextHash(Uint32 key, Uint32 size, Uint32 pos, Uint32 count);
+static bool findKey(const Uint32 * vals, Uint32 sz, Uint32 key, Uint32 * pos);
+
+/**
+ * Key
+ *
+ * t = Type - 4 bits 0-15
+ * s = Section - 14 bits 0-16383
+ * k = Key value - 14 bits 0-16383
+ *
+ * 1111111111222222222233
+ * 01234567890123456789012345678901
+ * kkkkkkkkkkkkkkssssssssssssssoooo
+ */
+#define KP_TYPE_MASK (15)
+#define KP_TYPE_SHIFT (28)
+#define KP_SECTION_MASK (0x3FFF)
+#define KP_SECTION_SHIFT (14)
+#define KP_KEYVAL_MASK (0x3FFF)
+#define KP_KEYVAL_SHIFT (0)
+#define KP_MASK (0x0FFFFFFF)
+
+static const Uint32 CFV_KEY_PARENT = (KP_KEYVAL_MASK - 1);
+static const Uint32 CFV_KEY_FREE = ~0;
+
+static const char Magic[] = { 'N', 'D', 'B', 'C', 'O', 'N', 'F', 'V' };
+
+//#define DEBUG_CV
+#ifdef DEBUG_CV
+#define DEBUG
+#else
+#define DEBUG if(0)
+#endif
+
+inline
+ConfigValues::ValueType
+getTypeOf(Uint32 k) {
+ return (ConfigValues::ValueType)((k >> KP_TYPE_SHIFT) & KP_TYPE_MASK);
+}
+
+ConfigValues::ConfigValues(Uint32 sz, Uint32 dsz){
+ m_size = sz;
+ m_dataSize = dsz;
+ m_stringCount = 0;
+ m_int64Count = 0;
+ for(Uint32 i = 0; i<m_size; i++){
+ m_values[i << 1] = CFV_KEY_FREE;
+ }
+}
+
+ConfigValues::~ConfigValues(){
+ for(Uint32 i = 0; i<m_stringCount; i++){
+ free(getString(i));
+ }
+}
+
+bool
+ConfigValues::ConstIterator::get(Uint32 key, Entry * result) const {
+ Uint32 pos;
+ if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
+ return false;
+ }
+
+ result->m_key = key;
+ return m_cfg.getByPos(pos, result);
+}
+
+bool
+ConfigValues::getByPos(Uint32 pos, Entry * result) const {
+ assert(pos < (2 * m_size));
+ Uint32 keypart = m_values[pos];
+ Uint32 val = m_values[pos+1];
+
+ switch(::getTypeOf(keypart)){
+ case IntType:
+ case SectionType:
+ result->m_int = val;
+ break;
+ case StringType:
+ result->m_string = getString(val);
+ break;
+ case Int64Type:
+ result->m_int64 = get64(val);
+ break;
+ case InvalidType:
+ default:
+ return false;
+ }
+
+ result->m_type = ::getTypeOf(keypart);
+
+ return true;
+}
+
+Uint64 &
+ConfigValues::get64(Uint32 index) const {
+ assert(index < m_int64Count);
+ Uint64 * ptr = (Uint64*)(&m_values[m_size << 1]);
+ return ptr[index];
+}
+
+char * &
+ConfigValues::getString(Uint32 index) const {
+ assert(index < m_stringCount);
+ char ** ptr = (char**)(((char *)&(m_values[m_size << 1])) + m_dataSize);
+ return ptr[-index];
+}
+
+bool
+ConfigValues::ConstIterator::openSection(Uint32 key, Uint32 no){
+ Uint32 curr = m_currentSection;
+
+ Entry tmp;
+ if(get(key, &tmp) && tmp.m_type == SectionType){
+ m_currentSection = tmp.m_int;
+ if(get(no, &tmp) && tmp.m_type == IntType){
+ m_currentSection = tmp.m_int;
+ /**
+ * Validate
+ */
+ if(get(CFV_KEY_PARENT, &tmp)){
+ return true;
+ }
+ }
+ }
+
+ m_currentSection = curr;
+ return false;
+}
+
+bool
+ConfigValues::ConstIterator::closeSection() {
+
+ Entry tmp;
+ if(get(CFV_KEY_PARENT, &tmp) && tmp.m_type == IntType){
+ m_currentSection = tmp.m_int;
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ConfigValues::Iterator::set(Uint32 key, Uint32 value){
+ Uint32 pos;
+ if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
+ return false;
+ }
+
+ if(::getTypeOf(m_cfg.m_values[pos]) != IntType){
+ return false;
+ }
+
+ m_cfg.m_values[pos+1] = value;
+ return true;
+}
+
+bool
+ConfigValues::Iterator::set(Uint32 key, Uint64 value){
+ Uint32 pos;
+ if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
+ return false;
+ }
+
+ if(::getTypeOf(m_cfg.m_values[pos]) != Int64Type){
+ return false;
+ }
+
+ m_cfg.get64(m_cfg.m_values[pos+1]) = value;
+ return true;
+}
+
+bool
+ConfigValues::Iterator::set(Uint32 key, const char * value){
+ Uint32 pos;
+ if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
+ return false;
+ }
+
+ if(::getTypeOf(m_cfg.m_values[pos]) != StringType){
+ return false;
+ }
+
+ char * & str = m_cfg.getString(m_cfg.m_values[pos+1]);
+ free(str);
+ str = strdup(value ? value : "");
+ return true;
+}
+
+static
+bool
+findKey(const Uint32 * values, Uint32 sz, Uint32 key, Uint32 * _pos){
+ Uint32 pos = hash(key, sz);
+ Uint32 count = 0;
+ while((values[pos] & KP_MASK) != key && count < sz){
+ pos = nextHash(key, sz, pos, ++count);
+ }
+
+ if((values[pos] & KP_MASK)== key){
+ *_pos = pos;
+ return true;
+ }
+ return false;
+}
+
+static
+Uint32
+hash(Uint32 key, Uint32 size){
+ Uint32 tmp = (key >> 16) ^ (key & 0xFFFF);
+ return (((tmp << 16) | tmp) % size) << 1;
+}
+
+static
+Uint32
+nextHash(Uint32 key, Uint32 size, Uint32 pos, Uint32 count){
+ Uint32 p = (pos >> 1);
+ if((key % size) != 0)
+ p += key;
+ else
+ p += 1;
+ return (p % size) << 1;
+}
+
+static
+Uint32
+directory(Uint32 sz){
+ const Uint32 _input = sz;
+ if((sz & 1) == 0)
+ sz ++;
+
+ bool prime = false;
+ while(!prime){
+ prime = true;
+ for(Uint32 n = 3; n*n <= sz; n += 2){
+ if((sz % n) == 0){
+ prime = false;
+ sz += 2;
+ break;
+ }
+ }
+ }
+ DEBUG printf("directory %d -> %d\n", _input, sz);
+ return sz;
+}
+
+ConfigValuesFactory::ConfigValuesFactory(Uint32 keys, Uint32 data){
+ m_sectionCounter = (1 << KP_SECTION_SHIFT);
+ m_freeKeys = directory(keys);
+ m_freeData = data;
+ m_currentSection = 0;
+ m_cfg = create(m_freeKeys, data);
+}
+
+ConfigValuesFactory::ConfigValuesFactory(ConfigValues * cfg){
+ m_cfg = cfg;
+ m_freeKeys = 0;
+ m_freeData = m_cfg->m_dataSize;
+ m_sectionCounter = (1 << KP_SECTION_SHIFT);
+ m_currentSection = 0;
+ const Uint32 sz = 2 * m_cfg->m_size;
+ for(Uint32 i = 0; i<sz; i += 2){
+ const Uint32 key = m_cfg->m_values[i];
+ if(key == CFV_KEY_FREE){
+ m_freeKeys++;
+ } else {
+ switch(::getTypeOf(key)){
+ case ConfigValues::IntType:
+ case ConfigValues::SectionType:
+ break;
+ case ConfigValues::Int64Type:
+ m_freeData -= sizeof(Uint64);
+ break;
+ case ConfigValues::StringType:
+ m_freeData -= sizeof(char *);
+ break;
+ case ConfigValues::InvalidType:
+ abort();
+ }
+ Uint32 sec = key & (KP_SECTION_MASK << KP_SECTION_SHIFT);
+ m_sectionCounter = (sec > m_sectionCounter ? sec : m_sectionCounter);
+ }
+ }
+}
+
+ConfigValues *
+ConfigValuesFactory::create(Uint32 keys, Uint32 data){
+ Uint32 sz = sizeof(ConfigValues);
+ sz += (2 * keys * sizeof(Uint32));
+ sz += data;
+
+ void * tmp = malloc(sz);
+ return new (tmp) ConfigValues(keys, data);
+}
+
+void
+ConfigValuesFactory::expand(Uint32 fk, Uint32 fs){
+ if(m_freeKeys >= fk && m_freeData >= fs){
+ return ;
+ }
+
+ m_freeKeys = (m_freeKeys >= fk ? m_cfg->m_size : fk + m_cfg->m_size);
+ m_freeData = (m_freeData >= fs ? m_cfg->m_dataSize : fs + m_cfg->m_dataSize);
+ m_freeKeys = directory(m_freeKeys);
+
+ ConfigValues * m_tmp = m_cfg;
+ m_cfg = create(m_freeKeys, m_freeData);
+ put(* m_tmp);
+ m_tmp->~ConfigValues();
+ free(m_tmp);
+}
+
+void
+ConfigValuesFactory::shrink(){
+ if(m_freeKeys == 0 && m_freeData == 0){
+ return ;
+ }
+
+ m_freeKeys = m_cfg->m_size - m_freeKeys;
+ m_freeData = m_cfg->m_dataSize - m_freeData;
+ m_freeKeys = directory(m_freeKeys);
+
+ ConfigValues * m_tmp = m_cfg;
+ m_cfg = create(m_freeKeys, m_freeData);
+ put(* m_tmp);
+ m_tmp->~ConfigValues();
+ free(m_tmp);
+}
+
+bool
+ConfigValuesFactory::openSection(Uint32 key, Uint32 no){
+ ConfigValues::Entry tmp;
+ const Uint32 parent = m_currentSection;
+
+ ConfigValues::ConstIterator iter(* m_cfg);
+ iter.m_currentSection = m_currentSection;
+ if(!iter.get(key, &tmp)){
+
+ tmp.m_key = key;
+ tmp.m_type = ConfigValues::SectionType;
+ tmp.m_int = m_sectionCounter;
+ m_sectionCounter += (1 << KP_SECTION_SHIFT);
+
+ if(!put(tmp)){
+ return false;
+ }
+ }
+
+ if(tmp.m_type != ConfigValues::SectionType){
+ return false;
+ }
+
+ m_currentSection = tmp.m_int;
+
+ tmp.m_key = no;
+ tmp.m_type = ConfigValues::IntType;
+ tmp.m_int = m_sectionCounter;
+ if(!put(tmp)){
+ m_currentSection = parent;
+ return false;
+ }
+ m_sectionCounter += (1 << KP_SECTION_SHIFT);
+
+ m_currentSection = tmp.m_int;
+ tmp.m_type = ConfigValues::IntType;
+ tmp.m_key = CFV_KEY_PARENT;
+ tmp.m_int = parent;
+ if(!put(tmp)){
+ m_currentSection = parent;
+ return false;
+ }
+
+ return true;
+}
+
+bool
+ConfigValuesFactory::closeSection(){
+ ConfigValues::ConstIterator iter(* m_cfg);
+ iter.m_currentSection = m_currentSection;
+ const bool b = iter.closeSection();
+ m_currentSection = iter.m_currentSection;
+ return b;
+}
+
+bool
+ConfigValuesFactory::put(const ConfigValues::Entry & entry){
+
+ if(m_freeKeys == 0 ||
+ (entry.m_type == ConfigValues::StringType && m_freeData < sizeof(char *))
+ || (entry.m_type == ConfigValues::Int64Type && m_freeData < 8 )){
+
+ DEBUG ndbout_c("m_freeKeys = %d, m_freeData = %d -> expand",
+ m_freeKeys, m_freeData);
+
+ expand(31, 20);
+ }
+
+ const Uint32 tmp = entry.m_key | m_currentSection;
+ const Uint32 sz = m_cfg->m_size;
+ Uint32 pos = hash(tmp, sz);
+ Uint32 count = 0;
+ Uint32 val = m_cfg->m_values[pos];
+
+ while((val & KP_MASK) != tmp && val != CFV_KEY_FREE && count < sz){
+ pos = nextHash(tmp, sz, pos, ++count);
+ val = m_cfg->m_values[pos];
+ }
+
+ if((val & KP_MASK) == tmp){
+ DEBUG ndbout_c("key %x already found at pos: %d", tmp, pos);
+ return false;
+ }
+
+ if(count >= sz){
+ pos = hash(tmp, sz);
+ count = 0;
+ Uint32 val = m_cfg->m_values[pos];
+
+ printf("key: %d, (key %% size): %d\n", entry.m_key, (entry.m_key % sz));
+ printf("pos: %d", pos);
+ while((val & KP_MASK) != tmp && val != CFV_KEY_FREE && count < sz){
+ pos = nextHash(tmp, sz, pos, ++count);
+ val = m_cfg->m_values[pos];
+ printf(" %d", pos);
+ }
+ printf("\n");
+
+ abort();
+ printf("Full\n");
+ return false;
+ }
+
+ assert(pos < (sz << 1));
+
+ Uint32 key = tmp;
+ key |= (entry.m_type << KP_TYPE_SHIFT);
+ m_cfg->m_values[pos] = key;
+ switch(entry.m_type){
+ case ConfigValues::IntType:
+ case ConfigValues::SectionType:
+ m_cfg->m_values[pos+1] = entry.m_int;
+ m_freeKeys--;
+ DEBUG printf("Putting at: %d(%d) (loop = %d) key: %d value: %d\n",
+ pos, sz, count,
+ (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
+ entry.m_int);
+ return true;
+ case ConfigValues::StringType:{
+ Uint32 index = m_cfg->m_stringCount++;
+ m_cfg->m_values[pos+1] = index;
+ m_cfg->getString(index) = strdup(entry.m_string ? entry.m_string : "");
+ m_freeKeys--;
+ m_freeData -= sizeof(char *);
+ DEBUG printf("Putting at: %d(%d) (loop = %d) key: %d value(%d): %s\n",
+ pos, sz, count,
+ (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
+ index,
+ entry.m_string);
+ return true;
+ }
+ case ConfigValues::Int64Type:{
+ Uint32 index = m_cfg->m_int64Count++;
+ m_cfg->m_values[pos+1] = index;
+ m_cfg->get64(index) = entry.m_int64;
+ m_freeKeys--;
+ m_freeData -= 8;
+ DEBUG printf("Putting at: %d(%d) (loop = %d) key: %d value64(%d): %lld\n",
+ pos, sz, count,
+ (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
+ index,
+ entry.m_int64);
+ return true;
+ }
+ case ConfigValues::InvalidType:
+ default:
+ return false;
+ }
+ return false;
+}
+
+void
+ConfigValuesFactory::put(const ConfigValues & cfg){
+
+ Uint32 curr = m_currentSection;
+ m_currentSection = 0;
+
+ ConfigValues::Entry tmp;
+ for(Uint32 i = 0; i < 2 * cfg.m_size; i += 2){
+ if(cfg.m_values[i] != CFV_KEY_FREE){
+ tmp.m_key = cfg.m_values[i];
+ cfg.getByPos(i, &tmp);
+ put(tmp);
+ }
+ }
+
+ m_currentSection = curr;
+}
+
+ConfigValues *
+ConfigValuesFactory::extractCurrentSection(const ConfigValues::ConstIterator & cfg){
+ ConfigValuesFactory * fac = new ConfigValuesFactory(20, 20);
+ Uint32 curr = cfg.m_currentSection;
+
+ ConfigValues::Entry tmp;
+ for(Uint32 i = 0; i < 2 * cfg.m_cfg.m_size; i += 2){
+ Uint32 keypart = cfg.m_cfg.m_values[i];
+ const Uint32 sec = keypart & (KP_SECTION_MASK << KP_SECTION_SHIFT);
+ const Uint32 key = keypart & KP_KEYVAL_MASK;
+ if(sec == curr && key != CFV_KEY_PARENT){
+ tmp.m_key = cfg.m_cfg.m_values[i];
+ cfg.m_cfg.getByPos(i, &tmp);
+ tmp.m_key = key;
+ fac->put(tmp);
+ }
+ }
+
+ ConfigValues * ret = fac->m_cfg;
+ delete fac;
+ return ret;
+}
+
+ConfigValues *
+ConfigValuesFactory::getConfigValues(){
+ ConfigValues * ret = m_cfg;
+ m_cfg = create(10, 10);
+ return ret;
+}
+
+static int
+mod4(unsigned int i){
+ int res = i + (4 - (i % 4));
+ return res;
+}
+
+Uint32
+ConfigValues::getPackedSize() const {
+
+ Uint32 size = 0;
+ for(Uint32 i = 0; i < 2 * m_size; i += 2){
+ Uint32 key = m_values[i];
+ if(key != CFV_KEY_FREE){
+ switch(::getTypeOf(key)){
+ case IntType:
+ case SectionType:
+ size += 8;
+ break;
+ case Int64Type:
+ size += 12;
+ break;
+ case StringType:
+ size += 8; // key + len
+ size += mod4(strlen(getString(m_values[i+1])) + 1);
+ break;
+ case InvalidType:
+ default:
+ abort();
+ }
+ }
+ }
+
+ return size + sizeof(Magic) + 4; // checksum also
+}
+
+Uint32
+ConfigValues::pack(void * _dst, Uint32 _len) const {
+
+ char * dst = (char*)_dst;
+ memcpy(dst, Magic, sizeof(Magic)); dst += sizeof(Magic);
+
+ for(Uint32 i = 0; i < 2 * m_size; i += 2){
+ Uint32 key = m_values[i];
+ Uint32 val = m_values[i+1];
+ if(key != CFV_KEY_FREE){
+ switch(::getTypeOf(key)){
+ case IntType:
+ case SectionType:
+ * (Uint32*)dst = htonl(key); dst += 4;
+ * (Uint32*)dst = htonl(val); dst += 4;
+ break;
+ case Int64Type:{
+ Uint64 i64 = get64(val);
+ Uint32 hi = (i64 >> 32);
+ Uint32 lo = (i64 & 0xFFFFFFFF);
+ * (Uint32*)dst = htonl(key); dst += 4;
+ * (Uint32*)dst = htonl(hi); dst += 4;
+ * (Uint32*)dst = htonl(lo); dst += 4;
+ }
+ break;
+ case StringType:{
+ const char * str = getString(val);
+ Uint32 len = strlen(str) + 1;
+ * (Uint32*)dst = htonl(key); dst += 4;
+ * (Uint32*)dst = htonl(len); dst += 4;
+ memcpy(dst, str, len);
+ memset(dst+len, 0, mod4(len) - len);
+ dst += mod4(len);
+ }
+ break;
+ case InvalidType:
+ default:
+ abort();
+ }
+ }
+ }
+
+ const Uint32 * sum = (Uint32*)_dst;
+ const Uint32 len = ((Uint32*)dst) - sum;
+ Uint32 chk = 0;
+ for(Uint32 i = 0; i<len; i++){
+ chk ^= htonl(sum[i]);
+ }
+
+ * (Uint32*)dst = htonl(chk); dst += 4;
+ return 4 * (len + 1);
+}
+
+bool
+ConfigValuesFactory::unpack(const void * _src, Uint32 len){
+
+ if(len < sizeof(Magic) + 4){
+ DEBUG abort();
+ return false;
+ }
+
+ if(memcmp(_src, Magic, sizeof(Magic)) != 0){
+ DEBUG abort();
+ return false;
+ }
+
+ const char * src = (const char *)_src;
+
+ {
+ Uint32 len32 = (len >> 2);
+ const Uint32 * tmp = (const Uint32*)_src;
+ Uint32 chk = 0;
+ for(Uint32 i = 0; (i+1)<len32; i++){
+ chk ^= ntohl(tmp[i]);
+ }
+
+ if(chk != ntohl(tmp[len32-1])){
+ DEBUG abort();
+ return false;
+ }
+ }
+
+ const char * end = src + len - 4;
+ src += sizeof(Magic);
+
+ ConfigValues::Entry entry;
+ while(end - src > 4){
+ Uint32 tmp = ntohl(* (const Uint32 *)src); src += 4;
+ entry.m_key = tmp & KP_MASK;
+ entry.m_type = ::getTypeOf(tmp);
+ switch(entry.m_type){
+ case ConfigValues::IntType:
+ case ConfigValues::SectionType:
+ entry.m_int = ntohl(* (const Uint32 *)src); src += 4;
+ break;
+ case ConfigValues::Int64Type:{
+ Uint64 hi = ntohl(* (const Uint32 *)src); src += 4;
+ Uint64 lo = ntohl(* (const Uint32 *)src); src += 4;
+ entry.m_int64 = (hi <<32) | lo;
+ }
+ break;
+ case ConfigValues::StringType:{
+ Uint32 s_len = ntohl(* (const Uint32 *)src); src += 4;
+ size_t s_len2 = strlen((const char*)src);
+ if(s_len2 + 1 != s_len){
+ DEBUG abort();
+ return false;
+ }
+
+ entry.m_string = (const char*)src; src+= mod4(s_len);
+ }
+ break;
+ case ConfigValues::InvalidType:
+ default:
+ DEBUG abort();
+ return false;
+ }
+ if(!put(entry)){
+ DEBUG abort();
+ return false;
+ }
+ }
+ if(src != end){
+ DEBUG abort();
+ return false;
+ }
+ return true;
+}
+
+#ifdef __TEST_CV_HASH_HPP
+
+int
+main(void){
+ srand(time(0));
+ for(int t = 0; t<100; t++){
+ const size_t len = directory(rand() % 1000);
+
+ printf("size = %d\n", len);
+ unsigned * buf = new unsigned[len];
+ for(size_t key = 0; key<len; key++){
+ Uint32 p = hash(key, len);
+ for(size_t j = 0; j<len; j++){
+ buf[j] = p;
+ p = nextHash(key, len, p, j+1);
+ }
+
+ for(size_t j = 0; j<len; j++){
+ Uint32 pos = buf[j];
+ int unique = 0;
+ for(size_t k = j + 1; k<len; k++){
+ if(pos == buf[k]){
+ if(unique > 0)
+ printf("size=%d key=%d pos(%d)=%d buf[%d]=%d\n", len, key, j, pos, k, buf[k]);
+ unique ++;
+ }
+ }
+ if(unique > 1){
+ printf("key = %d size = %d not uniqe!!\n", key, len);
+ for(size_t k = 0; k<len; k++){
+ printf("%d ", buf[k]);
+ }
+ printf("\n");
+ }
+ }
+ }
+ delete[] buf;
+ }
+ return 0;
+}
+
+#endif
diff --git a/ndb/src/common/util/Makefile b/ndb/src/common/util/Makefile
deleted file mode 100644
index e8ca2b87c20..00000000000
--- a/ndb/src/common/util/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-include .defs.mk
-
-TYPE := util
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := general
-
-SOURCES = File.cpp md5_hash.cpp Properties.cpp socket_io.cpp \
- SimpleProperties.cpp Parser.cpp InputStream.cpp SocketServer.cpp \
- OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \
- NdbSqlUtil.cpp new.cpp
-
-SOURCES.c = uucode.c random.c getarg.c version.c
-
-ifeq ($(NDB_OS), OSE)
- SOURCES += NdbErrHnd.cpp
-endif
-ifeq ($(NDB_OS), OSE)
- SOURCES += NdbErrHnd.cpp
-endif
- SOURCES.c += strdup.c strlcat.c strlcpy.c
-
-DIRS := testSimpleProperties
-
-include $(NDB_TOP)/Epilogue.mk
-
-testNdbSqlUtil: NdbSqlUtil.cpp
- $(CC) -o $@ NdbSqlUtil.cpp $(CCFLAGS) -DNDB_SQL_UTIL_TEST -L$(NDB_TOP)/lib -lportlib -lgeneral
diff --git a/ndb/src/common/util/Makefile.am b/ndb/src/common/util/Makefile.am
new file mode 100644
index 00000000000..59d9775b8e3
--- /dev/null
+++ b/ndb/src/common/util/Makefile.am
@@ -0,0 +1,17 @@
+
+noinst_LTLIBRARIES = libgeneral.la
+
+libgeneral_la_SOURCES = \
+ File.cpp md5_hash.cpp Properties.cpp socket_io.cpp \
+ SimpleProperties.cpp Parser.cpp InputStream.cpp SocketServer.cpp \
+ OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \
+ NdbSqlUtil.cpp new.cpp \
+ uucode.c random.c getarg.c version.c \
+ strdup.c strlcat.c strlcpy.c \
+ ConfigValues.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_util.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/common/util/Makefile_old b/ndb/src/common/util/Makefile_old
new file mode 100644
index 00000000000..65093396246
--- /dev/null
+++ b/ndb/src/common/util/Makefile_old
@@ -0,0 +1,28 @@
+include .defs.mk
+
+TYPE := util
+
+PIC_ARCHIVE := Y
+ARCHIVE_TARGET := general
+
+SOURCES = File.cpp md5_hash.cpp Properties.cpp socket_io.cpp \
+ SimpleProperties.cpp Parser.cpp InputStream.cpp SocketServer.cpp \
+ OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \
+ NdbSqlUtil.cpp ConfigValues.cpp new.cpp
+
+SOURCES.c = uucode.c random.c getarg.c version.c
+
+ifeq ($(NDB_OS), OSE)
+ SOURCES += NdbErrHnd.cpp
+endif
+ifeq ($(NDB_OS), OSE)
+ SOURCES += NdbErrHnd.cpp
+endif
+ SOURCES.c += strdup.c strlcat.c strlcpy.c
+
+DIRS := testSimpleProperties testProperties testConfigValues
+
+include $(NDB_TOP)/Epilogue.mk
+
+testNdbSqlUtil: NdbSqlUtil.cpp
+ $(CC) -o $@ NdbSqlUtil.cpp $(CCFLAGS) -DNDB_SQL_UTIL_TEST -L$(NDB_TOP)/lib -lportlib -lgeneral
diff --git a/ndb/src/common/util/NdbSqlUtil.cpp b/ndb/src/common/util/NdbSqlUtil.cpp
index e91ade374cf..e34d6d18539 100644
--- a/ndb/src/common/util/NdbSqlUtil.cpp
+++ b/ndb/src/common/util/NdbSqlUtil.cpp
@@ -155,6 +155,14 @@ NdbSqlUtil::m_typeList[] = {
{
Type::Timespec,
NULL // cmpTimespec
+ },
+ {
+ Type::Blob,
+ NULL // cmpDatetime
+ },
+ {
+ Type::Clob,
+ cmpClob
}
};
@@ -284,6 +292,18 @@ NdbSqlUtil::cmpTimespec(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32
return cmp(Type::Timespec, p1, p2, full, size);
}
+int
+NdbSqlUtil::cmpBlob(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+{
+ return cmp(Type::Blob, p1, p2, full, size);
+}
+
+int
+NdbSqlUtil::cmpClob(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+{
+ return cmp(Type::Clob, p1, p2, full, size);
+}
+
#ifdef NDB_SQL_UTIL_TEST
#include <NdbTick.h>
diff --git a/ndb/src/common/util/Properties.cpp b/ndb/src/common/util/Properties.cpp
index 2ab008142ba..3e41056ac18 100644
--- a/ndb/src/common/util/Properties.cpp
+++ b/ndb/src/common/util/Properties.cpp
@@ -21,6 +21,12 @@
#include <NdbTCP.h>
#include <NdbOut.hpp>
+static
+char * f_strdup(const char * s){
+ if(!s) return 0;
+ return strdup(s);
+}
+
/**
* Note has to be a multiple of 4 bytes
*/
@@ -36,6 +42,7 @@ struct PropertyImpl{
~PropertyImpl();
PropertyImpl(const char * name, Uint32 value);
+ PropertyImpl(const char * name, Uint64 value);
PropertyImpl(const char * name, const char * value);
PropertyImpl(const char * name, const Properties * value);
@@ -167,6 +174,11 @@ Properties::put(const char * name, Uint32 value, bool replace){
return ::put(impl, name, value, replace);
}
+bool
+Properties::put64(const char * name, Uint64 value, bool replace){
+ return ::put(impl, name, value, replace);
+}
+
bool
Properties::put(const char * name, const char * value, bool replace){
return ::put(impl, name, value, replace);
@@ -208,6 +220,40 @@ Properties::get(const char * name, Uint32 * value) const {
setErrno(E_PROPERTIES_OK);
return true;
}
+
+ if(nvp->valueType == PropertiesType_Uint64){
+ Uint64 tmp = * (Uint64 *)nvp->value;
+ Uint64 max = 1; max <<= 32;
+ if(tmp < max){
+ * value = (Uint32)tmp;
+ setErrno(E_PROPERTIES_OK);
+ return true;
+ }
+ }
+ setErrno(E_PROPERTIES_INVALID_TYPE);
+ return false;
+}
+
+bool
+Properties::get(const char * name, Uint64 * value) const {
+ PropertyImpl * nvp = impl->get(name);
+ if(nvp == 0){
+ setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
+ return false;
+ }
+
+ if(nvp->valueType == PropertiesType_Uint32){
+ Uint32 tmp = * (Uint32 *)nvp->value;
+ * value = (Uint64)tmp;
+ setErrno(E_PROPERTIES_OK);
+ return true;
+ }
+
+ if(nvp->valueType == PropertiesType_Uint64){
+ * value = * (Uint64 *)nvp->value;
+ setErrno(E_PROPERTIES_OK);
+ return true;
+ }
setErrno(E_PROPERTIES_INVALID_TYPE);
return false;
}
@@ -263,7 +309,7 @@ Properties::getCopy(const char * name, char ** value) const {
}
if(nvp->valueType == PropertiesType_char){
- * value = strdup((const char *)nvp->value);
+ * value = f_strdup((const char *)nvp->value);
setErrno(E_PROPERTIES_OK);
return true;
}
@@ -313,6 +359,10 @@ Properties::print(FILE * out, const char * prefix) const{
fprintf(out, "%s%s = (Uint32) %d\n", buf, impl->content[i]->name,
*(Uint32 *)impl->content[i]->value);
break;
+ case PropertiesType_Uint64:
+ fprintf(out, "%s%s = (Uint64) %lld\n", buf, impl->content[i]->name,
+ *(Uint64 *)impl->content[i]->value);
+ break;
case PropertiesType_char:
fprintf(out, "%s%s = (char*) \"%s\"\n", buf, impl->content[i]->name,
(char *)impl->content[i]->value);
@@ -598,11 +648,18 @@ PropertiesImpl::getPackedSize(Uint32 pLen) const {
sz += 4; // Name Len
sz += 4; // Value Len
sz += mod4(pLen + strlen(content[i]->name)); // Name
- if(content[i]->valueType == PropertiesType_char){
+ switch(content[i]->valueType){
+ case PropertiesType_char:
sz += mod4(strlen((char *)content[i]->value));
- } else if(content[i]->valueType == PropertiesType_Uint32){
+ break;
+ case PropertiesType_Uint32:
sz += mod4(4);
- } else {
+ break;
+ case PropertiesType_Uint64:
+ sz += mod4(8);
+ break;
+ case PropertiesType_Properties:
+ default:
assert(0);
}
}
@@ -700,6 +757,9 @@ PropertiesImpl::pack(Uint32 *& buf, const char * prefix, Uint32 pLen) const {
case PropertiesType_Uint32:
valLenData = 4;
break;
+ case PropertiesType_Uint64:
+ valLenData = 8;
+ break;
case PropertiesType_char:
valLenData = strlen((char *)content[i]->value);
break;
@@ -722,6 +782,14 @@ PropertiesImpl::pack(Uint32 *& buf, const char * prefix, Uint32 pLen) const {
case PropertiesType_Uint32:
* (Uint32 *)valBuf = htonl(* (Uint32 *)content[i]->value);
break;
+ case PropertiesType_Uint64:{
+ Uint64 val = * (Uint64 *)content[i]->value;
+ Uint32 hi = (val >> 32);
+ Uint32 lo = (val & 0xFFFFFFFF);
+ * (Uint32 *)valBuf = htonl(hi);
+ * (Uint32 *)(valBuf + 4) = htonl(lo);
+ }
+ break;
case PropertiesType_char:
memcpy(valBuf, content[i]->value, strlen((char*)content[i]->value));
break;
@@ -788,6 +856,12 @@ PropertiesImpl::unpack(const Uint32 * buf, Uint32 &bufLen, Properties * top,
case PropertiesType_Uint32:
res3 = top->put(nameBuf, ntohl(* (Uint32 *)valBuf), true);
break;
+ case PropertiesType_Uint64:{
+ Uint64 hi = ntohl(* (Uint32 *)valBuf);
+ Uint64 lo = ntohl(* (Uint32 *)(valBuf + 4));
+ res3 = top->put64(nameBuf, (hi << 32) + lo, true);
+ }
+ break;
case PropertiesType_char:
res3 = top->put(nameBuf, valBuf, true);
break;
@@ -808,6 +882,9 @@ PropertyImpl::~PropertyImpl(){
case PropertiesType_Uint32:
delete (Uint32 *)value;
break;
+ case PropertiesType_Uint64:
+ delete (Uint64 *)value;
+ break;
case PropertiesType_char:
free((char *)value);
break;
@@ -822,6 +899,8 @@ PropertyImpl::copyPropertyImpl(const PropertyImpl & org){
switch(org.valueType){
case PropertiesType_Uint32:
return new PropertyImpl(org.name, * (Uint32 *)org.value);
+ case PropertiesType_Uint64:
+ return new PropertyImpl(org.name, * (Uint64 *)org.value);
break;
case PropertiesType_char:
return new PropertyImpl(org.name, (char *)org.value);
@@ -836,21 +915,28 @@ PropertyImpl::copyPropertyImpl(const PropertyImpl & org){
}
PropertyImpl::PropertyImpl(const char * _name, Uint32 _value){
- this->name = strdup(_name);
+ this->name = f_strdup(_name);
this->value = new Uint32;
* ((Uint32 *)this->value) = _value;
this->valueType = PropertiesType_Uint32;
}
+PropertyImpl::PropertyImpl(const char * _name, Uint64 _value){
+ this->name = f_strdup(_name);
+ this->value = new Uint64;
+ * ((Uint64 *)this->value) = _value;
+ this->valueType = PropertiesType_Uint64;
+}
+
PropertyImpl::PropertyImpl(const char * _name, const char * _value){
- this->name = strdup(_name);
- this->value = strdup(_value);
+ this->name = f_strdup(_name);
+ this->value = f_strdup(_value);
this->valueType = PropertiesType_char;
}
PropertyImpl::PropertyImpl(const char * _name, const Properties * _value){
- this->name = strdup(_name);
+ this->name = f_strdup(_name);
this->value = new Properties(* _value);
this->valueType = PropertiesType_Properties;
}
@@ -902,6 +988,16 @@ Properties::put(const char * name, Uint32 no, Uint32 val, bool replace){
return res;
}
+bool
+Properties::put64(const char * name, Uint32 no, Uint64 val, bool replace){
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = put(tmp, val, replace);
+ free(tmp);
+ return res;
+}
+
bool
Properties::put(const char * name, Uint32 no, const char * val, bool replace){
@@ -957,6 +1053,16 @@ Properties::get(const char * name, Uint32 no, Uint32 * value) const{
return res;
}
+bool
+Properties::get(const char * name, Uint32 no, Uint64 * value) const{
+ size_t tmp_len = strlen(name)+20;
+ char * tmp = (char*)malloc(tmp_len);
+ snprintf(tmp, tmp_len, "%s_%d", name, no);
+ bool res = get(tmp, value);
+ free(tmp);
+ return res;
+}
+
bool
Properties::get(const char * name, Uint32 no, const char ** value) const {
diff --git a/ndb/src/common/util/md5_hash.cpp b/ndb/src/common/util/md5_hash.cpp
index 5e28edcf8fa..068843183ac 100644
--- a/ndb/src/common/util/md5_hash.cpp
+++ b/ndb/src/common/util/md5_hash.cpp
@@ -48,7 +48,7 @@ void byteReverse(unsigned char *buf, unsigned longs);
*/
void byteReverse(unsigned char *buf, unsigned longs)
{
- uint32 t;
+ Uint32 t;
do {
t = (Uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
diff --git a/ndb/src/common/util/new.cpp b/ndb/src/common/util/new.cpp
index 889e83edf6f..b61541b7474 100644
--- a/ndb/src/common/util/new.cpp
+++ b/ndb/src/common/util/new.cpp
@@ -5,6 +5,8 @@ extern "C" {
void (* ndb_new_handler)() = 0;
}
+#ifdef USE_MYSYS_NEW
+
void *operator new (size_t sz)
{
void * p = malloc (sz ? sz : 1);
@@ -36,3 +38,5 @@ void operator delete[] (void *ptr) throw ()
if (ptr)
free(ptr);
}
+
+#endif // USE_MYSYS_NEW
diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp
index 8def7ebe91b..97bb4863a67 100644
--- a/ndb/src/common/util/socket_io.cpp
+++ b/ndb/src/common/util/socket_io.cpp
@@ -202,13 +202,13 @@ vprintln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
size_t size = sizeof(buf);
if (fmt != 0) {
- size = vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ size = vsnprintf(buf, sizeof(buf), fmt, ap);
/* Check if the output was truncated */
- if(size >= sizeof(buf)) {
+ if(size >= sizeof(buf)-1) {
buf2 = (char *)malloc(size+2);
if(buf2 == NULL)
return -1;
- vsnprintf(buf2, size, fmt, ap);
+ vsnprintf(buf2, size+1, fmt, ap);
} else
size = sizeof(buf);
} else
diff --git a/ndb/src/common/util/testConfigValues/Makefile b/ndb/src/common/util/testConfigValues/Makefile
new file mode 100644
index 00000000000..5b7400f5ee3
--- /dev/null
+++ b/ndb/src/common/util/testConfigValues/Makefile
@@ -0,0 +1,12 @@
+include .defs.mk
+
+TYPE := util
+
+BIN_TARGET := testConfigValues
+BIN_TARGET_ARCHIVES := portlib general
+
+SOURCES := testConfigValues.cpp
+
+CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/util)
+
+include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/common/util/testConfigValues/testConfigValues.cpp b/ndb/src/common/util/testConfigValues/testConfigValues.cpp
new file mode 100644
index 00000000000..362deb1ddad
--- /dev/null
+++ b/ndb/src/common/util/testConfigValues/testConfigValues.cpp
@@ -0,0 +1,122 @@
+#include <ConfigValues.hpp>
+#include <NdbOut.hpp>
+#include <stdlib.h>
+#include <string.h>
+
+#define CF_NODES 1
+#define CF_LOG_PAGES 2
+#define CF_MEM_PAGES 3
+#define CF_START_TO 4
+#define CF_STOP_TO 5
+
+void print(Uint32 i, ConfigValues::ConstIterator & cf){
+ ndbout_c("---");
+ for(Uint32 j = 2; j<=7; j++){
+ switch(cf.getTypeOf(j)){
+ case ConfigValues::IntType:
+ ndbout_c("Node %d : CFG(%d) : %d",
+ i, j, cf.get(j, 999));
+ break;
+ case ConfigValues::Int64Type:
+ ndbout_c("Node %d : CFG(%d) : %lld (64)",
+ i, j, cf.get64(j, 999));
+ break;
+ case ConfigValues::StringType:
+ ndbout_c("Node %d : CFG(%d) : %s",
+ i, j, cf.get(j, "<NOT FOUND>"));
+ break;
+ default:
+ ndbout_c("Node %d : CFG(%d) : TYPE: %d",
+ i, j, cf.getTypeOf(j));
+ }
+ }
+}
+
+void print(Uint32 i, ConfigValues & _cf){
+ ConfigValues::ConstIterator cf(_cf);
+ print(i, cf);
+}
+
+void
+print(ConfigValues & _cf){
+ ConfigValues::ConstIterator cf(_cf);
+ Uint32 i = 0;
+ while(cf.openSection(CF_NODES, i)){
+ print(i, cf);
+ cf.closeSection();
+ i++;
+ }
+}
+
+inline
+void
+require(bool b){
+ if(!b)
+ abort();
+}
+
+int
+main(void){
+
+ {
+ ConfigValuesFactory cvf(10, 20);
+ cvf.openSection(1, 0);
+ cvf.put(2, 12);
+ cvf.put64(3, 13);
+ cvf.put(4, 14);
+ cvf.put64(5, 15);
+ cvf.put(6, "Keso");
+ cvf.put(7, "Kent");
+ cvf.closeSection();
+
+ cvf.openSection(1, 1);
+ cvf.put(2, 22);
+ cvf.put64(3, 23);
+ cvf.put(4, 24);
+ cvf.put64(5, 25);
+ cvf.put(6, "Kalle");
+ cvf.put(7, "Anka");
+ cvf.closeSection();
+
+ ndbout_c("-- print --");
+ print(* cvf.m_cfg);
+
+ cvf.shrink();
+ ndbout_c("shrink\n-- print --");
+ print(* cvf.m_cfg);
+ cvf.expand(10, 10);
+ ndbout_c("expand\n-- print --");
+ print(* cvf.m_cfg);
+
+ ndbout_c("packed size: %d", cvf.m_cfg->getPackedSize());
+
+ ConfigValues::ConstIterator iter(* cvf.m_cfg);
+ iter.openSection(CF_NODES, 0);
+ ConfigValues * cfg2 = ConfigValuesFactory::extractCurrentSection(iter);
+ print(99, * cfg2);
+
+ cvf.shrink();
+ ndbout_c("packed size: %d", cfg2->getPackedSize());
+
+ UtilBuffer buf;
+ Uint32 l1 = cvf.m_cfg->pack(buf);
+ Uint32 l2 = cvf.m_cfg->getPackedSize();
+ require(l1 == l2);
+
+ ConfigValuesFactory cvf2;
+ require(cvf2.unpack(buf));
+ UtilBuffer buf2;
+ cvf2.shrink();
+ Uint32 l3 = cvf2.m_cfg->pack(buf2);
+ require(l1 == l3);
+
+ ndbout_c("unpack\n-- print --");
+ print(* cvf2.m_cfg);
+
+ cfg2->~ConfigValues();;
+ cvf.m_cfg->~ConfigValues();
+ free(cfg2);
+ free(cvf.m_cfg);
+ }
+ return 0;
+}
diff --git a/ndb/src/common/util/testProperties/Makefile b/ndb/src/common/util/testProperties/Makefile
index 00b4465b69d..343c07a49e7 100644
--- a/ndb/src/common/util/testProperties/Makefile
+++ b/ndb/src/common/util/testProperties/Makefile
@@ -1,12 +1,9 @@
include .defs.mk
-TYPE :=
+TYPE := util
BIN_TARGET := keso
-BIN_TARGET_ARCHIVES := portlib general
SOURCES := testProperties.cpp
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/util)
-
include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/common/util/testProperties/testProperties.cpp b/ndb/src/common/util/testProperties/testProperties.cpp
index 3aa2af92c5b..e445f7ca3e4 100644
--- a/ndb/src/common/util/testProperties/testProperties.cpp
+++ b/ndb/src/common/util/testProperties/testProperties.cpp
@@ -63,12 +63,6 @@ readFromFile(Properties & p, const char *fname, bool uu = true){
return res;
}
-Property defs[] = {
- Property("Rolf", 123)
- ,Property("Keso", "Kent")
-};
-
-
void putALot(Properties & tmp){
int i = 123;
tmp.put("LockPagesInMainMemory", i++);
@@ -124,7 +118,6 @@ main(void){
p.put("Ank4", "anka");
putALot(p);
- //p.put(defs, 2);
Properties tmp;
tmp.put("Type", "TCP");
tmp.put("OwnNodeId", 1);
@@ -136,8 +129,8 @@ main(void){
tmp.put("Compression", (Uint32)false);
tmp.put("Checksum", 1);
- tmp.put("SendBufferSize", 2000);
- tmp.put("MaxReceiveSize", 1000);
+ tmp.put64("SendBufferSize", 2000);
+ tmp.put64("MaxReceiveSize", 1000);
tmp.put("PortNumber", 1233);
putALot(tmp);
diff --git a/ndb/src/cw/Makefile.am b/ndb/src/cw/Makefile.am
new file mode 100644
index 00000000000..b530922a3a7
--- /dev/null
+++ b/ndb/src/cw/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = cpcd
diff --git a/ndb/src/cw/Makefile b/ndb/src/cw/Makefile_old
index e710c1e244d..e710c1e244d 100644
--- a/ndb/src/cw/Makefile
+++ b/ndb/src/cw/Makefile_old
diff --git a/ndb/src/cw/cpcd/Makefile.am b/ndb/src/cw/cpcd/Makefile.am
new file mode 100644
index 00000000000..6345bae9bbe
--- /dev/null
+++ b/ndb/src/cw/cpcd/Makefile.am
@@ -0,0 +1,14 @@
+
+ndbtools_PROGRAMS = ndb_cpcd
+
+ndb_cpcd_SOURCES = main.cpp CPCD.cpp Process.cpp APIService.cpp Monitor.cpp common.cpp
+
+LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_util.mk.am
+
+ndb_cpcd_LDFLAGS = @ndb_bin_am_ldflags@
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/cw/cpcd/Makefile b/ndb/src/cw/cpcd/Makefile_old
index f214fb087d2..f214fb087d2 100644
--- a/ndb/src/cw/cpcd/Makefile
+++ b/ndb/src/cw/cpcd/Makefile_old
diff --git a/ndb/src/kernel/Main.cpp b/ndb/src/kernel/Main.cpp
new file mode 100644
index 00000000000..7bd4e75ca18
--- /dev/null
+++ b/ndb/src/kernel/Main.cpp
@@ -0,0 +1,305 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+
+#include <ndb_version.h>
+#include "Configuration.hpp"
+#include <TransporterRegistry.hpp>
+
+#include "SimBlockList.hpp"
+#include "ThreadConfig.hpp"
+#include <SignalLoggerManager.hpp>
+#include <NdbOut.hpp>
+#include <NdbMain.h>
+#include <NdbDaemon.h>
+#include <NdbConfig.h>
+#include <WatchDog.hpp>
+
+#include <LogLevel.hpp>
+#include <EventLogger.hpp>
+#include <NodeState.hpp>
+
+#if defined NDB_SOLARIS // ok
+#include <sys/processor.h> // For system informatio
+#endif
+
+#if !defined NDB_SOFTOSE && !defined NDB_OSE
+#include <signal.h> // For process signals
+#endif
+
+extern EventLogger g_eventLogger;
+
+void catchsigs(bool ignore); // for process signal handling
+extern "C" void handler(int signo); // for process signal handling
+
+// Shows system information
+void systemInfo(const Configuration & conf,
+ const LogLevel & ll);
+
+const char programName[] = "NDB Kernel";
+
+NDB_MAIN(ndb_kernel){
+
+ // Print to stdout/console
+ g_eventLogger.createConsoleHandler();
+ g_eventLogger.setCategory("NDB");
+ g_eventLogger.enable(Logger::LL_INFO, Logger::LL_ALERT); // Log INFO to ALERT
+
+ globalEmulatorData.create();
+
+ // Parse command line options
+ Configuration* theConfig = globalEmulatorData.theConfiguration;
+ if(!theConfig->init(argc, argv)){
+ return 0;
+ }
+
+ { // Do configuration
+ theConfig->setupConfiguration();
+ }
+
+ // Get NDB_HOME path
+ char homePath[255];
+ NdbConfig_HomePath(homePath, 255);
+
+ if (theConfig->getDaemonMode()) {
+ // Become a daemon
+ char lockfile[255], logfile[255];
+ snprintf(lockfile, 255, "%snode%d.pid", homePath, globalData.ownId);
+ snprintf(logfile, 255, "%snode%d.out", homePath, globalData.ownId);
+ if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
+ ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
+ return 1;
+ }
+ }
+
+ for(pid_t child = fork(); child != 0; child = fork()){
+ /**
+ * Parent
+ */
+ catchsigs(true);
+
+ int status = 0;
+ while(waitpid(child, &status, 0) != child);
+ if(WIFEXITED(status)){
+ switch(WEXITSTATUS(status)){
+ case NRT_Default:
+ g_eventLogger.info("Angel shutting down");
+ exit(0);
+ break;
+ case NRT_NoStart_Restart:
+ theConfig->setInitialStart(false);
+ globalData.theRestartFlag = initial_state;
+ break;
+ case NRT_NoStart_InitialStart:
+ theConfig->setInitialStart(true);
+ globalData.theRestartFlag = initial_state;
+ break;
+ case NRT_DoStart_InitialStart:
+ theConfig->setInitialStart(true);
+ globalData.theRestartFlag = perform_start;
+ break;
+ default:
+ if(theConfig->stopOnError()){
+ /**
+ * Error shutdown && stopOnError()
+ */
+ exit(0);
+ }
+ // Fall-through
+ case NRT_DoStart_Restart:
+ theConfig->setInitialStart(false);
+ globalData.theRestartFlag = perform_start;
+ break;
+ }
+ } else if(theConfig->stopOnError()){
+ /**
+ * Error shutdown && stopOnError()
+ */
+ exit(0);
+ }
+ g_eventLogger.info("Ndb has terminated (pid %d) restarting", child);
+ }
+
+ g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid());
+ systemInfo(* theConfig, * theConfig->m_logLevel);
+
+ // Load blocks
+ globalEmulatorData.theSimBlockList->load(* theConfig);
+
+ // Set thread concurrency for Solaris' light weight processes
+ int status;
+ status = NdbThread_SetConcurrencyLevel(30);
+ NDB_ASSERT(status == 0, "Can't set appropriate concurrency level.");
+
+#ifdef VM_TRACE
+ // Create a signal logger
+ char buf[255];
+ strcpy(buf, homePath);
+ FILE * signalLog = fopen(strncat(buf,"Signal.log", 255), "a");
+ globalSignalLoggers.setOwnNodeId(globalData.ownId);
+ globalSignalLoggers.setOutputStream(signalLog);
+#endif
+
+ catchsigs(false);
+
+ /**
+ * Do startup
+ */
+ switch(globalData.theRestartFlag){
+ case initial_state:
+ globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
+ break;
+ case perform_start:
+ globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
+ globalEmulatorData.theThreadConfig->doStart(NodeState::SL_STARTING);
+ break;
+ default:
+ NDB_ASSERT(0, "Illegal state globalData.theRestartFlag");
+ }
+
+ globalTransporterRegistry.startSending();
+ globalTransporterRegistry.startReceiving();
+ globalEmulatorData.theWatchDog->doStart();
+
+ globalEmulatorData.theThreadConfig->ipControlLoop();
+
+ NdbShutdown(NST_Normal);
+ return NRT_Default;
+}
+
+
+void
+systemInfo(const Configuration & config, const LogLevel & logLevel){
+#ifdef NDB_WIN32
+ int processors = 0;
+ int speed;
+ SYSTEM_INFO sinfo;
+ GetSystemInfo(&sinfo);
+ processors = sinfo.dwNumberOfProcessors;
+ HKEY hKey;
+ if(ERROR_SUCCESS==RegOpenKeyEx
+ (HKEY_LOCAL_MACHINE,
+ TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
+ 0, KEY_READ, &hKey)) {
+ DWORD dwMHz;
+ DWORD cbData = sizeof(dwMHz);
+ if(ERROR_SUCCESS==RegQueryValueEx(hKey,
+ "~MHz", 0, 0, (LPBYTE)&dwMHz, &cbData)) {
+ speed = int(dwMHz);
+ }
+ RegCloseKey(hKey);
+ }
+#elif defined NDB_SOLARIS // ok
+ // Search for at max 16 processors among the first 256 processor ids
+ processor_info_t pinfo; memset(&pinfo, 0, sizeof(pinfo));
+ int pid = 0;
+ while(processors < 16 && pid < 256){
+ if(!processor_info(pid++, &pinfo))
+ processors++;
+ }
+ speed = pinfo.pi_clock;
+#endif
+
+ if(logLevel.getLogLevel(LogLevel::llStartUp) > 0){
+ g_eventLogger.info("NDB Cluster -- DB node %d", globalData.ownId);
+ g_eventLogger.info("%s --", NDB_VERSION_STRING);
+#ifdef NDB_SOLARIS // ok
+ g_eventLogger.info("NDB is running on a machine with %d processor(s) at %d MHz",
+ processor, speed);
+#endif
+ }
+ if(logLevel.getLogLevel(LogLevel::llStartUp) > 3){
+ Uint32 t = config.timeBetweenWatchDogCheck();
+ g_eventLogger.info("WatchDog timer is set to %d ms", t);
+ }
+
+}
+
+void
+catchsigs(bool ignore){
+#if ! defined NDB_SOFTOSE && !defined NDB_OSE
+
+#if defined SIGRTMIN
+ #define MAX_SIG_CATCH SIGRTMIN
+#elif defined NSIG
+ #define MAX_SIG_CATCH NSIG
+#else
+ #error "neither SIGRTMIN or NSIG is defined on this platform, please report bug at bugs.mysql.com"
+#endif
+
+ // Makes the main process catch process signals, eg installs a
+ // handler named "handler". "handler" will then be called is instead
+ // of the defualt process signal handler)
+ if(ignore){
+ for(int i = 1; i < MAX_SIG_CATCH; i++){
+ if(i != SIGCHLD)
+ signal(i, SIG_IGN);
+ }
+ } else {
+ for(int i = 1; i < MAX_SIG_CATCH; i++){
+ signal(i, handler);
+ }
+ }
+#endif
+}
+
+extern "C"
+void
+handler(int sig){
+ switch(sig){
+ case SIGHUP: /* 1 - Hang up */
+ case SIGINT: /* 2 - Interrupt */
+ case SIGQUIT: /* 3 - Quit */
+ case SIGTERM: /* 15 - Terminate */
+#ifdef SIGPWR
+ case SIGPWR: /* 19 - Power fail */
+#endif
+#ifdef SIGPOLL
+ case SIGPOLL: /* 22 */
+#endif
+ case SIGSTOP: /* 23 */
+ case SIGTSTP: /* 24 */
+ case SIGTTIN: /* 26 */
+ case SIGTTOU: /* 27 */
+ globalData.theRestartFlag = perform_stop;
+ break;
+#ifdef SIGWINCH
+ case SIGWINCH:
+#endif
+ case SIGPIPE:
+ /**
+ * Can happen in TCP Transporter
+ *
+ * Just ignore
+ */
+ break;
+ default:
+ // restart the system
+ char errorData[40];
+ snprintf(errorData, 40, "Signal %d received", sig);
+ ERROR_SET(fatal, 0, errorData, __FILE__);
+ break;
+ }
+}
+
+
+
+
+
+
+
+
diff --git a/ndb/src/kernel/Makefile b/ndb/src/kernel/Makefile
deleted file mode 100644
index 11261c047a6..00000000000
--- a/ndb/src/kernel/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-include .defs.mk
-
-DIRS := error blocks vm ndb-main
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am
new file mode 100644
index 00000000000..b2aa5f2e074
--- /dev/null
+++ b/ndb/src/kernel/Makefile.am
@@ -0,0 +1,58 @@
+SUBDIRS = error blocks vm
+
+include $(top_srcdir)/ndb/config/common.mk.am
+
+ndbbin_PROGRAMS = ndbd
+
+ndbd_SOURCES = Main.cpp SimBlockList.cpp
+
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+INCLUDES += \
+ -Iblocks/cmvmi \
+ -Iblocks/dbacc \
+ -Iblocks/dbdict \
+ -Iblocks/dbdih \
+ -Iblocks/dblqh \
+ -Iblocks/dbtc \
+ -Iblocks/dbtup \
+ -Iblocks/ndbfs \
+ -Iblocks/ndbcntr \
+ -Iblocks/qmgr \
+ -Iblocks/trix \
+ -Iblocks/backup \
+ -Iblocks/dbutil \
+ -Iblocks/suma \
+ -Iblocks/grep \
+ -Iblocks/dbtux
+
+LDADD += \
+ blocks/cmvmi/libcmvmi.a \
+ blocks/dbacc/libdbacc.a \
+ blocks/dbdict/libdbdict.a \
+ blocks/dbdih/libdbdih.a \
+ blocks/dblqh/libdblqh.a \
+ blocks/dbtc/libdbtc.a \
+ blocks/dbtup/libdbtup.a \
+ blocks/ndbfs/libndbfs.a \
+ blocks/ndbcntr/libndbcntr.a \
+ blocks/qmgr/libqmgr.a \
+ blocks/trix/libtrix.a \
+ blocks/backup/libbackup.a \
+ blocks/dbutil/libdbutil.a \
+ blocks/suma/libsuma.a \
+ blocks/grep/libgrep.a \
+ blocks/dbtux/libdbtux.a \
+ vm/libkernel.a \
+ error/liberror.a \
+ $(top_builddir)/ndb/src/common/transporter/libtransporter.la \
+ $(top_builddir)/ndb/src/common/debugger/libtrace.la \
+ $(top_builddir)/ndb/src/common/debugger/signaldata/libsignaldataprint.la \
+ $(top_builddir)/ndb/src/common/logger/liblogger.la \
+ $(top_builddir)/ndb/src/common/mgmcommon/libmgmsrvcommon.la \
+ $(top_builddir)/ndb/src/mgmapi/libmgmapi.la \
+ $(top_builddir)/ndb/src/common/portlib/libportlib.la \
+ $(top_builddir)/ndb/src/common/util/libgeneral.la
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/Makefile_old b/ndb/src/kernel/Makefile_old
new file mode 100644
index 00000000000..d1f1741aca4
--- /dev/null
+++ b/ndb/src/kernel/Makefile_old
@@ -0,0 +1,5 @@
+include .defs.mk
+
+DIRS := error vm ndb-main blocks
+
+include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/SimBlockList.cpp b/ndb/src/kernel/SimBlockList.cpp
new file mode 100644
index 00000000000..75a52ae0c4b
--- /dev/null
+++ b/ndb/src/kernel/SimBlockList.cpp
@@ -0,0 +1,126 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "SimBlockList.hpp"
+#include <SimulatedBlock.hpp>
+#include <Cmvmi.hpp>
+#include <Ndbfs.hpp>
+#include <Dbacc.hpp>
+#include <Dbdict.hpp>
+#include <Dbdih.hpp>
+#include <Dblqh.hpp>
+#include <Dbtc.hpp>
+#include <Dbtup.hpp>
+#include <Ndbcntr.hpp>
+#include <Qmgr.hpp>
+#include <Trix.hpp>
+#include <Backup.hpp>
+#include <DbUtil.hpp>
+#include <Suma.hpp>
+#include <Grep.hpp>
+#include <Dbtux.hpp>
+#include <NdbEnv.h>
+
+#ifndef VM_TRACE
+#define NEW_BLOCK(B) new B
+#else
+enum SIMBLOCKLIST_DUMMY { A_VALUE = 0 };
+
+static
+void * operator new (size_t sz, SIMBLOCKLIST_DUMMY dummy){
+ char * tmp = (char *)malloc(sz);
+
+#ifndef NDB_PURIFY
+#ifdef VM_TRACE
+ const int initValue = 0xf3;
+#else
+ const int initValue = 0x0;
+#endif
+
+ const int p = (sz / 4096);
+ const int r = (sz % 4096);
+
+ for(int i = 0; i<p; i++)
+ memset(tmp+(i*4096), initValue, 4096);
+
+ if(r > 0)
+ memset(tmp+p*4096, initValue, r);
+
+#endif
+
+ return tmp;
+}
+#define NEW_BLOCK(B) new(A_VALUE) B
+#endif
+
+void
+SimBlockList::load(const Configuration & conf){
+ noOfBlocks = 16;
+ theList = new SimulatedBlock * [noOfBlocks];
+ Dbdict* dbdict = 0;
+ Dbdih* dbdih = 0;
+
+ SimulatedBlock * fs = 0;
+ {
+ Uint32 dl;
+ const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
+ if(p && !ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &dl) && dl){
+ fs = NEW_BLOCK(VoidFs)(conf);
+ } else {
+ fs = NEW_BLOCK(Ndbfs)(conf);
+ }
+ }
+
+ theList[0] = NEW_BLOCK(Dbacc)(conf);
+ theList[1] = NEW_BLOCK(Cmvmi)(conf);
+ theList[2] = fs;
+ theList[3] = dbdict = NEW_BLOCK(Dbdict)(conf);
+ theList[4] = dbdih = NEW_BLOCK(Dbdih)(conf);
+ theList[5] = NEW_BLOCK(Dblqh)(conf);
+ theList[6] = NEW_BLOCK(Dbtc)(conf);
+ theList[7] = NEW_BLOCK(Dbtup)(conf);
+ theList[8] = NEW_BLOCK(Ndbcntr)(conf);
+ theList[9] = NEW_BLOCK(Qmgr)(conf);
+ theList[10] = NEW_BLOCK(Trix)(conf);
+ theList[11] = NEW_BLOCK(Backup)(conf);
+ theList[12] = NEW_BLOCK(DbUtil)(conf);
+ theList[13] = NEW_BLOCK(Suma)(conf);
+ theList[14] = NEW_BLOCK(Grep)(conf);
+ theList[15] = NEW_BLOCK(Dbtux)(conf);
+
+ // Metadata common part shared by block instances
+ ptrMetaDataCommon = new MetaData::Common(*dbdict, *dbdih);
+ for (int i = 0; i < noOfBlocks; i++)
+ theList[i]->setMetaDataCommon(ptrMetaDataCommon);
+}
+
+void
+SimBlockList::unload(){
+ if(theList != 0){
+ for(int i = 0; i<noOfBlocks; i++){
+ if(theList[i] != 0){
+ theList[i]->~SimulatedBlock();
+ free(theList[i]);
+ theList[i] = 0;
+ }
+ }
+ delete [] theList;
+ delete ptrMetaDataCommon;
+ theList = 0;
+ noOfBlocks = 0;
+ ptrMetaDataCommon = 0;
+ }
+}
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index 331333c101e..92dbfd067f7 100644
--- a/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/ndb/src/kernel/blocks/ERROR_codes.txt
@@ -4,7 +4,7 @@ Next NDBFS 2000
Next DBACC 3001
Next DBTUP 4007
Next DBLQH 5036
-Next DBDICT 6003
+Next DBDICT 6006
Next DBDIH 7173
Next DBTC 8035
Next CMVMI 9000
@@ -12,7 +12,6 @@ Next BACKUP 10022
Next DBUTIL 11002
Next DBTUX 12001
Next SUMA 13001
-Next DBDICT 14003
TESTING NODE FAILURE, ARBITRATION
---------------------------------
@@ -425,6 +424,6 @@ Ordered index:
Dbdict:
-------
-14000 Crash in participant @ CreateTabReq::Prepare
-14001 Crash in participant @ CreateTabReq::Commit
-14002 Crash in participant @ CreateTabReq::CreateDrop
+6003 Crash in participant @ CreateTabReq::Prepare
+6004 Crash in participant @ CreateTabReq::Commit
+6005 Crash in participant @ CreateTabReq::CreateDrop
diff --git a/ndb/src/kernel/blocks/Makefile.am b/ndb/src/kernel/blocks/Makefile.am
new file mode 100644
index 00000000000..0b2bc3b8c88
--- /dev/null
+++ b/ndb/src/kernel/blocks/Makefile.am
@@ -0,0 +1,17 @@
+SUBDIRS = \
+ cmvmi \
+ dbacc \
+ dbdict \
+ dbdih \
+ dblqh \
+ dbtc \
+ dbtup \
+ ndbfs \
+ ndbcntr \
+ qmgr \
+ trix \
+ backup \
+ dbutil \
+ suma \
+ grep \
+ dbtux
diff --git a/ndb/src/kernel/blocks/Makefile b/ndb/src/kernel/blocks/Makefile_old
index ce554dfc3b8..ce554dfc3b8 100644
--- a/ndb/src/kernel/blocks/Makefile
+++ b/ndb/src/kernel/blocks/Makefile_old
diff --git a/ndb/src/kernel/blocks/Start.txt b/ndb/src/kernel/blocks/Start.txt
index 545296d44f1..3e805ebab55 100644
--- a/ndb/src/kernel/blocks/Start.txt
+++ b/ndb/src/kernel/blocks/Start.txt
@@ -60,8 +60,8 @@ Cluster participant -
including info in DIH_RESTART_REF/CONF
4) Wait until -
-a) Receiving CNTR_MASTER_CONF -> continue
-b) Receiving CNTR_MASTER_REF -> P = node specified in REF, goto 3
+b) Receiving CNTR_START_CONF -> continue
+b) Receiving CNTR_START_REF -> P = node specified in REF, goto 3
c) TimeToWaitAlive has passed -> Failure to start
4) Run ndb-startphase 1
@@ -70,18 +70,23 @@ c) TimeToWaitAlive has passed -> Failure to start
Initial start/System restart NdbCntr (on qmgr president node)
1) Wait until -
-a) Receiving all CNTR_MASTER_REQ (all = those in READ_NODES_CONF)
-b) TimeToWaitAlive has passed -> Failure to start
+a) Receiving CNTR_START_REQ with GCI > than own GCI
+ send CNTR_START_REF to all waiting nodes
+b) Receiving all CNTR_START_REQ (for all defined nodes)
+c) TimeToWait has passed and partition win
+d) TimeToWait has passed and partitioning
+ and configuration "start with partition" = true
-2) Wait until -
-a) Enough nodes (at least 1 in each node group and 1 full node group)
- has sent me CNTR_MASTER_REQ
-b) TimeToWaitAlive has passed -> Failure to start
+2) Send CNTR_START_CONF to all nodes "with filesystem"
+
+3) Wait until -
+ Receiving CNTR_START_REP for all starting nodes
-3) Decide what kind of start to perform (initial / system restart)
- Decide who should be the master (the one with greatest GCI)
- Send CNTR_MASTER_CONF(initial/system restart) to all nodes included in start
+4) Start waiting nodes (if any)
+NOTE:
+1c) Partition win = 1 node in each node group and 1 full node group
+1d) Pattitioning = at least 1 node in each node group
--
Running NdbCntr
@@ -90,8 +95,3 @@ When receiving CNTR_MASTER_REQ
2) If I'm master
Coordinate parallell node restarts
send CNTR_MASTER_CONF (node restart)
-
-NOTE:
-2a Specified with a command line/config parameter the system could
- start using only one node in each node group (if possible w.r.t LCP/GCP)
-
diff --git a/ndb/src/kernel/blocks/backup/BackupInit.cpp b/ndb/src/kernel/blocks/backup/BackupInit.cpp
index 1997e560bb9..36ce1857144 100644
--- a/ndb/src/kernel/blocks/backup/BackupInit.cpp
+++ b/ndb/src/kernel/blocks/backup/BackupInit.cpp
@@ -38,14 +38,14 @@ Backup::Backup(const Configuration & conf) :
c_nodePool.setSize(MAX_NDB_NODES);
c_masterNodeId = getOwnNodeId();
- const Properties * p = conf.getOwnProperties();
+ const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
ndbrequire(p != 0);
Uint32 noBackups = 0, noTables = 0, noAttribs = 0;
- p->get("ParallelBackups", &noBackups);
- ndbrequire(p->get("MaxNoOfTables", &noTables));
- ndbrequire(p->get("MaxNoOfAttributes", &noAttribs));
-
+ ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_BACKUPS, &noBackups);
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TABLES, &noTables));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_ATTRIBUTES, &noAttribs));
+
// To allow for user tables AND SYSTAB
// See ClusterConfig
//TODO get this infor from NdbCntr
@@ -65,7 +65,7 @@ Backup::Backup(const Configuration & conf) :
c_fragmentPool.setSize(noBackups * 2 * NO_OF_FRAG_PER_NODE * noTables);
Uint32 szMem = 0;
- p->get("BackupMemory", &szMem);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_MEM, &szMem);
Uint32 noPages = (szMem + sizeof(Page32) - 1) / sizeof(Page32);
// We need to allocate an additional of 2 pages. 1 page because of a bug in
// ArrayPool and another one for DICTTAINFO.
@@ -74,9 +74,9 @@ Backup::Backup(const Configuration & conf) :
Uint32 szDataBuf = (2 * 1024 * 1024);
Uint32 szLogBuf = (2 * 1024 * 1024);
Uint32 szWrite = 32768;
- p->get("BackupDataBufferSize", &szDataBuf);
- p->get("BackupLogBufferSize", &szLogBuf);
- p->get("BackupWriteSize", &szWrite);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_DATA_BUFFER_MEM, &szDataBuf);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_LOG_BUFFER_MEM, &szLogBuf);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_WRITE_SIZE, &szWrite);
c_defaults.m_logBufferSize = szLogBuf;
c_defaults.m_dataBufferSize = szDataBuf;
diff --git a/ndb/src/kernel/blocks/backup/Makefile.am b/ndb/src/kernel/blocks/backup/Makefile.am
new file mode 100644
index 00000000000..85bf5b12415
--- /dev/null
+++ b/ndb/src/kernel/blocks/backup/Makefile.am
@@ -0,0 +1,12 @@
+
+SUBDIRS = restore
+
+noinst_LIBRARIES = libbackup.a
+
+libbackup_a_SOURCES = Backup.cpp BackupInit.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/backup/Makefile b/ndb/src/kernel/blocks/backup/Makefile_old
index 989199cbe02..989199cbe02 100644
--- a/ndb/src/kernel/blocks/backup/Makefile
+++ b/ndb/src/kernel/blocks/backup/Makefile_old
diff --git a/ndb/src/kernel/blocks/backup/restore/Makefile b/ndb/src/kernel/blocks/backup/restore/Makefile
deleted file mode 100644
index 4c884525d73..00000000000
--- a/ndb/src/kernel/blocks/backup/restore/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-include .defs.mk
-
-TYPE := *
-
-BIN_TARGET := restore
-BIN_TARGET_LIBS :=
-BIN_TARGET_ARCHIVES := NDB_API
-
-CCFLAGS_LOC = -I.. -I$(NDB_TOP)/src/ndbapi -I$(NDB_TOP)/include/ndbapi -I$(NDB_TOP)/include/util -I$(NDB_TOP)/include/portlib -I$(NDB_TOP)/include/kernel
-
-#ifneq ($(MYSQLCLUSTER_TOP),)
-#CCFLAGS_LOC +=-I$(MYSQLCLUSTER_TOP)/include -D USE_MYSQL
-#LDFLAGS_LOC += -L$(MYSQLCLUSTER_TOP)/libmysql_r/ -lmysqlclient_r
-#endif
-
-SOURCES = main.cpp Restore.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
-
diff --git a/ndb/src/kernel/blocks/backup/restore/Makefile.am b/ndb/src/kernel/blocks/backup/restore/Makefile.am
new file mode 100644
index 00000000000..e0429c60723
--- /dev/null
+++ b/ndb/src/kernel/blocks/backup/restore/Makefile.am
@@ -0,0 +1,12 @@
+
+ndbtools_PROGRAMS = ndb_restore
+
+ndb_restore_SOURCES = main.cpp consumer.cpp consumer_restore.cpp consumer_printer.cpp Restore.cpp
+
+LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la
+
+include $(top_srcdir)/ndb/config/common.mk.am
+
+INCLUDES += -I.. -I$(top_srcdir)/include -I$(top_srcdir)/ndb/include -I$(top_srcdir)/ndb/src/ndbapi -I$(top_srcdir)/ndb/include/ndbapi -I$(top_srcdir)/ndb/include/util -I$(top_srcdir)/ndb/include/portlib -I$(top_srcdir)/ndb/include/kernel
+
+ndb_restore_LDFLAGS = @ndb_bin_am_ldflags@
diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.cpp b/ndb/src/kernel/blocks/backup/restore/Restore.cpp
index 2c3c1c8df7b..24d2cfbfe35 100644
--- a/ndb/src/kernel/blocks/backup/restore/Restore.cpp
+++ b/ndb/src/kernel/blocks/backup/restore/Restore.cpp
@@ -33,32 +33,32 @@ Uint32 Twiddle32(Uint32 in); // Byte shift 32-bit data
Uint64 Twiddle64(Uint64 in); // Byte shift 64-bit data
bool
-BackupFile::Twiddle(AttributeS* attr, Uint32 arraySize){
+BackupFile::Twiddle(const AttributeDesc* attr_desc, AttributeData* attr_data, Uint32 arraySize){
if(m_hostByteOrder)
return true;
if(arraySize == 0){
- arraySize = attr->Desc->arraySize;
+ arraySize = attr_desc->arraySize;
}
- switch(attr->Desc->size){
+ switch(attr_desc->size){
case 8:
return true;
case 16:
for(unsigned i = 0; i<arraySize; i++){
- attr->Data.u_int16_value[i] = Twiddle16(attr->Data.u_int16_value[i]);
+ attr_data->u_int16_value[i] = Twiddle16(attr_data->u_int16_value[i]);
}
return true;
case 32:
for(unsigned i = 0; i<arraySize; i++){
- attr->Data.u_int32_value[i] = Twiddle32(attr->Data.u_int32_value[i]);
+ attr_data->u_int32_value[i] = Twiddle32(attr_data->u_int32_value[i]);
}
return true;
case 64:
for(unsigned i = 0; i<arraySize; i++){
- attr->Data.u_int64_value[i] = Twiddle64(attr->Data.u_int64_value[i]);
+ attr_data->u_int64_value[i] = Twiddle64(attr_data->u_int64_value[i]);
}
return true;
default:
@@ -82,14 +82,14 @@ RestoreMetaData::RestoreMetaData(const char* path, Uint32 nodeId, Uint32 bNo) {
}
RestoreMetaData::~RestoreMetaData(){
- for(int i = 0; i<allTables.size(); i++)
+ for(Uint32 i= 0; i < allTables.size(); i++)
delete allTables[i];
allTables.clear();
}
const TableS *
RestoreMetaData::getTable(Uint32 tableId) const {
- for(int i = 0; i<allTables.size(); i++)
+ for(Uint32 i= 0; i < allTables.size(); i++)
if(allTables[i]->getTableId() == tableId)
return allTables[i];
return NULL;
@@ -101,42 +101,14 @@ RestoreMetaData::getStopGCP() const {
}
int
-RestoreMetaData::loadContent(const char * catalog,
- const char * schema)
+RestoreMetaData::loadContent()
{
-
-#if NDB_VERSION_MAJOR >= VERSION_3X
- if(getMajor(m_fileHeader.NdbVersion) < VERSION_3X) {
- if(catalog == NULL)
- return -1;
- if(schema == NULL)
- return -1;
- }
-
-
- /**
- * if backup is of version 3 or higher, then
- * return -2 to indicate for the user that he
- * cannot restore tables to a certain catalog/schema
- */
- if(getMajor(m_fileHeader.NdbVersion) >= VERSION_3X &&
- (catalog != NULL ||
- schema != NULL)) {
- return -2;
- }
-#endif
-#if NDB_VERSION_MAJOR < VERSION_3X
- if(getMajor(m_fileHeader.NdbVersion) >= VERSION_3X)
- {
- return -2;
- }
-#endif
-
Uint32 noOfTables = readMetaTableList();
- if(noOfTables == 0)
- return -3;
+ if(noOfTables == 0) {
+ return 1;
+ }
for(Uint32 i = 0; i<noOfTables; i++){
- if(!readMetaTableDesc(catalog, schema)){
+ if(!readMetaTableDesc()){
return 0;
}
}
@@ -150,7 +122,8 @@ RestoreMetaData::readMetaTableList() {
Uint32 sectionInfo[2];
- if (fread(&sectionInfo, sizeof(sectionInfo), 1, m_file) != 1){
+ if (buffer_read(&sectionInfo, sizeof(sectionInfo), 1) != 1){
+ err << "readMetaTableList read header error" << endl;
return 0;
}
sectionInfo[0] = ntohl(sectionInfo[0]);
@@ -158,11 +131,9 @@ RestoreMetaData::readMetaTableList() {
const Uint32 tabCount = sectionInfo[1] - 2;
- const Uint32 len = 4 * tabCount;
- if(createBuffer(len) == 0)
- abort();
-
- if (fread(m_buffer, 1, len, m_file) != len){
+ void *tmp;
+ if (buffer_get_ptr(&tmp, 4, tabCount) != tabCount){
+ err << "readMetaTableList read tabCount error" << endl;
return 0;
}
@@ -170,13 +141,12 @@ RestoreMetaData::readMetaTableList() {
}
bool
-RestoreMetaData::readMetaTableDesc(const char * catalog,
- const char * schema) {
+RestoreMetaData::readMetaTableDesc() {
Uint32 sectionInfo[2];
// Read section header
- if (fread(&sectionInfo, sizeof(sectionInfo), 1, m_file) != 1){
+ if (buffer_read(&sectionInfo, sizeof(sectionInfo), 1) != 1){
err << "readMetaTableDesc read header error" << endl;
return false;
} // if
@@ -185,23 +155,15 @@ RestoreMetaData::readMetaTableDesc(const char * catalog,
assert(sectionInfo[0] == BackupFormat::TABLE_DESCRIPTION);
- // Allocate temporary storage for dictTabInfo buffer
- const Uint32 len = (sectionInfo[1] - 2);
- if (createBuffer(4 * (len+1)) == NULL) {
- err << "readMetaTableDesc allocation error" << endl;
- return false;
- } // if
-
// Read dictTabInfo buffer
- if (fread(m_buffer, 4, len, m_file) != len){
+ const Uint32 len = (sectionInfo[1] - 2);
+ void *ptr;
+ if (buffer_get_ptr(&ptr, 4, len) != len){
err << "readMetaTableDesc read error" << endl;
return false;
} // if
- return parseTableDescriptor(m_buffer,
- len,
- catalog,
- schema);
+ return parseTableDescriptor((Uint32*)ptr, len);
}
bool
@@ -209,11 +171,10 @@ RestoreMetaData::readGCPEntry() {
Uint32 data[4];
-
BackupFormat::CtlFile::GCPEntry * dst =
(BackupFormat::CtlFile::GCPEntry *)&data[0];
- if(fread(dst, 4, 4, m_file) != 4){
+ if(buffer_read(dst, 4, 4) != 4){
err << "readGCPEntry read error" << endl;
return false;
}
@@ -234,369 +195,118 @@ RestoreMetaData::readGCPEntry() {
return true;
}
+TableS::TableS(NdbTableImpl* tableImpl)
+ : m_dictTable(tableImpl)
+{
+ m_dictTable = tableImpl;
+ m_noOfNullable = m_nullBitmaskSize = 0;
-struct tmpTableS {
- Uint32 tableId;
- Uint32 schemaVersion;
- Uint32 noOfAttributes;
-}; // tmpTableS
-
-static const
-SimpleProperties::SP2StructMapping
-RestoreTabMap[] = {
- // Map the basic stuff to begin with
- DTIMAP(tmpTableS, TableId, tableId),
- DTIMAP(tmpTableS, TableVersion, schemaVersion),
- DTIMAP(tmpTableS, NoOfAttributes, noOfAttributes),
-
- DTIBREAK(AttributeName)
-}; // RestoreTabMap
-
-static const Uint32
-TabMapSize = sizeof(RestoreTabMap)
- / sizeof(SimpleProperties::SP2StructMapping);
-
-/**
- * Use a temporary struct to keep variables in AttributeDesc private
- * and DTIMAP requires all Uint32
- */
-struct tmpAttrS {
- // Just the basic needed stuff is yet implemented
- char name[AttrNameLenC];
- Uint32 attrId;
- Uint32 type;
- Uint32 nullable;
- Uint32 key;
- Uint32 size;
- Uint32 arraySize;
-};
-
-static const
-SimpleProperties::SP2StructMapping
-RestoreAttrMap[] = {
- // Map the most basic properties
- DTIMAP(tmpAttrS, AttributeId, attrId),
- DTIMAP(tmpAttrS, AttributeType, type),
- DTIMAP(tmpAttrS, AttributeNullableFlag, nullable),
- DTIMAP(tmpAttrS, AttributeKeyFlag, key),
- DTIMAP(tmpAttrS, AttributeSize, size),
- DTIMAP(tmpAttrS, AttributeArraySize, arraySize),
- DTIBREAK(AttributeEnd)
-}; // RestoreAttrMap
-static const Uint32
-AttrMapSize = sizeof(RestoreAttrMap)
- / sizeof(SimpleProperties::SP2StructMapping);
-
-struct v2xKernel_to_v3xAPIMapping {
- Int32 kernelConstant;
- Int32 apiConstant;
-};
-
-enum v2xKernelTypes {
- ExtUndefined=0,// Undefined
- ExtInt, // 32 bit
- ExtUnsigned, // 32 bit
- ExtBigint, // 64 bit
- ExtBigunsigned,// 64 Bit
- ExtFloat, // 32-bit float
- ExtDouble, // 64-bit float
- ExtDecimal, // Precision, Scale
- ExtChar, // Len
- ExtVarchar, // Max len
- ExtBinary, // Len
- ExtVarbinary, // Max len
- ExtDatetime, // Precision down to 1 sec (sizeof(Datetime) == 8 bytes )
- ExtTimespec // Precision down to 1 nsec (sizeof(Datetime) == 12 bytes )
-};
-
-const
-v2xKernel_to_v3xAPIMapping
-columnTypeMapping[] = {
- { ExtInt, NdbDictionary::Column::Int },
- { ExtUnsigned, NdbDictionary::Column::Unsigned },
- { ExtBigint, NdbDictionary::Column::Bigint },
- { ExtBigunsigned, NdbDictionary::Column::Bigunsigned },
- { ExtFloat, NdbDictionary::Column::Float },
- { ExtDouble, NdbDictionary::Column::Double },
- { ExtDecimal, NdbDictionary::Column::Decimal },
- { ExtChar, NdbDictionary::Column::Char },
- { ExtVarchar, NdbDictionary::Column::Varchar },
- { ExtBinary, NdbDictionary::Column::Binary },
- { ExtVarbinary, NdbDictionary::Column::Varbinary },
- { ExtDatetime, NdbDictionary::Column::Datetime },
- { ExtTimespec, NdbDictionary::Column::Timespec },
- { -1, -1 }
-};
+ for (int i = 0; i < tableImpl->getNoOfColumns(); i++)
+ createAttr(tableImpl->getColumn(i));
+}
-static
-NdbDictionary::Column::Type
-convertToV3x(Int32 kernelConstant, const v2xKernel_to_v3xAPIMapping map[],
- Int32 def)
+TableS::~TableS()
{
- int i = 0;
- while(map[i].kernelConstant != kernelConstant){
- if(map[i].kernelConstant == -1 &&
- map[i].apiConstant == -1){
- return (NdbDictionary::Column::Type)def;
- }
- i++;
- }
- return (NdbDictionary::Column::Type)map[i].apiConstant;
+ for (Uint32 i= 0; i < allAttributesDesc.size(); i++)
+ delete allAttributesDesc[i];
}
-
-
// Parse dictTabInfo buffer and pushback to to vector storage
-// Using SimpleProperties (here we don't need ntohl, ref:ejonore)
bool
-RestoreMetaData::parseTableDescriptor(const Uint32 * data,
- Uint32 len,
- const char * catalog,
- const char * schema) {
- SimplePropertiesLinearReader it(data, len);
- SimpleProperties::UnpackStatus spStatus;
-
- // Parse table name
- if (it.getKey() != DictTabInfo::TableName) {
- err << "readMetaTableDesc getKey table name error" << endl;
- return false;
- } // if
-
- /**
- * if backup was taken in v21x then there is no info about catalog,
- * and schema. This infomration is concatenated to the tableName.
- *
- */
- char tableName[MAX_TAB_NAME_SIZE*2]; // * 2 for db and schema.-.
-
-
- char tmpTableName[MAX_TAB_NAME_SIZE];
- it.getString(tmpTableName);
-#if NDB_VERSION_MAJOR >= VERSION_3X
- /**
- * only mess with name in version 3.
- */
- /* switch(getMajor(m_fileHeader.NdbVersion)) {
- */
- if(getMajor(m_fileHeader.NdbVersion) < VERSION_3X)
- {
+RestoreMetaData::parseTableDescriptor(const Uint32 * data, Uint32 len)
+{
+ NdbTableImpl* tableImpl = 0;
+ int ret = NdbDictInterface::parseTableInfo(&tableImpl, data, len, false);
- if(strcmp(tmpTableName, "SYSTAB_0") == 0 ||
- strcmp(tmpTableName, "NDB$EVENTS_0") == 0)
- {
- sprintf(tableName,"sys/def/%s",tmpTableName);
- }
- else {
- if(catalog == NULL && schema == NULL)
- {
- sprintf(tableName,"%s",tmpTableName);
- }
- else
- {
- sprintf(tableName,"%s/%s/%s",catalog,schema,tmpTableName);
- }
- }
- }
- else
- sprintf(tableName,"%s",tmpTableName);
-#elif NDB_VERSION_MAJOR < VERSION_3X
- /**
- * this is version two!
- */
- sprintf(tableName,"%s",tmpTableName);
-#endif
- if (strlen(tableName) == 0) {
- err << "readMetaTableDesc getString table name error" << endl;
+ if (ret != 0) {
+ err << "parseTableInfo " << " failed" << endl;
return false;
- } // if
+ }
+ if(tableImpl == 0)
+ return false;
+
+ debug << "parseTableInfo " << tableImpl->getName() << " done" << endl;
- TableS * table = new TableS(tableName);
+ TableS * table = new TableS(tableImpl);
if(table == NULL) {
return false;
}
-
table->setBackupVersion(m_fileHeader.NdbVersion);
- tmpTableS tmpTable;
- spStatus = SimpleProperties::unpack(it, &tmpTable,
- RestoreTabMap, TabMapSize, true, true);
- if ((spStatus != SimpleProperties::Break) ||
- it.getKey() != DictTabInfo::AttributeName) {
- err << "readMetaTableDesc sp.unpack error" << endl;
- delete table;
- return false;
- } // if
- debug << "Parsed table id " << tmpTable.tableId << endl;
- table->setTableId(tmpTable.tableId);
- debug << "Parsed table #attr " << tmpTable.noOfAttributes << endl;
+ debug << "Parsed table id " << table->getTableId() << endl;
+ debug << "Parsed table #attr " << table->getNoOfAttributes() << endl;
debug << "Parsed table schema version not used " << endl;
- for (Uint32 i = 0; i < tmpTable.noOfAttributes; i++) {
- if (it.getKey() != DictTabInfo::AttributeName) {
- err << "readMetaTableDesc error " << endl;
- delete table;
- return false;
- } // if
-
- tmpAttrS tmpAttr;
- if(it.getValueLen() > AttrNameLenC){
- err << "readMetaTableDesc attribute name too long??" << endl;
- delete table;
- return false;
- }
- it.getString(tmpAttr.name);
-
- spStatus = SimpleProperties::unpack(it, &tmpAttr, RestoreAttrMap,
- AttrMapSize, true, true);
- if ((spStatus != SimpleProperties::Break) ||
- (it.getKey() != DictTabInfo::AttributeEnd)) {
- err << "readMetaTableDesc sp unpack attribute " << i << " error"
- << endl;
- delete table;
- return false;
- } // if
-
- debug << "Creating attribute " << i << " " << tmpAttr.name << endl;
-
- bool thisNullable = (bool)(tmpAttr.nullable); // Really not needed (now)
- KeyType thisKey = (KeyType)(tmpAttr.key); // These are identical (right now)
- // Convert attribute size from enum to Uint32
- // The static consts are really enum taking the value in DictTabInfo
- // e.g. 3 is not ...0011 but rather ...0100
- //TODO: rather do a switch if the constants should change
- Uint32 thisSize = 1 << tmpAttr.size;
- // Convert attribute type to AttrType
- AttrType thisType;
- switch (tmpAttr.type) {
- case 0: // SignedType
- thisType = Signed;
- break;
- case 1: // UnSignedType
- thisType = UnSigned;
- break;
- case 2: // FloatingPointType
- thisType = Float;
- break;
- case 3: // StringType:
- debug << "String type detected " << endl;
- thisType = String;
- break;
- default:
- // What, default to unsigned?
- thisType = UnSigned;
- break;
- } // switch
- /* ndbout_c << " type: " << thisType << " size: " << thisSize <<" arraySize: "
- << tmpAttr.arraySize << " nullable: " << thisNullable << " key: "
- << thisKey << endl;
- */
- table->createAttr(tmpAttr.name, thisType,
- thisSize, tmpAttr.arraySize,
- thisNullable, thisKey);
- if (!it.next()) {
- break;
- // Check number of created attributes and compare with expected
- //ndbout << "readMetaTableDesc expecting more attributes" << endl;
- //return false;
- } // if
- } // for
-
- debug << "Pushing table " << tableName << endl;
+ debug << "Pushing table " << table->getTableName() << endl;
debug << " with " << table->getNoOfAttributes() << " attributes" << endl;
allTables.push_back(table);
-#ifndef restore_old_types
- NdbTableImpl* tableImpl = 0;
- int ret = NdbDictInterface::parseTableInfo(&tableImpl, data, len);
-#if NDB_VERSION_MAJOR >= VERSION_3X
- NdbDictionary::Column::Type type;
- if(getMajor(m_fileHeader.NdbVersion) < VERSION_3X) {
- tableImpl->setName(tableName);
- Uint32 noOfColumns = tableImpl->getNoOfColumns();
- for(Uint32 i = 0 ; i < noOfColumns; i++) {
- type = convertToV3x(tableImpl->getColumn(i)->m_extType,
- columnTypeMapping,
- -1);
- if(type == -1)
- {
- ndbout_c("Restore: Was not able to map external type %d (in v2x) "
- " to a proper type in v3x", tableImpl->getColumn(i)->m_extType);
- return false;
- }
- else
- {
- tableImpl->getColumn(i)->m_type = type;
- }
-
-
-
-
- }
- }
-#endif
- if (ret != 0) {
- err << "parseTableInfo " << tableName << " failed" << endl;
- return false;
- }
- if(tableImpl == 0)
- return false;
- debug << "parseTableInfo " << tableName << " done" << endl;
- table->m_dictTable = tableImpl;
-#endif
return true;
}
// Constructor
-RestoreDataIterator::RestoreDataIterator(const RestoreMetaData & md)
- : m_metaData(md)
+RestoreDataIterator::RestoreDataIterator(const RestoreMetaData & md, void (* _free_data_callback)())
+ : BackupFile(_free_data_callback), m_metaData(md)
{
debug << "RestoreDataIterator constructor" << endl;
setDataFile(md, 0);
}
-RestoreDataIterator::~RestoreDataIterator(){
+TupleS & TupleS::operator=(const TupleS& tuple)
+{
+ prepareRecord(*tuple.m_currentTable);
+
+ if (allAttrData)
+ memcpy(allAttrData, tuple.allAttrData, getNoOfAttributes()*sizeof(AttributeData));
+
+ return *this;
+};
+int TupleS::getNoOfAttributes() const {
+ if (m_currentTable == 0)
+ return 0;
+ return m_currentTable->getNoOfAttributes();
+};
+
+const TableS * TupleS::getTable() const {
+ return m_currentTable;
+};
+
+const AttributeDesc * TupleS::getDesc(int i) const {
+ return m_currentTable->allAttributesDesc[i];
}
+AttributeData * TupleS::getData(int i) const{
+ return &(allAttrData[i]);
+};
+
bool
TupleS::prepareRecord(const TableS & tab){
- m_currentTable = &tab;
- for(int i = 0; i<allAttributes.size(); i++) {
- if(allAttributes[i] != NULL)
- delete allAttributes[i];
- }
- allAttributes.clear();
- AttributeS * a;
- for(int i = 0; i<tab.getNoOfAttributes(); i++){
- a = new AttributeS;
- if(a == NULL) {
- ndbout_c("Restore: Failed to allocate memory");
- return false;
+ if (allAttrData) {
+ if (getNoOfAttributes() == tab.getNoOfAttributes())
+ {
+ m_currentTable = &tab;
+ return true;
}
- a->Desc = tab[i];
- allAttributes.push_back(a);
+ delete [] allAttrData;
+ m_currentTable= 0;
}
+
+ allAttrData = new AttributeData[tab.getNoOfAttributes()];
+ if (allAttrData == 0)
+ return false;
+
+ m_currentTable = &tab;
+
return true;
}
const TupleS *
-RestoreDataIterator::getNextTuple(int & res) {
- TupleS * tup = new TupleS();
- if(tup == NULL) {
- ndbout_c("Restore: Failed to allocate memory");
- res = -1;
- return NULL;
- }
- if(!tup->prepareRecord(* m_currentTable)) {
- res =-1;
- return NULL;
- }
-
-
+RestoreDataIterator::getNextTuple(int & res)
+{
Uint32 dataLength = 0;
// Read record length
- if (fread(&dataLength, sizeof(dataLength), 1, m_file) != 1){
+ if (buffer_read(&dataLength, sizeof(dataLength), 1) != 1){
err << "getNextTuple:Error reading length of data part" << endl;
- delete tup;
res = -1;
return NULL;
} // if
@@ -610,34 +320,34 @@ RestoreDataIterator::getNextTuple(int & res) {
// End of this data fragment
debug << "End of fragment" << endl;
res = 0;
- delete tup;
return NULL;
} // if
-
- tup->createDataRecord(dataLenBytes);
+
// Read tuple data
- if (fread(tup->getDataRecord(), 1, dataLenBytes, m_file) != dataLenBytes) {
+ void *_buf_ptr;
+ if (buffer_get_ptr(&_buf_ptr, 1, dataLenBytes) != dataLenBytes) {
err << "getNextTuple:Read error: " << endl;
- delete tup;
res = -1;
return NULL;
}
- Uint32 * ptr = tup->getDataRecord();
+ Uint32 *buf_ptr = (Uint32*)_buf_ptr, *ptr = buf_ptr;
ptr += m_currentTable->m_nullBitmaskSize;
- for(int i = 0; i < m_currentTable->m_fixedKeys.size(); i++){
- assert(ptr < tup->getDataRecord() + dataLength);
-
+ for(Uint32 i= 0; i < m_currentTable->m_fixedKeys.size(); i++){
+ assert(ptr < buf_ptr + dataLength);
+
const Uint32 attrId = m_currentTable->m_fixedKeys[i]->attrId;
- AttributeS * attr = tup->allAttributes[attrId];
- const Uint32 sz = attr->Desc->getSizeInWords();
+ AttributeData * attr_data = m_tuple.getData(attrId);
+ const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
+
+ const Uint32 sz = attr_desc->getSizeInWords();
- attr->Data.null = false;
- attr->Data.void_value = ptr;
+ attr_data->null = false;
+ attr_data->void_value = ptr;
- if(!Twiddle(attr))
+ if(!Twiddle(attr_desc, attr_data))
{
res = -1;
return NULL;
@@ -645,18 +355,20 @@ RestoreDataIterator::getNextTuple(int & res) {
ptr += sz;
}
- for(int i = 0; i<m_currentTable->m_fixedAttribs.size(); i++){
- assert(ptr < tup->getDataRecord() + dataLength);
+ for(Uint32 i = 0; i < m_currentTable->m_fixedAttribs.size(); i++){
+ assert(ptr < buf_ptr + dataLength);
const Uint32 attrId = m_currentTable->m_fixedAttribs[i]->attrId;
- AttributeS * attr = tup->allAttributes[attrId];
- const Uint32 sz = attr->Desc->getSizeInWords();
+ AttributeData * attr_data = m_tuple.getData(attrId);
+ const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
+
+ const Uint32 sz = attr_desc->getSizeInWords();
- attr->Data.null = false;
- attr->Data.void_value = ptr;
+ attr_data->null = false;
+ attr_data->void_value = ptr;
- if(!Twiddle(attr))
+ if(!Twiddle(attr_desc, attr_data))
{
res = -1;
return NULL;
@@ -665,21 +377,23 @@ RestoreDataIterator::getNextTuple(int & res) {
ptr += sz;
}
- for(int i = 0; i<m_currentTable->m_variableAttribs.size(); i++){
+ for(Uint32 i = 0; i < m_currentTable->m_variableAttribs.size(); i++){
const Uint32 attrId = m_currentTable->m_variableAttribs[i]->attrId;
- AttributeS * attr = tup->allAttributes[attrId];
+
+ AttributeData * attr_data = m_tuple.getData(attrId);
+ const AttributeDesc * attr_desc = m_tuple.getDesc(attrId);
- if(attr->Desc->nullable){
- const Uint32 ind = attr->Desc->m_nullBitIndex;
+ if(attr_desc->m_column->getNullable()){
+ const Uint32 ind = attr_desc->m_nullBitIndex;
if(BitmaskImpl::get(m_currentTable->m_nullBitmaskSize,
- tup->getDataRecord(),ind)){
- attr->Data.null = true;
- attr->Data.void_value = NULL;
+ buf_ptr,ind)){
+ attr_data->null = true;
+ attr_data->void_value = NULL;
continue;
}
}
- assert(ptr < tup->getDataRecord() + dataLength);
+ assert(ptr < buf_ptr + dataLength);
typedef BackupFormat::DataFile::VariableData VarData;
VarData * data = (VarData *)ptr;
@@ -687,15 +401,15 @@ RestoreDataIterator::getNextTuple(int & res) {
Uint32 id = ntohl(data->Id);
assert(id == attrId);
- attr->Data.null = false;
- attr->Data.void_value = &data->Data[0];
+ attr_data->null = false;
+ attr_data->void_value = &data->Data[0];
/**
* Compute array size
*/
- const Uint32 arraySize = (4 * sz) / (attr->Desc->size / 8);
- assert(arraySize >= attr->Desc->arraySize);
- if(!Twiddle(attr, attr->Desc->arraySize))
+ const Uint32 arraySize = (4 * sz) / (attr_desc->size / 8);
+ assert(arraySize >= attr_desc->arraySize);
+ if(!Twiddle(attr_desc, attr_data, attr_desc->arraySize))
{
res = -1;
return NULL;
@@ -706,15 +420,20 @@ RestoreDataIterator::getNextTuple(int & res) {
m_count ++;
res = 0;
- return tup;
+ return &m_tuple;
} // RestoreDataIterator::getNextTuple
-BackupFile::BackupFile(){
+BackupFile::BackupFile(void (* _free_data_callback)())
+ : free_data_callback(_free_data_callback)
+{
m_file = 0;
m_path[0] = 0;
m_fileName[0] = 0;
- m_buffer = 0;
- m_bufferSize = 0;
+
+ m_buffer_sz = 64*1024;
+ m_buffer = malloc(m_buffer_sz);
+ m_buffer_ptr = m_buffer;
+ m_buffer_data_left = 0;
}
BackupFile::~BackupFile(){
@@ -735,15 +454,54 @@ BackupFile::openFile(){
return m_file != 0;
}
-Uint32 *
-BackupFile::createBuffer(Uint32 bytes){
- if(bytes > m_bufferSize){
- if(m_buffer != 0)
- free(m_buffer);
- m_bufferSize = m_bufferSize + 2 * bytes;
- m_buffer = (Uint32*)malloc(m_bufferSize);
+Uint32 BackupFile::buffer_get_ptr_ahead(void **p_buf_ptr, Uint32 size, Uint32 nmemb)
+{
+ Uint32 sz = size*nmemb;
+ if (sz > m_buffer_data_left) {
+
+ if (free_data_callback)
+ (*free_data_callback)();
+
+ memcpy(m_buffer, m_buffer_ptr, m_buffer_data_left);
+
+ size_t r = fread(((char *)m_buffer) + m_buffer_data_left, 1, m_buffer_sz - m_buffer_data_left, m_file);
+ m_buffer_data_left += r;
+ m_buffer_ptr = m_buffer;
+
+ if (sz > m_buffer_data_left)
+ sz = size * (m_buffer_data_left / size);
}
- return m_buffer;
+
+ *p_buf_ptr = m_buffer_ptr;
+
+ return sz/size;
+}
+Uint32 BackupFile::buffer_get_ptr(void **p_buf_ptr, Uint32 size, Uint32 nmemb)
+{
+ Uint32 r = buffer_get_ptr_ahead(p_buf_ptr, size, nmemb);
+
+ m_buffer_ptr = ((char*)m_buffer_ptr)+(r*size);
+ m_buffer_data_left -= (r*size);
+
+ return r;
+}
+
+Uint32 BackupFile::buffer_read_ahead(void *ptr, Uint32 size, Uint32 nmemb)
+{
+ void *buf_ptr;
+ Uint32 r = buffer_get_ptr_ahead(&buf_ptr, size, nmemb);
+ memcpy(ptr, buf_ptr, r*size);
+
+ return r;
+}
+
+Uint32 BackupFile::buffer_read(void *ptr, Uint32 size, Uint32 nmemb)
+{
+ void *buf_ptr;
+ Uint32 r = buffer_get_ptr(&buf_ptr, size, nmemb);
+ memcpy(ptr, buf_ptr, r*size);
+
+ return r;
}
void
@@ -804,7 +562,7 @@ BackupFile::readHeader(){
return false;
}
- if(fread(&m_fileHeader, sizeof(m_fileHeader), 1, m_file) != 1){
+ if(buffer_read(&m_fileHeader, sizeof(m_fileHeader), 1) != 1){
err << "readDataFileHeader: Error reading header" << endl;
return false;
}
@@ -852,14 +610,13 @@ BackupFile::validateFooter(){
return true;
}
-bool
-RestoreDataIterator::readFragmentHeader(int & ret)
+bool RestoreDataIterator::readFragmentHeader(int & ret)
{
BackupFormat::DataFile::FragmentHeader Header;
debug << "RestoreDataIterator::getNextFragment" << endl;
- if (fread(&Header, sizeof(Header), 1, m_file) != 1){
+ if (buffer_read(&Header, sizeof(Header), 1) != 1){
ret = 0;
return false;
} // if
@@ -882,6 +639,12 @@ RestoreDataIterator::readFragmentHeader(int & ret)
return false;
}
+ if(!m_tuple.prepareRecord(*m_currentTable))
+ {
+ ret =-1;
+ return false;
+ }
+
info << "_____________________________________________________" << endl
<< "Restoring data in table: " << m_currentTable->getTableName()
<< "(" << Header.TableId << ") fragment "
@@ -889,6 +652,7 @@ RestoreDataIterator::readFragmentHeader(int & ret)
m_count = 0;
ret = 0;
+
return true;
} // RestoreDataIterator::getNextFragment
@@ -897,7 +661,7 @@ bool
RestoreDataIterator::validateFragmentFooter() {
BackupFormat::DataFile::FragmentFooter footer;
- if (fread(&footer, sizeof(footer), 1, m_file) != 1){
+ if (buffer_read(&footer, sizeof(footer), 1) != 1){
err << "getFragmentFooter:Error reading fragment footer" << endl;
return false;
}
@@ -915,44 +679,39 @@ RestoreDataIterator::validateFragmentFooter() {
return true;
} // RestoreDataIterator::getFragmentFooter
-void TableS::createAttr(const char* name,
- const AttrType type,
- const unsigned int size, // in bytes
- const unsigned int arraySize,
- const bool nullable,
- const KeyType key)
+AttributeDesc::AttributeDesc(NdbDictionary::Column *c)
+ : m_column(c)
{
- AttributeDesc desc;
-
- strncpy(desc.name, name, AttrNameLenC);
- desc.type = type;
- desc.size = size;
- desc.arraySize = arraySize;
- desc.nullable = nullable;
- desc.key = key;
- desc.attrId = allAttributesDesc.size();
+ size = c->getSize()*8;
+ arraySize = c->getLength();
+}
- AttributeDesc * d = new AttributeDesc(desc);
+void TableS::createAttr(NdbDictionary::Column *column)
+{
+ AttributeDesc * d = new AttributeDesc(column);
if(d == NULL) {
ndbout_c("Restore: Failed to allocate memory");
abort();
}
- d->m_table = this;
+ d->attrId = allAttributesDesc.size();
allAttributesDesc.push_back(d);
- if(desc.key != NoKey /* && not variable */){
+ if(d->m_column->getPrimaryKey() /* && not variable */)
+ {
m_fixedKeys.push_back(d);
return;
}
- if(!nullable){
+
+ if(!d->m_column->getNullable())
+ {
m_fixedAttribs.push_back(d);
return;
}
- if(nullable){
- d->m_nullBitIndex = m_noOfNullable;
- m_noOfNullable++;
- m_nullBitmaskSize = (m_noOfNullable + 31) / 32;
- }
+
+ /* Nullable attr*/
+ d->m_nullBitIndex = m_noOfNullable;
+ m_noOfNullable++;
+ m_nullBitmaskSize = (m_noOfNullable + 31) / 32;
m_variableAttribs.push_back(d);
} // TableS::createAttr
@@ -1010,45 +769,32 @@ RestoreLogIterator::getNextLogEntry(int & res) {
// Read record length
typedef BackupFormat::LogFile::LogEntry LogE;
- Uint32 gcp = 0;
- LogE * logE = 0;
- Uint32 len = ~0;
+ Uint32 gcp= 0;
+ LogE * logE= 0;
+ Uint32 len= ~0;
const Uint32 stopGCP = m_metaData.getStopGCP();
do {
-
- if(createBuffer(4) == 0) {
- res = -1;
- return NULL;
+ if (buffer_read_ahead(&len, sizeof(Uint32), 1) != 1){
+ res= -1;
+ return 0;
}
-
+ len= ntohl(len);
- if (fread(m_buffer, sizeof(Uint32), 1, m_file) != 1){
- res = -1;
- return NULL;
+ Uint32 data_len = sizeof(Uint32) + len*4;
+ if (buffer_get_ptr((void **)(&logE), 1, data_len) != data_len) {
+ res= -2;
+ return 0;
}
- m_buffer[0] = ntohl(m_buffer[0]);
- len = m_buffer[0];
if(len == 0){
- res = 0;
+ res= 0;
return 0;
}
- if(createBuffer(4 * (len + 1)) == 0){
- res = -1;
- return NULL;
- }
-
- if (fread(&m_buffer[1], 4, len, m_file) != len) {
- res = -1;
- return NULL;
- }
+ logE->TableId= ntohl(logE->TableId);
+ logE->TriggerEvent= ntohl(logE->TriggerEvent);
- logE = (LogE *)&m_buffer[0];
- logE->TableId = ntohl(logE->TableId);
- logE->TriggerEvent = ntohl(logE->TriggerEvent);
-
- const bool hasGcp = (logE->TriggerEvent & 0x10000) != 0;
+ const bool hasGcp= (logE->TriggerEvent & 0x10000) != 0;
logE->TriggerEvent &= 0xFFFF;
if(hasGcp){
@@ -1057,9 +803,6 @@ RestoreLogIterator::getNextLogEntry(int & res) {
}
} while(gcp > stopGCP + 1);
- for(int i=0; i<m_logEntry.m_values.size();i++)
- delete m_logEntry.m_values[i];
- m_logEntry.m_values.clear();
m_logEntry.m_table = m_metaData.getTable(logE->TableId);
switch(logE->TriggerEvent){
case TriggerEvent::TE_INSERT:
@@ -1077,17 +820,19 @@ RestoreLogIterator::getNextLogEntry(int & res) {
}
const TableS * tab = m_logEntry.m_table;
+ m_logEntry.clear();
AttributeHeader * ah = (AttributeHeader *)&logE->Data[0];
AttributeHeader *end = (AttributeHeader *)&logE->Data[len - 2];
AttributeS * attr;
while(ah < end){
- attr = new AttributeS;
+ attr= m_logEntry.add_attr();
if(attr == NULL) {
ndbout_c("Restore: Failed to allocate memory");
res = -1;
- return NULL;
+ return 0;
}
+
attr->Desc = (* tab)[ah->getAttributeId()];
assert(attr->Desc != 0);
@@ -1100,13 +845,94 @@ RestoreLogIterator::getNextLogEntry(int & res) {
attr->Data.void_value = ah->getDataPtr();
}
- Twiddle(attr);
- m_logEntry.m_values.push_back(attr);
+ Twiddle(attr->Desc, &(attr->Data));
ah = ah->getNext();
}
-
+
m_count ++;
res = 0;
return &m_logEntry;
}
+
+NdbOut &
+operator<<(NdbOut& ndbout, const AttributeS& attr){
+ const AttributeData & data = attr.Data;
+ const AttributeDesc & desc = *(attr.Desc);
+
+ if (data.null)
+ {
+ ndbout << "<NULL>";
+ return ndbout;
+ }
+
+ NdbRecAttr tmprec;
+ tmprec.setup(desc.m_column, (char *)data.void_value);
+ ndbout << tmprec;
+
+ return ndbout;
+}
+
+// Print tuple data
+NdbOut&
+operator<<(NdbOut& ndbout, const TupleS& tuple)
+{
+ ndbout << tuple.getTable()->getTableName() << "; ";
+ for (int i = 0; i < tuple.getNoOfAttributes(); i++)
+ {
+ AttributeData * attr_data = tuple.getData(i);
+ const AttributeDesc * attr_desc = tuple.getDesc(i);
+ const AttributeS attr = {attr_desc, *attr_data};
+ debug << i << " " << attr_desc->m_column->getName();
+ ndbout << attr;
+
+ if (i != (tuple.getNoOfAttributes() - 1))
+ ndbout << delimiter << " ";
+ } // for
+ return ndbout;
+}
+
+// Print tuple data
+NdbOut&
+operator<<(NdbOut& ndbout, const LogEntry& logE)
+{
+ switch(logE.m_type)
+ {
+ case LogEntry::LE_INSERT:
+ ndbout << "INSERT " << logE.m_table->getTableName() << " ";
+ break;
+ case LogEntry::LE_DELETE:
+ ndbout << "DELETE " << logE.m_table->getTableName() << " ";
+ break;
+ case LogEntry::LE_UPDATE:
+ ndbout << "UPDATE " << logE.m_table->getTableName() << " ";
+ break;
+ default:
+ ndbout << "Unknown log entry type (not insert, delete or update)" ;
+ }
+
+ for (Uint32 i= 0; i < logE.size();i++)
+ {
+ const AttributeS * attr = logE[i];
+ ndbout << attr->Desc->m_column->getName() << "=";
+ ndbout << (* attr);
+ if (i < (logE.size() - 1))
+ ndbout << ", ";
+ }
+ return ndbout;
+}
+
+
+NdbOut &
+operator<<(NdbOut& ndbout, const TableS & table){
+ ndbout << endl << "Table: " << table.getTableName() << endl;
+ for (int j = 0; j < table.getNoOfAttributes(); j++)
+ {
+ const AttributeDesc * desc = table[j];
+ ndbout << desc->m_column->getName() << ": " << desc->m_column->getType();
+ ndbout << " key: " << desc->m_column->getPrimaryKey();
+ ndbout << " array: " << desc->arraySize;
+ ndbout << " size: " << desc->size << endl;
+ } // for
+ return ndbout;
+}
diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.hpp b/ndb/src/kernel/blocks/backup/restore/Restore.hpp
index 0c075e18933..e9149e38e44 100644
--- a/ndb/src/kernel/blocks/backup/restore/Restore.hpp
+++ b/ndb/src/kernel/blocks/backup/restore/Restore.hpp
@@ -18,18 +18,14 @@
#define RESTORE_H
#include <ndb_global.h>
+#include <NdbOut.hpp>
#include <BackupFormat.hpp>
#include <NdbApi.hpp>
-#include <AttrType.hpp>
-
-#include <NdbOut.hpp>
-#include "myVector.hpp"
#include <ndb_version.h>
#include <version.h>
-#define VERSION_3X 3
-
+static const char * delimiter = ";"; // Delimiter in file dump
const int FileNameLenC = 256;
const int TableNameLenC = 256;
@@ -67,29 +63,22 @@ struct AttributeData {
struct AttributeDesc {
//private:
- // TODO (sometimes): use a temporary variable in DTIMAP so we can
- // hide AttributeDesc private variables
friend class TupleS;
friend class TableS;
friend class RestoreDataIterator;
friend class RestoreMetaData;
friend struct AttributeS;
- char name[AttrNameLenC];
- Uint32 attrId;
- AttrType type;
- bool nullable;
- KeyType key;
Uint32 size; // bits
Uint32 arraySize;
+ Uint32 attrId;
+ NdbDictionary::Column *m_column;
Uint32 m_nullBitIndex;
public:
- AttributeDesc() {
- name[0] = 0;
- }
+ AttributeDesc(NdbDictionary::Column *column);
+ AttributeDesc();
- const TableS * m_table;
Uint32 getSizeInWords() const { return (size * arraySize + 31)/ 32;}
}; // AttributeDesc
@@ -102,19 +91,26 @@ class TupleS {
private:
friend class RestoreDataIterator;
- const TableS * m_currentTable;
- myVector<AttributeS*> allAttributes;
- Uint32 * dataRecord;
+ const TableS *m_currentTable;
+ AttributeData *allAttrData;
bool prepareRecord(const TableS &);
public:
- TupleS() {dataRecord = NULL;};
- ~TupleS() {if(dataRecord != NULL) delete [] dataRecord;};
- int getNoOfAttributes() const { return allAttributes.size(); };
- const TableS * getTable() const { return m_currentTable;};
- const AttributeS * operator[](int i) const { return allAttributes[i];};
- Uint32 * getDataRecord() { return dataRecord;};
- void createDataRecord(Uint32 bytes) { dataRecord = new Uint32[bytes];};
+ TupleS() {
+ m_currentTable= 0;
+ allAttrData= 0;
+ };
+ ~TupleS()
+ {
+ if (allAttrData)
+ delete [] allAttrData;
+ };
+ TupleS(const TupleS& tuple); // disable copy constructor
+ TupleS & operator=(const TupleS& tuple);
+ int getNoOfAttributes() const;
+ const TableS * getTable() const;
+ const AttributeDesc * getDesc(int i) const;
+ AttributeData * getData(int i) const;
}; // class TupleS
class TableS {
@@ -123,49 +119,28 @@ class TableS {
friend class RestoreMetaData;
friend class RestoreDataIterator;
- Uint32 tableId;
- char tableName[TableNameLenC];
Uint32 schemaVersion;
Uint32 backupVersion;
- myVector<AttributeDesc *> allAttributesDesc;
- myVector<AttributeDesc *> m_fixedKeys;
- //myVector<AttributeDesc *> m_variableKey;
- myVector<AttributeDesc *> m_fixedAttribs;
- myVector<AttributeDesc *> m_variableAttribs;
+ Vector<AttributeDesc *> allAttributesDesc;
+ Vector<AttributeDesc *> m_fixedKeys;
+ //Vector<AttributeDesc *> m_variableKey;
+ Vector<AttributeDesc *> m_fixedAttribs;
+ Vector<AttributeDesc *> m_variableAttribs;
Uint32 m_noOfNullable;
Uint32 m_nullBitmaskSize;
int pos;
- char create_string[2048];
- /*
- char mysqlTableName[1024];
- char mysqlDatabaseName[1024];
- */
- void createAttr(const char* name,
- const AttrType type,
- const unsigned int size, // in bits
- const unsigned int arraySize,
- const bool nullable,
- const KeyType key);
+ void createAttr(NdbDictionary::Column *column);
-#ifndef restore_old_types
public:
class NdbDictionary::Table* m_dictTable;
-#endif
-public:
- TableS (const char * name){
- snprintf(tableName, sizeof(tableName), name);
- m_noOfNullable = m_nullBitmaskSize = 0;
- }
+ TableS (class NdbTableImpl* dictTable);
+ ~TableS();
- void setTableId (Uint32 id) {
- tableId = id;
- }
-
Uint32 getTableId() const {
- return tableId;
+ return m_dictTable->getTableId();
}
/*
void setMysqlTableName(char * tableName) {
@@ -182,7 +157,6 @@ public:
void setBackupVersion(Uint32 version) {
backupVersion = version;
}
-
Uint32 getBackupVersion() const {
return backupVersion;
@@ -216,18 +190,26 @@ protected:
BackupFormat::FileHeader m_expectedFileHeader;
Uint32 m_nodeId;
- Uint32 * m_buffer;
- Uint32 m_bufferSize;
- Uint32 * createBuffer(Uint32 bytes);
+ void * m_buffer;
+ void * m_buffer_ptr;
+ Uint32 m_buffer_sz;
+ Uint32 m_buffer_data_left;
+ void (* free_data_callback)();
+
bool openFile();
void setCtlFile(Uint32 nodeId, Uint32 backupId, const char * path);
void setDataFile(const BackupFile & bf, Uint32 no);
void setLogFile(const BackupFile & bf, Uint32 no);
+ Uint32 buffer_get_ptr(void **p_buf_ptr, Uint32 size, Uint32 nmemb);
+ Uint32 buffer_read(void *ptr, Uint32 size, Uint32 nmemb);
+ Uint32 buffer_get_ptr_ahead(void **p_buf_ptr, Uint32 size, Uint32 nmemb);
+ Uint32 buffer_read_ahead(void *ptr, Uint32 size, Uint32 nmemb);
+
void setName(const char * path, const char * name);
- BackupFile();
+ BackupFile(void (* free_data_callback)() = 0);
~BackupFile();
public:
bool readHeader();
@@ -237,15 +219,14 @@ public:
const char * getFilename() const { return m_fileName;}
Uint32 getNodeId() const { return m_nodeId;}
const BackupFormat::FileHeader & getFileHeader() const { return m_fileHeader;}
- bool Twiddle(AttributeS * attr, Uint32 arraySize = 0);
+ bool Twiddle(const AttributeDesc * attr_desc, AttributeData * attr_data, Uint32 arraySize = 0);
};
class RestoreMetaData : public BackupFile {
- myVector<TableS *> allTables;
+ Vector<TableS *> allTables;
bool readMetaFileHeader();
- bool readMetaTableDesc(const char * catalog,
- const char * schema);
+ bool readMetaTableDesc();
bool readGCPEntry();
Uint32 readMetaTableList();
@@ -253,20 +234,14 @@ class RestoreMetaData : public BackupFile {
Uint32 m_startGCP;
Uint32 m_stopGCP;
- bool parseTableDescriptor(const Uint32 * data, Uint32 len,
- const char * catalog,
- const char * schema);
+ bool parseTableDescriptor(const Uint32 * data, Uint32 len);
public:
-
RestoreMetaData(const char * path, Uint32 nodeId, Uint32 bNo);
- ~RestoreMetaData();
+ virtual ~RestoreMetaData();
- int loadContent(const char * catalog,
- const char * schema);
+ int loadContent();
-
-
Uint32 getNoOfTables() const { return allTables.size();}
const TableS * operator[](int i) const { return allTables[i];}
@@ -278,20 +253,20 @@ public:
class RestoreDataIterator : public BackupFile {
const RestoreMetaData & m_metaData;
-
Uint32 m_count;
- TupleS m_tuple;
const TableS* m_currentTable;
+ TupleS m_tuple;
+
public:
// Constructor
- RestoreDataIterator(const RestoreMetaData &);
- ~RestoreDataIterator();
+ RestoreDataIterator(const RestoreMetaData &, void (* free_data_callback)());
+ ~RestoreDataIterator() {};
// Read data file fragment header
bool readFragmentHeader(int & res);
bool validateFragmentFooter();
-
+
const TupleS *getNextTuple(int & res);
};
@@ -304,9 +279,35 @@ public:
};
EntryType m_type;
const TableS * m_table;
- myVector<AttributeS*> m_values;
-
-
+ Vector<AttributeS*> m_values;
+ Vector<AttributeS*> m_values_e;
+ AttributeS *add_attr() {
+ AttributeS * attr;
+ if (m_values_e.size() > 0) {
+ attr = m_values_e[m_values_e.size()-1];
+ m_values_e.erase(m_values_e.size()-1);
+ }
+ else
+ {
+ attr = new AttributeS;
+ }
+ m_values.push_back(attr);
+ return attr;
+ }
+ void clear() {
+ for(Uint32 i= 0; i < m_values.size(); i++)
+ m_values_e.push_back(m_values[i]);
+ m_values.clear();
+ }
+ ~LogEntry()
+ {
+ for(Uint32 i= 0; i< m_values.size(); i++)
+ delete m_values[i];
+ for(Uint32 i= 0; i< m_values_e.size(); i++)
+ delete m_values_e[i];
+ }
+ Uint32 size() const { return m_values.size(); }
+ const AttributeS * operator[](int i) const { return m_values[i];}
};
class RestoreLogIterator : public BackupFile {
@@ -317,10 +318,16 @@ private:
LogEntry m_logEntry;
public:
RestoreLogIterator(const RestoreMetaData &);
-
+ virtual ~RestoreLogIterator() {};
+
const LogEntry * getNextLogEntry(int & res);
};
+NdbOut& operator<<(NdbOut& ndbout, const TableS&);
+NdbOut& operator<<(NdbOut& ndbout, const TupleS&);
+NdbOut& operator<<(NdbOut& ndbout, const LogEntry&);
+NdbOut& operator<<(NdbOut& ndbout, const RestoreMetaData&);
+
#endif
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer.cpp b/ndb/src/kernel/blocks/backup/restore/consumer.cpp
new file mode 100644
index 00000000000..e94c31b2666
--- /dev/null
+++ b/ndb/src/kernel/blocks/backup/restore/consumer.cpp
@@ -0,0 +1,107 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "consumer.hpp"
+
+#ifdef USE_MYSQL
+int
+BackupConsumer::create_table_string(const TableS & table,
+ char * tableName,
+ char *buf){
+ int pos = 0;
+ int pos2 = 0;
+ char buf2[2048];
+
+ pos += sprintf(buf+pos, "%s%s", "CREATE TABLE ", tableName);
+ pos += sprintf(buf+pos, "%s", "(");
+ pos2 += sprintf(buf2+pos2, "%s", " primary key(");
+
+ for (int j = 0; j < table.getNoOfAttributes(); j++)
+ {
+ const AttributeDesc * desc = table[j];
+ // ndbout << desc->name << ": ";
+ pos += sprintf(buf+pos, "%s%s", desc->m_column->getName()," ");
+ switch(desc->m_column->getType()){
+ case NdbDictionary::Column::Int:
+ pos += sprintf(buf+pos, "%s", "int");
+ break;
+ case NdbDictionary::Column::Unsigned:
+ pos += sprintf(buf+pos, "%s", "int unsigned");
+ break;
+ case NdbDictionary::Column::Float:
+ pos += sprintf(buf+pos, "%s", "float");
+ break;
+ case NdbDictionary::Column::Decimal:
+ pos += sprintf(buf+pos, "%s", "decimal");
+ break;
+ case NdbDictionary::Column::Char:
+ pos += sprintf(buf+pos, "%s", "char");
+ break;
+ case NdbDictionary::Column::Varchar:
+ pos += sprintf(buf+pos, "%s", "varchar");
+ break;
+ case NdbDictionary::Column::Binary:
+ pos += sprintf(buf+pos, "%s", "binary");
+ break;
+ case NdbDictionary::Column::Varbinary:
+ pos += sprintf(buf+pos, "%s", "varchar binary");
+ break;
+ case NdbDictionary::Column::Bigint:
+ pos += sprintf(buf+pos, "%s", "bigint");
+ break;
+ case NdbDictionary::Column::Bigunsigned:
+ pos += sprintf(buf+pos, "%s", "bigint unsigned");
+ break;
+ case NdbDictionary::Column::Double:
+ pos += sprintf(buf+pos, "%s", "double");
+ break;
+ case NdbDictionary::Column::Datetime:
+ pos += sprintf(buf+pos, "%s", "datetime");
+ break;
+ case NdbDictionary::Column::Timespec:
+ pos += sprintf(buf+pos, "%s", "time");
+ break;
+ case NdbDictionary::Column::Undefined:
+ // pos += sprintf(buf+pos, "%s", "varchar binary");
+ return -1;
+ break;
+ default:
+ //pos += sprintf(buf+pos, "%s", "varchar binary");
+ return -1;
+ }
+ if (desc->arraySize > 1) {
+ int attrSize = desc->arraySize;
+ pos += sprintf(buf+pos, "%s%u%s",
+ "(",
+ attrSize,
+ ")");
+ }
+ if (desc->m_column->getPrimaryKey()) {
+ pos += sprintf(buf+pos, "%s", " not null");
+ pos2 += sprintf(buf2+pos2, "%s%s", desc->m_column->getName(), ",");
+ }
+ pos += sprintf(buf+pos, "%s", ",");
+ } // for
+ pos2--; // remove trailing comma
+ pos2 += sprintf(buf2+pos2, "%s", ")");
+ // pos--; // remove trailing comma
+
+ pos += sprintf(buf+pos, "%s", buf2);
+ pos += sprintf(buf+pos, "%s", ") type=ndbcluster");
+ return 0;
+}
+
+#endif // USE_MYSQL
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer.hpp b/ndb/src/kernel/blocks/backup/restore/consumer.hpp
new file mode 100644
index 00000000000..e3ba2041a22
--- /dev/null
+++ b/ndb/src/kernel/blocks/backup/restore/consumer.hpp
@@ -0,0 +1,34 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef CONSUMER_HPP
+#define CONSUMER_HPP
+
+#include "Restore.hpp"
+
+class BackupConsumer {
+public:
+ virtual ~BackupConsumer() { }
+ virtual bool init() { return true;}
+ virtual bool table(const TableS &){return true;}
+ virtual void tuple(const TupleS &){}
+ virtual void tuple_free(){}
+ virtual void endOfTuples(){}
+ virtual void logEntry(const LogEntry &){}
+ virtual void endOfLogEntrys(){}
+};
+
+#endif
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_printer.cpp b/ndb/src/kernel/blocks/backup/restore/consumer_printer.cpp
new file mode 100644
index 00000000000..0aa5b521d29
--- /dev/null
+++ b/ndb/src/kernel/blocks/backup/restore/consumer_printer.cpp
@@ -0,0 +1,55 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "consumer_printer.hpp"
+
+bool
+BackupPrinter::table(const TableS & tab)
+{
+ if (m_print || m_print_meta)
+ {
+ m_ndbout << tab;
+ ndbout_c("Successfully printed table: %s", tab.m_dictTable->getName());
+ }
+ return true;
+}
+
+void
+BackupPrinter::tuple(const TupleS & tup)
+{
+ m_dataCount++;
+ if (m_print || m_print_data)
+ m_ndbout << tup << endl;
+}
+
+void
+BackupPrinter::logEntry(const LogEntry & logE)
+{
+ if (m_print || m_print_log)
+ m_ndbout << logE << endl;
+ m_logCount++;
+}
+
+void
+BackupPrinter::endOfLogEntrys()
+{
+ if (m_print || m_print_log)
+ {
+ ndbout << "Printed " << m_dataCount << " tuples and "
+ << m_logCount << " log entries"
+ << " to stdout." << endl;
+ }
+}
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_printer.hpp b/ndb/src/kernel/blocks/backup/restore/consumer_printer.hpp
new file mode 100644
index 00000000000..7cbc924e364
--- /dev/null
+++ b/ndb/src/kernel/blocks/backup/restore/consumer_printer.hpp
@@ -0,0 +1,50 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef CONSUMER_PRINTER_HPP
+#define CONSUMER_PRINTER_HPP
+
+#include "consumer.hpp"
+
+class BackupPrinter : public BackupConsumer
+{
+ NdbOut & m_ndbout;
+public:
+ BackupPrinter(NdbOut & out = ndbout) : m_ndbout(out)
+ {
+ m_print = false;
+ m_print_log = false;
+ m_print_data = false;
+ m_print_meta = false;
+ }
+
+ virtual bool table(const TableS &);
+#ifdef USE_MYSQL
+ virtual bool table(const TableS &, MYSQL* mysqlp);
+#endif
+ virtual void tuple(const TupleS &);
+ virtual void logEntry(const LogEntry &);
+ virtual void endOfTuples() {};
+ virtual void endOfLogEntrys();
+ bool m_print;
+ bool m_print_log;
+ bool m_print_data;
+ bool m_print_meta;
+ Uint32 m_logCount;
+ Uint32 m_dataCount;
+};
+
+#endif
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp b/ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp
new file mode 100644
index 00000000000..5731a9a3883
--- /dev/null
+++ b/ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp
@@ -0,0 +1,516 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "consumer_restore.hpp"
+#include <NdbSleep.h>
+
+extern FilteredNdbOut err;
+extern FilteredNdbOut info;
+extern FilteredNdbOut debug;
+
+static void callback(int, NdbConnection*, void*);
+
+bool
+BackupRestore::init()
+{
+ release();
+
+ if (!m_restore && !m_restore_meta)
+ return true;
+
+ m_ndb = new Ndb();
+
+ if (m_ndb == NULL)
+ return false;
+
+ // Turn off table name completion
+ m_ndb->useFullyQualifiedNames(false);
+
+ m_ndb->init(1024);
+ if (m_ndb->waitUntilReady(30) != 0)
+ {
+ err << "Failed to connect to ndb!!" << endl;
+ return false;
+ }
+ info << "Connected to ndb!!" << endl;
+
+ m_callback = new restore_callback_t[m_parallelism];
+
+ if (m_callback == 0)
+ {
+ err << "Failed to allocate callback structs" << endl;
+ return false;
+ }
+
+ m_tuples = new TupleS[m_parallelism];
+
+ if (m_tuples == 0)
+ {
+ err << "Failed to allocate tuples" << endl;
+ return false;
+ }
+
+ m_free_callback= m_callback;
+ for (Uint32 i= 0; i < m_parallelism; i++) {
+ m_callback[i].restore= this;
+ m_callback[i].connection= 0;
+ m_callback[i].tup= &m_tuples[i];
+ if (i > 0)
+ m_callback[i-1].next= &(m_callback[i]);
+ }
+ m_callback[m_parallelism-1].next = 0;
+
+ return true;
+}
+
+void BackupRestore::release()
+{
+ if (m_ndb)
+ {
+ delete m_ndb;
+ m_ndb= 0;
+ }
+
+ if (m_callback)
+ {
+ delete [] m_callback;
+ m_callback= 0;
+ }
+
+ if (m_tuples)
+ {
+ delete [] m_tuples;
+ m_tuples= 0;
+ }
+}
+
+BackupRestore::~BackupRestore()
+{
+ release();
+}
+
+bool
+BackupRestore::table(const TableS & table){
+ if (!m_restore_meta)
+ return true;
+
+ NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
+ if (dict->createTable(*table.m_dictTable) == -1)
+ {
+ err << "Create table " << table.getTableName() << " failed: "
+ << dict->getNdbError() << endl;
+ return false;
+ }
+ info << "Successfully restored table " << table.getTableName()<< endl ;
+ return true;
+}
+
+void BackupRestore::tuple(const TupleS & tup)
+{
+ if (!m_restore)
+ return;
+
+ restore_callback_t * cb = m_free_callback;
+
+ if (cb == 0)
+ assert(false);
+
+ m_free_callback = cb->next;
+ cb->retries = 0;
+ *(cb->tup) = tup; // must do copy!
+ tuple_a(cb);
+
+ if (m_free_callback == 0)
+ {
+ // send-poll all transactions
+ // close transaction is done in callback
+ m_ndb->sendPollNdb(3000, 1);
+ }
+}
+
+void BackupRestore::tuple_a(restore_callback_t *cb)
+{
+ while (cb->retries < 10)
+ {
+ /**
+ * start transactions
+ */
+ cb->connection = m_ndb->startTransaction();
+ if (cb->connection == NULL)
+ {
+ /*
+ if (errorHandler(cb))
+ {
+ continue;
+ }
+ */
+ exitHandler();
+ } // if
+
+ const TupleS &tup = *(cb->tup);
+ const TableS * table = tup.getTable();
+ NdbOperation * op = cb->connection->getNdbOperation(table->getTableName());
+
+ if (op == NULL)
+ {
+ if (errorHandler(cb))
+ continue;
+ exitHandler();
+ } // if
+
+ if (op->writeTuple() == -1)
+ {
+ if (errorHandler(cb))
+ continue;
+ exitHandler();
+ } // if
+
+ int ret = 0;
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < tup.getNoOfAttributes(); i++)
+ {
+ const AttributeDesc * attr_desc = tup.getDesc(i);
+ const AttributeData * attr_data = tup.getData(i);
+ int size = attr_desc->size;
+ int arraySize = attr_desc->arraySize;
+ char * dataPtr = attr_data->string_value;
+ Uint32 length = (size * arraySize) / 8;
+ if (attr_desc->m_column->getPrimaryKey())
+ {
+ if (j == 1) continue;
+ ret = op->equal(i, dataPtr, length);
+ }
+ else
+ {
+ if (j == 0) continue;
+ if (attr_data->null)
+ ret = op->setValue(i, NULL, 0);
+ else
+ ret = op->setValue(i, dataPtr, length);
+ }
+ if (ret < 0) {
+ ndbout_c("Column: %d type %d",i,
+ attr_desc->m_column->getType());
+ break;
+ }
+ }
+ if (ret < 0)
+ break;
+ }
+ if (ret < 0)
+ {
+ if (errorHandler(cb))
+ continue;
+ exitHandler();
+ }
+
+ // Prepare transaction (the transaction is NOT yet sent to NDB)
+ cb->connection->executeAsynchPrepare(Commit, &callback, cb);
+ m_transactions++;
+ return;
+ }
+ err << "Unable to recover from errors. Exiting..." << endl;
+ exitHandler();
+}
+
+void BackupRestore::cback(int result, restore_callback_t *cb)
+{
+ m_transactions--;
+
+ if (result < 0)
+ {
+ /**
+ * Error. temporary or permanent?
+ */
+ if (errorHandler(cb))
+ tuple_a(cb); // retry
+ else
+ {
+ err << "Restore: Failed to restore data due to a unrecoverable error. Exiting..." << endl;
+ exitHandler();
+ }
+ }
+ else
+ {
+ /**
+ * OK! close transaction
+ */
+ m_ndb->closeTransaction(cb->connection);
+ cb->connection= 0;
+ cb->next= m_free_callback;
+ m_free_callback= cb;
+ m_dataCount++;
+ }
+}
+
+/**
+ * returns true if is recoverable,
+ * Error handling based on hugo
+ * false if it is an error that generates an abort.
+ */
+bool BackupRestore::errorHandler(restore_callback_t *cb)
+{
+ NdbError error= cb->connection->getNdbError();
+ m_ndb->closeTransaction(cb->connection);
+ cb->connection= 0;
+ cb->retries++;
+ switch(error.status)
+ {
+ case NdbError::Success:
+ return false;
+ // ERROR!
+ break;
+
+ case NdbError::TemporaryError:
+ NdbSleep_MilliSleep(10);
+ return true;
+ // RETRY
+ break;
+
+ case NdbError::UnknownResult:
+ err << error << endl;
+ return false;
+ // ERROR!
+ break;
+
+ default:
+ case NdbError::PermanentError:
+ switch (error.code)
+ {
+ case 499:
+ case 250:
+ NdbSleep_MilliSleep(10);
+ return true; //temp errors?
+ default:
+ break;
+ }
+ //ERROR
+ err << error << endl;
+ return false;
+ break;
+ }
+ return false;
+}
+
+void BackupRestore::exitHandler()
+{
+ release();
+ exit(-1);
+}
+
+
+void
+BackupRestore::tuple_free()
+{
+ if (!m_restore)
+ return;
+
+ if (m_transactions > 0) {
+ // Send all transactions to NDB
+ m_ndb->sendPreparedTransactions(0);
+
+ // Poll all transactions
+ while (m_transactions > 0)
+ m_ndb->pollNdb(3000, m_transactions);
+ }
+}
+
+void
+BackupRestore::endOfTuples()
+{
+ tuple_free();
+}
+
+void
+BackupRestore::logEntry(const LogEntry & tup)
+{
+ if (!m_restore)
+ return;
+
+ NdbConnection * trans = m_ndb->startTransaction();
+ if (trans == NULL)
+ {
+ // Deep shit, TODO: handle the error
+ err << "Cannot start transaction" << endl;
+ exit(-1);
+ } // if
+
+ const TableS * table = tup.m_table;
+ NdbOperation * op = trans->getNdbOperation(table->getTableName());
+ if (op == NULL)
+ {
+ err << "Cannot get operation: " << trans->getNdbError() << endl;
+ exit(-1);
+ } // if
+
+ int check = 0;
+ switch(tup.m_type)
+ {
+ case LogEntry::LE_INSERT:
+ check = op->insertTuple();
+ break;
+ case LogEntry::LE_UPDATE:
+ check = op->updateTuple();
+ break;
+ case LogEntry::LE_DELETE:
+ check = op->deleteTuple();
+ break;
+ default:
+ err << "Log entry has wrong operation type."
+ << " Exiting...";
+ exit(-1);
+ }
+
+ for (Uint32 i= 0; i < tup.size(); i++)
+ {
+ const AttributeS * attr = tup[i];
+ int size = attr->Desc->size;
+ int arraySize = attr->Desc->arraySize;
+ const char * dataPtr = attr->Data.string_value;
+
+ const Uint32 length = (size / 8) * arraySize;
+ if (attr->Desc->m_column->getPrimaryKey())
+ op->equal(attr->Desc->attrId, dataPtr, length);
+ else
+ op->setValue(attr->Desc->attrId, dataPtr, length);
+ }
+
+ const int ret = trans->execute(Commit);
+ if (ret != 0)
+ {
+ // Both insert update and delete can fail during log running
+ // and it's ok
+ // TODO: check that the error is either tuple exists or tuple does not exist?
+ switch(tup.m_type)
+ {
+ case LogEntry::LE_INSERT:
+ break;
+ case LogEntry::LE_UPDATE:
+ break;
+ case LogEntry::LE_DELETE:
+ break;
+ }
+ if (false)
+ {
+ err << "execute failed: " << trans->getNdbError() << endl;
+ exit(-1);
+ }
+ }
+
+ m_ndb->closeTransaction(trans);
+ m_logCount++;
+}
+
+void
+BackupRestore::endOfLogEntrys()
+{
+ if (!m_restore)
+ return;
+
+ info << "Restored " << m_dataCount << " tuples and "
+ << m_logCount << " log entries" << endl;
+}
+
+/*
+ * callback : This is called when the transaction is polled
+ *
+ * (This function must have three arguments:
+ * - The result of the transaction,
+ * - The NdbConnection object, and
+ * - A pointer to an arbitrary object.)
+ */
+
+static void
+callback(int result, NdbConnection* trans, void* aObject)
+{
+ restore_callback_t *cb = (restore_callback_t *)aObject;
+ (cb->restore)->cback(result, cb);
+}
+
+#if 0 // old tuple impl
+void
+BackupRestore::tuple(const TupleS & tup)
+{
+ if (!m_restore)
+ return;
+ while (1)
+ {
+ NdbConnection * trans = m_ndb->startTransaction();
+ if (trans == NULL)
+ {
+ // Deep shit, TODO: handle the error
+ ndbout << "Cannot start transaction" << endl;
+ exit(-1);
+ } // if
+
+ const TableS * table = tup.getTable();
+ NdbOperation * op = trans->getNdbOperation(table->getTableName());
+ if (op == NULL)
+ {
+ ndbout << "Cannot get operation: ";
+ ndbout << trans->getNdbError() << endl;
+ exit(-1);
+ } // if
+
+ // TODO: check return value and handle error
+ if (op->writeTuple() == -1)
+ {
+ ndbout << "writeTuple call failed: ";
+ ndbout << trans->getNdbError() << endl;
+ exit(-1);
+ } // if
+
+ for (int i = 0; i < tup.getNoOfAttributes(); i++)
+ {
+ const AttributeS * attr = tup[i];
+ int size = attr->Desc->size;
+ int arraySize = attr->Desc->arraySize;
+ const char * dataPtr = attr->Data.string_value;
+
+ const Uint32 length = (size * arraySize) / 8;
+ if (attr->Desc->m_column->getPrimaryKey())
+ op->equal(i, dataPtr, length);
+ }
+
+ for (int i = 0; i < tup.getNoOfAttributes(); i++)
+ {
+ const AttributeS * attr = tup[i];
+ int size = attr->Desc->size;
+ int arraySize = attr->Desc->arraySize;
+ const char * dataPtr = attr->Data.string_value;
+
+ const Uint32 length = (size * arraySize) / 8;
+ if (!attr->Desc->m_column->getPrimaryKey())
+ if (attr->Data.null)
+ op->setValue(i, NULL, 0);
+ else
+ op->setValue(i, dataPtr, length);
+ }
+ int ret = trans->execute(Commit);
+ if (ret != 0)
+ {
+ ndbout << "execute failed: ";
+ ndbout << trans->getNdbError() << endl;
+ exit(-1);
+ }
+ m_ndb->closeTransaction(trans);
+ if (ret == 0)
+ break;
+ }
+ m_dataCount++;
+}
+#endif
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_restore.hpp b/ndb/src/kernel/blocks/backup/restore/consumer_restore.hpp
new file mode 100644
index 00000000000..2d36501bf40
--- /dev/null
+++ b/ndb/src/kernel/blocks/backup/restore/consumer_restore.hpp
@@ -0,0 +1,75 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef CONSUMER_RESTORE_HPP
+#define CONSUMER_RESTORE_HPP
+
+#include "consumer.hpp"
+
+struct restore_callback_t {
+ class BackupRestore *restore;
+ class TupleS *tup;
+ class NdbConnection *connection;
+ int retries;
+ restore_callback_t *next;
+};
+
+
+class BackupRestore : public BackupConsumer
+{
+public:
+ BackupRestore(Uint32 parallelism=1)
+ {
+ m_ndb = 0;
+ m_logCount = m_dataCount = 0;
+ m_restore = false;
+ m_restore_meta = false;
+ m_parallelism = parallelism;
+ m_callback = 0;
+ m_tuples = 0;
+ m_free_callback = 0;
+ m_transactions = 0;
+ }
+
+ virtual ~BackupRestore();
+ virtual bool init();
+ virtual void release();
+ virtual bool table(const TableS &);
+ virtual void tuple(const TupleS &);
+ virtual void tuple_free();
+ virtual void tuple_a(restore_callback_t *cb);
+ virtual void cback(int result, restore_callback_t *cb);
+ virtual bool errorHandler(restore_callback_t *cb);
+ virtual void exitHandler();
+ virtual void endOfTuples();
+ virtual void logEntry(const LogEntry &);
+ virtual void endOfLogEntrys();
+ void connectToMysql();
+ Ndb * m_ndb;
+ bool m_restore;
+ bool m_restore_meta;
+ Uint32 m_logCount;
+ Uint32 m_dataCount;
+
+ Uint32 m_parallelism;
+ Uint32 m_transactions;
+
+ TupleS *m_tuples;
+ restore_callback_t *m_callback;
+ restore_callback_t *m_free_callback;
+};
+
+#endif
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_restorem.cpp b/ndb/src/kernel/blocks/backup/restore/consumer_restorem.cpp
new file mode 100644
index 00000000000..6a9ec07148a
--- /dev/null
+++ b/ndb/src/kernel/blocks/backup/restore/consumer_restorem.cpp
@@ -0,0 +1,652 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "consumer_restore.hpp"
+#include <NdbSleep.h>
+
+extern FilteredNdbOut err;
+extern FilteredNdbOut info;
+extern FilteredNdbOut debug;
+
+static bool asynchErrorHandler(NdbConnection * trans, Ndb * ndb);
+static void callback(int result, NdbConnection* trans, void* aObject);
+
+bool
+BackupRestore::init()
+{
+
+ if (!m_restore && !m_restore_meta)
+ return true;
+
+ m_ndb = new Ndb();
+
+ if (m_ndb == NULL)
+ return false;
+
+ // Turn off table name completion
+ m_ndb->useFullyQualifiedNames(false);
+
+ m_ndb->init(1024);
+ if (m_ndb->waitUntilReady(30) != 0)
+ {
+ ndbout << "Failed to connect to ndb!!" << endl;
+ return false;
+ }
+ ndbout << "Connected to ndb!!" << endl;
+
+#if USE_MYSQL
+ if(use_mysql)
+ {
+ if ( mysql_thread_safe() == 0 )
+ {
+ ndbout << "Not thread safe mysql library..." << endl;
+ exit(-1);
+ }
+
+ ndbout << "Connecting to MySQL..." <<endl;
+
+ /**
+ * nwe param:
+ * port
+ * host
+ * user
+ */
+ bool returnValue = true;
+ mysql_init(&mysql);
+ {
+ int portNo = 3306;
+ if ( mysql_real_connect(&mysql,
+ ga_host,
+ ga_user,
+ ga_password,
+ ga_database,
+ ga_port,
+:: ga_socket,
+ 0) == NULL )
+ {
+ ndbout_c("Connect failed: %s", mysql_error(&mysql));
+ returnValue = false;
+ }
+ ndbout << "Connected to MySQL!!!" <<endl;
+ }
+
+ /* if(returnValue){
+ mysql_set_server_option(&mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON);
+ }
+ */
+ return returnValue;
+ }
+#endif
+
+ if (m_callback) {
+ delete [] m_callback;
+ m_callback = 0;
+ }
+
+ m_callback = new restore_callback_t[m_parallelism];
+
+ if (m_callback == 0)
+ {
+ ndbout << "Failed to allocate callback structs" << endl;
+ return false;
+ }
+
+ m_free_callback = m_callback;
+ for (int i= 0; i < m_parallelism; i++) {
+ m_callback[i].restore = this;
+ m_callback[i].connection = 0;
+ m_callback[i].retries = 0;
+ if (i > 0)
+ m_callback[i-1].next = &(m_callback[i]);
+ }
+ m_callback[m_parallelism-1].next = 0;
+
+ return true;
+
+}
+
+BackupRestore::~BackupRestore()
+{
+ if (m_ndb != 0)
+ delete m_ndb;
+
+ if (m_callback)
+ delete [] m_callback;
+}
+
+#ifdef USE_MYSQL
+bool
+BackupRestore::table(const TableS & table, MYSQL * mysqlp){
+ if (!m_restore_meta)
+ {
+ return true;
+ }
+
+ char tmpTabName[MAX_TAB_NAME_SIZE*2];
+ sprintf(tmpTabName, "%s", table.getTableName());
+ char * database = strtok(tmpTabName, "/");
+ char * schema = strtok( NULL , "/");
+ char * tableName = strtok( NULL , "/");
+
+ /**
+ * this means that the user did not specify schema
+ * and it is a v2x backup
+ */
+ if(database == NULL)
+ return false;
+ if(schema == NULL)
+ return false;
+ if(tableName==NULL)
+ tableName = schema;
+
+ char stmtCreateDB[255];
+ sprintf(stmtCreateDB,"CREATE DATABASE %s", database);
+
+ /*ignore return value. mysql_select_db will trap errors anyways*/
+ if (mysql_query(mysqlp,stmtCreateDB) == 0)
+ {
+ //ndbout_c("%s", stmtCreateDB);
+ }
+
+ if (mysql_select_db(&mysql, database) != 0)
+ {
+ ndbout_c("Error: %s", mysql_error(&mysql));
+ return false;
+ }
+
+ char buf [2048];
+ /**
+ * create table ddl
+ */
+ if (create_table_string(table, tableName, buf))
+ {
+ ndbout_c("Unable to create a table definition since the "
+ "backup contains undefined types");
+ return false;
+ }
+
+ //ndbout_c("%s", buf);
+
+ if (mysql_query(mysqlp,buf) != 0)
+ {
+ ndbout_c("Error: %s", mysql_error(&mysql));
+ return false;
+ } else
+ {
+ ndbout_c("Successfully restored table %s into database %s", tableName, database);
+ }
+
+ return true;
+}
+#endif
+
+bool
+BackupRestore::table(const TableS & table){
+ if (!m_restore_meta)
+ {
+ return true;
+ }
+ NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
+ if (dict->createTable(*table.m_dictTable) == -1)
+ {
+ err << "Create table " << table.getTableName() << " failed: "
+ << dict->getNdbError() << endl;
+ return false;
+ }
+ info << "Successfully restored table " << table.getTableName()<< endl ;
+ return true;
+}
+
+void BackupRestore::tuple(const TupleS & tup)
+{
+ if (!m_restore)
+ {
+ delete &tup;
+ return;
+ }
+
+ restore_callback_t * cb = m_free_callback;
+
+ if (cb)
+ {
+ m_free_callback = cb->next;
+ cb->retries = 0;
+ cb->tup = &tup;
+ tuple_a(cb);
+ }
+
+ if (m_free_callback == 0)
+ {
+ // send-poll all transactions
+ // close transaction is done in callback
+ m_ndb->sendPollNdb(3000, 1);
+ }
+}
+
+void BackupRestore::tuple_a(restore_callback_t *cb)
+{
+ while (cb->retries < 10)
+ {
+ /**
+ * start transactions
+ */
+ cb->connection = m_ndb->startTransaction();
+ if (cb->connection == NULL)
+ {
+ /*
+ if (asynchErrorHandler(cb->connection, m_ndb))
+ {
+ cb->retries++;
+ continue;
+ }
+ */
+ asynchExitHandler();
+ } // if
+
+ const TupleS &tup = *(cb->tup);
+ const TableS * table = tup.getTable();
+ NdbOperation * op = cb->connection->getNdbOperation(table->getTableName());
+
+ if (op == NULL)
+ {
+ if (asynchErrorHandler(cb->connection, m_ndb))
+ {
+ cb->retries++;
+ continue;
+ }
+ asynchExitHandler();
+ } // if
+
+ if (op->writeTuple() == -1)
+ {
+ if (asynchErrorHandler(cb->connection, m_ndb))
+ {
+ cb->retries++;
+ continue;
+ }
+ asynchExitHandler();
+ } // if
+
+ Uint32 ret = 0;
+ for (int i = 0; i < tup.getNoOfAttributes(); i++)
+ {
+ const AttributeS * attr = tup[i];
+ int size = attr->Desc->size;
+ int arraySize = attr->Desc->arraySize;
+ char * dataPtr = attr->Data.string_value;
+ Uint32 length = (size * arraySize) / 8;
+ if (attr->Desc->m_column->getPrimaryKey())
+ {
+ ret = op->equal(i, dataPtr, length);
+ }
+ else
+ {
+ if (attr->Data.null)
+ ret = op->setValue(i, NULL, 0);
+ else
+ ret = op->setValue(i, dataPtr, length);
+ }
+
+ if (ret<0)
+ {
+ ndbout_c("Column: %d type %d",i,
+ tup.getTable()->m_dictTable->getColumn(i)->getType());
+ if (asynchErrorHandler(cb->connection, m_ndb))
+ {
+ cb->retries++;
+ break;
+ }
+ asynchExitHandler();
+ }
+ }
+ if (ret < 0)
+ continue;
+
+ // Prepare transaction (the transaction is NOT yet sent to NDB)
+ cb->connection->executeAsynchPrepare(Commit, &callback, cb);
+ m_transactions++;
+ }
+ ndbout_c("Unable to recover from errors. Exiting...");
+ asynchExitHandler();
+}
+
+void BackupRestore::cback(int result, restore_callback_t *cb)
+{
+ if (result<0)
+ {
+ /**
+ * Error. temporary or permanent?
+ */
+ if (asynchErrorHandler(cb->connection, m_ndb))
+ {
+ cb->retries++;
+ tuple_a(cb);
+ }
+ else
+ {
+ ndbout_c("Restore: Failed to restore data "
+ "due to a unrecoverable error. Exiting...");
+ delete m_ndb;
+ delete cb->tup;
+ exit(-1);
+ }
+ }
+ else
+ {
+ /**
+ * OK! close transaction
+ */
+ m_ndb->closeTransaction(cb->connection);
+ delete cb->tup;
+ m_transactions--;
+ }
+}
+
+void BackupRestore::asynchExitHandler()
+{
+ if (m_ndb != NULL)
+ delete m_ndb;
+ exit(-1);
+}
+
+#if 0 // old tuple impl
+void
+BackupRestore::tuple(const TupleS & tup)
+{
+ if (!m_restore)
+ return;
+ while (1)
+ {
+ NdbConnection * trans = m_ndb->startTransaction();
+ if (trans == NULL)
+ {
+ // Deep shit, TODO: handle the error
+ ndbout << "Cannot start transaction" << endl;
+ exit(-1);
+ } // if
+
+ const TableS * table = tup.getTable();
+ NdbOperation * op = trans->getNdbOperation(table->getTableName());
+ if (op == NULL)
+ {
+ ndbout << "Cannot get operation: ";
+ ndbout << trans->getNdbError() << endl;
+ exit(-1);
+ } // if
+
+ // TODO: check return value and handle error
+ if (op->writeTuple() == -1)
+ {
+ ndbout << "writeTuple call failed: ";
+ ndbout << trans->getNdbError() << endl;
+ exit(-1);
+ } // if
+
+ for (int i = 0; i < tup.getNoOfAttributes(); i++)
+ {
+ const AttributeS * attr = tup[i];
+ int size = attr->Desc->size;
+ int arraySize = attr->Desc->arraySize;
+ const char * dataPtr = attr->Data.string_value;
+
+ const Uint32 length = (size * arraySize) / 8;
+ if (attr->Desc->m_column->getPrimaryKey())
+ op->equal(i, dataPtr, length);
+ }
+
+ for (int i = 0; i < tup.getNoOfAttributes(); i++)
+ {
+ const AttributeS * attr = tup[i];
+ int size = attr->Desc->size;
+ int arraySize = attr->Desc->arraySize;
+ const char * dataPtr = attr->Data.string_value;
+
+ const Uint32 length = (size * arraySize) / 8;
+ if (!attr->Desc->m_column->getPrimaryKey())
+ if (attr->Data.null)
+ op->setValue(i, NULL, 0);
+ else
+ op->setValue(i, dataPtr, length);
+ }
+ int ret = trans->execute(Commit);
+ if (ret != 0)
+ {
+ ndbout << "execute failed: ";
+ ndbout << trans->getNdbError() << endl;
+ exit(-1);
+ }
+ m_ndb->closeTransaction(trans);
+ if (ret == 0)
+ break;
+ }
+ m_dataCount++;
+}
+#endif
+
+void
+BackupRestore::endOfTuples()
+{
+ if (!m_restore)
+ return;
+
+ // Send all transactions to NDB
+ m_ndb->sendPreparedTransactions(0);
+
+ // Poll all transactions
+ m_ndb->pollNdb(3000, m_transactions);
+
+ // Close all transactions
+ // for (int i = 0; i < nPreparedTransactions; i++)
+ // m_ndb->closeTransaction(asynchTrans[i]);
+}
+
+void
+BackupRestore::logEntry(const LogEntry & tup)
+{
+ if (!m_restore)
+ return;
+
+ NdbConnection * trans = m_ndb->startTransaction();
+ if (trans == NULL)
+ {
+ // Deep shit, TODO: handle the error
+ ndbout << "Cannot start transaction" << endl;
+ exit(-1);
+ } // if
+
+ const TableS * table = tup.m_table;
+ NdbOperation * op = trans->getNdbOperation(table->getTableName());
+ if (op == NULL)
+ {
+ ndbout << "Cannot get operation: ";
+ ndbout << trans->getNdbError() << endl;
+ exit(-1);
+ } // if
+
+ int check = 0;
+ switch(tup.m_type)
+ {
+ case LogEntry::LE_INSERT:
+ check = op->insertTuple();
+ break;
+ case LogEntry::LE_UPDATE:
+ check = op->updateTuple();
+ break;
+ case LogEntry::LE_DELETE:
+ check = op->deleteTuple();
+ break;
+ default:
+ ndbout << "Log entry has wrong operation type."
+ << " Exiting...";
+ exit(-1);
+ }
+
+ for (int i = 0; i < tup.m_values.size(); i++)
+ {
+ const AttributeS * attr = tup.m_values[i];
+ int size = attr->Desc->size;
+ int arraySize = attr->Desc->arraySize;
+ const char * dataPtr = attr->Data.string_value;
+
+ const Uint32 length = (size / 8) * arraySize;
+ if (attr->Desc->m_column->getPrimaryKey())
+ op->equal(attr->Desc->attrId, dataPtr, length);
+ else
+ op->setValue(attr->Desc->attrId, dataPtr, length);
+ }
+
+#if 1
+ trans->execute(Commit);
+#else
+ const int ret = trans->execute(Commit);
+ // Both insert update and delete can fail during log running
+ // and it's ok
+
+ if (ret != 0)
+ {
+ ndbout << "execute failed: ";
+ ndbout << trans->getNdbError() << endl;
+ exit(-1);
+ }
+#endif
+
+ m_ndb->closeTransaction(trans);
+ m_logCount++;
+}
+
+void
+BackupRestore::endOfLogEntrys()
+{
+ if (m_restore)
+ {
+ ndbout << "Restored " << m_dataCount << " tuples and "
+ << m_logCount << " log entries" << endl;
+ }
+}
+#if 0
+/*****************************************
+ *
+ * Callback function for asynchronous transactions
+ *
+ * Idea for error handling: Transaction objects have to be stored globally when
+ * they are prepared.
+ * In the callback function if the transaction:
+ * succeeded: delete the object from global storage
+ * failed but can be retried: execute the object that is in global storage
+ * failed but fatal: delete the object from global storage
+ *
+ ******************************************/
+static void restoreCallback(int result, // Result for transaction
+ NdbConnection *object, // Transaction object
+ void *anything) // Not used
+{
+ static Uint32 counter = 0;
+
+
+ debug << "restoreCallback function called " << counter << " time(s)" << endl;
+
+ ++counter;
+
+ if (result == -1)
+ {
+ ndbout << " restoreCallback (" << counter;
+ if ((counter % 10) == 1)
+ {
+ ndbout << "st";
+ } // if
+ else if ((counter % 10) == 2)
+ {
+ ndbout << "nd";
+ } // else if
+ else if ((counter % 10 ) ==3)
+ {
+ ndbout << "rd";
+ } // else if
+ else
+ {
+ ndbout << "th";
+ } // else
+ err << " time: error detected " << object->getNdbError() << endl;
+ } // if
+
+} // restoreCallback
+#endif
+
+
+
+/*
+ * callback : This is called when the transaction is polled
+ *
+ * (This function must have three arguments:
+ * - The result of the transaction,
+ * - The NdbConnection object, and
+ * - A pointer to an arbitrary object.)
+ */
+
+static void
+callback(int result, NdbConnection* trans, void* aObject)
+{
+ restore_callback_t *cb = (restore_callback_t *)aObject;
+ (cb->restore)->cback(result, cb);
+}
+
+/**
+ * returns true if is recoverable,
+ * Error handling based on hugo
+ * false if it is an error that generates an abort.
+ */
+static
+bool asynchErrorHandler(NdbConnection * trans, Ndb* ndb)
+{
+ NdbError error = trans->getNdbError();
+ ndb->closeTransaction(trans);
+ switch(error.status)
+ {
+ case NdbError::Success:
+ return false;
+ // ERROR!
+ break;
+
+ case NdbError::TemporaryError:
+ NdbSleep_MilliSleep(10);
+ return true;
+ // RETRY
+ break;
+
+ case NdbError::UnknownResult:
+ ndbout << error << endl;
+ return false;
+ // ERROR!
+ break;
+
+ default:
+ case NdbError::PermanentError:
+ switch (error.code)
+ {
+ case 499:
+ case 250:
+ NdbSleep_MilliSleep(10);
+ return true; //temp errors?
+ default:
+ break;
+ }
+ //ERROR
+ ndbout << error << endl;
+ return false;
+ break;
+ }
+ return false;
+}
diff --git a/ndb/src/kernel/blocks/backup/restore/main.cpp b/ndb/src/kernel/blocks/backup/restore/main.cpp
index 4c15785d5c2..99deeb3115c 100644
--- a/ndb/src/kernel/blocks/backup/restore/main.cpp
+++ b/ndb/src/kernel/blocks/backup/restore/main.cpp
@@ -14,165 +14,37 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "Restore.hpp"
#include <getarg.h>
-#include <NdbSleep.h>
#include <Vector.hpp>
#include <ndb_limits.h>
#include <NdbTCP.h>
-#ifdef USE_MYSQL
-#include <mysql.h>
-#endif
-NdbOut& operator<<(NdbOut& ndbout, const TupleS& tuple);
-NdbOut& operator<<(NdbOut& ndbout, const LogEntry& logEntry);
-NdbOut& operator<<(NdbOut& ndbout, const RestoreMetaData &);
+#include <NdbOut.hpp>
+
+#include "consumer_restore.hpp"
+#include "consumer_printer.hpp"
extern FilteredNdbOut err;
extern FilteredNdbOut info;
extern FilteredNdbOut debug;
-static const char * delimiter = ";"; // Delimiter in file dump
-
static int ga_nodeId = 0;
-static int ga_nParallelism = 1;
+static int ga_nParallelism = 128;
static int ga_backupId = 0;
static bool ga_dont_ignore_systab_0 = false;
-static myVector<class BackupConsumer *> g_consumers;
-
-#ifdef USE_MYSQL
-/**
- * mysql specific stuff:
- */
-static const char* ga_user = "root";
-static const char* ga_host = "localhost";
-static const char* ga_socket = "/tmp/mysql.sock";
-static const char* ga_password = "";
-static const char* ga_database = "";
-static int ga_port = 3306;
-static bool use_mysql = false;
-static MYSQL mysql;
-#endif
+static Vector<class BackupConsumer *> g_consumers;
-
-#ifdef NDB_WIN32
-static const char* ga_backupPath = ".\\";
-#else
-static const char* ga_backupPath = "./";
-#endif
-
-typedef struct {
- void * ndb;
- void * restore;
- TupleS * tup;
- int transaction;
- int retries;
-} restore_callback_t;
+static const char* ga_backupPath = "." DIR_SEPARATOR;
static const char* ga_connect_NDB = NULL;
-static const char* ga_schema = NULL;
-static const char* ga_catalog = NULL;
-
-
/**
* print and restore flags
*/
static bool ga_restore = false;
static bool ga_print = false;
-
-
-
-class BackupConsumer {
-public:
- virtual bool init() { return true;}
- virtual bool table(const TableS &){return true;}
-#ifdef USE_MYSQL
- virtual bool table(const TableS &, MYSQL* mysqlp) {return true;};
-#endif
- virtual void tuple(const TupleS &){}
- virtual void tupleAsynch(const TupleS &, restore_callback_t * callback) {};
- // virtual bool asynchErrorHandler(NdbConnection * trans){return true;};
- virtual void asynchExitHandler(){};
- virtual void endOfTuples(){}
- virtual void logEntry(const LogEntry &){}
- virtual void endOfLogEntrys(){}
-protected:
- int create_table_string(const TableS & table, char * ,char *);
-};
-
-class BackupPrinter : public BackupConsumer
-{
- NdbOut & m_ndbout;
-public:
- BackupPrinter(NdbOut & out = ndbout) : m_ndbout(out)
- {
- m_print = false;
- m_print_log = false;
- m_print_data = false;
- m_print_meta = false;
- }
-
- virtual bool table(const TableS &);
-#ifdef USE_MYSQL
- virtual bool table(const TableS &, MYSQL* mysqlp);
-#endif
- virtual void tuple(const TupleS &);
- virtual void logEntry(const LogEntry &);
- virtual void endOfTuples() {};
- virtual void endOfLogEntrys();
- virtual void tupleAsynch(const TupleS &, restore_callback_t * callback);
- bool m_print;
- bool m_print_log;
- bool m_print_data;
- bool m_print_meta;
- Uint32 m_logCount;
- Uint32 m_dataCount;
-
-};
-
-class BackupRestore : public BackupConsumer
-{
-public:
- BackupRestore()
- {
- m_ndb = 0;
- m_logCount = m_dataCount = 0;
- m_restore = false;
- m_restore_meta = false;
- }
-
- virtual ~BackupRestore();
-
- virtual bool init();
- virtual bool table(const TableS &);
-#ifdef USE_MYSQL
- virtual bool table(const TableS &, MYSQL* mysqlp);
-#endif
- virtual void tuple(const TupleS &);
- virtual void tupleAsynch(const TupleS &, restore_callback_t * callback);
- virtual void asynchExitHandler();
- virtual void endOfTuples();
- virtual void logEntry(const LogEntry &);
- virtual void endOfLogEntrys();
- void connectToMysql();
- Ndb * m_ndb;
- bool m_restore;
- bool m_restore_meta;
- Uint32 m_logCount;
- Uint32 m_dataCount;
-};
bool
readArguments(const int argc, const char** argv)
{
- BackupPrinter* printer = new BackupPrinter();
- if (printer == NULL)
- return false;
- BackupRestore* restore = new BackupRestore();
- if (restore == NULL)
- {
- delete printer;
- return false;
- }
int _print = 0;
int _print_meta = 0;
@@ -206,18 +78,6 @@ readArguments(const int argc, const char** argv)
"No of parallel transactions during restore of data."
"(parallelism can be 1 to 1024)",
"Parallelism"},
-#if NDB_VERSION_MAJOR >= VERSION_3X
- { "catalog", 'd', arg_string, &ga_catalog,
- "Specifies the catalog/database where the data should be restored to. "
- "Restores only to backups taken with v.2.x and restored on >v.3.x "
- "systems. Note: system tables (if restored) defaults to sys/def/ ",
- "catalog"},
- { "schema", 's', arg_string, &ga_schema,
- "Specifies the schema where the data should be restored to."
- "Restores only to backups taken with v.2.x and restored on >v.3.x "
- "systems. Note: system tables (if restored) defaults to sys/def/ ",
- "schema"},
-#endif
#ifdef USE_MYSQL
{ "use_mysql", '\0', arg_flag, &use_mysql,
"Restore meta data via mysql. Systab will be ignored. Data is restored "
@@ -247,10 +107,18 @@ readArguments(const int argc, const char** argv)
ga_nParallelism < 1 ||
ga_nParallelism >1024)
{
-
arg_printusage(args, num_args, argv[0], "<path to backup files>\n");
+ return false;
+ }
+
+ BackupPrinter* printer = new BackupPrinter();
+ if (printer == NULL)
+ return false;
+
+ BackupRestore* restore = new BackupRestore(ga_nParallelism);
+ if (restore == NULL)
+ {
delete printer;
- delete restore;
return false;
}
@@ -293,11 +161,11 @@ readArguments(const int argc, const char** argv)
}
{
- BackupConsumer * c = printer;
+ BackupConsumer * c = printer;
g_consumers.push_back(c);
}
{
- BackupConsumer * c = restore;
+ BackupConsumer * c = restore;
g_consumers.push_back(c);
}
// Set backup file path
@@ -305,20 +173,6 @@ readArguments(const int argc, const char** argv)
{
ga_backupPath = argv[optind];
}
-#ifdef USE_MYSQL
- if(use_mysql) {
- ga_dont_ignore_systab_0 = false;
- ga_database = ""; //not used yet. pethaps later if we want to
- // restore meta data in an existing mysql database,
- // and not just restore it to the same database
- // as when the backup was taken.
- // If implementing this, then the
- // tupleAsynch must also be changed so that the
- // table data is restored to the correct table.
- // also, mysql_select_db must be set properly (ie.,
- // ignored in codw below)
- }
-#endif
return true;
}
@@ -327,15 +181,12 @@ readArguments(const int argc, const char** argv)
void
clearConsumers()
{
- for(int i = 0; i<g_consumers.size(); i++)
+ for(Uint32 i= 0; i<g_consumers.size(); i++)
delete g_consumers[i];
g_consumers.clear();
}
-static bool asynchErrorHandler(NdbConnection * trans, Ndb * ndb);
-static NdbConnection * asynchTrans[1024];
-
-bool
+static bool
checkSysTable(const char *tableName)
{
return ga_dont_ignore_systab_0 ||
@@ -345,6 +196,12 @@ checkSysTable(const char *tableName)
strcmp(tableName, "sys/def/NDB$EVENTS_0") != 0);
}
+static void
+free_data_callback()
+{
+ for(Uint32 i= 0; i < g_consumers.size(); i++)
+ g_consumers[i]->tuple_free();
+}
int
main(int argc, const char** argv)
@@ -353,10 +210,12 @@ main(int argc, const char** argv)
{
return -1;
}
- // Turn off table name completion
-#if NDB_VERSION_MAJOR >= VERSION_3X
- Ndb::useFullyQualifiedNames(false);
-#endif
+
+ if (ga_connect_NDB != NULL)
+ {
+ // Use connection string
+ Ndb::setConnectString(ga_connect_NDB);
+ }
/**
* we must always load meta data, even if we will only print it to stdout
@@ -368,41 +227,19 @@ main(int argc, const char** argv)
return -1;
}
/**
- * check wheater we can restore the backup (right version, and if that
- * version needs catalog and schema specified.
+ * check wheater we can restore the backup (right version).
*/
- int res = metaData.loadContent(ga_catalog, ga_schema);
+ int res = metaData.loadContent();
- if (res == 0)
+ if (res == 0)
{
ndbout_c("Restore: Failed to load content");
return -1;
}
- if (res == -1)
- {
- ndbout_c("Restore: The backup is from a NDB Cluster v.2.x version. "
- "To restore this backup on a > 3.x version you must specify "
- "catalog and schema.");
- return -1;
- }
- if (res == -2)
- {
-#ifdef NDB_VERSION
- ndbout_c("Restore: The backup is from a NDB Cluster v.3.x version "
- "Catalog and schema are invalid parameters since they "
- "already exist implicitly.");
-#endif
-#ifdef NDB_KERNEL_VERSION
- ndbout_c("Restore: The backup is from a NDB Cluster v.3.x version "
- "It is not possible to restore a 3.x backup on v.2.x. ");
-#endif
- return -1;
- }
- if (res == -3)
+ if (metaData.getNoOfTables() == 0)
{
- ndbout_c("Restore: The backup contains no tables "
- "Catalog and schema are invalid parameters. ");
+ ndbout_c("Restore: The backup contains no tables ");
return -1;
}
@@ -414,7 +251,7 @@ main(int argc, const char** argv)
}
- for(int i = 0; i<g_consumers.size(); i++)
+ for(Uint32 i= 0; i < g_consumers.size(); i++)
{
if (!g_consumers[i]->init())
{
@@ -428,36 +265,22 @@ main(int argc, const char** argv)
{
if (checkSysTable(metaData[i]->getTableName()))
{
- for(int j = 0; j<g_consumers.size(); j++)
-#ifdef USE_MYSQL
- if(use_mysql) {
- if (!g_consumers[j]->table(* metaData[i], &mysql))
- {
- ndbout_c("Restore: Failed to restore table: %s. "
- "Exiting...",
- metaData[i]->getTableName());
- return -11;
- }
- } else
-#endif
- if (!g_consumers[j]->table(* metaData[i]))
- {
- ndbout_c("Restore: Failed to restore table: %s. "
- "Exiting...",
- metaData[i]->getTableName());
- return -11;
- }
-
+ for(Uint32 j= 0; j < g_consumers.size(); j++)
+ if (!g_consumers[j]->table(* metaData[i]))
+ {
+ ndbout_c("Restore: Failed to restore table: %s. "
+ "Exiting...",
+ metaData[i]->getTableName());
+ return -11;
+ }
}
}
-
-
if (ga_restore || ga_print)
{
if (ga_restore)
{
- RestoreDataIterator dataIter(metaData);
+ RestoreDataIterator dataIter(metaData, &free_data_callback);
// Read data file header
if (!dataIter.readHeader())
@@ -467,19 +290,15 @@ main(int argc, const char** argv)
}
- while (dataIter.readFragmentHeader(res))
+ while (dataIter.readFragmentHeader(res= 0))
{
- const TupleS* tuple = 0;
- while ((tuple = dataIter.getNextTuple(res)) != NULL)
+ const TupleS* tuple;
+ while ((tuple = dataIter.getNextTuple(res= 1)) != 0)
{
if (checkSysTable(tuple->getTable()->getTableName()))
- {
- for(int i = 0; i<g_consumers.size(); i++)
- {
- g_consumers[i]->tupleAsynch(* tuple, 0);
- }
- }
- } while (tuple != NULL);
+ for(Uint32 i= 0; i < g_consumers.size(); i++)
+ g_consumers[i]->tuple(* tuple);
+ } // while (tuple != NULL);
if (res < 0)
{
@@ -496,44 +315,37 @@ main(int argc, const char** argv)
if (res < 0)
{
- ndbout_c("Restore: An error occured while restoring data. "
- "Exiting...");
+ err << "Restore: An error occured while restoring data. Exiting... res=" << res << endl;
return -1;
}
dataIter.validateFooter(); //not implemented
- for (int i = 0; i<g_consumers.size(); i++)
+
+ for (Uint32 i= 0; i < g_consumers.size(); i++)
g_consumers[i]->endOfTuples();
RestoreLogIterator logIter(metaData);
if (!logIter.readHeader())
{
- ndbout << "Failed to read header of data file. Exiting...";
+ err << "Failed to read header of data file. Exiting..." << endl;
return -1;
}
- /**
- * I have not touched the part below : -johan 040218
- * except fixing return values.
- */
const LogEntry * logEntry = 0;
- while ((logEntry = logIter.getNextLogEntry(res)))
+ while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0)
{
if (checkSysTable(logEntry->m_table->getTableName()))
- {
- for(int i = 0; i<g_consumers.size(); i++)
+ for(Uint32 i= 0; i < g_consumers.size(); i++)
g_consumers[i]->logEntry(* logEntry);
- }
}
if (res < 0)
{
- ndbout_c("Restore: An restoring the data log"
- "Exiting...");
+ err << "Restore: An restoring the data log. Exiting... res=" << res << endl;
return -1;
}
logIter.validateFooter(); //not implemented
- for (int i = 0; i<g_consumers.size(); i++)
+ for (Uint32 i= 0; i < g_consumers.size(); i++)
g_consumers[i]->endOfLogEntrys();
}
}
@@ -541,1152 +353,3 @@ main(int argc, const char** argv)
return 1;
} // main
-NdbOut &
-operator<<(NdbOut& ndbout, const AttributeS& attr){
- const AttributeData & data = attr.Data;
- const AttributeDesc & desc = * attr.Desc;
-
- if (data.null)
- {
- ndbout << "<NULL>";
- return ndbout;
- }
-
- if (desc.arraySize > 1)
- ndbout << "[ ";
- for (Uint32 j = 0; j < desc.arraySize; j++)
- {
- // Print strings without spaces,
- // (but ndbout char does not work as expected, see below)
- switch (desc.type)
- {
- case Signed:
- switch (desc.size)
- {
- case 8:
- ndbout << (short)data.int8_value[j];
- break;
- case 16:
- ndbout << data.int16_value[j];
- break;
- case 32:
- ndbout << data.int32_value[j];
- break;
- case 64:
- ndbout << data.int64_value[j];
- break;
- case 128:
- ndbout << "Signed sz = 128 - this is something wrong??" << endl;
- break;
- default:
- // Unknown, error
- break;
- } // switch size
- break;
- case UnSigned:
- switch (desc.size)
- {
- case 8:
- ndbout << (short)data.u_int8_value[j];
- break;
- case 16:
- ndbout << data.u_int16_value[j];
- break;
- case 32:
- ndbout << data.u_int32_value[j];
- break;
- case 64:
- ndbout << data.u_int64_value[j];
- break;
- case 128:
- ndbout << "UnSigned sz = 128 - this is something wrong??" << endl;
- break;
- default:
- // Unknown, error
- break;
- } // switch size
- break;
- case (String):
- if (desc.size == 8){
- NdbDictionary::Column::Type type = desc.m_table->m_dictTable->getColumn(desc.attrId)->getType();
- if(type == NdbDictionary::Column::Varchar){
- short len = ntohs(data.u_int16_value[0]);
- ndbout.print("%.*s", len, (data.string_value+2));
- } else {
- ndbout << data.string_value;
- }
- } // if
- else
- {
- ndbout << "String sz != 8 - this is something wrong??" << endl;
- }
- j = desc.arraySize;
- break;
- case (Float):
- // Not yet supported to print float
- ndbout << "float";
- break;
- default:
- ndbout << "Not defined Attr Type";
- } // switch AttrType
- ndbout << " ";
- } // for ArraySize
- if (desc.arraySize > 1)
- {
- ndbout << "]";
- }
- return ndbout;
-}
-
-// Print tuple data
-NdbOut&
-operator<<(NdbOut& ndbout, const TupleS& tuple)
-{
- ndbout << tuple.getTable()->getTableName() << "; ";
- for (int i = 0; i < tuple.getNoOfAttributes(); i++)
- {
- const AttributeS * attr = tuple[i];
- debug << i << " " << attr->Desc->name;
- ndbout << (* attr);
-
- if (i != (tuple.getNoOfAttributes() - 1))
- ndbout << delimiter << " ";
- } // for
- return ndbout;
-}
-
-// Print tuple data
-NdbOut&
-operator<<(NdbOut& ndbout, const LogEntry& logE)
-{
- switch(logE.m_type)
- {
- case LogEntry::LE_INSERT:
- ndbout << "INSERT " << logE.m_table->getTableName() << " ";
- break;
- case LogEntry::LE_DELETE:
- ndbout << "DELETE " << logE.m_table->getTableName() << " ";
- break;
- case LogEntry::LE_UPDATE:
- ndbout << "UPDATE " << logE.m_table->getTableName() << " ";
- break;
- default:
- ndbout << "Unknown log entry type (not insert, delete or update)" ;
- }
-
- for (int i = 0; i < logE.m_values.size();i++)
- {
- const AttributeS * attr = logE.m_values[i];
- ndbout << attr->Desc->name << "=";
- ndbout << (* attr);
- if (i < (logE.m_values.size() - 1))
- ndbout << ", ";
- }
- return ndbout;
-}
-
-
-NdbOut &
-operator<<(NdbOut& ndbout, const TableS & table){
- ndbout << endl << "Table: " << table.getTableName() << endl;
- for (int j = 0; j < table.getNoOfAttributes(); j++)
- {
- const AttributeDesc * desc = table[j];
- ndbout << desc->name << ": ";
- NdbDictionary::Column::Type type = table.m_dictTable->getColumn(desc->attrId)->getType();
- switch(type){
- case NdbDictionary::Column::Int:
- ndbout << "Int ";
- break;
- case NdbDictionary::Column::Unsigned:
- ndbout << "Unsigned ";
- break;
- case NdbDictionary::Column::Float:
- ndbout << "Float ";
- break;
- case NdbDictionary::Column::Decimal:
- ndbout << "Decimal ";
- break;
- case NdbDictionary::Column::Char:
- ndbout << "Char ";
- break;
- case NdbDictionary::Column::Varchar:
- ndbout << "Varchar ";
- break;
- case NdbDictionary::Column::Binary:
- ndbout << "Binary ";
- break;
- case NdbDictionary::Column::Varbinary:
- ndbout << "Varbinary ";
- break;
- case NdbDictionary::Column::Bigint:
- ndbout << "Bigint ";
- break;
- case NdbDictionary::Column::Bigunsigned:
- ndbout << "Bigunsigned ";
- break;
- case NdbDictionary::Column::Double:
- ndbout << "Double ";
- break;
- case NdbDictionary::Column::Datetime:
- ndbout << "Datetime ";
- break;
- case NdbDictionary::Column::Timespec:
- ndbout << "Timespec ";
- break;
- case NdbDictionary::Column::Undefined:
- ndbout << "Undefined ";
- break;
- default:
- ndbout << "Unknown(" << type << ")";
- }
- ndbout << " key: " << desc->key;
- ndbout << " array: " << desc->arraySize;
- ndbout << " size: " << desc->size << endl;
- } // for
- return ndbout;
-}
-
-
-#if 0
-/*****************************************
- *
- * Callback function for asynchronous transactions
- *
- * Idea for error handling: Transaction objects have to be stored globally when
- * they are prepared.
- * In the callback function if the transaction:
- * succeeded: delete the object from global storage
- * failed but can be retried: execute the object that is in global storage
- * failed but fatal: delete the object from global storage
- *
- ******************************************/
-static void restoreCallback(int result, // Result for transaction
- NdbConnection *object, // Transaction object
- void *anything) // Not used
-{
- static Uint32 counter = 0;
-
-
- debug << "restoreCallback function called " << counter << " time(s)" << endl;
-
- ++counter;
-
- if (result == -1)
- {
- ndbout << " restoreCallback (" << counter;
- if ((counter % 10) == 1)
- {
- ndbout << "st";
- } // if
- else if ((counter % 10) == 2)
- {
- ndbout << "nd";
- } // else if
- else if ((counter % 10 ) ==3)
- {
- ndbout << "rd";
- } // else if
- else
- {
- ndbout << "th";
- } // else
- err << " time: error detected " << object->getNdbError() << endl;
- } // if
-
-} // restoreCallback
-#endif
-
-
-
-bool
-BackupPrinter::table(const TableS & tab)
-{
- if (m_print || m_print_meta)
- {
- m_ndbout << tab;
- ndbout_c("Successfully printed table: %s", tab.m_dictTable->getName());
- }
- return true;
-}
-
-#ifdef USE_MYSQL
-bool
-BackupPrinter::table(const TableS & tab, MYSQL * mysql)
-{
- if (m_print || m_print_meta)
- {
-
- char tmpTabName[MAX_TAB_NAME_SIZE*2];
- sprintf(tmpTabName, "%s", tab.getTableName());
- char * database = strtok(tmpTabName, "/");
- char * schema = strtok( NULL , "/");
- char * tableName = strtok( NULL , "/");
-
- /**
- * this means that the user did not specify schema
- * and it is a v2x backup
- */
- if(database == NULL)
- return false;
- if(schema == NULL)
- return false;
- if(tableName==NULL)
- tableName = schema;
-
- char stmtCreateDB[255];
-
- sprintf(stmtCreateDB,"CREATE DATABASE %s", database);
- ndbout_c("%s", stmtCreateDB);
-
-
- char buf [2048];
- create_table_string(tab, tableName, buf);
- ndbout_c("%s", buf);
-
- ndbout_c("Successfully printed table: %s", tab.m_dictTable->getName());
- }
- return true;
-}
-
-#endif
-
-void
-BackupPrinter::tuple(const TupleS & tup)
-{
- if (m_print || m_print_data)
- m_ndbout << tup << endl;
-}
-
-void
-BackupPrinter::logEntry(const LogEntry & logE)
-{
- if (m_print || m_print_log)
- m_ndbout << logE << endl;
- m_logCount++;
-}
-
-bool
-BackupRestore::init()
-{
-
- if (!m_restore && !m_restore_meta)
- return true;
-
- if (ga_connect_NDB != NULL)
- {
- // Use connection string
- Ndb::setConnectString(ga_connect_NDB);
- }
-
- m_ndb = new Ndb("TEST_DB");
- if (m_ndb == NULL)
- return false;
-
- m_ndb->init(1024);
- if (m_ndb->waitUntilReady(30) != 0)
- {
- ndbout << "Failed to connect to ndb!!" << endl;
- delete m_ndb;
- return false;
- }
- ndbout << "Connected to ndb!!" << endl;
-
-#if USE_MYSQL
- if(use_mysql)
- {
- if ( mysql_thread_safe() == 0 )
- {
- ndbout << "Not thread safe mysql library..." << endl;
- exit(-1);
- }
-
- ndbout << "Connecting to MySQL..." <<endl;
-
- /**
- * nwe param:
- * port
- * host
- * user
- */
- bool returnValue = true;
- mysql_init(&mysql);
- {
- int portNo = 3306;
- if ( mysql_real_connect(&mysql,
- ga_host,
- ga_user,
- ga_password,
- ga_database,
- ga_port,
- ga_socket,
- 0) == NULL )
- {
- ndbout_c("Connect failed: %s", mysql_error(&mysql));
- returnValue = false;
- }
- ndbout << "Connected to MySQL!!!" <<endl;
- }
-
- /* if(returnValue){
- mysql_set_server_option(&mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON);
- }
- */
- return returnValue;
- }
-#endif
- return true;
-
-}
-
-BackupRestore::~BackupRestore()
-{
- if (m_ndb != 0)
- delete m_ndb;
-}
-#ifdef USE_MYSQL
-bool
-BackupRestore::table(const TableS & table, MYSQL * mysqlp){
- if (!m_restore_meta)
- {
- return true;
- }
-
- char tmpTabName[MAX_TAB_NAME_SIZE*2];
- sprintf(tmpTabName, "%s", table.getTableName());
- char * database = strtok(tmpTabName, "/");
- char * schema = strtok( NULL , "/");
- char * tableName = strtok( NULL , "/");
-
- /**
- * this means that the user did not specify schema
- * and it is a v2x backup
- */
- if(database == NULL)
- return false;
- if(schema == NULL)
- return false;
- if(tableName==NULL)
- tableName = schema;
-
- char stmtCreateDB[255];
- sprintf(stmtCreateDB,"CREATE DATABASE %s", database);
-
- /*ignore return value. mysql_select_db will trap errors anyways*/
- if (mysql_query(mysqlp,stmtCreateDB) == 0)
- {
- //ndbout_c("%s", stmtCreateDB);
- }
-
- if (mysql_select_db(&mysql, database) != 0)
- {
- ndbout_c("Error: %s", mysql_error(&mysql));
- return false;
- }
-
- char buf [2048];
- /**
- * create table ddl
- */
- if (create_table_string(table, tableName, buf))
- {
- ndbout_c("Unable to create a table definition since the "
- "backup contains undefined types");
- return false;
- }
-
- //ndbout_c("%s", buf);
-
- if (mysql_query(mysqlp,buf) != 0)
- {
- ndbout_c("Error: %s", mysql_error(&mysql));
- return false;
- } else
- {
- ndbout_c("Successfully restored table %s into database %s", tableName, database);
- }
-
- return true;
-}
-#endif
-
-int
-BackupConsumer::create_table_string(const TableS & table,
- char * tableName,
- char *buf){
- int pos = 0;
- int pos2 = 0;
- char buf2[2048];
-
- pos += sprintf(buf+pos, "%s%s", "CREATE TABLE ", tableName);
- pos += sprintf(buf+pos, "%s", "(");
- pos2 += sprintf(buf2+pos2, "%s", " primary key(");
-
- for (int j = 0; j < table.getNoOfAttributes(); j++)
- {
- const AttributeDesc * desc = table[j];
- // ndbout << desc->name << ": ";
- pos += sprintf(buf+pos, "%s%s", desc->name," ");
- NdbDictionary::Column::Type type = table.m_dictTable->getColumn(desc->attrId)->getType();
- switch(type){
- case NdbDictionary::Column::Int:
- pos += sprintf(buf+pos, "%s", "int");
- break;
- case NdbDictionary::Column::Unsigned:
- pos += sprintf(buf+pos, "%s", "int unsigned");
- break;
- case NdbDictionary::Column::Float:
- pos += sprintf(buf+pos, "%s", "float");
- break;
- case NdbDictionary::Column::Decimal:
- pos += sprintf(buf+pos, "%s", "decimal");
- break;
- case NdbDictionary::Column::Char:
- pos += sprintf(buf+pos, "%s", "char");
- break;
- case NdbDictionary::Column::Varchar:
- pos += sprintf(buf+pos, "%s", "varchar");
- break;
- case NdbDictionary::Column::Binary:
- pos += sprintf(buf+pos, "%s", "binary");
- break;
- case NdbDictionary::Column::Varbinary:
- pos += sprintf(buf+pos, "%s", "varchar binary");
- break;
- case NdbDictionary::Column::Bigint:
- pos += sprintf(buf+pos, "%s", "bigint");
- break;
- case NdbDictionary::Column::Bigunsigned:
- pos += sprintf(buf+pos, "%s", "bigint unsigned");
- break;
- case NdbDictionary::Column::Double:
- pos += sprintf(buf+pos, "%s", "double");
- break;
- case NdbDictionary::Column::Datetime:
- pos += sprintf(buf+pos, "%s", "datetime");
- break;
- case NdbDictionary::Column::Timespec:
- pos += sprintf(buf+pos, "%s", "time");
- break;
- case NdbDictionary::Column::Undefined:
- // pos += sprintf(buf+pos, "%s", "varchar binary");
- return -1;
- break;
- default:
- //pos += sprintf(buf+pos, "%s", "varchar binary");
- return -1;
- }
- if (desc->arraySize > 1) {
- int attrSize = desc->arraySize;
- pos += sprintf(buf+pos, "%s%u%s",
- "(",
- attrSize,
- ")");
- }
- if (table.m_dictTable->getColumn(desc->attrId)->getPrimaryKey()) {
- pos += sprintf(buf+pos, "%s", " not null");
- pos2 += sprintf(buf2+pos2, "%s%s", desc->name, ",");
- }
- pos += sprintf(buf+pos, "%s", ",");
- } // for
- pos2--; // remove trailing comma
- pos2 += sprintf(buf2+pos2, "%s", ")");
- // pos--; // remove trailing comma
-
- pos += sprintf(buf+pos, "%s", buf2);
- pos += sprintf(buf+pos, "%s", ") type=ndbcluster");
- return 0;
-}
-
-
-
-bool
-BackupRestore::table(const TableS & table){
- if (!m_restore_meta)
- {
- return true;
- }
-#ifndef restore_old_types
- NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
- if (dict->createTable(*table.m_dictTable) == -1)
- {
- err << "Create table " << table.getTableName() << " failed: "
- << dict->getNdbError() << endl;
- return false;
- }
- info << "Successfully restored table " << table.getTableName()<< endl ;
- return true;
-#else
- NdbSchemaCon * tableTransaction = 0;
- NdbSchemaOp * tableOp = 0;
-
- tableTransaction = m_ndb->startSchemaTransaction();
- if (tableTransaction == NULL)
- {
- err << table.getTableName()
- << " - BackupRestore::table cannot startSchemaTransaction: "
- << tableTransaction->getNdbError() << endl;
- return false;
- } // if
-
- tableOp = tableTransaction->getNdbSchemaOp();
- if (tableOp == NULL)
- {
- err << table.getTableName()
- << " - BackupRestore::table cannot getNdbSchemaOp: "
- << tableTransaction->getNdbError() << endl;
- m_ndb->closeSchemaTransaction(tableTransaction);
- return false;
- } // if
-
- // TODO: check for errors in table attributes. set aTupleKey
- int check = 0;
- check = tableOp->createTable(table.getTableName());
- // aTableSize = 8, Not used?
- // aTupleKey = TupleKey, go through attributes and check if there is a PK
- // and so on....
- if (check == -1)
- {
- err << table.getTableName()
- << " - BackupRestore::table cannot createTable: "
- << tableTransaction->getNdbError() << endl;
- m_ndb->closeSchemaTransaction(tableTransaction);
- return false;
- } // if
-
- // Create attributes from meta data
- for (int i = 0; i < table.getNoOfAttributes(); i++)
- {
- const AttributeDesc* desc = table[i];
- check = tableOp->createAttribute(desc->name, // Attr name
- desc->key, // Key type
- desc->size, // bits
- desc->arraySize,
- desc->type,
- MMBased, // only supported
- desc->nullable
- // Rest is don't care for the moment
- );
-
- if (check == -1)
- {
- err << table.getTableName()
- << " - RestoreDataIterator::createTable cannot createAttribute: "
- << tableTransaction->getNdbError() << endl;
- m_ndb->closeSchemaTransaction(tableTransaction);
- return false;
- } // if
- } // for
-
- if (tableTransaction->execute() == -1)
- {
- err << table.getTableName()
- << " - RestoreDataIterator::createTable cannot execute transaction: "
- << tableTransaction->getNdbError() << endl;
- m_ndb->closeSchemaTransaction(tableTransaction);
- return false;
- } // if
-
- m_ndb->closeSchemaTransaction(tableTransaction);
- info << "Successfully created table " << table.getTableName() << endl;
- return true ;
-#endif
-}
-
-
-
-/*
- * callback : This is called when the transaction is polled
- *
- * (This function must have three arguments:
- * - The result of the transaction,
- * - The NdbConnection object, and
- * - A pointer to an arbitrary object.)
- */
-
-static void
-callback(int result, NdbConnection* trans, void* aObject)
-{
- restore_callback_t * cbData = (restore_callback_t *)aObject;
- if (result<0)
- {
- /**
- * Error. temporary or permanent?
- */
- if (asynchErrorHandler(trans, (Ndb*)cbData->ndb))
- {
- ((Ndb*)cbData->ndb)->closeTransaction(asynchTrans[cbData->transaction]);
- cbData->retries++;
- ((BackupRestore*)cbData)->tupleAsynch( * (TupleS*)(cbData->tup), cbData);
- }
- else
- {
- ndbout_c("Restore: Failed to restore data "
- "due to a unrecoverable error. Exiting...");
- delete (Ndb*)cbData->ndb;
- delete cbData->tup;
- delete cbData;
- exit(-1);
- }
- }
- else
- {
- /**
- * OK! close transaction
- */
- ((Ndb*)cbData->ndb)->closeTransaction(asynchTrans[cbData->transaction]);
- delete cbData->tup;
- delete cbData;
- }
-}
-
-static int nPreparedTransactions = 0;
-void
-BackupPrinter::tupleAsynch(const TupleS & tup, restore_callback_t * callback)
-{
- m_dataCount++;
- if (m_print || m_print_data)
- m_ndbout << tup << endl;
-}
-
-void BackupRestore::tupleAsynch(const TupleS & tup, restore_callback_t * cbData)
-{
-
- if (!m_restore)
- {
- delete &tup;
- return;
- }
- Uint32 retries;
- if (cbData!=0)
- retries = cbData->retries;
- else
- retries = 0;
-
- while (retries < 10)
- {
- /**
- * start transactions
- */
- asynchTrans[nPreparedTransactions] = m_ndb->startTransaction();
- if (asynchTrans[nPreparedTransactions] == NULL)
- {
- if (asynchErrorHandler(asynchTrans[nPreparedTransactions], m_ndb))
- {
- retries++;
- continue;
- }
- asynchExitHandler();
- } // if
-
- const TableS * table = tup.getTable();
- NdbOperation * op =
- asynchTrans[nPreparedTransactions]->getNdbOperation(table->getTableName());
-
- if (op == NULL)
- {
- if (asynchErrorHandler(asynchTrans[nPreparedTransactions], m_ndb))
- {
- retries++;
- continue;
- }
- asynchExitHandler();
- } // if
-
- if (op->writeTuple() == -1)
- {
- if (asynchErrorHandler(asynchTrans[nPreparedTransactions], m_ndb))
- {
- retries++;
- continue;
- }
- asynchExitHandler();
- } // if
-
- Uint32 ret = 0;
- for (int i = 0; i < tup.getNoOfAttributes(); i++)
- {
- const AttributeS * attr = tup[i];
- int size = attr->Desc->size;
- int arraySize = attr->Desc->arraySize;
- const KeyType key = attr->Desc->key;
- char * dataPtr = attr->Data.string_value;
- Uint32 length = (size * arraySize) / 8;
- if (key == TupleKey)
- {
-#if NDB_VERSION_MAJOR >= VERSION3X
- /**
- * Convert VARCHAR from v.2x to v3x representation
- */
- if (getMajor(tup.getTable()->getBackupVersion()) < VERSION_3X &&
- ((tup.getTable()->m_dictTable->getColumn(i)->getType() ==
- NdbDictionary::Column::Varbinary ) ||
- (tup.getTable()->m_dictTable->getColumn(i)->getType() ==
- NdbDictionary::Column::Varchar)) && !attr->Data.null)
- {
- char * src = dataPtr;
- char var_len[2];
- var_len[0]= *(dataPtr+length - 2);
- var_len[1]= *(dataPtr+length - 1);
- memmove((char*)dataPtr+2, dataPtr, length);
- src[0] = var_len[0];
- src[1] = var_len[1];
- dataPtr = src;
- }
-#endif
- ret = op->equal(i, dataPtr, length);
- if (ret<0)
- {
- ndbout_c("Column: %d type %d",i,
- tup.getTable()->m_dictTable->getColumn(i)->getType());
-
- if (asynchErrorHandler(asynchTrans[nPreparedTransactions],m_ndb))
- {
- retries++;
- continue;
- }
- asynchExitHandler();
- }
- }
- }
-
- for (int i = 0; i < tup.getNoOfAttributes(); i++)
- {
- const AttributeS * attr = tup[i];
- int size = attr->Desc->size;
- int arraySize = attr->Desc->arraySize;
- KeyType key = attr->Desc->key;
- char * dataPtr = attr->Data.string_value;
- Uint32 length = (size * arraySize) / 8;
-#if NDB_VERSION_MAJOR >= VERSION3X
- /**
- * Convert VARCHAR from v.2x to v3x representation
- */
- if (getMajor(tup.getTable()->getBackupVersion()) < VERSION_3X &&
- ((tup.getTable()->m_dictTable->getColumn(i)->getType() ==
- NdbDictionary::Column::Varbinary ) ||
- (tup.getTable()->m_dictTable->getColumn(i)->getType() ==
- NdbDictionary::Column::Varchar)) && !attr->Data.null)
- {
- char * src = dataPtr;
- char var_len[2];
- var_len[0]= *(dataPtr+length - 2);//length is last 2 bytes
- var_len[1]= *(dataPtr+length - 1);
- memmove((char*)dataPtr+2, dataPtr, length);
- src[0] = var_len[0];
- src[1] = var_len[1];
- dataPtr = src;
- }
-#endif
-
- if (key == NoKey && !attr->Data.null)
- {
- ret = op->setValue(i, dataPtr, length);
- }
- else if (key == NoKey && attr->Data.null)
- {
- ret = op->setValue(i, NULL, 0);
- }
-
- if (ret<0)
- {
- ndbout_c("Column: %d type %d",i,
- tup.getTable()->m_dictTable->getColumn(i)->getType());
-
- if (asynchErrorHandler(asynchTrans[nPreparedTransactions], m_ndb))
- {
- retries++;
- continue;
- }
-
-
- asynchExitHandler();
- }
- }
- restore_callback_t * cb;
- if (cbData ==0)
- {
- cb = new restore_callback_t;
- cb->retries = 0;
- }
- else
- cb =cbData;
- cb->ndb = m_ndb;
- cb->restore = this;
- cb->tup = (TupleS*)&tup;
- cb->transaction = nPreparedTransactions;
-
- // Prepare transaction (the transaction is NOT yet sent to NDB)
- asynchTrans[nPreparedTransactions]->executeAsynchPrepare(Commit,
- &callback,
- cb);
- if (nPreparedTransactions == ga_nParallelism-1)
- {
- // send-poll all transactions
- // close transaction is done in callback
- m_ndb->sendPollNdb(3000, ga_nParallelism);
- nPreparedTransactions=0;
- }
- else
- nPreparedTransactions++;
- m_dataCount++;
- return;
- }
- ndbout_c("Unable to recover from errors. Exiting...");
- asynchExitHandler();
-}
-
-void BackupRestore::asynchExitHandler()
-{
- if (m_ndb != NULL)
- delete m_ndb;
- exit(-1);
-}
-/**
- * returns true if is recoverable,
- * Error handling based on hugo
- * false if it is an error that generates an abort.
- */
-static
-bool asynchErrorHandler(NdbConnection * trans, Ndb* ndb)
-{
-
- NdbError error = trans->getNdbError();
- ndb->closeTransaction(trans);
- switch(error.status)
- {
- case NdbError::Success:
- return false;
- // ERROR!
- break;
-
- case NdbError::TemporaryError:
- NdbSleep_MilliSleep(10);
- return true;
- // RETRY
- break;
-
- case NdbError::UnknownResult:
- ndbout << error << endl;
- return false;
- // ERROR!
- break;
-
- default:
- case NdbError::PermanentError:
- switch (error.code)
- {
- case 499:
- case 250:
- NdbSleep_MilliSleep(10);
- return true; //temp errors?
- default:
- break;
- }
- //ERROR
- ndbout << error << endl;
- return false;
- break;
- }
- return false;
-}
-
-
-
-void
-BackupRestore::tuple(const TupleS & tup)
-{
- if (!m_restore)
- return;
- while (1)
- {
- NdbConnection * trans = m_ndb->startTransaction();
- if (trans == NULL)
- {
- // Deep shit, TODO: handle the error
- ndbout << "Cannot start transaction" << endl;
- exit(-1);
- } // if
-
- const TableS * table = tup.getTable();
- NdbOperation * op = trans->getNdbOperation(table->getTableName());
- if (op == NULL)
- {
- ndbout << "Cannot get operation: ";
- ndbout << trans->getNdbError() << endl;
- exit(-1);
- } // if
-
- // TODO: check return value and handle error
- if (op->writeTuple() == -1)
- {
- ndbout << "writeTuple call failed: ";
- ndbout << trans->getNdbError() << endl;
- exit(-1);
- } // if
-
- for (int i = 0; i < tup.getNoOfAttributes(); i++)
- {
- const AttributeS * attr = tup[i];
- int size = attr->Desc->size;
- int arraySize = attr->Desc->arraySize;
- KeyType key = attr->Desc->key;
- const char * dataPtr = attr->Data.string_value;
-
- const Uint32 length = (size * arraySize) / 8;
- if (key == TupleKey)
- {
- op->equal(i, dataPtr, length);
- }
- }
-
- for (int i = 0; i < tup.getNoOfAttributes(); i++)
- {
- const AttributeS * attr = tup[i];
- int size = attr->Desc->size;
- int arraySize = attr->Desc->arraySize;
- KeyType key = attr->Desc->key;
- const char * dataPtr = attr->Data.string_value;
-
- const Uint32 length = (size * arraySize) / 8;
- if (key == NoKey && !attr->Data.null)
- {
- op->setValue(i, dataPtr, length);
- }
- else if (key == NoKey && attr->Data.null)
- {
- op->setValue(i, NULL, 0);
- }
- }
- int ret = trans->execute(Commit);
- if (ret != 0)
- {
- ndbout << "execute failed: ";
- ndbout << trans->getNdbError() << endl;
- exit(-1);
- }
- m_ndb->closeTransaction(trans);
- if (ret == 0)
- break;
- }
- m_dataCount++;
-}
-
-void
-BackupRestore::endOfTuples()
-{
- if (!m_restore)
- return;
- // Send all transactions to NDB
- m_ndb->sendPreparedTransactions(0);
- // Poll all transactions
- m_ndb->pollNdb(3000, nPreparedTransactions);
- // Close all transactions
- // for (int i = 0; i < nPreparedTransactions; i++)
- // m_ndb->closeTransaction(asynchTrans[i]);
- nPreparedTransactions=0;
-}
-
-void
-BackupRestore::logEntry(const LogEntry & tup)
-{
- if (!m_restore)
- return;
-
- NdbConnection * trans = m_ndb->startTransaction();
- if (trans == NULL)
- {
- // Deep shit, TODO: handle the error
- ndbout << "Cannot start transaction" << endl;
- exit(-1);
- } // if
-
- const TableS * table = tup.m_table;
- NdbOperation * op = trans->getNdbOperation(table->getTableName());
- if (op == NULL)
- {
- ndbout << "Cannot get operation: ";
- ndbout << trans->getNdbError() << endl;
- exit(-1);
- } // if
-
- int check = 0;
- switch(tup.m_type)
- {
- case LogEntry::LE_INSERT:
- check = op->insertTuple();
- break;
- case LogEntry::LE_UPDATE:
- check = op->updateTuple();
- break;
- case LogEntry::LE_DELETE:
- check = op->deleteTuple();
- break;
- default:
- ndbout << "Log entry has wrong operation type."
- << " Exiting...";
- exit(-1);
- }
-
- for (int i = 0; i < tup.m_values.size(); i++)
- {
- const AttributeS * attr = tup.m_values[i];
- int size = attr->Desc->size;
- int arraySize = attr->Desc->arraySize;
- KeyType key = attr->Desc->key;
- const char * dataPtr = attr->Data.string_value;
-
- const Uint32 length = (size / 8) * arraySize;
- if (key == TupleKey)
- {
- op->equal(attr->Desc->attrId, dataPtr, length);
- }
- else if (key == NoKey)
- {
- op->setValue(attr->Desc->attrId, dataPtr, length);
- }
- }
-
-#if 1
- trans->execute(Commit);
-#else
- const int ret = trans->execute(Commit);
- // Both insert update and delete can fail during log running
- // and it's ok
-
- if (ret != 0)
- {
- ndbout << "execute failed: ";
- ndbout << trans->getNdbError() << endl;
- exit(-1);
- }
-#endif
-
- m_ndb->closeTransaction(trans);
- m_logCount++;
-}
-
-void
-BackupRestore::endOfLogEntrys()
-{
- if (ga_restore)
- {
- ndbout << "Restored " << m_dataCount << " tuples and "
- << m_logCount << " log entries" << endl;
- }
-}
-
-void
-BackupPrinter::endOfLogEntrys()
-{
- if (m_print || m_print_log)
- {
- ndbout << "Printed " << m_dataCount << " tuples and "
- << m_logCount << " log entries"
- << " to stdout." << endl;
- }
-}
-
-
-
-
diff --git a/ndb/src/kernel/blocks/backup/restore/myVector.hpp b/ndb/src/kernel/blocks/backup/restore/myVector.hpp
deleted file mode 100644
index c858999d2be..00000000000
--- a/ndb/src/kernel/blocks/backup/restore/myVector.hpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef MY_VECTOR_HPP
-#define MY_VECTOR_HPP
-
-// Template class for std::vector-like class (hopefully works in OSE)
-template <class T>
-class myVector
-{
-
- // Note that last element in array is used for end() and is always empty
- int sizeIncrement;
- int thisSize;
- int used;
- T *storage;
-
-public:
-
- // Assignment of whole vector
- myVector<T> & operator=(myVector<T> & org) {
-
- // Don't copy if they point to the same address
- if (!(this == &org)) {
- // Check memory space
- if (thisSize < org.thisSize) {
- // We have to increase memory for destination
- T* tmpStorage = new T[org.thisSize];
- delete[] storage;
- storage = tmpStorage;
- } // if
- thisSize = org.thisSize;
- sizeIncrement = org.sizeIncrement;
- used = org.used;
- for (int i = 0; i < thisSize; i++) {
- storage[i] = org.storage[i];
- } // for
- } // if
- return *this;
- } // operator=
-
- // Construct with size s+1
- myVector(int s = 1) : sizeIncrement(5), // sizeIncrement(s),
- thisSize(s + 1),
- used(0),
- storage(new T[s + 1]) { }
-
- ~myVector() { delete[] storage; } // Destructor: deallocate memory
-
- T& operator[](int i) { // Return by index
- if ((i < 0) || (i >= used)) {
- // Index error
- ndbout << "vector index out of range" << endl;
- abort();
- return storage[used - 1];
- } // if
- else {
- return storage[i];
- } // else
- } // operator[]
-
- const T& operator[](int i) const { // Return by index
- if ((i < 0) || (i >= used)) {
- // Index error
- ndbout << "vector index out of range" << endl;
- abort();
- return storage[used - 1];
- } // if
- else {
- return storage[i];
- } // else
- } // operator[]
-
- int getSize() const { return used; }
-
- void push_back (T& item) {
- if (used >= thisSize - 1) {
- // We have to allocate new storage
- int newSize = thisSize + sizeIncrement;
- T* tmpStorage = new T[newSize];
- if (tmpStorage == NULL) {
- // Memory allocation error! break
- ndbout << "PANIC: Memory allocation error in vector" << endl;
- return;
- } // if
- thisSize = newSize;
- for (int i = 0; i < used; i++) {
- tmpStorage[i] = storage[i];
- } // for
- delete[] storage;
- storage = tmpStorage;
- } // if
-
- // Now push
- storage[used] = item;
- used++;
- }; // myVector<> push_back()
-
- // Remove item at back
- void pop_back() {
- if (used > 0) {
- used--;
- } // if
- } // pop_back()
-
- int size() const { return used; };
-
- bool empty() const { return(used == 0); }
-
- void clear() {
- used = 0;
- }
-};
-
-#endif
diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
index cd6198eff23..694007c8508 100644
--- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
+++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
@@ -16,7 +16,6 @@
#include "Cmvmi.hpp"
-#include <ClusterConfiguration.hpp>
#include <Configuration.hpp>
#include <kernel_types.h>
#include <TransporterRegistry.hpp>
@@ -31,15 +30,11 @@
#include <signaldata/TestOrd.hpp>
#include <signaldata/EventReport.hpp>
#include <signaldata/TamperOrd.hpp>
-#include <signaldata/SetVarReq.hpp>
#include <signaldata/StartOrd.hpp>
-#include <signaldata/CmvmiCfgConf.hpp>
-#include <signaldata/CmInit.hpp>
#include <signaldata/CloseComReqConf.hpp>
#include <signaldata/SetLogLevelOrd.hpp>
#include <signaldata/EventSubscribeReq.hpp>
#include <signaldata/DumpStateOrd.hpp>
-#include <signaldata/ArbitSignalData.hpp>
#include <signaldata/DisconnectRep.hpp>
#include <EventLogger.hpp>
@@ -55,8 +50,7 @@ EventLogger g_eventLogger;
Cmvmi::Cmvmi(const Configuration & conf) :
SimulatedBlock(CMVMI, conf)
,theConfig((Configuration&)conf)
- ,theCConfig(conf.clusterConfiguration()),
- subscribers(subscriberPool)
+ ,subscribers(subscriberPool)
{
BLOCK_CONSTRUCTOR(Cmvmi);
@@ -67,14 +61,10 @@ Cmvmi::Cmvmi(const Configuration & conf) :
addRecSignal(GSN_NDB_TAMPER, &Cmvmi::execNDB_TAMPER, true);
addRecSignal(GSN_SET_LOGLEVELORD, &Cmvmi::execSET_LOGLEVELORD);
addRecSignal(GSN_EVENT_REP, &Cmvmi::execEVENT_REP);
- addRecSignal(GSN_STTOR, &Cmvmi::execSTTOR_Local);
- addRecSignal(GSN_CM_RUN, &Cmvmi::execCM_RUN);
- addRecSignal(GSN_CM_INFOREQ, &Cmvmi::execCM_INFOREQ);
- addRecSignal(GSN_CMVMI_CFGREQ, &Cmvmi::execCMVMI_CFGREQ);
+ addRecSignal(GSN_STTOR, &Cmvmi::execSTTOR);
addRecSignal(GSN_CLOSE_COMREQ, &Cmvmi::execCLOSE_COMREQ);
addRecSignal(GSN_ENABLE_COMORD, &Cmvmi::execENABLE_COMORD);
addRecSignal(GSN_OPEN_COMREQ, &Cmvmi::execOPEN_COMREQ);
- addRecSignal(GSN_SIZEALT_ACK, &Cmvmi::execSIZEALT_ACK);
addRecSignal(GSN_TEST_ORD, &Cmvmi::execTEST_ORD);
addRecSignal(GSN_STATISTICS_REQ, &Cmvmi::execSTATISTICS_REQ);
@@ -93,16 +83,28 @@ Cmvmi::Cmvmi(const Configuration & conf) :
subscriberPool.setSize(5);
- const ClusterConfiguration::ClusterData & clData =
- theConfig.clusterConfigurationData() ;
+ const ndb_mgm_configuration_iterator * db = theConfig.getOwnConfigIterator();
+ for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
+ Uint32 logLevel;
+ if(!ndb_mgm_get_int_parameter(db, LogLevel::MIN_LOGLEVEL_ID+j, &logLevel)){
+ clogLevel.setLogLevel((LogLevel::EventCategory)j,
+ logLevel);
+ }
+ }
- clogLevel = clData.SizeAltData.logLevel;
-
- for(Uint32 i= 0; i< clData.SizeAltData.noOfNodes; i++ ){
+ ndb_mgm_configuration_iterator * iter = theConfig.getClusterConfigIterator();
+ for(ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)){
jam();
- const Uint32 nodeId = clData.nodeData[i].nodeId;
- switch(clData.nodeData[i].nodeType){
+ Uint32 nodeId;
+ Uint32 nodeType;
+
+ ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_NODE_ID, &nodeId));
+ ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_TYPE_OF_SECTION,&nodeType));
+
+ switch(nodeType){
case NodeInfo::DB:
+ c_dbNodes.set(nodeId);
+ break;
case NodeInfo::API:
case NodeInfo::MGM:
case NodeInfo::REP:
@@ -110,7 +112,7 @@ Cmvmi::Cmvmi(const Configuration & conf) :
default:
ndbrequire(false);
}
- setNodeInfo(nodeId).m_type = clData.nodeData[i].nodeType;
+ setNodeInfo(nodeId).m_type = nodeType;
}
}
@@ -130,6 +132,10 @@ void Cmvmi::execNDB_TAMPER(Signal* signal)
if(ERROR_INSERTED(9998)){
while(true) NdbSleep_SecSleep(1);
}
+
+ if(ERROR_INSERTED(9997)){
+ ndbrequire(false);
+ }
}//execNDB_TAMPER()
void Cmvmi::execSET_LOGLEVELORD(Signal* signal)
@@ -278,121 +284,42 @@ Cmvmi::cancelSubscription(NodeId nodeId){
void Cmvmi::sendSTTORRY(Signal* signal)
{
- if( theStartPhase == 1 ) {
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData() ;
- const int myNodeId = globalData.ownId;
- int MyNodeFound = 0;
-
- jam();
-
- CmInit * const cmInit = (CmInit *)&signal->theData[0];
-
- cmInit->heartbeatDbDb = clusterConf.ispValues[0][2];
- cmInit->heartbeatDbApi = clusterConf.ispValues[0][3];
- cmInit->arbitTimeout = clusterConf.ispValues[0][5];
-
- NodeBitmask::clear(cmInit->allNdbNodes);
- for(unsigned int i = 0; i < clusterConf.SizeAltData.noOfNodes; i++ ) {
- jam();
- if (clusterConf.nodeData[i].nodeType == NodeInfo::DB){
- jam();
- const NodeId nodeId = clusterConf.nodeData[i].nodeId;
- if (nodeId == myNodeId) {
- jam();
- MyNodeFound = 1;
- }//if
- NodeBitmask::set(cmInit->allNdbNodes, nodeId);
- }//if
- }//for
-
- if (MyNodeFound == 0) {
- ERROR_SET(fatal, ERR_NODE_NOT_IN_CONFIG, "", "");
- }//if
-
- sendSignal(QMGR_REF, GSN_CM_INIT, signal, CmInit::SignalLength, JBB);
-
- // these do not fit into CM_INIT
- ArbitSignalData* const sd = (ArbitSignalData*)&signal->theData[0];
- for (unsigned rank = 1; rank <= 2; rank++) {
- sd->sender = myNodeId;
- sd->code = rank;
- sd->node = 0;
- sd->ticket.clear();
- sd->mask.clear();
- for (int i = 0; i < MAX_NODES; i++) {
- if (clusterConf.nodeData[i].arbitRank == rank)
- sd->mask.set(clusterConf.nodeData[i].nodeId);
- }
- sendSignal(QMGR_REF, GSN_ARBIT_CFG, signal,
- ArbitSignalData::SignalLength, JBB);
- }
- } else {
- jam();
- signal->theData[0] = theSignalKey;
- signal->theData[3] = 1;
- signal->theData[4] = 3;
- signal->theData[5] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal,6, JBB);
- }
+ jam();
+ signal->theData[3] = 1;
+ signal->theData[4] = 3;
+ signal->theData[5] = 8;
+ signal->theData[6] = 255;
+ sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
}//Cmvmi::sendSTTORRY
-// Received a restart signal.
-// Answer it like any other block
-// PR0 : StartCase
-// DR0 : StartPhase
-// DR1 : ?
-// DR2 : ?
-// DR3 : ?
-// DR4 : ?
-// DR5 : SignalKey
-
-void Cmvmi::execSTTOR_Local(Signal* signal)
+void Cmvmi::execSTTOR(Signal* signal)
{
- theStartPhase = signal->theData[1];
- theSignalKey = signal->theData[6];
+ Uint32 theStartPhase = signal->theData[1];
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData();
jamEntry();
- if (theStartPhase == 1 && clusterConf.SizeAltData.exist == true){
+ if (theStartPhase == 1){
jam();
- signalCount = 0;
- execSIZEALT_ACK(signal);
+ sendSTTORRY(signal);
return;
} else if (theStartPhase == 3) {
jam();
globalData.activateSendPacked = 1;
sendSTTORRY(signal);
- } else {
- jam();
+ } else if (theStartPhase == 8){
+ /*---------------------------------------------------*/
+ /* Open com to API + REP nodes */
+ /*---------------------------------------------------*/
+ signal->theData[0] = 0; // no answer
+ signal->theData[1] = 0; // no id
+ signal->theData[2] = NodeInfo::API;
+ execOPEN_COMREQ(signal);
+ signal->theData[0] = 0; // no answer
+ signal->theData[1] = 0; // no id
+ signal->theData[2] = NodeInfo::REP;
+ execOPEN_COMREQ(signal);
+ globalData.theStartLevel = NodeState::SL_STARTED;
sendSTTORRY(signal);
- }
-}
-
-void Cmvmi::execSIZEALT_ACK(Signal* signal)
-{
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData();
- jamEntry();
-
- if (signalCount < NDB_SIZEALT_OFF){
- jam();
- BlockNumber blockNo = clusterConf.SizeAltData.blockNo[signalCount];
- signal->theData[0] = CMVMI_REF;
-
- /**
- * This send SizeAlt(s) to blocks
- * Definition of data content can be found in SignalData/XXXSizeAltReq.H
- */
- const unsigned int noOfWords = 20;
- for(unsigned int i = 1; i<noOfWords; i++){
- signal->theData[i] = clusterConf.SizeAltData.varSize[signalCount][i].nrr;
- }
-
- signalCount++;
- sendSignal(numberToRef(blockNo, 0), GSN_SIZEALT_REP, signal,21, JBB);
} else {
jam();
@@ -408,90 +335,6 @@ void Cmvmi::execSIZEALT_ACK(Signal* signal)
}
}
-void Cmvmi::execCM_INFOREQ(Signal* signal)
-{
- int id = signal->theData[1];
- const BlockReference userRef = signal->theData[0];
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData();
- const int myNodeId = globalData.ownId;
-
- jamEntry();
- signal->theData[0] = id;
-
- for(unsigned int i= 0; i< clusterConf.SizeAltData.noOfNodes; i++ ) {
- jam();
- if (clusterConf.nodeData[i].nodeType == NodeInfo::DB){
- NodeId nodeId = clusterConf.nodeData[i].nodeId;
- if (nodeId != myNodeId) {
- jam();
- globalTransporterRegistry.setPerformState(nodeId, PerformConnect);
- }
- }
- }
-
- sendSignal(userRef, GSN_CM_INFOCONF, signal, 1, JBB);
-}
-
-void Cmvmi::execCM_RUN(Signal* signal)
-{
- jamEntry();
- if (signal->theData[0] == 0) {
- jam();
- signal->theData[0] = theSignalKey;
- signal->theData[3] = 1;
- signal->theData[4] = 3;
- signal->theData[5] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
- } else {
- globalData.theStartLevel = NodeState::SL_STARTED;
-
- // Connect to all application nodes.
- // Enable communication with all NDB blocks.
-
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData();
- jam();
- for(unsigned int i= 0; i< clusterConf.SizeAltData.noOfNodes; i++ ) {
- NodeId nodeId = clusterConf.nodeData[i].nodeId;
- jam();
- if (clusterConf.nodeData[i].nodeType != NodeInfo::DB &&
- clusterConf.nodeData[i].nodeType != NodeInfo::MGM){
-
- jam();
- globalTransporterRegistry.setPerformState(nodeId, PerformConnect);
- globalTransporterRegistry.setIOState(nodeId, HaltIO);
- //-----------------------------------------------------
- // Report that the connection to the node is opened
- //-----------------------------------------------------
- signal->theData[0] = EventReport::CommunicationOpened;
- signal->theData[1] = clusterConf.nodeData[i].nodeId;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
- //-----------------------------------------------------
- }
- }
- }
-}
-
-void Cmvmi::execCMVMI_CFGREQ(Signal* signal)
-{
- const BlockReference userRef = signal->theData[0];
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData();
-
- int theStart_phase = signal->theData[1];
-
- jamEntry();
-
- CmvmiCfgConf * const cfgConf = (CmvmiCfgConf *)&signal->theData[0];
-
- cfgConf->startPhase = theStart_phase;
- for(unsigned int i = 0; i<CmvmiCfgConf::NO_OF_WORDS; i++)
- cfgConf->theData[i] = clusterConf.ispValues[theStart_phase][i];
-
- sendSignal(userRef, GSN_CMVMI_CFGCONF, signal, CmvmiCfgConf::LENGTH,JBB );
-}
-
void Cmvmi::execCLOSE_COMREQ(Signal* signal)
{
// Close communication with the node and halt input/output from
@@ -540,21 +383,42 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal)
const BlockReference userRef = signal->theData[0];
Uint32 tStartingNode = signal->theData[1];
-
+ Uint32 tData2 = signal->theData[2];
jamEntry();
+
+ const Uint32 len = signal->getLength();
+ if(len == 2){
+ globalTransporterRegistry.setPerformState(tStartingNode, PerformConnect);
+ globalTransporterRegistry.setIOState(tStartingNode, HaltIO);
+
+ //-----------------------------------------------------
+ // Report that the connection to the node is opened
+ //-----------------------------------------------------
+ signal->theData[0] = EventReport::CommunicationOpened;
+ signal->theData[1] = tStartingNode;
+ sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
+ //-----------------------------------------------------
+ } else {
+ for(unsigned int i = 1; i < MAX_NODES; i++ ) {
+ jam();
+ if (i != getOwnNodeId() && getNodeInfo(i).m_type == tData2){
+ jam();
+ globalTransporterRegistry.setPerformState(i, PerformConnect);
+ globalTransporterRegistry.setIOState(i, HaltIO);
+
+ signal->theData[0] = EventReport::CommunicationOpened;
+ signal->theData[1] = i;
+ sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
+ }
+ }
+ }
+
if (userRef != 0) {
jam();
- signal->theData[0] = signal->theData[1];
- sendSignal(userRef, GSN_OPEN_COMCONF, signal, 2,JBA);
+ signal->theData[0] = tStartingNode;
+ signal->theData[1] = tData2;
+ sendSignal(userRef, GSN_OPEN_COMCONF, signal, len - 1,JBA);
}
- globalTransporterRegistry.setPerformState(tStartingNode, PerformConnect);
- //-----------------------------------------------------
- // Report that the connection to the node is opened
- //-----------------------------------------------------
- signal->theData[0] = EventReport::CommunicationOpened;
- signal->theData[1] = tStartingNode;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
- //-----------------------------------------------------
}
void Cmvmi::execENABLE_COMORD(Signal* signal)
@@ -888,18 +752,11 @@ Cmvmi::execSTART_ORD(Signal* signal) {
/**
* Open connections to management servers
*/
-
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData() ;
-
- for(unsigned int i= 0; i < clusterConf.SizeAltData.noOfNodes; i++ ){
- NodeId nodeId = clusterConf.nodeData[i].nodeId;
-
- if (clusterConf.nodeData[i].nodeType == NodeInfo::MGM){
-
- if(globalTransporterRegistry.performState(nodeId) != PerformIO){
- globalTransporterRegistry.setPerformState(nodeId, PerformConnect);
- globalTransporterRegistry.setIOState(nodeId, NoHalt);
+ for(unsigned int i = 1; i < MAX_NODES; i++ ){
+ if (getNodeInfo(i).m_type == NodeInfo::MGM){
+ if(globalTransporterRegistry.performState(i) != PerformIO){
+ globalTransporterRegistry.setPerformState(i, PerformConnect);
+ globalTransporterRegistry.setIOState(i, NoHalt);
}
}
}
@@ -922,17 +779,10 @@ Cmvmi::execSTART_ORD(Signal* signal) {
// Disconnect all nodes as part of the system restart.
// We need to ensure that we are starting up
// without any connected nodes.
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData() ;
- const int myNodeId = globalData.ownId;
-
- for(unsigned int i= 0; i < clusterConf.SizeAltData.noOfNodes; i++ ){
- NodeId nodeId = clusterConf.nodeData[i].nodeId;
- if (myNodeId != nodeId &&
- clusterConf.nodeData[i].nodeType != NodeInfo::MGM){
-
- globalTransporterRegistry.setPerformState(nodeId, PerformDisconnect);
- globalTransporterRegistry.setIOState(nodeId, HaltIO);
+ for(unsigned int i = 1; i < MAX_NODES; i++ ){
+ if (i != getOwnNodeId() && getNodeInfo(i).m_type != NodeInfo::MGM){
+ globalTransporterRegistry.setPerformState(i, PerformDisconnect);
+ globalTransporterRegistry.setIOState(i, HaltIO);
}
}
@@ -963,6 +813,7 @@ void Cmvmi::execTAMPER_ORD(Signal* signal)
void Cmvmi::execSET_VAR_REQ(Signal* signal)
{
+#if 0
SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0];
ConfigParamId var = setVarReq->variable();
@@ -1047,7 +898,7 @@ void Cmvmi::execSET_VAR_REQ(Signal* signal)
sendSignal(mgmtSrvr, GSN_SET_VAR_REF, signal, 0, JBB);
} // switch
-
+#endif
}//execSET_VAR_REQ()
@@ -1068,7 +919,7 @@ void Cmvmi::execSET_VAR_REF(Signal* signal)
void Cmvmi::handleSET_VAR_REQ(Signal* signal) {
-
+#if 0
SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0];
ConfigParamId var = setVarReq->variable();
int val = setVarReq->value();
@@ -1109,7 +960,7 @@ void Cmvmi::handleSET_VAR_REQ(Signal* signal) {
sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB);
return;
} // switch
-
+#endif
}
#ifdef VM_TRACE
@@ -1184,14 +1035,9 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
if (dumpState->args[0] == DumpStateOrd::CmvmiDumpConnections){
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData() ;
-
- for(unsigned int i= 0; i < clusterConf.SizeAltData.noOfNodes; i++ ){
- NodeId nodeId = clusterConf.nodeData[i].nodeId;
-
+ for(unsigned int i = 1; i < MAX_NODES; i++ ){
const char* nodeTypeStr = "";
- switch(clusterConf.nodeData[i].nodeType){
+ switch(getNodeInfo(i).m_type){
case NodeInfo::DB:
nodeTypeStr = "DB";
break;
@@ -1204,12 +1050,18 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
case NodeInfo::REP:
nodeTypeStr = "REP";
break;
+ case NodeInfo::INVALID:
+ nodeTypeStr = 0;
+ break;
default:
nodeTypeStr = "<UNKNOWN>";
}
+ if(nodeTypeStr == 0)
+ continue;
+
const char* actionStr = "";
- switch (globalTransporterRegistry.performState(nodeId)){
+ switch (globalTransporterRegistry.performState(i)){
case PerformNothing:
actionStr = "does nothing";
break;
@@ -1228,18 +1080,18 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
}
infoEvent("Connection to %d (%s) %s",
- nodeId,
+ i,
nodeTypeStr,
actionStr);
}
}
-
+
if (dumpState->args[0] == DumpStateOrd::CmvmiDumpLongSignalMemory){
infoEvent("Cmvmi: g_sectionSegmentPool size: %d free: %d",
g_sectionSegmentPool.getSize(),
g_sectionSegmentPool.getNoOfFree());
}
-
+
if (dumpState->args[0] == DumpStateOrd::CmvmiSetRestartOnErrorInsert){
if(signal->getLength() == 1)
theConfig.setRestartOnErrorInsert((int)NRT_NoStart_Restart);
@@ -1372,15 +1224,7 @@ Cmvmi::execTESTSIG(Signal* signal){
return;
}
- NodeReceiverGroup rg; rg.m_block = CMVMI;
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfig.clusterConfigurationData() ;
- for(unsigned int i = 0; i < clusterConf.SizeAltData.noOfNodes; i++ ){
- NodeId nodeId = clusterConf.nodeData[i].nodeId;
- if (clusterConf.nodeData[i].nodeType == NodeInfo::DB){
- rg.m_nodes.set(nodeId);
- }
- }
+ NodeReceiverGroup rg(CMVMI, c_dbNodes);
if(signal->getSendersBlockRef() == ref){
/**
@@ -1550,6 +1394,26 @@ Cmvmi::execTESTSIG(Signal* signal){
}
break;
}
+ case 13:{
+ ndbrequire(signal->getNoOfSections() == 0);
+ Uint32 loop = signal->theData[9];
+ if(loop > 0){
+ signal->theData[9] --;
+ sendSignal(CMVMI_REF, GSN_TESTSIG, signal, signal->length(), JBB);
+ return;
+ }
+ sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB);
+ return;
+ }
+ case 14:{
+ Uint32 count = signal->theData[8];
+ signal->theData[10] = count * rg.m_nodes.count();
+ for(Uint32 i = 0; i<count; i++){
+ sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB);
+ }
+ return;
+ }
+
default:
ndbrequire(false);
}
diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp
index 4f42c2efc93..1c91f564749 100644
--- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp
+++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp
@@ -48,10 +48,7 @@ private:
void execNDB_TAMPER(Signal* signal);
void execSET_LOGLEVELORD(Signal* signal);
void execEVENT_REP(Signal* signal);
- void execSTTOR_Local(Signal* signal);
- void execCM_RUN(Signal* signal);
- void execCM_INFOREQ(Signal* signal);
- void execCMVMI_CFGREQ(Signal* signal);
+ void execSTTOR(Signal* signal);
void execCLOSE_COMREQ(Signal* signal);
void execENABLE_COMORD(Signal* signal);
void execOPEN_COMREQ(Signal* signal);
@@ -75,17 +72,13 @@ private:
void execTESTSIG(Signal* signal);
- int signalCount;
- int theSignalKey;
- int theStartPhase;
- int theNumberOfNodes;
-
char theErrorMessage[256];
void sendSTTORRY(Signal* signal);
LogLevel clogLevel;
+ NdbNodeBitmask c_dbNodes;
+
class Configuration & theConfig;
- const class ClusterConfiguration & theCConfig;
/**
* This struct defines the data needed for a EVENT_REP subscriber
diff --git a/ndb/src/kernel/blocks/cmvmi/Makefile.am b/ndb/src/kernel/blocks/cmvmi/Makefile.am
new file mode 100644
index 00000000000..fdd43932682
--- /dev/null
+++ b/ndb/src/kernel/blocks/cmvmi/Makefile.am
@@ -0,0 +1,10 @@
+
+noinst_LIBRARIES = libcmvmi.a
+
+libcmvmi_a_SOURCES = Cmvmi.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/cmvmi/Makefile b/ndb/src/kernel/blocks/cmvmi/Makefile_old
index d75e5dbf08b..d75e5dbf08b 100644
--- a/ndb/src/kernel/blocks/cmvmi/Makefile
+++ b/ndb/src/kernel/blocks/cmvmi/Makefile_old
diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
index fef41be88c4..6ba2d083e58 100644
--- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
+++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
@@ -958,7 +958,7 @@ private:
void execDROP_TAB_REQ(Signal* signal);
void execFSREMOVECONF(Signal* signal);
void execFSREMOVEREF(Signal* signal);
- void execSIZEALT_REP(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execSET_VAR_REQ(Signal* signal);
void execDUMP_STATE_ORD(Signal* signal);
@@ -1000,7 +1000,6 @@ private:
void initScanFragmentPart(Signal* signal);
Uint32 checkScanExpand(Signal* signal);
Uint32 checkScanShrink(Signal* signal);
- void sendInitialiseRecords(Signal* signal);
void initialiseDirRec(Signal* signal);
void initialiseDirRangeRec(Signal* signal);
void initialiseFragRec(Signal* signal);
@@ -1174,7 +1173,7 @@ private:
void srReadPagesLab(Signal* signal);
void srDoUndoLab(Signal* signal);
void ndbrestart1Lab(Signal* signal);
- void initialiseRecordsLab(Signal* signal);
+ void initialiseRecordsLab(Signal* signal, Uint32 returnRef, Uint32 retData);
void srReadPagesAllocLab(Signal* signal);
void checkNextBucketLab(Signal* signal);
void endsavepageLab(Signal* signal);
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
index 107420c7148..90e914987c3 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
@@ -179,7 +179,7 @@ Dbacc::Dbacc(const class Configuration & conf):
addRecSignal(GSN_DROP_TAB_REQ, &Dbacc::execDROP_TAB_REQ);
addRecSignal(GSN_FSREMOVECONF, &Dbacc::execFSREMOVECONF);
addRecSignal(GSN_FSREMOVEREF, &Dbacc::execFSREMOVEREF);
- addRecSignal(GSN_SIZEALT_REP, &Dbacc::execSIZEALT_REP);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Dbacc::execREAD_CONFIG_REQ, true);
addRecSignal(GSN_SET_VAR_REQ, &Dbacc::execSET_VAR_REQ);
initData();
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
index ea8d808458b..933ee2cf8e1 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -20,13 +20,11 @@
#include <signaldata/AccFrag.hpp>
#include <signaldata/AccScan.hpp>
#include <signaldata/AccLock.hpp>
-#include <signaldata/AccSizeAltReq.hpp>
#include <signaldata/EventReport.hpp>
#include <signaldata/FsConf.hpp>
#include <signaldata/FsRef.hpp>
#include <signaldata/FsRemoveReq.hpp>
#include <signaldata/DropTab.hpp>
-#include <signaldata/SetVarReq.hpp>
#include <signaldata/DumpStateOrd.hpp>
// TO_DO_RONM is a label for comments on what needs to be improved in future versions
@@ -127,7 +125,7 @@ void Dbacc::execCONTINUEB(Signal* signal)
break;
case ZINITIALISE_RECORDS:
jam();
- initialiseRecordsLab(signal);
+ initialiseRecordsLab(signal, signal->theData[3], signal->theData[4]);
return;
break;
case ZSR_READ_PAGES_ALLOC:
@@ -496,9 +494,6 @@ void Dbacc::execFSWRITEREF(Signal* signal)
void Dbacc::execNDB_STTOR(Signal* signal)
{
Uint32 tstartphase;
- Uint32 tconfig1;
- Uint32 tconfig2;
- Uint32 tlqhConfig1;
Uint32 tStartType;
jamEntry();
@@ -506,9 +501,6 @@ void Dbacc::execNDB_STTOR(Signal* signal)
cmynodeid = signal->theData[1];
tstartphase = signal->theData[2];
tStartType = signal->theData[3];
- tlqhConfig1 = signal->theData[10]; /* DBLQH */
- tconfig1 = signal->theData[16]; /* DBACC */
- tconfig2 = signal->theData[17]; /* DBACC */
switch (tstartphase) {
case ZSPH1:
jam();
@@ -534,21 +526,7 @@ void Dbacc::execNDB_STTOR(Signal* signal)
//---------------------------------------------
csystemRestart = ZFALSE;
}//if
- if (tconfig1 > 0) {
- jam();
- clblPagesPerTick = tconfig1;
- } else {
- jam();
- clblPagesPerTick = 1;
- }//if
- clblPageCounter = clblPagesPerTick;
- if (tconfig2 > 0) {
- jam();
- clblPagesPerTickAfterSr = tconfig2;
- } else {
- jam();
- clblPagesPerTickAfterSr = 1;
- }//if
+
signal->theData[0] = ZLOAD_BAL_LCP_TIMER;
sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 1);
break;
@@ -606,98 +584,86 @@ void Dbacc::ndbrestart1Lab(Signal* signal)
for (Uint32 tmp = 0; tmp < ZMAX_UNDO_VERSION; tmp++) {
csrVersList[tmp] = RNIL;
}//for
- tdata0 = 0;
- initialiseRecordsLab(signal);
return;
}//Dbacc::ndbrestart1Lab()
-void Dbacc::initialiseRecordsLab(Signal* signal)
+void Dbacc::initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data)
{
switch (tdata0) {
case 0:
jam();
initialiseTableRec(signal);
- sendInitialiseRecords(signal);
break;
case 1:
jam();
initialiseFsConnectionRec(signal);
- sendInitialiseRecords(signal);
break;
case 2:
jam();
initialiseFsOpRec(signal);
- sendInitialiseRecords(signal);
break;
case 3:
jam();
initialiseLcpConnectionRec(signal);
- sendInitialiseRecords(signal);
break;
case 4:
jam();
initialiseDirRec(signal);
- sendInitialiseRecords(signal);
break;
case 5:
jam();
initialiseDirRangeRec(signal);
- sendInitialiseRecords(signal);
break;
case 6:
jam();
initialiseFragRec(signal);
- sendInitialiseRecords(signal);
break;
case 7:
jam();
initialiseOverflowRec(signal);
- sendInitialiseRecords(signal);
break;
case 8:
jam();
initialiseOperationRec(signal);
- sendInitialiseRecords(signal);
break;
case 9:
jam();
initialisePageRec(signal);
- sendInitialiseRecords(signal);
break;
case 10:
jam();
initialiseRootfragRec(signal);
- sendInitialiseRecords(signal);
break;
case 11:
jam();
initialiseScanRec(signal);
- sendInitialiseRecords(signal);
break;
case 12:
jam();
initialiseSrVerRec(signal);
- signal->theData[0] = cownBlockref;
- sendSignal(CMVMI_REF, GSN_SIZEALT_ACK, signal, 1, JBB);
+
+ {
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = data;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+ }
return;
break;
default:
ndbrequire(false);
break;
}//switch
- return;
-}//Dbacc::initialiseRecordsLab()
-/* --------------------------------------------------------------------------------- */
-/* SEND REAL-TIME BREAK DURING INITIALISATION OF VARIABLES DURING SYSTEM RESTART.*/
-/* --------------------------------------------------------------------------------- */
-void Dbacc::sendInitialiseRecords(Signal* signal)
-{
signal->theData[0] = ZINITIALISE_RECORDS;
signal->theData[1] = tdata0 + 1;
signal->theData[2] = 0;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 3, JBB);
-}//Dbacc::sendInitialiseRecords()
+ signal->theData[3] = ref;
+ signal->theData[4] = data;
+ sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
+ return;
+}//Dbacc::initialiseRecordsLab()
/* *********************************<< */
/* NDB_STTORRY */
@@ -712,23 +678,41 @@ void Dbacc::ndbsttorryLab(Signal* signal)
/* *********************************<< */
/* SIZEALT_REP SIZE ALTERATION */
/* *********************************<< */
-void Dbacc::execSIZEALT_REP(Signal* signal)
+void Dbacc::execREAD_CONFIG_REQ(Signal* signal)
{
- Uint32 tsizealtBlockRef;
-
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+ ndbrequire(req->noOfParameters == 0);
+
jamEntry();
- tsizealtBlockRef = signal->theData[AccSizeAltReq::IND_BLOCK_REF];
- cdirrangesize = signal->theData[AccSizeAltReq::IND_DIR_RANGE];
- cdirarraysize = signal->theData[AccSizeAltReq::IND_DIR_ARRAY];
- cfragmentsize = signal->theData[AccSizeAltReq::IND_FRAGMENT];
- coprecsize = signal->theData[AccSizeAltReq::IND_OP_RECS];
- coverflowrecsize = signal->theData[AccSizeAltReq::IND_OVERFLOW_RECS];
- cpagesize = signal->theData[AccSizeAltReq::IND_PAGE8];
- crootfragmentsize = signal->theData[AccSizeAltReq::IND_ROOT_FRAG];
- ctablesize = signal->theData[AccSizeAltReq::IND_TABLE];
- cscanRecSize = signal->theData[AccSizeAltReq::IND_SCAN];
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_RANGE, &cdirrangesize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_ARRAY, &cdirarraysize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_FRAGMENT, &cfragmentsize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OP_RECS, &coprecsize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OVERFLOW_RECS,
+ &coverflowrecsize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_PAGE8, &cpagesize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_ROOT_FRAG,
+ &crootfragmentsize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_TABLE, &ctablesize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_SCAN, &cscanRecSize));
initRecords();
ndbrestart1Lab(signal);
+
+ clblPagesPerTick = 50;
+ //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTick);
+
+ clblPagesPerTickAfterSr = 50;
+ //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTickAfterSr);
+
+ tdata0 = 0;
+ initialiseRecordsLab(signal, ref, senderData);
return;
}//Dbacc::execSIZEALT_REP()
@@ -2448,6 +2432,7 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
}
fragrecptr.i = req->fragPtrI;
ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
+ ndbrequire(req->fragId == fragrecptr.p->myfid);
// caller must be explicit here
ndbrequire(req->accOpPtr == RNIL);
// seize operation to hold the lock
@@ -13260,6 +13245,7 @@ Dbacc::execDUMP_STATE_ORD(Signal* signal)
void Dbacc::execSET_VAR_REQ(Signal* signal)
{
+#if 0
SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0];
ConfigParamId var = setVarReq->variable();
int val = setVarReq->value();
@@ -13280,6 +13266,6 @@ void Dbacc::execSET_VAR_REQ(Signal* signal)
default:
sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB);
} // switch
-
+#endif
}//execSET_VAR_REQ()
diff --git a/ndb/src/kernel/blocks/dbacc/Makefile.am b/ndb/src/kernel/blocks/dbacc/Makefile.am
new file mode 100644
index 00000000000..7ccfbe22f76
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbacc/Makefile.am
@@ -0,0 +1,10 @@
+
+noinst_LIBRARIES = libdbacc.a
+
+libdbacc_a_SOURCES = DbaccInit.cpp DbaccMain.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/dbacc/Makefile b/ndb/src/kernel/blocks/dbacc/Makefile_old
index 93a830cec95..93a830cec95 100644
--- a/ndb/src/kernel/blocks/dbacc/Makefile
+++ b/ndb/src/kernel/blocks/dbacc/Makefile_old
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index 790c29737e9..2ef9e721e22 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -14,6 +14,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <ndb_global.h>
+
#define DBDICT_C
#include "Dbdict.hpp"
@@ -25,7 +27,6 @@
#include <SimpleProperties.hpp>
#include <AttributeHeader.hpp>
#include <signaldata/DictSchemaInfo.hpp>
-#include <signaldata/DictSizeAltReq.hpp>
#include <signaldata/DictTabInfo.hpp>
#include <signaldata/DropTabFile.hpp>
@@ -110,7 +111,7 @@ Dbdict::execDUMP_STATE_ORD(Signal* signal)
{
jamEntry();
-#ifdef NDB_DEBUG
+#ifdef VM_TRACE
if(signal->theData[0] == 1222){
const Uint32 tab = signal->theData[1];
PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
@@ -1040,10 +1041,10 @@ Dbdict::Dbdict(const class Configuration & conf):
{
BLOCK_CONSTRUCTOR(Dbdict);
- const Properties * p = conf.getOwnProperties();
+ const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
ndbrequire(p != 0);
- p->get("MaxNoOfTriggers", &c_maxNoOfTriggers);
+ ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS, &c_maxNoOfTriggers);
// Transit signals
addRecSignal(GSN_DUMP_STATE_ORD, &Dbdict::execDUMP_STATE_ORD);
addRecSignal(GSN_GET_TABINFOREQ, &Dbdict::execGET_TABINFOREQ);
@@ -1159,7 +1160,7 @@ Dbdict::Dbdict(const class Configuration & conf):
addRecSignal(GSN_LQHADDATTREF, &Dbdict::execLQHADDATTREF);
addRecSignal(GSN_LQHFRAGREF, &Dbdict::execLQHFRAGREF);
addRecSignal(GSN_NDB_STTOR, &Dbdict::execNDB_STTOR);
- addRecSignal(GSN_SIZEALT_REP, &Dbdict::execSIZEALT_REP);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Dbdict::execREAD_CONFIG_REQ, true);
addRecSignal(GSN_STTOR, &Dbdict::execSTTOR);
addRecSignal(GSN_TC_SCHVERCONF, &Dbdict::execTC_SCHVERCONF);
addRecSignal(GSN_NODE_FAILREP, &Dbdict::execNODE_FAILREP);
@@ -1522,7 +1523,6 @@ void Dbdict::execSTTOR(Signal* signal)
c_startPhase = signal->theData[1];
switch (c_startPhase) {
case 1:
- initCommonData();
break;
case 3:
c_restartType = signal->theData[7]; /* valid if 3 */
@@ -1549,14 +1549,22 @@ void Dbdict::sendSTTORRY(Signal* signal)
/* ---------------------------------------------------------------- */
// We receive information about sizes of records.
/* ---------------------------------------------------------------- */
-void Dbdict::execSIZEALT_REP(Signal* signal)
+void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
{
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+ ndbrequire(req->noOfParameters == 0);
+
jamEntry();
- BlockReference tblockref;
- tblockref = signal->theData[DictSizeAltReq::IND_BLOCK_REF];
- Uint32 attributesize = signal->theData[DictSizeAltReq::IND_ATTRIBUTE];
-// Uint32 connectsize = signal->theData[DictSizeAltReq::IND_CONNECT];
- Uint32 tablerecSize = signal->theData[DictSizeAltReq::IND_TABLE];
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ Uint32 attributesize, tablerecSize;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_ATTRIBUTE,&attributesize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE, &tablerecSize));
c_attributeRecordPool.setSize(attributesize);
c_attributeRecordHash.setSize(64);
@@ -1592,9 +1600,14 @@ void Dbdict::execSIZEALT_REP(Signal* signal)
bat[1].bits.q = ZLOG_SIZE_OF_PAGES_IN_WORDS; // 2**13 = 8192 elements
bat[1].bits.v = 5; // 32 bits per element
+ initCommonData();
initRecords();
- signal->theData[0] = DBDICT_REF;
- sendSignal(tblockref, GSN_SIZEALT_ACK, signal, 2, JBB);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
}//execSIZEALT_REP()
/* ---------------------------------------------------------------- */
@@ -2388,7 +2401,7 @@ Dbdict::execGET_TABINFO_CONF(Signal* signal){
SegmentedSectionPtr tabInfoPtr;
signal->getSection(tabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
-
+
CreateTableRecordPtr createTabPtr;
ndbrequire(c_opCreateTable.find(createTabPtr, senderData));
ndbrequire(!createTabPtr.isNull());
@@ -2410,7 +2423,10 @@ Dbdict::execGET_TABINFO_CONF(Signal* signal){
callback.m_callbackFunction =
safe_cast(&Dbdict::restartCreateTab_writeTableConf);
+ signal->header.m_noOfSections = 0;
writeTableFile(signal, createTabPtr.p->m_tablePtrI, tabInfoPtr, &callback);
+ signal->setSection(tabInfoPtr, 0);
+ releaseSections(signal);
}
void
@@ -3818,15 +3834,15 @@ Dbdict::execCREATE_TAB_REQ(Signal* signal){
CreateTabReq::RequestType rt = (CreateTabReq::RequestType)req->requestType;
switch(rt){
case CreateTabReq::CreateTablePrepare:
- CRASH_INSERTION2(14000, getOwnNodeId() != c_masterNodeId);
+ CRASH_INSERTION2(6003, getOwnNodeId() != c_masterNodeId);
createTab_prepare(signal, req);
return;
case CreateTabReq::CreateTableCommit:
- CRASH_INSERTION2(14001, getOwnNodeId() != c_masterNodeId);
+ CRASH_INSERTION2(6004, getOwnNodeId() != c_masterNodeId);
createTab_commit(signal, req);
return;
case CreateTabReq::CreateTableDrop:
- CRASH_INSERTION2(14002, getOwnNodeId() != c_masterNodeId);
+ CRASH_INSERTION2(6005, getOwnNodeId() != c_masterNodeId);
createTab_drop(signal, req);
return;
}
@@ -3926,9 +3942,9 @@ Dbdict::createTab_writeSchemaConf1(Signal* signal,
SegmentedSectionPtr tabInfoPtr;
getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
-
writeTableFile(signal, createTabPtr.p->m_tablePtrI, tabInfoPtr, &callback);
+ createTabPtr.p->m_tabInfoPtrI = RNIL;
signal->setSection(tabInfoPtr, 0);
releaseSections(signal);
}
@@ -5703,7 +5719,7 @@ void Dbdict::sendGET_TABINFOREF(Signal* signal,
}//sendGET_TABINFOREF()
Uint32 convertEndian(Uint32 in) {
-#ifdef _BIG_ENDIAN
+#ifdef WORDS_BIGENDIAN
Uint32 ut = 0;
ut += ((in >> 24) & 255);
ut += (((in >> 16) & 255) << 8);
@@ -7760,8 +7776,9 @@ Dbdict::createEventComplete_RT_USER_GET(Signal* signal,
#endif
NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- evntRecPtr.p->m_reqTracker.init<CreateEvntRef>
- (c_counterMgr, rg, GSN_CREATE_EVNT_REF, evntRecPtr.i);
+ RequestTracker & p = evntRecPtr.p->m_reqTracker;
+ p.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, evntRecPtr.i);
+
sendSignal(rg, GSN_CREATE_EVNT_REQ, signal, CreateEvntReq::SignalLength, JBB);
}
@@ -8109,7 +8126,8 @@ void Dbdict::execSUB_START_REQ(Signal* signal)
subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- subbPtr.p->m_reqTracker.init<SubStartRef>(c_counterMgr, rg, GSN_SUB_START_REF, subbPtr.i);
+ RequestTracker & p = subbPtr.p->m_reqTracker;
+ p.init<SubStartRef>(c_counterMgr, rg, GSN_SUB_START_REF, subbPtr.i);
SubStartReq* req = (SubStartReq*) signal->getDataPtrSend();
@@ -8322,7 +8340,8 @@ void Dbdict::execSUB_STOP_REQ(Signal* signal)
#endif
subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- subbPtr.p->m_reqTracker.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF, subbPtr.i);
+ RequestTracker & p = subbPtr.p->m_reqTracker;
+ p.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF, subbPtr.i);
SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
@@ -8609,7 +8628,8 @@ Dbdict::dropEventUTIL_EXECUTE_READ(Signal* signal,
parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- evntRecPtr.p->m_reqTracker.init<SubRemoveRef>(c_counterMgr, rg, GSN_SUB_REMOVE_REF,
+ RequestTracker & p = evntRecPtr.p->m_reqTracker;
+ p.init<SubRemoveRef>(c_counterMgr, rg, GSN_SUB_REMOVE_REF,
evntRecPtr.i);
SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
@@ -11492,7 +11512,7 @@ Dbdict::initSchemaFile(SchemaFile * sf, Uint32 fileSz){
ndbrequire(noEntries > MAX_TABLES);
sf->NoOfTableEntries = noEntries;
- memset(sf->TableEntries, 0, sizeof(noEntries*sizeof(SchemaFile::TableEntry)));
+ memset(sf->TableEntries, 0, noEntries*sizeof(SchemaFile::TableEntry));
memset(&(sf->TableEntries[noEntries]), 0, slack);
computeChecksum(sf);
}
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
index 02e2d4496bf..68214785234 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -102,6 +102,22 @@
#endif
/**
+ * Systable NDB$EVENTS_0
+ */
+
+#define EVENT_SYSTEM_TABLE_NAME "sys/def/NDB$EVENTS_0"
+#define EVENT_SYSTEM_TABLE_LENGTH 6
+
+struct sysTab_NDBEVENTS_0 {
+ char NAME[MAX_TAB_NAME_SIZE];
+ Uint32 EVENT_TYPE;
+ char TABLE_NAME[MAX_TAB_NAME_SIZE];
+ Uint32 ATTRIBUTE_MASK[MAXNROFATTRIBUTESINWORDS];
+ Uint32 SUBID;
+ Uint32 SUBKEY;
+};
+
+/**
* DICT - This blocks handles all metadata
*/
class Dbdict: public SimulatedBlock {
@@ -451,7 +467,7 @@ private:
void execFSWRITECONF(Signal* signal);
void execFSWRITEREF(Signal* signal);
void execNDB_STTOR(Signal* signal);
- void execSIZEALT_REP(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execSTTOR(Signal* signal);
void execTC_SCHVERCONF(Signal* signal);
void execNODE_FAILREP(Signal* signal);
@@ -1227,22 +1243,6 @@ private:
};
typedef Ptr<OpSubEvent> OpSubEventPtr;
- /**
- * Systable NDB$EVENTS_0
- */
-
-#define EVENT_SYSTEM_TABLE_NAME "sys/def/NDB$EVENTS_0"
-#define EVENT_SYSTEM_TABLE_LENGTH 6
-
- struct sysTab_NDBEVENTS_0 {
- char NAME[MAX_TAB_NAME_SIZE];
- Uint32 EVENT_TYPE;
- char TABLE_NAME[MAX_TAB_NAME_SIZE];
- Uint32 ATTRIBUTE_MASK[MAXNROFATTRIBUTESINWORDS];
- Uint32 SUBID;
- Uint32 SUBKEY;
- };
-
static const Uint32 sysTab_NDBEVENTS_0_szs[];
/**
diff --git a/ndb/src/kernel/blocks/dbdict/Makefile.am b/ndb/src/kernel/blocks/dbdict/Makefile.am
new file mode 100644
index 00000000000..dc4c4fe4734
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbdict/Makefile.am
@@ -0,0 +1,11 @@
+#SUBDIRS = printSchemafile
+
+noinst_LIBRARIES = libdbdict.a
+
+libdbdict_a_SOURCES = Dbdict.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/dbdict/Makefile b/ndb/src/kernel/blocks/dbdict/Makefile_old
index 46d938114fb..46d938114fb 100644
--- a/ndb/src/kernel/blocks/dbdict/Makefile
+++ b/ndb/src/kernel/blocks/dbdict/Makefile_old
diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
index 4ec699cebec..e029af70574 100644
--- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
+++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
@@ -312,7 +312,6 @@ public:
Bitmask<1> m_nodefailSteps;
Uint32 activeTabptr;
Uint32 nextNode;
- Uint32 ndbversion;
Uint32 nodeGroup;
SignalCounter m_NF_COMPLETE_REP;
@@ -663,7 +662,7 @@ private:
void execSTOP_ME_REF(Signal *);
void execSTOP_ME_CONF(Signal *);
- void execSIZEALT_REP(Signal *);
+ void execREAD_CONFIG_REQ(Signal *);
void execUNBLO_DICTCONF(Signal *);
void execCOPY_ACTIVECONF(Signal *);
void execTAB_COMMITREQ(Signal *);
@@ -685,7 +684,6 @@ private:
void execNDB_STARTREQ(Signal *);
void execGETGCIREQ(Signal *);
void execDIH_RESTARTREQ(Signal *);
- void execCNTR_CHANGEREP(Signal *);
void execSTART_RECCONF(Signal *);
void execSTART_FRAGCONF(Signal *);
void execADD_FRAGCONF(Signal *);
@@ -798,6 +796,7 @@ private:
void closeFileDelete(Signal *, FileRecordPtr regFilePtr);
void createFileRw(Signal *, FileRecordPtr regFilePtr);
void openFileRw(Signal *, FileRecordPtr regFilePtr);
+ void openFileRo(Signal *, FileRecordPtr regFilePtr);
void seizeFile(FileRecordPtr& regFilePtr);
void releaseFile(Uint32 fileIndex);
@@ -969,7 +968,7 @@ private:
void checkCopyTab(NodeRecordPtr failedNodePtr);
void initCommonData();
- void initialiseRecordsLab(Signal *, Uint32 stepNo);
+ void initialiseRecordsLab(Signal *, Uint32 stepNo, Uint32, Uint32);
void findReplica(ReplicaRecordPtr& regReplicaPtr,
Fragmentstore* fragPtrP, Uint32 nodeId);
@@ -1409,7 +1408,6 @@ private:
Uint32 startNode;
Uint32 wait;
Uint32 failNr;
- Uint32 ndbVersion;
bool activeState;
bool blockLcp;
bool blockGcp;
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
index b115cc0297a..df47237ae59 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
@@ -179,7 +179,7 @@ Dbdih::Dbdih(const class Configuration & config):
addRecSignal(GSN_START_LCP_REQ, &Dbdih::execSTART_LCP_REQ);
addRecSignal(GSN_START_LCP_CONF, &Dbdih::execSTART_LCP_CONF);
- addRecSignal(GSN_SIZEALT_REP, &Dbdih::execSIZEALT_REP);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Dbdih::execREAD_CONFIG_REQ, true);
addRecSignal(GSN_UNBLO_DICTCONF, &Dbdih::execUNBLO_DICTCONF);
addRecSignal(GSN_COPY_ACTIVECONF, &Dbdih::execCOPY_ACTIVECONF);
addRecSignal(GSN_TAB_COMMITREQ, &Dbdih::execTAB_COMMITREQ);
@@ -201,7 +201,6 @@ Dbdih::Dbdih(const class Configuration & config):
addRecSignal(GSN_NDB_STARTREQ, &Dbdih::execNDB_STARTREQ);
addRecSignal(GSN_GETGCIREQ, &Dbdih::execGETGCIREQ);
addRecSignal(GSN_DIH_RESTARTREQ, &Dbdih::execDIH_RESTARTREQ);
- addRecSignal(GSN_CNTR_CHANGEREP, &Dbdih::execCNTR_CHANGEREP);
addRecSignal(GSN_START_RECCONF, &Dbdih::execSTART_RECCONF);
addRecSignal(GSN_START_FRAGCONF, &Dbdih::execSTART_FRAGCONF);
addRecSignal(GSN_ADD_FRAGCONF, &Dbdih::execADD_FRAGCONF);
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index cefbb3e66a3..0ce1f1e4bbe 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -32,7 +32,6 @@
#include <signaldata/DictStart.hpp>
#include <signaldata/DiGetNodes.hpp>
#include <signaldata/DihContinueB.hpp>
-#include <signaldata/DihSizeAltReq.hpp>
#include <signaldata/DihSwitchReplica.hpp>
#include <signaldata/DumpStateOrd.hpp>
#include <signaldata/EmptyLcp.hpp>
@@ -45,7 +44,6 @@
#include <signaldata/NFCompleteRep.hpp>
#include <signaldata/NodeFailRep.hpp>
#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/SetVarReq.hpp>
#include <signaldata/StartFragReq.hpp>
#include <signaldata/StartInfo.hpp>
#include <signaldata/StartMe.hpp>
@@ -68,7 +66,7 @@
#include <signaldata/DictTabInfo.hpp>
#include <signaldata/CreateFragmentation.hpp>
#include <signaldata/LqhFrag.hpp>
-
+#include <signaldata/FsOpenReq.hpp>
#include <DebuggerNames.hpp>
#define SYSFILE ((Sysfile *)&sysfileData[0])
@@ -212,7 +210,7 @@ void Dbdih::sendINCL_NODEREQ(Signal* signal, Uint32 nodeId)
signal->theData[0] = reference();
signal->theData[1] = c_nodeStartMaster.startNode;
signal->theData[2] = c_nodeStartMaster.failNr;
- signal->theData[3] = c_nodeStartMaster.ndbVersion;
+ signal->theData[3] = 0;
signal->theData[4] = currentgcp;
sendSignal(nodeDihRef, GSN_INCL_NODEREQ, signal, 5, JBB);
}//Dbdih::sendINCL_NODEREQ()
@@ -291,13 +289,6 @@ void Dbdih::sendUPDATE_TOREQ(Signal* signal, Uint32 nodeId)
sendSignal(ref, GSN_UPDATE_TOREQ, signal, UpdateToReq::SignalLength, JBB);
}//sendUPDATE_TOREQ()
-void Dbdih::execCNTR_CHANGEREP(Signal* signal)
-{
- (void)signal; // Don't want compiler warning
- jamEntry();
- return;
-}//Dbdih::execCNTR_CHANGEREP()
-
void Dbdih::execCONTINUEB(Signal* signal)
{
jamEntry();
@@ -542,7 +533,10 @@ void Dbdih::execCONTINUEB(Signal* signal)
}
case DihContinueB::ZINITIALISE_RECORDS:
jam();
- initialiseRecordsLab(signal, signal->theData[1]);
+ initialiseRecordsLab(signal,
+ signal->theData[1],
+ signal->theData[2],
+ signal->theData[3]);
return;
break;
case DihContinueB::ZSTART_PERMREQ_AGAIN:
@@ -1023,17 +1017,30 @@ void Dbdih::execGETGCIREQ(Signal* signal)
sendSignal(userRef, GSN_GETGCICONF, signal, 2, JBB);
}//Dbdih::execGETGCIREQ()
-void Dbdih::execSIZEALT_REP(Signal* signal)
+void Dbdih::execREAD_CONFIG_REQ(Signal* signal)
{
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+ ndbrequire(req->noOfParameters == 0);
+
jamEntry();
- capiConnectFileSize = signal->theData[DihSizeAltReq::IND_API_CONNECT];
- cconnectFileSize = signal->theData[DihSizeAltReq::IND_CONNECT];
- cfragstoreFileSize = signal->theData[DihSizeAltReq::IND_FRAG_CONNECT];
- creplicaFileSize = signal->theData[DihSizeAltReq::IND_REPLICAS];
- ctabFileSize = signal->theData[DihSizeAltReq::IND_TABLE];
- cfileFileSize = (2 * ctabFileSize) + 2;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_API_CONNECT,
+ &capiConnectFileSize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_CONNECT,&cconnectFileSize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_FRAG_CONNECT,
+ &cfragstoreFileSize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_REPLICAS,
+ &creplicaFileSize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_TABLE, &ctabFileSize))
+ cfileFileSize = (2 * ctabFileSize) + 2;
initRecords();
- initialiseRecordsLab(signal, 0);
+ initialiseRecordsLab(signal, 0, ref, senderData);
return;
}//Dbdih::execSIZEALT_REP()
@@ -1158,11 +1165,8 @@ void Dbdih::execNDB_STTOR(Signal* signal)
Uint32 ownNodeId = signal->theData[1]; /* OWN PROCESSOR ID*/
Uint32 phase = signal->theData[2]; /* INTERNAL START PHASE*/
Uint32 typestart = signal->theData[3];
- const Uint32 tconfig1 = signal->theData[8];
- const Uint32 tconfig2 = signal->theData[9];
cstarttype = typestart;
-
cstartPhase = phase;
switch (phase){
@@ -1171,10 +1175,6 @@ void Dbdih::execNDB_STTOR(Signal* signal)
/*----------------------------------------------------------------------*/
/* Set the delay between local checkpoints in ndb startphase 1. */
/*----------------------------------------------------------------------*/
- c_lcpState.clcpDelay = tconfig1 > 31 ? 31 : tconfig1;
-
- cminHotSpareNodes = tconfig2 > 2 ? 2 : tconfig2;
-
cownNodeId = ownNodeId;
/*-----------------------------------------------------------------------*/
// Compute all static block references in this node as part of
@@ -1193,8 +1193,6 @@ void Dbdih::execNDB_STTOR(Signal* signal)
// Set the number of replicas, maximum is 4 replicas.
// Read the ndb nodes from the configuration.
/*-----------------------------------------------------------------------*/
- cnoReplicas = tconfig1 > 4 ? 4 : tconfig1;
- cgcpDelay = tconfig2 > 60000 ? 60000 : (tconfig2 < 10 ? 10 : tconfig2);
/*-----------------------------------------------------------------------*/
// For node restarts we will also add a request for permission
@@ -1261,7 +1259,7 @@ void Dbdih::execNDB_STTOR(Signal* signal)
*/
StartMeReq * req = (StartMeReq*)&signal->theData[0];
req->startingRef = reference();
- req->startingVersion = NDB_VERSION;
+ req->startingVersion = 0; // Obsolete
sendSignal(cmasterdihref, GSN_START_MEREQ, signal,
StartMeReq::SignalLength, JBB);
return;
@@ -1623,7 +1621,8 @@ void Dbdih::execSTART_PERMREQ(Signal* signal)
c_nodeStartMaster.startInfoErrorCode = 0;
c_nodeStartMaster.startNode = nodeId;
c_nodeStartMaster.activeState = true;
-
+ c_nodeStartMaster.m_outstandingGsn = GSN_START_INFOREQ;
+
setNodeStatus(nodeId, NodeRecord::STARTING);
/**
* But if it's a NodeState::ST_INITIAL_NODE_RESTART
@@ -1704,13 +1703,11 @@ void Dbdih::execSTART_MEREQ(Signal* signal)
jamEntry();
const BlockReference Tblockref = req->startingRef;
const Uint32 Tnodeid = refToNode(Tblockref);
- const Uint32 TndbVersion = req->startingVersion;
ndbrequire(isMaster());
ndbrequire(c_nodeStartMaster.startNode == Tnodeid);
ndbrequire(getNodeStatus(Tnodeid) == NodeRecord::STARTING);
- c_nodeStartMaster.ndbVersion = TndbVersion;
sendSTART_RECREQ(signal, Tnodeid);
}//Dbdih::execSTART_MEREQ()
@@ -2011,7 +2008,6 @@ void Dbdih::execINCL_NODEREQ(Signal* signal)
Uint32 retRef = signal->theData[0];
Uint32 nodeId = signal->theData[1];
Uint32 tnodeStartFailNr = signal->theData[2];
- Uint32 TndbVersion = signal->theData[3];
currentgcp = signal->theData[4];
CRASH_INSERTION(7127);
cnewgcp = currentgcp;
@@ -2063,7 +2059,6 @@ void Dbdih::execINCL_NODEREQ(Signal* signal)
nodePtr.p->nodeStatus = NodeRecord::ALIVE;
nodePtr.p->useInTransactions = true;
nodePtr.p->m_inclDihLcp = true;
- nodePtr.p->ndbversion = TndbVersion;
removeDeadNode(nodePtr);
insertAlive(nodePtr);
@@ -3391,7 +3386,8 @@ void Dbdih::readGciFileLab(Signal* signal)
filePtr.i = crestartInfoFile[0];
ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
filePtr.p->reqStatus = FileRecord::OPENING_GCP;
- openFileRw(signal, filePtr);
+
+ openFileRo(signal, filePtr);
}//Dbdih::readGciFileLab()
void Dbdih::openingGcpLab(Signal* signal, FileRecordPtr filePtr)
@@ -3455,6 +3451,7 @@ void Dbdih::selectMasterCandidateAndSend(Signal* signal)
signal->theData[0] = masterCandidateId;
signal->theData[1] = gci;
sendSignal(cntrlblockref, GSN_DIH_RESTARTCONF, signal, 2, JBB);
+ setNodeGroups();
}//Dbdih::selectMasterCandidate()
/* ------------------------------------------------------------------------- */
@@ -3472,7 +3469,7 @@ void Dbdih::openingGcpErrorLab(Signal* signal, FileRecordPtr filePtr)
/* --------------------------------------------------------------------- */
filePtr.i = crestartInfoFile[1];
ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- openFileRw(signal, filePtr);
+ openFileRo(signal, filePtr);
filePtr.p->reqStatus = FileRecord::OPENING_GCP;
} else {
jam();
@@ -3762,6 +3759,7 @@ void Dbdih::checkCopyTab(NodeRecordPtr failedNodePtr)
c_COPY_TABREQ_Counter.clearWaitingFor(failedNodePtr.i);
c_nodeStartMaster.wait = ZFALSE;
break;
+ case GSN_START_INFOREQ:
case GSN_START_PERMCONF:
case GSN_DICTSTARTREQ:
case GSN_START_MECONF:
@@ -10863,6 +10861,26 @@ void Dbdih::initCommonData()
c_nodeStartMaster.wait = ZFALSE;
memset(&sysfileData[0], 0, sizeof(sysfileData));
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ c_lcpState.clcpDelay = 20;
+ ndb_mgm_get_int_parameter(p, CFG_DB_LCP_INTERVAL, &c_lcpState.clcpDelay);
+ c_lcpState.clcpDelay = c_lcpState.clcpDelay > 31 ? 31 : c_lcpState.clcpDelay;
+
+ cminHotSpareNodes = 0;
+ //ndb_mgm_get_int_parameter(p, CFG_DB_MIN_HOT_SPARES, &cminHotSpareNodes);
+ cminHotSpareNodes = cminHotSpareNodes > 2 ? 2 : cminHotSpareNodes;
+
+ cnoReplicas = 1;
+ ndb_mgm_get_int_parameter(p, CFG_DB_NO_REPLICAS, &cnoReplicas);
+ cnoReplicas = cnoReplicas > 4 ? 4 : cnoReplicas;
+
+ cgcpDelay = 2000;
+ ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL, &cgcpDelay);
+ cgcpDelay = cgcpDelay > 60000 ? 60000 : (cgcpDelay < 10 ? 10 : cgcpDelay);
}//Dbdih::initCommonData()
void Dbdih::initFragstore(FragmentstorePtr fragPtr)
@@ -10901,7 +10919,6 @@ void Dbdih::initNodeState(NodeRecordPtr nodePtr)
nodePtr.p->nodeStatus = NodeRecord::NOT_IN_CLUSTER;
nodePtr.p->useInTransactions = false;
nodePtr.p->copyCompleted = false;
- nodePtr.p->ndbversion = 0xffff;
}//Dbdih::initNodeState()
/*************************************************************************/
@@ -11070,44 +11087,43 @@ void Dbdih::initTableFile(TabRecordPtr tabPtr)
/* --------------------------------------------------------------------- */
}//Dbdih::initTableFile()
-void Dbdih::initialiseRecordsLab(Signal* signal, Uint32 stepNo)
+void Dbdih::initialiseRecordsLab(Signal* signal,
+ Uint32 stepNo, Uint32 retRef, Uint32 retData)
{
switch (stepNo) {
case 0:
jam();
initCommonData();
break;
- case 1:
- {
- ApiConnectRecordPtr apiConnectptr;
- jam();
- /******** INTIALIZING API CONNECT RECORDS ********/
- for (apiConnectptr.i = 0; apiConnectptr.i < capiConnectFileSize; apiConnectptr.i++) {
- ptrAss(apiConnectptr, apiConnectRecord);
- apiConnectptr.p->nextApi = RNIL;
- }//for
- jam();
- break;
- }
- case 2:
- {
- ConnectRecordPtr connectPtr;
- jam();
- /****** CONNECT ******/
- for (connectPtr.i = 0; connectPtr.i < cconnectFileSize; connectPtr.i++) {
- ptrAss(connectPtr, connectRecord);
- connectPtr.p->userpointer = RNIL;
- connectPtr.p->userblockref = ZNIL;
- connectPtr.p->connectState = ConnectRecord::FREE;
- connectPtr.p->table = RNIL;
- connectPtr.p->nfConnect = connectPtr.i + 1;
- }//for
- connectPtr.i = cconnectFileSize - 1;
+ case 1:{
+ ApiConnectRecordPtr apiConnectptr;
+ jam();
+ /******** INTIALIZING API CONNECT RECORDS ********/
+ for (apiConnectptr.i = 0; apiConnectptr.i < capiConnectFileSize; apiConnectptr.i++) {
+ ptrAss(apiConnectptr, apiConnectRecord);
+ apiConnectptr.p->nextApi = RNIL;
+ }//for
+ jam();
+ break;
+ }
+ case 2:{
+ ConnectRecordPtr connectPtr;
+ jam();
+ /****** CONNECT ******/
+ for (connectPtr.i = 0; connectPtr.i < cconnectFileSize; connectPtr.i++) {
ptrAss(connectPtr, connectRecord);
- connectPtr.p->nfConnect = RNIL;
- cfirstconnect = 0;
- break;
- }
+ connectPtr.p->userpointer = RNIL;
+ connectPtr.p->userblockref = ZNIL;
+ connectPtr.p->connectState = ConnectRecord::FREE;
+ connectPtr.p->table = RNIL;
+ connectPtr.p->nfConnect = connectPtr.i + 1;
+ }//for
+ connectPtr.i = cconnectFileSize - 1;
+ ptrAss(connectPtr, connectRecord);
+ connectPtr.p->nfConnect = RNIL;
+ cfirstconnect = 0;
+ break;
+ }
case 3:
{
FileRecordPtr filePtr;
@@ -11208,8 +11224,12 @@ void Dbdih::initialiseRecordsLab(Signal* signal, Uint32 stepNo)
initTakeOver(takeOverPtr);
releaseTakeOver(takeOverPtr.i);
}//for
- signal->theData[0] = DBDIH_REF;
- sendSignal(CMVMI_REF, GSN_SIZEALT_ACK, signal, 2, JBB);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = retData;
+ sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
return;
break;
}
@@ -11218,12 +11238,14 @@ void Dbdih::initialiseRecordsLab(Signal* signal, Uint32 stepNo)
break;
}//switch
jam();
- /* ------------------------------------------------------------------------- */
- /* SEND REAL-TIME BREAK DURING INIT OF VARIABLES DURING SYSTEM RESTART. */
- /* ------------------------------------------------------------------------- */
+ /* ---------------------------------------------------------------------- */
+ /* SEND REAL-TIME BREAK DURING INIT OF VARIABLES DURING SYSTEM RESTART. */
+ /* ---------------------------------------------------------------------- */
signal->theData[0] = DihContinueB::ZINITIALISE_RECORDS;
signal->theData[1] = stepNo + 1;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
+ signal->theData[2] = retRef;
+ signal->theData[3] = retData;
+ sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
}//Dbdih::initialiseRecordsLab()
/*************************************************************************/
@@ -11512,8 +11534,6 @@ void Dbdih::makePrnList(ReadNodesConf * readNodes, Uint32 nodeArray[])
nodePtr.p->nodeStatus = NodeRecord::DEAD;
insertDeadNode(nodePtr);
}//if
- nodePtr.p->ndbversion = readNodes->getVersionId(nodePtr.i,
- readNodes->theVersionIds);
}//for
}//Dbdih::makePrnList()
@@ -11563,7 +11583,19 @@ void Dbdih::openFileRw(Signal* signal, FileRecordPtr filePtr)
signal->theData[3] = filePtr.p->fileName[1];
signal->theData[4] = filePtr.p->fileName[2];
signal->theData[5] = filePtr.p->fileName[3];
- signal->theData[6] = ZOPEN_READ_WRITE;
+ signal->theData[6] = FsOpenReq::OM_READWRITE;
+ sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
+}//Dbdih::openFileRw()
+
+void Dbdih::openFileRo(Signal* signal, FileRecordPtr filePtr)
+{
+ signal->theData[0] = reference();
+ signal->theData[1] = filePtr.i;
+ signal->theData[2] = filePtr.p->fileName[0];
+ signal->theData[3] = filePtr.p->fileName[1];
+ signal->theData[4] = filePtr.p->fileName[2];
+ signal->theData[5] = filePtr.p->fileName[3];
+ signal->theData[6] = FsOpenReq::OM_READONLY;
sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
}//Dbdih::openFileRw()
@@ -12502,7 +12534,10 @@ void Dbdih::setNodeGroups()
}//for
for (sngNodeptr.i = 1; sngNodeptr.i < MAX_NDB_NODES; sngNodeptr.i++) {
ptrAss(sngNodeptr, nodeRecord);
- switch (sngNodeptr.p->activeStatus) {
+ Sysfile::ActiveStatus s =
+ (Sysfile::ActiveStatus)Sysfile::getNodeStatus(sngNodeptr.i,
+ SYSFILE->nodeStatus);
+ switch (s){
case Sysfile::NS_Active:
case Sysfile::NS_ActiveMissed_1:
case Sysfile::NS_ActiveMissed_2:
@@ -12911,8 +12946,7 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal)
cnoHotSpare, c_nodeStartMaster.startNode, c_nodeStartMaster.wait);
}//if
if (signal->theData[0] == 7007) {
- infoEvent("c_nodeStartMaster.failNr = %d, c_nodeStartMaster.ndbVersion = %d",
- c_nodeStartMaster.failNr, c_nodeStartMaster.ndbVersion);
+ infoEvent("c_nodeStartMaster.failNr = %d", c_nodeStartMaster.failNr);
infoEvent("c_nodeStartMaster.startInfoErrorCode = %d",
c_nodeStartMaster.startInfoErrorCode);
infoEvent("c_nodeStartMaster.blockLcp = %d, c_nodeStartMaster.blockGcp = %d",
@@ -13391,7 +13425,7 @@ Dbdih::execNDB_TAMPER(Signal* signal)
}//Dbdih::execNDB_TAMPER()
void Dbdih::execSET_VAR_REQ(Signal* signal) {
-
+#if 0
SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0];
ConfigParamId var = setVarReq->variable();
int val = setVarReq->value();
@@ -13411,6 +13445,7 @@ void Dbdih::execSET_VAR_REQ(Signal* signal) {
default:
sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB);
} // switch
+#endif
}
void Dbdih::execBLOCK_COMMIT_ORD(Signal* signal){
diff --git a/ndb/src/kernel/blocks/dbdih/Makefile.am b/ndb/src/kernel/blocks/dbdih/Makefile.am
new file mode 100644
index 00000000000..2ee8017ec13
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbdih/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libdbdih.a
+
+libdbdih_a_SOURCES = DbdihInit.cpp DbdihMain.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/dbdih/Makefile b/ndb/src/kernel/blocks/dbdih/Makefile_old
index 83c1b95b5c4..83c1b95b5c4 100644
--- a/ndb/src/kernel/blocks/dbdih/Makefile
+++ b/ndb/src/kernel/blocks/dbdih/Makefile_old
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index 3d7980f0e73..824f74c59af 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -560,7 +560,6 @@ public:
UintR scanLocalFragid;
UintR scanSchemaVersion;
Uint32 fragPtrI;
- UintR scanSearchCondFalseCount;
UintR scanStoredProcId;
ScanState scanState;
UintR scanTcrec;
@@ -2110,7 +2109,7 @@ private:
void execCHECK_LCP_STOP(Signal* signal);
void execSEND_PACKED(Signal* signal);
void execTUP_ATTRINFO(Signal* signal);
- void execSIZEALT_REP(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execLQHFRAGREQ(Signal* signal);
void execLQHADDATTREQ(Signal* signal);
void execTUP_ADD_ATTCONF(Signal* signal);
@@ -2329,7 +2328,6 @@ private:
void initialiseLogPage(Signal* signal);
void initialiseLogPart(Signal* signal);
void initialisePageRef(Signal* signal);
- void sendInitialiseRecords(Signal* signal, Uint32 data);
void initialiseScanrec(Signal* signal);
void initialiseTabrec(Signal* signal);
void initialiseTcrec(Signal* signal);
@@ -2463,7 +2461,6 @@ private:
void closeCopyRequestLab(Signal* signal);
void closeScanRequestLab(Signal* signal);
void scanTcConnectLab(Signal* signal, Uint32 startTcCon, Uint32 fragId);
- void returnInitialiseRecordsLab(Signal* signal);
void initGcpRecLab(Signal* signal);
void prepareContinueAfterBlockedLab(Signal* signal);
void commitContinueAfterBlockedLab(Signal* signal);
@@ -2480,7 +2477,7 @@ private:
void accFragRefLab(Signal* signal);
void rwConcludedLab(Signal* signal);
void sendsttorryLab(Signal* signal);
- void initialiseRecordsLab(Signal* signal, Uint32 data);
+ void initialiseRecordsLab(Signal* signal, Uint32 data, Uint32, Uint32);
void startphase2Lab(Signal* signal, Uint32 config);
void startphase3Lab(Signal* signal);
void startphase4Lab(Signal* signal);
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
index cb1698ec8c0..d5f40ec143c 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
@@ -220,7 +220,7 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_CHECK_LCP_STOP, &Dblqh::execCHECK_LCP_STOP);
addRecSignal(GSN_SEND_PACKED, &Dblqh::execSEND_PACKED);
addRecSignal(GSN_TUP_ATTRINFO, &Dblqh::execTUP_ATTRINFO);
- addRecSignal(GSN_SIZEALT_REP, &Dblqh::execSIZEALT_REP);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Dblqh::execREAD_CONFIG_REQ, true);
addRecSignal(GSN_LQHFRAGREQ, &Dblqh::execLQHFRAGREQ);
addRecSignal(GSN_LQHADDATTREQ, &Dblqh::execLQHADDATTREQ);
addRecSignal(GSN_TUP_ADD_ATTCONF, &Dblqh::execTUP_ADD_ATTCONF);
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index debea883cfc..1abf4b3a7e9 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -32,14 +32,12 @@
#include <signaldata/GCPSave.hpp>
#include <signaldata/TcKeyRef.hpp>
#include <signaldata/LqhKey.hpp>
-#include <signaldata/LqhSizeAltReq.hpp>
#include <signaldata/NextScan.hpp>
#include <signaldata/NFCompleteRep.hpp>
#include <signaldata/NodeFailRep.hpp>
#include <signaldata/ReadNodesConf.hpp>
#include <signaldata/RelTabMem.hpp>
#include <signaldata/ScanFrag.hpp>
-#include <signaldata/SetVarReq.hpp>
#include <signaldata/SrFragidConf.hpp>
#include <signaldata/StartFragReq.hpp>
#include <signaldata/StartRec.hpp>
@@ -333,7 +331,7 @@ void Dblqh::execCONTINUEB(Signal* signal)
break;
case ZINITIALISE_RECORDS:
jam();
- initialiseRecordsLab(signal, data0);
+ initialiseRecordsLab(signal, data0, data2, signal->theData[4]);
return;
break;
case ZINIT_GCP_REC:
@@ -467,7 +465,6 @@ void Dblqh::execNDB_STTOR(Signal* signal)
Uint32 ownNodeId = signal->theData[1]; /* START PHASE*/
cstartPhase = signal->theData[2]; /* MY NODE ID */
cstartType = signal->theData[3]; /* START TYPE */
- Uint32 config1 = signal->theData[10]; /* CONFIG INFO LQH */
switch (cstartPhase) {
case ZSTART_PHASE1:
@@ -488,7 +485,7 @@ void Dblqh::execNDB_STTOR(Signal* signal)
// Dont setAPIVersion
LqhKeyReq::setMarkerFlag(preComputedRequestInfoMask, 1);
//preComputedRequestInfoMask = 0x003d7fff;
- startphase1Lab(signal, config1, ownNodeId);
+ startphase1Lab(signal, /* dummy */ ~0, ownNodeId);
signal->theData[0] = ZOPERATION_EVENT_REP;
signal->theData[1] = 1;
@@ -497,7 +494,7 @@ void Dblqh::execNDB_STTOR(Signal* signal)
break;
case ZSTART_PHASE2:
jam();
- startphase2Lab(signal, config1);
+ startphase2Lab(signal, /* dummy */ ~0);
return;
break;
case ZSTART_PHASE3:
@@ -539,17 +536,12 @@ void Dblqh::sttorStartphase1Lab(Signal* signal)
/* */
/* INITIATE ALL RECORDS WITHIN THE BLOCK */
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-void Dblqh::startphase1Lab(Signal* signal, Uint32 config, Uint32 ownNodeId)
+void Dblqh::startphase1Lab(Signal* signal, Uint32 _dummy, Uint32 ownNodeId)
{
UintR Ti;
HostRecordPtr ThostPtr;
/* ------- INITIATE ALL RECORDS ------- */
- if (config == 0) {
- jam();
- config = 1;
- }//if
- cnoLogFiles = config;
cownNodeid = ownNodeId;
caccBlockref = calcAccBlockRef (cownNodeid);
ctupBlockref = calcTupBlockRef (cownNodeid);
@@ -576,15 +568,8 @@ void Dblqh::startphase1Lab(Signal* signal, Uint32 config, Uint32 ownNodeId)
/* EVERY CONNECTION RECORD IN LQH IS ASSIGNED TO ONE ACC CONNECTION RECORD */
/* AND ONE TUP CONNECTION RECORD. */
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-void Dblqh::startphase2Lab(Signal* signal, Uint32 config)
+void Dblqh::startphase2Lab(Signal* signal, Uint32 _dummy)
{
- if (config == 0) {
- jam();
- config = 1;
- } else if (config > 4) {
- jam();
- config = 4;
- }//if
cmaxWordsAtNodeRec = MAX_NO_WORDS_OUTSTANDING_COPY_FRAGMENT;
/* -- ACC AND TUP CONNECTION PROCESS -- */
tcConnectptr.i = 0;
@@ -836,30 +821,38 @@ void Dblqh::execREAD_NODESREF(Signal* signal)
/* *************** */
/* SIZEALT_REP > */
/* *************** */
-void Dblqh::execSIZEALT_REP(Signal* signal)
+void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
{
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+ ndbrequire(req->noOfParameters == 0);
+
jamEntry();
- cfragrecFileSize = signal->theData[LqhSizeAltReq::IND_FRAG];
- ctabrecFileSize = signal->theData[LqhSizeAltReq::IND_TABLE];
- ctcConnectrecFileSize = signal->theData[LqhSizeAltReq::IND_TC_CONNECT];
- clogFileFileSize = signal->theData[LqhSizeAltReq::IND_LOG_FILES];
- cscanrecFileSize = signal->theData[LqhSizeAltReq::IND_SCAN];
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ cnoLogFiles = 8;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_REDOLOG_FILES,
+ &cnoLogFiles));
+ ndbrequire(cnoLogFiles > 0);
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_FRAG, &cfragrecFileSize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TABLE, &ctabrecFileSize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TC_CONNECT,
+ &ctcConnectrecFileSize));
+ clogFileFileSize = 4 * cnoLogFiles;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_SCAN, &cscanrecFileSize));
cmaxAccOps = cscanrecFileSize * MAX_PARALLEL_SCANS_PER_FRAG;
+
initRecords();
- initialiseRecordsLab(signal, 0);
+ initialiseRecordsLab(signal, 0, ref, senderData);
return;
}//Dblqh::execSIZEALT_REP()
-void Dblqh::returnInitialiseRecordsLab(Signal* signal)
-{
- signal->theData[0] = DBLQH_REF;
- sendSignal(CMVMI_REF, GSN_SIZEALT_ACK, signal, 2, JBB);
-
-
- return;
-}//Dblqh::returnInitialiseRecordsLab()
-
/* ########################################################################## */
/* ####### ADD/DELETE FRAGMENT MODULE ####### */
/* THIS MODULE IS USED BY DICTIONARY TO CREATE NEW FRAGMENTS AND DELETE */
@@ -1232,6 +1225,18 @@ Dblqh::sendAddFragReq(Signal* signal)
tuxreq->fragOff = addfragptr.p->lh3DistrBits;
tuxreq->tableType = addfragptr.p->tableType;
tuxreq->primaryTableId = addfragptr.p->primaryTableId;
+ // pointer to index fragment in TUP
+ tuxreq->tupIndexFragPtrI =
+ addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUX ?
+ fragptr.p->tupFragptr[0] : fragptr.p->tupFragptr[1];
+ // pointers to table fragments in TUP and ACC
+ FragrecordPtr tFragPtr;
+ tFragPtr.i = fragptr.p->tableFragptr;
+ ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+ tuxreq->tupTableFragPtrI[0] = tFragPtr.p->tupFragptr[0];
+ tuxreq->tupTableFragPtrI[1] = tFragPtr.p->tupFragptr[1];
+ tuxreq->accTableFragPtrI[0] = tFragPtr.p->accFragptr[0];
+ tuxreq->accTableFragPtrI[1] = tFragPtr.p->accFragptr[1];
sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ,
signal, TuxFragReq::SignalLength, JBB);
return;
@@ -2064,8 +2069,6 @@ void Dblqh::execTIME_SIGNAL(Signal* signal)
<< " scanLocalFragid="<<TscanPtr.p->scanLocalFragid
<< endl;
ndbout << " scanSchemaVersion="<<TscanPtr.p->scanSchemaVersion
- << " scanSearchCondFalseCount="<<
- TscanPtr.p->scanSearchCondFalseCount
<< " scanStoredProcId="<<TscanPtr.p->scanStoredProcId
<< " scanTcrec="<<TscanPtr.p->scanTcrec
<< endl;
@@ -7099,14 +7102,26 @@ void Dblqh::scanLockReleasedLab(Signal* signal)
sendScanFragConf(signal, ZFALSE);
} else {
jam();
+ /*
+ We came here after releasing locks after receiving SCAN_NEXTREQ from TC. We only
+ come here when scanHoldLock == ZTRUE
+ */
continueScanNextReqLab(signal);
}//if
- } else {
- ndbrequire(scanptr.p->scanReleaseCounter <=
- scanptr.p->scanCompletedOperations);
+ } else if (scanptr.p->scanReleaseCounter < scanptr.p->scanCompletedOperations) {
jam();
scanptr.p->scanReleaseCounter++;
scanReleaseLocksLab(signal);
+ } else {
+ jam();
+ /*
+ We come here when we have been scanning for a long time and not been able
+ to find scanConcurrentOperations records to return. We needed to release
+ the record we didn't want, but now we are returning all found records to
+ the API.
+ */
+ scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
+ sendScanFragConf(signal, ZFALSE);
}//if
}//Dblqh::scanLockReleasedLab()
@@ -8000,28 +8015,28 @@ void Dblqh::scanTupkeyRefLab(Signal* signal)
scanReleaseLocksLab(signal);
return;
}//if
+ Uint32 time_passed= tcConnectptr.p->tcTimer - cLqhTimeOutCount;
+ if (scanptr.p->scanCompletedOperations > 0) {
+ if (time_passed > 1) {
/* -----------------------------------------------------------------------
* WE NEED TO ENSURE THAT WE DO NOT SEARCH FOR THE NEXT TUPLE FOR A
* LONG TIME WHILE WE KEEP A LOCK ON A FOUND TUPLE. WE RATHER REPORT
- * THE FOUND TUPLE IF FOUND TUPLES ARE RARE. WE SELECT 20 TUPLES
- * WHICH SHOULD BE ROUGHLY 10 MS OF LOCK HOLD TIME.
+ * THE FOUND TUPLE IF FOUND TUPLES ARE RARE. If more than 10 ms passed we
+ * send the found tuples to the API.
* ----------------------------------------------------------------------- */
- scanptr.p->scanSearchCondFalseCount++;
-#if 0
- // MASV Uncomment this feature since it forgets
- // to release on operation record in DBACC
- // This is the quick fix and should be changed in
- // the future
- if (scanptr.p->scanSearchCondFalseCount > 20) {
- if (scanptr.p->scanCompletedOperations > 0) {
- jam();
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
- sendScanFragConf(signal, ZFALSE);
+ scanptr.p->scanReleaseCounter = scanptr.p->scanCompletedOperations + 1;
+ scanReleaseLocksLab(signal);
return;
- }//if
- }//if
-#endif
-
+ }
+ } else {
+ if (time_passed > 10) {
+ jam();
+ signal->theData[0]= scanptr.i;
+ signal->theData[1]= tcConnectptr.p->transid[0];
+ signal->theData[2]= tcConnectptr.p->transid[1];
+ execSCAN_HBREP(signal);
+ }
+ }
scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_ABORT;
scanNextLoopLab(signal);
}//Dblqh::scanTupkeyRefLab()
@@ -8179,7 +8194,6 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
scanptr.p->scanLockMode = scanLockMode;
scanptr.p->readCommitted = readCommitted;
scanptr.p->rangeScan = idx;
- scanptr.p->scanSearchCondFalseCount = 0;
scanptr.p->scanState = ScanRecord::SCAN_FREE;
scanptr.p->scanFlag = ZFALSE;
scanptr.p->scanLocalref[0] = 0;
@@ -8480,7 +8494,6 @@ void Dblqh::sendKeyinfo20(Signal* signal,
* ------------------------------------------------------------------------ */
void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
{
- scanptr.p->scanSearchCondFalseCount = 0;
scanptr.p->scanTcWaiting = ZFALSE;
ScanFragConf * conf = (ScanFragConf*)&signal->theData[0];
@@ -16024,7 +16037,8 @@ void Dblqh::initialisePageRef(Signal* signal)
*
* TAKES CARE OF INITIATION OF ALL RECORDS IN THIS BLOCK.
* ========================================================================= */
-void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data)
+void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data,
+ Uint32 retRef, Uint32 retData)
{
switch (data) {
case 0:
@@ -16062,90 +16076,81 @@ void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data)
csrExecUndoLogState = EULS_IDLE;
c_lcpId = 0;
cnoOfFragsCheckpointed = 0;
- sendInitialiseRecords(signal, data);
break;
case 1:
jam();
initialiseAddfragrec(signal);
- sendInitialiseRecords(signal, data);
break;
case 2:
jam();
initialiseAttrbuf(signal);
- sendInitialiseRecords(signal, data);
break;
case 3:
jam();
initialiseDatabuf(signal);
- sendInitialiseRecords(signal, data);
break;
case 4:
jam();
initialiseFragrec(signal);
- sendInitialiseRecords(signal,data);
break;
case 5:
jam();
initialiseGcprec(signal);
initialiseLcpRec(signal);
initialiseLcpLocrec(signal);
- sendInitialiseRecords(signal, data);
break;
case 6:
jam();
initialiseLogPage(signal);
- sendInitialiseRecords(signal, data);
break;
case 7:
jam();
initialiseLfo(signal);
- sendInitialiseRecords(signal, data);
break;
case 8:
jam();
initialiseLogFile(signal);
initialiseLogPart(signal);
- sendInitialiseRecords(signal, data);
break;
case 9:
jam();
initialisePageRef(signal);
- sendInitialiseRecords(signal, data);
break;
case 10:
jam();
initialiseScanrec(signal);
- sendInitialiseRecords(signal, data);
break;
case 11:
jam();
initialiseTabrec(signal);
- sendInitialiseRecords(signal, data);
break;
case 12:
jam();
initialiseTcNodeFailRec(signal);
initialiseTcrec(signal);
- returnInitialiseRecordsLab(signal);
+ {
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = retData;
+ sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+ }
return;
break;
default:
ndbrequire(false);
break;
}//switch
- return;
-}//Dblqh::initialiseRecordsLab()
-/* --------------------------------------------------------------------------
- * SEND REAL-TIME BREAK SIGNAL DURING INITIALISATION IN SYSTEM RESTART.
- * ------------------------------------------------------------------------- */
-void Dblqh::sendInitialiseRecords(Signal* signal, Uint32 data)
-{
signal->theData[0] = ZINITIALISE_RECORDS;
signal->theData[1] = data + 1;
signal->theData[2] = 0;
- sendSignal(DBLQH_REF, GSN_CONTINUEB, signal, 3, JBB);
-}//Dblqh::sendInitialiseRecords()
+ signal->theData[3] = retRef;
+ signal->theData[4] = retData;
+ sendSignal(DBLQH_REF, GSN_CONTINUEB, signal, 5, JBB);
+
+ return;
+}//Dblqh::initialiseRecordsLab()
/* ==========================================================================
* ======= INITIATE TC CONNECTION RECORD =======
@@ -17956,11 +17961,10 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
sp.p->scanAiLength,
sp.p->scanCompletedOperations,
sp.p->scanConcurrentOperations);
- infoEvent(" errCnt=%d, localFid=%d, schV=%d, searcCondFalseC=%d",
+ infoEvent(" errCnt=%d, localFid=%d, schV=%d",
sp.p->scanErrorCounter,
sp.p->scanLocalFragid,
- sp.p->scanSchemaVersion,
- sp.p->scanSearchCondFalseCount);
+ sp.p->scanSchemaVersion);
infoEvent(" stpid=%d, flag=%d, lhold=%d, lmode=%d, num=%d",
sp.p->scanStoredProcId,
sp.p->scanFlag,
@@ -18013,7 +18017,7 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
void Dblqh::execSET_VAR_REQ(Signal* signal)
{
-
+#if 0
SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0];
ConfigParamId var = setVarReq->variable();
@@ -18031,7 +18035,7 @@ void Dblqh::execSET_VAR_REQ(Signal* signal)
default:
sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB);
} // switch
-
+#endif
}//execSET_VAR_REQ()
diff --git a/ndb/src/kernel/blocks/dblqh/Makefile.am b/ndb/src/kernel/blocks/dblqh/Makefile.am
new file mode 100644
index 00000000000..3a58dba742e
--- /dev/null
+++ b/ndb/src/kernel/blocks/dblqh/Makefile.am
@@ -0,0 +1,11 @@
+#SUBDIRS = redoLogReader
+
+noinst_LIBRARIES = libdblqh.a
+
+libdblqh_a_SOURCES = DblqhInit.cpp DblqhMain.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/dblqh/Makefile b/ndb/src/kernel/blocks/dblqh/Makefile_old
index 520486d8058..520486d8058 100644
--- a/ndb/src/kernel/blocks/dblqh/Makefile
+++ b/ndb/src/kernel/blocks/dblqh/Makefile_old
diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index 3fc79120942..c87712e1887 100644
--- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -955,7 +955,6 @@ public:
LqhTransState lqhTransStatus;
TakeOverState takeOverStatus;
bool inPackedList;
- UintR ndbVersion;
UintR noOfPackedWordsLqh;
UintR packedWordsLqh[26];
UintR noOfWordsTCKEYCONF;
@@ -1336,7 +1335,7 @@ private:
void execSCAN_TABINFO(Signal* signal);
void execSCAN_FRAGCONF(Signal* signal);
void execSCAN_FRAGREF(Signal* signal);
- void execSIZEALT_REP(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execLQH_TRANSCONF(Signal* signal);
void execCOMPLETECONF(Signal* signal);
void execCOMMITCONF(Signal* signal);
@@ -1496,7 +1495,6 @@ private:
AttrbufRecord * const regAttrPtr,
UintR TBref);
void sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr);
- void sendInitialiseRecords(Signal* signal, UintR Tnext);
void sendKeyinfo(Signal* signal, BlockReference TBRef, Uint32 len);
void sendlqhkeyreq(Signal* signal, BlockReference TBRef);
void sendSystemError(Signal* signal);
@@ -1613,7 +1611,6 @@ private:
void scanCompletedLab(Signal* signal);
void scanFragError(Signal* signal, Uint32 errorCode);
void diverify010Lab(Signal* signal);
- void returnInitialiseRecordsLab(Signal* signal);
void intstartphase2x010Lab(Signal* signal);
void intstartphase3x010Lab(Signal* signal);
void sttorryLab(Signal* signal);
@@ -1627,7 +1624,7 @@ private:
void completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd);
void completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd);
void timeOutLoopStartLab(Signal* signal, Uint32 apiConnectPtr);
- void initialiseRecordsLab(Signal* signal, UintR Tdata0);
+ void initialiseRecordsLab(Signal* signal, UintR Tdata0, Uint32, Uint32);
void tckeyreq020Lab(Signal* signal);
void intstartphase2x020Lab(Signal* signal);
void intstartphase1x010Lab(Signal* signal);
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
index 0982ae5bff5..61ecca513f0 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
@@ -182,19 +182,24 @@ Dbtc::Dbtc(const class Configuration & conf):
BLOCK_CONSTRUCTOR(Dbtc);
- const Properties * p = conf.getOwnProperties();
+ const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
ndbrequire(p != 0);
Uint32 transactionBufferMemory = 0;
Uint32 maxNoOfIndexes = 0, maxNoOfConcurrentIndexOperations = 0;
Uint32 maxNoOfTriggers = 0, maxNoOfFiredTriggers = 0;
- p->get("TransactionBufferMemory", &transactionBufferMemory);
- p->get("MaxNoOfIndexes", &maxNoOfIndexes);
- p->get("MaxNoOfConcurrentIndexOperations", &maxNoOfConcurrentIndexOperations);
- p->get("MaxNoOfTriggers", &maxNoOfTriggers);
- p->get("MaxNoOfFiredTriggers", &maxNoOfFiredTriggers);
-
+ ndb_mgm_get_int_parameter(p, CFG_DB_TRANS_BUFFER_MEM,
+ &transactionBufferMemory);
+ ndb_mgm_get_int_parameter(p, CFG_DB_NO_INDEXES,
+ &maxNoOfIndexes);
+ ndb_mgm_get_int_parameter(p, CFG_DB_NO_INDEX_OPS,
+ &maxNoOfConcurrentIndexOperations);
+ ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
+ &maxNoOfTriggers);
+ ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGER_OPS,
+ &maxNoOfFiredTriggers);
+
c_transactionBufferSpace =
transactionBufferMemory / AttributeBuffer::getSegmentSize();
c_maxNumberOfIndexes = maxNoOfIndexes;
@@ -247,7 +252,7 @@ Dbtc::Dbtc(const class Configuration & conf):
addRecSignal(GSN_SCAN_TABREQ, &Dbtc::execSCAN_TABREQ);
addRecSignal(GSN_SCAN_FRAGCONF, &Dbtc::execSCAN_FRAGCONF);
addRecSignal(GSN_SCAN_FRAGREF, &Dbtc::execSCAN_FRAGREF);
- addRecSignal(GSN_SIZEALT_REP, &Dbtc::execSIZEALT_REP);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Dbtc::execREAD_CONFIG_REQ, true);
addRecSignal(GSN_LQH_TRANSCONF, &Dbtc::execLQH_TRANSCONF);
addRecSignal(GSN_COMPLETECONF, &Dbtc::execCOMPLETECONF);
addRecSignal(GSN_COMMITCONF, &Dbtc::execCOMMITCONF);
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index feb5712d9d3..5afd79687a1 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -29,8 +29,6 @@
#include <signaldata/AttrInfo.hpp>
#include <signaldata/TransIdAI.hpp>
#include <signaldata/TcRollbackRep.hpp>
-#include <signaldata/TcSizeAltReq.hpp>
-#include <signaldata/SetVarReq.hpp>
#include <signaldata/NodeFailRep.hpp>
#include <signaldata/ReadNodesConf.hpp>
#include <signaldata/NFCompleteRep.hpp>
@@ -108,6 +106,7 @@ void Dbtc::execCONTINUEB(Signal* signal)
tcase = signal->theData[0];
UintR Tdata0 = signal->theData[1];
UintR Tdata1 = signal->theData[2];
+ UintR Tdata2 = signal->theData[3];
switch (tcase) {
case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
jam();
@@ -138,7 +137,7 @@ void Dbtc::execCONTINUEB(Signal* signal)
return;
case TcContinueB::ZINITIALISE_RECORDS:
jam();
- initialiseRecordsLab(signal, Tdata0);
+ initialiseRecordsLab(signal, Tdata0, Tdata2, signal->theData[4]);
return;
case TcContinueB::ZSEND_COMMIT_LOOP:
jam();
@@ -497,15 +496,30 @@ void Dbtc::execALTER_TAB_REQ(Signal * signal)
/* ***************************************************************************/
/* START / RESTART */
/* ***************************************************************************/
-void Dbtc::execSIZEALT_REP(Signal* signal)
+void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
{
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+ ndbrequire(req->noOfParameters == 0);
+
jamEntry();
- tblockref = signal->theData[TcSizeAltReq::IND_BLOCK_REF];
- const UintR apiConnect = signal->theData[TcSizeAltReq::IND_API_CONNECT];
- const UintR tcConnect = signal->theData[TcSizeAltReq::IND_TC_CONNECT];
- const UintR tables = signal->theData[TcSizeAltReq::IND_TABLE];
- const UintR localScan = signal->theData[TcSizeAltReq::IND_LOCAL_SCAN];
- const UintR tcScan = signal->theData[TcSizeAltReq::IND_TC_SCAN];
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ UintR apiConnect;
+ UintR tcConnect;
+ UintR tables;
+ UintR localScan;
+ UintR tcScan;
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_API_CONNECT, &apiConnect));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TC_CONNECT, &tcConnect));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TABLE, &tables));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_LOCAL_SCAN, &localScan));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_SCAN, &tcScan));
ccacheFilesize = (apiConnect/3) + 1;
capiConnectFilesize = apiConnect;
@@ -516,14 +530,22 @@ void Dbtc::execSIZEALT_REP(Signal* signal)
cscanFragrecFileSize = localScan;
initRecords();
- initialiseRecordsLab(signal, (UintR)0);
-}//Dbtc::execSIZEALT_REP()
+ initialiseRecordsLab(signal, 0, ref, senderData);
-void Dbtc::returnInitialiseRecordsLab(Signal* signal)
-{
- signal->theData[0] = DBTC_REF;
- sendSignal(CMVMI_REF, GSN_SIZEALT_ACK, signal, 2, JBB);
-}//Dbtc::returnInitialiseRecordsLab()
+ Uint32 val = 3000;
+ ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
+ set_timeout_value(val);
+
+ val = 3000;
+ ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, &val);
+ set_appl_timeout_value(val);
+
+ val = 1;
+ //ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_TRANSACTION_TAKEOVER, &val);
+ set_no_parallel_takeover(val);
+
+ ctimeOutCheckDelay = 50; // 500ms
+}//Dbtc::execSIZEALT_REP()
void Dbtc::execSTTOR(Signal* signal)
{
@@ -568,19 +590,13 @@ void Dbtc::execNDB_STTOR(Signal* signal)
tnodeid = signal->theData[1];
tndbstartphase = signal->theData[2]; /* START PHASE */
tstarttype = signal->theData[3]; /* START TYPE */
- Uint32 config1 = signal->theData[12]; /* CONFIG INFO TC */
- Uint32 config2 = signal->theData[13]; /* CONFIG INFO TC */
switch (tndbstartphase) {
case ZINTSPH1:
jam();
- ctimeOutCheckDelay = 50; // 500ms
- set_timeout_value(config1);
- set_no_parallel_takeover(config2);
intstartphase1x010Lab(signal);
return;
case ZINTSPH2:
jam();
- set_appl_timeout_value(config2);
intstartphase2x010Lab(signal);
return;
case ZINTSPH3:
@@ -747,10 +763,8 @@ void Dbtc::execREAD_NODESCONF(Signal* signal)
if (NodeBitmask::get(readNodes->allNodes, i)) {
hostptr.i = i;
ptrCheckGuard(hostptr, chostFilesize, hostRecord);
-
+
hostptr.p->takeOverStatus = TOS_IDLE;
- hostptr.p->ndbVersion = ReadNodesConf::getVersionId
- (i, readNodes->theVersionIds);
if (NodeBitmask::get(readNodes->inactiveNodes, i)) {
jam();
@@ -2722,8 +2736,8 @@ void Dbtc::execTCKEYREQ(Signal* signal)
case ZUPDATE:
jam();
if (Tattrlength == 0) {
- TCKEY_abort(signal, 5);
- return;
+ //TCKEY_abort(signal, 5);
+ //return;
}//if
/*---------------------------------------------------------------------*/
// The missing break is intentional since we also want to set the opLock
@@ -5936,62 +5950,70 @@ void Dbtc::checkStartFragTimeout(Signal* signal)
/* BEEN DELAYED FOR SO LONG THAT WE ARE FORCED TO PERFORM */
/* SOME ACTION, EITHER ABORT OR RESEND OR REMOVE A NODE FROM */
/* THE WAITING PART OF A PROTOCOL. */
+/*
+The algorithm used here is to check 1024 transactions at a time before
+doing a real-time break.
+To avoid aborting both transactions in a deadlock detected by time-out
+we insert a random extra time-out of upto 630 ms by using the lowest
+six bits of the api connect reference.
+We spread it out from 0 to 630 ms if base time-out is larger than 3 sec,
+we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec,
+and otherwise we spread it out 310 ms.
+*/
/*------------------------------------------------------------------*/
-void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 TapiConPtr)
+void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
{
- UintR texpiredTime[8];
- UintR TloopCount = 0;
+ Uint32 end_ptr, time_passed, time_out_value, mask_value;
+ const Uint32 api_con_sz= capiConnectFilesize;
+ const Uint32 tc_timer= ctcTimer;
+ const Uint32 time_out_param= ctimeOutValue;
- ctimeOutCheckHeartbeat = ctcTimer;
+ ctimeOutCheckHeartbeat = tc_timer;
- const Uint32 TapiConSz = capiConnectFilesize;
- const Uint32 TtcTimer = ctcTimer;
- const Uint32 TtimeOutValue = ctimeOutValue;
-
- while ((TapiConPtr + 8) < TapiConSz) {
- jam();
- texpiredTime[0] = TtcTimer - getApiConTimer(TapiConPtr + 0);
- texpiredTime[1] = TtcTimer - getApiConTimer(TapiConPtr + 1);
- texpiredTime[2] = TtcTimer - getApiConTimer(TapiConPtr + 2);
- texpiredTime[3] = TtcTimer - getApiConTimer(TapiConPtr + 3);
- texpiredTime[4] = TtcTimer - getApiConTimer(TapiConPtr + 4);
- texpiredTime[5] = TtcTimer - getApiConTimer(TapiConPtr + 5);
- texpiredTime[6] = TtcTimer - getApiConTimer(TapiConPtr + 6);
- texpiredTime[7] = TtcTimer - getApiConTimer(TapiConPtr + 7);
- for (Uint32 Ti = 0; Ti < 8; Ti++) {
- if (getApiConTimer(TapiConPtr + Ti) != 0) {
- if (texpiredTime[Ti] > TtimeOutValue) {
- jam();
- timeOutFoundLab(signal, TapiConPtr + Ti);
- return;
- }//if
- }//if
- }//for
- TapiConPtr += 8;
- if (TloopCount++ > 128) {
- jam();
- sendContinueTimeOutControl(signal, TapiConPtr);
- return;
- }//if
- }//while
- for ( ; TapiConPtr < TapiConSz; TapiConPtr++) {
+ if (api_con_ptr + 1024 < api_con_sz) {
+ jam();
+ end_ptr= api_con_ptr + 1024;
+ } else {
+ jam();
+ end_ptr= api_con_sz;
+ }
+ if (time_out_param > 300) {
+ jam();
+ mask_value= 63;
+ } else if (time_out_param < 30) {
+ jam();
+ mask_value= 7;
+ } else {
+ jam();
+ mask_value= 31;
+ }
+ for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
+ Uint32 api_timer= getApiConTimer(api_con_ptr);
jam();
- if (getApiConTimer(TapiConPtr) != 0) {
- texpiredTime[0] = TtcTimer - getApiConTimer(TapiConPtr);
- if (texpiredTime[0] > TtimeOutValue) {
+ if (api_timer != 0) {
+ time_out_value= time_out_param + (api_con_ptr & mask_value);
+ time_passed= tc_timer - api_timer;
+ if (time_passed > time_out_value) {
jam();
- timeOutFoundLab(signal, TapiConPtr);
+ timeOutFoundLab(signal, api_con_ptr);
return;
- }//if
- }//if
- }//for
- /*------------------------------------------------------------------*/
- /* */
- /* WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
- /* STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW */
- /* READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK. */
- /*------------------------------------------------------------------*/
- ctimeOutCheckActive = TOCS_FALSE;
+ }
+ }
+ }
+ if (api_con_ptr == api_con_sz) {
+ jam();
+ /*------------------------------------------------------------------*/
+ /* */
+ /* WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
+ /* STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW */
+ /* READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK. */
+ /*------------------------------------------------------------------*/
+ ctimeOutCheckActive = TOCS_FALSE;
+ } else {
+ jam();
+ sendContinueTimeOutControl(signal, api_con_ptr);
+ }
+ return;
}//Dbtc::timeOutLoopStartLab()
void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr)
@@ -10032,7 +10054,6 @@ void Dbtc::inithost(Signal* signal)
hostptr.p->inPackedList = false;
hostptr.p->takeOverStatus = TOS_NOT_DEFINED;
hostptr.p->lqhTransStatus = LTS_IDLE;
- hostptr.p->ndbVersion = ZNIL;
hostptr.p->noOfWordsTCKEYCONF = 0;
hostptr.p->noOfWordsTCINDXCONF = 0;
hostptr.p->noOfPackedWordsLqh = 0;
@@ -10040,7 +10061,8 @@ void Dbtc::inithost(Signal* signal)
}//for
}//Dbtc::inithost()
-void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0)
+void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
+ Uint32 retRef, Uint32 retData)
{
switch (Tdata0) {
case 0:
@@ -10090,7 +10112,14 @@ void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0)
case 11:
jam();
initTcFail(signal);
- returnInitialiseRecordsLab(signal);
+
+ {
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = retData;
+ sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+ }
return;
break;
default:
@@ -10099,10 +10128,19 @@ void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0)
return;
break;
}//switch
- sendInitialiseRecords(signal, (Tdata0 + 1));
- return;
-}//Dbtc::initialiseRecordsLab()
+ signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
+ signal->theData[1] = Tdata0 + 1;
+ signal->theData[2] = 0;
+ signal->theData[3] = retRef;
+ signal->theData[4] = retData;
+ sendSignal(DBTC_REF, GSN_CONTINUEB, signal, 5, JBB);
+}
+
+/* ========================================================================= */
+/* ======= INITIALISE_SCANREC ======= */
+/* */
+/* ========================================================================= */
void Dbtc::initialiseScanrec(Signal* signal)
{
ndbrequire(cscanrecFileSize > 0);
@@ -10529,18 +10567,6 @@ void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr)
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
}//Dbtc::sendContinueTimeOutControl()
-/* -------------------------------------------------------------------------
- * SEND REAL-TIME BREAK DURING INITIALISATION OF VARIABLES DURING
- * SYSTEM RESTART.
- * ------------------------------------------------------------------------- */
-void Dbtc::sendInitialiseRecords(Signal* signal, UintR Tnext)
-{
- signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
- signal->theData[1] = Tnext;
- signal->theData[2] = 0;
- sendSignal(DBTC_REF, GSN_CONTINUEB, signal, 3, JBB);
-}//Dbtc::sendInitialiseRecords()
-
void Dbtc::sendKeyinfo(Signal* signal, BlockReference TBRef, Uint32 len)
{
signal->theData[0] = tcConnectptr.i;
@@ -10861,7 +10887,7 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
void Dbtc::execSET_VAR_REQ(Signal* signal)
{
-
+#if 0
SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0];
ConfigParamId var = setVarReq->variable();
int val = setVarReq->value();
@@ -10886,7 +10912,7 @@ void Dbtc::execSET_VAR_REQ(Signal* signal)
default:
sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB);
} // switch
-
+#endif
}
void Dbtc::execABORT_ALL_REQ(Signal* signal)
@@ -10933,7 +10959,6 @@ void Dbtc::execABORT_ALL_REQ(Signal* signal)
c_abortRec.oldTimeOutValue = ctimeOutValue;
ctimeOutValue = 0;
-
const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
diff --git a/ndb/src/kernel/blocks/dbtc/Makefile.am b/ndb/src/kernel/blocks/dbtc/Makefile.am
new file mode 100644
index 00000000000..4aa514c0aba
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbtc/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libdbtc.a
+
+libdbtc_a_SOURCES = DbtcInit.cpp DbtcMain.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/dbtc/Makefile b/ndb/src/kernel/blocks/dbtc/Makefile_old
index ae876ab1f84..ae876ab1f84 100644
--- a/ndb/src/kernel/blocks/dbtc/Makefile
+++ b/ndb/src/kernel/blocks/dbtc/Makefile_old
diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
index 053b853fa82..4781230a311 100644
--- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
@@ -996,6 +996,31 @@ public:
Dbtup(const class Configuration &);
virtual ~Dbtup();
+ /*
+ * TUX uses logical tuple address when talking to ACC and LQH.
+ */
+ void tuxGetTupAddr(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32& tupAddr);
+
+ /*
+ * TUX index in TUP has single Uint32 array attribute which stores an
+ * index node. TUX reads and writes the node directly via pointer.
+ */
+ int tuxAllocNode(Signal* signal, Uint32 fragPtrI, Uint32& pageId, Uint32& pageOffset, Uint32*& node);
+ void tuxFreeNode(Signal* signal, Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* node);
+ void tuxGetNode(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32*& node);
+
+ /*
+ * TUX reads primary table attributes for index keys. Input is
+ * attribute ids in AttributeHeader format. Output is pointers to
+ * attribute data within tuple or 0 for NULL value.
+ */
+ void tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tupVersion, Uint32 numAttrs, const Uint32* attrIds, const Uint32** attrData);
+
+ /*
+ * TUX reads primary key for md5 summing and when returning keyinfo.
+ */
+ void tuxReadKeys(); // under construction
+
private:
BLOCK_DEFINES(Dbtup);
@@ -1029,7 +1054,7 @@ private:
void execFSREADCONF(Signal* signal);
void execFSREADREF(Signal* signal);
void execNDB_STTOR(Signal* signal);
- void execSIZEALT_REP(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execSET_VAR_REQ(Signal* signal);
void execDROP_TAB_REQ(Signal* signal);
void execALTER_TAB_REQ(Signal* signal);
@@ -1900,7 +1925,7 @@ private:
void releaseTabDescr(Tablerec* const regTabPtr);
void getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* const regTabPtr);
- void initialiseRecordsLab(Signal* signal, Uint32 switchData);
+ void initialiseRecordsLab(Signal* signal, Uint32 switchData, Uint32, Uint32);
void initializeAttrbufrec();
void initializeCheckpointInfoRec();
void initializeDiskBufferSegmentRecord();
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
index 982e1b8df24..095ea412701 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
@@ -27,10 +27,8 @@
#include <signaldata/FsConf.hpp>
#include <signaldata/FsRef.hpp>
#include <signaldata/FsRemoveReq.hpp>
-#include <signaldata/SetVarReq.hpp>
#include <signaldata/TupCommit.hpp>
#include <signaldata/TupKey.hpp>
-#include <signaldata/TupSizeAltReq.hpp>
#include <signaldata/DropTab.hpp>
#include <new>
@@ -118,7 +116,7 @@ Dbtup::Dbtup(const class Configuration & conf)
addRecSignal(GSN_FSREADCONF, &Dbtup::execFSREADCONF);
addRecSignal(GSN_FSREADREF, &Dbtup::execFSREADREF);
addRecSignal(GSN_NDB_STTOR, &Dbtup::execNDB_STTOR);
- addRecSignal(GSN_SIZEALT_REP, &Dbtup::execSIZEALT_REP);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Dbtup::execREAD_CONFIG_REQ, true);
addRecSignal(GSN_SET_VAR_REQ, &Dbtup::execSET_VAR_REQ);
// Trigger Signals
@@ -538,7 +536,8 @@ void Dbtup::execCONTINUEB(Signal* signal)
break;
case ZINITIALISE_RECORDS:
ljam();
- initialiseRecordsLab(signal, dataPtr);
+ initialiseRecordsLab(signal, dataPtr,
+ signal->theData[2], signal->theData[3]);
break;
case ZREL_FRAG:
ljam();
@@ -610,22 +609,37 @@ void Dbtup::execSTTOR(Signal* signal)
// SIZE_ALTREP INITIALIZE DATA STRUCTURES, FILES AND DS VARIABLES, GET READY FOR EXTERNAL
// CONNECTIONS.
/************************************************************************************************/
-void Dbtup::execSIZEALT_REP(Signal* signal)
+void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
{
- BlockReference tsizealtBlockRef;
-
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+ ndbrequire(req->noOfParameters == 0);
+
ljamEntry();
- tsizealtBlockRef = signal->theData[TupSizeAltReq::IND_BLOCK_REF];
- cnoOfFragrec = signal->theData[TupSizeAltReq::IND_FRAG];
- cnoOfOprec = signal->theData[TupSizeAltReq::IND_OP_RECS];
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_FRAG, &cnoOfFragrec));
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_OP_RECS, &cnoOfOprec));
+
// MemorySpaceTuples is specified in 8k pages, divide by 4 for 32k pages
- Uint64 noOfWords = (signal->theData[TupSizeAltReq::IND_PAGE] * 2048) + (ZWORDS_ON_PAGE - 1);
- Uint64 noOfPages = noOfWords / (Uint64)ZWORDS_ON_PAGE;
- cnoOfPage = (Uint32)noOfPages;
- initPageRangeSize(signal->theData[TupSizeAltReq::IND_PAGE_RANGE]);
- cnoOfTablerec = signal->theData[TupSizeAltReq::IND_TABLE];
- cnoOfTabDescrRec = signal->theData[TupSizeAltReq::IND_TABLE_DESC];
- Uint32 noOfStoredProc = signal->theData[TupSizeAltReq::IND_STORED_PROC];
+ Uint32 tmp;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_PAGE, &tmp));
+ Uint64 pages = (tmp * 2048 + (ZWORDS_ON_PAGE - 1))/ (Uint64)ZWORDS_ON_PAGE;
+ cnoOfPage = (Uint32)pages;
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_PAGE_RANGE, &tmp));
+ initPageRangeSize(tmp);
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_TABLE, &cnoOfTablerec));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_TABLE_DESC,
+ &cnoOfTabDescrRec));
+ Uint32 noOfStoredProc;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_STORED_PROC,
+ &noOfStoredProc));
cnoOfTabDescrRec = (cnoOfTabDescrRec & 0xFFFFFFF0) + 16;
c_storedProcPool.setSize(noOfStoredProc);
@@ -639,7 +653,14 @@ void Dbtup::execSIZEALT_REP(Signal* signal)
cnoOfLocalLogInfo = 0;
cnoFreeUndoSeg = 0;
- initialiseRecordsLab(signal, 0);
+ initialiseRecordsLab(signal, 0, ref, senderData);
+
+ clblPagesPerTick = 50;
+ //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTick);
+
+ clblPagesPerTickAfterSr = 50;
+ //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTickAfterSr);
+
}//Dbtup::execSIZEALT_REP()
void Dbtup::initRecords()
@@ -732,7 +753,8 @@ void Dbtup::initRecords()
bat[2].bits.v = 5;
}//Dbtup::initRecords()
-void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData)
+void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData,
+ Uint32 retRef, Uint32 retData)
{
switch (switchData) {
case 0:
@@ -794,19 +816,24 @@ void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData)
case 14:
ljam();
initializeRestartInfoRec();
- signal->theData[0] = cownref;
- sendSignal(CMVMI_REF, GSN_SIZEALT_ACK, signal, 1, JBB);
+
+ {
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = retData;
+ sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+ }
return;
default:
ndbrequire(false);
break;
}//switch
-/******************************************************************************/
-/* SEND REAL-TIME BREAK DURING INITIALISATION OF VARIABLES IN SYSTEM RESTART */
-/******************************************************************************/
signal->theData[0] = ZINITIALISE_RECORDS;
signal->theData[1] = switchData + 1;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
+ signal->theData[2] = retRef;
+ signal->theData[3] = retData;
+ sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
return;
}//Dbtup::initialiseRecordsLab()
@@ -816,8 +843,6 @@ void Dbtup::execNDB_STTOR(Signal* signal)
cndbcntrRef = signal->theData[0];
Uint32 ownNodeId = signal->theData[1];
Uint32 startPhase = signal->theData[2];
- Uint32 data1 = signal->theData[14];
- Uint32 data2 = signal->theData[15];
switch (startPhase) {
case ZSTARTPHASE1:
ljam();
@@ -829,7 +854,7 @@ void Dbtup::execNDB_STTOR(Signal* signal)
break;
case ZSTARTPHASE3:
ljam();
- startphase3Lab(signal, data1, data2);
+ startphase3Lab(signal, ~0, ~0);
break;
case ZSTARTPHASE4:
ljam();
@@ -856,20 +881,6 @@ void Dbtup::execNDB_STTOR(Signal* signal)
void Dbtup::startphase3Lab(Signal* signal, Uint32 config1, Uint32 config2)
{
- if (config1 > 0) {
- ljam();
- clblPagesPerTick = config1;
- } else {
- ljam();
- clblPagesPerTick = 1;
- }//if
- if (config2 > 0) {
- ljam();
- clblPagesPerTickAfterSr = config2;
- } else {
- ljam();
- clblPagesPerTickAfterSr = 1;
- }//if
clblPageCounter = clblPagesPerTick;
signal->theData[0] = ZLOAD_BAL_LCP_TIMER;
sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 1);
@@ -1291,6 +1302,7 @@ void Dbtup::seizePendingFileOpenInfoRecord(PendingFileOpenInfoPtr& pfoiPtr)
void Dbtup::execSET_VAR_REQ(Signal* signal)
{
+#if 0
SetVarReq* const setVarReq = (SetVarReq*)signal->getDataPtrSend();
ConfigParamId var = setVarReq->variable();
int val = setVarReq->value();
@@ -1310,7 +1322,7 @@ void Dbtup::execSET_VAR_REQ(Signal* signal)
default:
sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB);
} // switch
-
+#endif
}//execSET_VAR_REQ()
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
index 3a074f7fe5b..f11de5238e2 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
@@ -31,6 +31,154 @@
// methods used by ordered index
void
+Dbtup::tuxGetTupAddr(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32& tupAddr)
+{
+ ljamEntry();
+ FragrecordPtr fragPtr;
+ fragPtr.i = fragPtrI;
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ TablerecPtr tablePtr;
+ tablePtr.i = fragPtr.p->fragTableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ PagePtr pagePtr;
+ pagePtr.i = pageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, page);
+ Uint32 fragPageId = pagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
+ Uint32 tupheadsize = tablePtr.p->tupheadsize;
+ ndbrequire(pageOffset >= ZPAGE_HEADER_SIZE);
+ Uint32 offset = pageOffset - ZPAGE_HEADER_SIZE;
+ ndbrequire(offset % tupheadsize == 0);
+ Uint32 pageIndex = (offset / tupheadsize) << 1;
+ tupAddr = (fragPageId << MAX_TUPLES_BITS) | pageIndex;
+}
+
+int
+Dbtup::tuxAllocNode(Signal* signal, Uint32 fragPtrI, Uint32& pageId, Uint32& pageOffset, Uint32*& node)
+{
+ ljamEntry();
+ FragrecordPtr fragPtr;
+ fragPtr.i = fragPtrI;
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ TablerecPtr tablePtr;
+ tablePtr.i = fragPtr.p->fragTableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ PagePtr pagePtr;
+ terrorCode = 0;
+ if (! allocTh(fragPtr.p, tablePtr.p, NORMAL_PAGE, signal, pageOffset, pagePtr)) {
+ ljam();
+ ndbrequire(terrorCode != 0);
+ return terrorCode;
+ }
+ pageId = pagePtr.i;
+ Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
+ Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
+ node = &pagePtr.p->pageWord[pageOffset] + attrDataOffset;
+ return 0;
+}
+
+void
+Dbtup::tuxFreeNode(Signal* signal, Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* node)
+{
+ ljamEntry();
+ FragrecordPtr fragPtr;
+ fragPtr.i = fragPtrI;
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ TablerecPtr tablePtr;
+ tablePtr.i = fragPtr.p->fragTableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ PagePtr pagePtr;
+ pagePtr.i = pageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, page);
+ Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
+ Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
+ ndbrequire(node == &pagePtr.p->pageWord[pageOffset] + attrDataOffset);
+ freeTh(fragPtr.p, tablePtr.p, signal, pagePtr.p, pageOffset);
+}
+
+void
+Dbtup::tuxGetNode(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32*& node)
+{
+ ljamEntry();
+ FragrecordPtr fragPtr;
+ fragPtr.i = fragPtrI;
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ TablerecPtr tablePtr;
+ tablePtr.i = fragPtr.p->fragTableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ PagePtr pagePtr;
+ pagePtr.i = pageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, page);
+ Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
+ Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
+ node = &pagePtr.p->pageWord[pageOffset] + attrDataOffset;
+}
+
+void
+Dbtup::tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tupVersion, Uint32 numAttrs, const Uint32* attrIds, const Uint32** attrData)
+{
+ ljamEntry();
+ FragrecordPtr fragPtr;
+ fragPtr.i = fragPtrI;
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ TablerecPtr tablePtr;
+ tablePtr.i = fragPtr.p->fragTableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ PagePtr pagePtr;
+ pagePtr.i = pageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, page);
+ // search for tuple version if not original
+ if (pagePtr.p->pageWord[pageOffset + 1] != tupVersion) {
+ ljam();
+ OperationrecPtr opPtr;
+ opPtr.i = pagePtr.p->pageWord[pageOffset];
+ Uint32 loopGuard = 0;
+ while (true) {
+ ptrCheckGuard(opPtr, cnoOfOprec, operationrec);
+ if (opPtr.p->realPageIdC != RNIL) {
+ pagePtr.i = opPtr.p->realPageIdC;
+ pageOffset = opPtr.p->pageOffsetC;
+ ptrCheckGuard(pagePtr, cnoOfPage, page);
+ if (pagePtr.p->pageWord[pageOffset + 1] == tupVersion) {
+ ljam();
+ break;
+ }
+ }
+ ljam();
+ opPtr.i = opPtr.p->nextActiveOp;
+ ndbrequire(++loopGuard < (1 << ZTUP_VERSION_BITS));
+ }
+ }
+ const Uint32 tabDescriptor = tablePtr.p->tabDescriptor;
+ const Uint32* tupleHeader = &pagePtr.p->pageWord[pageOffset];
+ for (Uint32 i = 0; i < numAttrs; i++) {
+ AttributeHeader ah(attrIds[i]);
+ Uint32 attrId = ah.getAttributeId();
+ Uint32 index = tabDescriptor + (attrId << ZAD_LOG_SIZE);
+ Uint32 desc1 = tableDescriptor[index].tabDescr;
+ Uint32 desc2 = tableDescriptor[index + 1].tabDescr;
+ if (AttributeDescriptor::getNullable(desc1)) {
+ Uint32 offset = AttributeOffset::getNullFlagOffset(desc2);
+ ndbrequire(offset < tablePtr.p->tupNullWords);
+ offset += tablePtr.p->tupNullIndex;
+ ndbrequire(offset < tablePtr.p->tupheadsize);
+ if (AttributeOffset::isNULL(tupleHeader[offset], desc2)) {
+ ljam();
+ attrData[i] = 0;
+ continue;
+ }
+ }
+ attrData[i] = tupleHeader + AttributeOffset::getOffset(desc2);
+ }
+}
+
+void // under construction
+Dbtup::tuxReadKeys()
+{
+}
+
+// deprecated signal interfaces
+
+void
Dbtup::execTUP_READ_ATTRS(Signal* signal)
{
ljamEntry();
@@ -168,10 +316,10 @@ Dbtup::execTUP_QUERY_TH(Signal* signal)
for this transaction and savepoint id. If its tuple version equals
the requested then we have a visible tuple otherwise not.
*/
- jam();
+ ljam();
Uint32 read_tupVersion = pagePtr.p->pageWord[tempOp.pageOffset + 1];
if (read_tupVersion == req_tupVersion) {
- jam();
+ ljam();
ret_result = 1;
}
}
@@ -425,7 +573,8 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
buildPtr.p->m_tupleNo = 0;
break;
}
- pagePtr.i = getRealpid(fragPtr.p, buildPtr.p->m_pageId);
+ Uint32 realPageId = getRealpid(fragPtr.p, buildPtr.p->m_pageId);
+ pagePtr.i = realPageId;
ptrCheckGuard(pagePtr, cnoOfPage, page);
const Uint32 pageState = pagePtr.p->pageWord[ZPAGE_STATE_POS];
if (pageState != ZTH_MM_FREE &&
@@ -439,8 +588,7 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
}
// get tuple
const Uint32 tupheadsize = tablePtr.p->tupheadsize;
- const Uint32 pageOffset = ZPAGE_HEADER_SIZE +
- buildPtr.p->m_tupleNo * tupheadsize;
+ Uint32 pageOffset = ZPAGE_HEADER_SIZE + buildPtr.p->m_tupleNo * tupheadsize;
if (pageOffset + tupheadsize > ZWORDS_ON_PAGE) {
ljam();
buildPtr.p->m_pageId++;
@@ -472,15 +620,14 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
buildPtr.p->m_tupleNo++;
break;
}
+ Uint32 tupVersion = pagePtr.p->pageWord[pageOffset + 1];
OperationrecPtr pageOperPtr;
pageOperPtr.i = pagePtr.p->pageWord[pageOffset];
- Uint32 pageId = buildPtr.p->m_pageId;
- Uint32 pageIndex = buildPtr.p->m_tupleNo << 1;
if (pageOperPtr.i != RNIL) {
/*
If there is an ongoing operation on the tuple then it is either a
copy tuple or an original tuple with an ongoing transaction. In
- both cases fragPageId and pageIndex refers to the original tuple.
+ both cases realPageId and pageOffset refer to the original tuple.
The tuple address stored in TUX will always be the original tuple
but with the tuple version of the tuple we found.
@@ -490,12 +637,11 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
tuple as a copy tuple. The original tuple is stable and is thus
preferrable to store in TUX.
*/
- jam();
+ ljam();
ptrCheckGuard(pageOperPtr, cnoOfOprec, operationrec);
- pageId = pageOperPtr.p->fragPageId;
- pageIndex = pageOperPtr.p->pageIndex;
+ realPageId = pageOperPtr.p->realPageId;
+ pageOffset = pageOperPtr.p->pageOffset;
}//if
- Uint32 tup_version = pagePtr.p->pageWord[pageOffset + 1];
#ifdef TIME_MEASUREMENT
NdbTick_getMicroTimer(&start);
#endif
@@ -505,8 +651,9 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
req->tableId = tablePtr.i;
req->indexId = triggerPtr.p->indexId;
req->fragId = tablePtr.p->fragid[buildPtr.p->m_fragNo];
- req->tupAddr = (pageId << MAX_TUPLES_BITS) | pageIndex;
- req->tupVersion = tup_version;
+ req->pageId = realPageId;
+ req->pageOffset = pageOffset;
+ req->tupVersion = tupVersion;
req->opInfo = TuxMaintReq::OpAdd;
EXECUTE_DIRECT(DBTUX, GSN_TUX_MAINT_REQ,
signal, TuxMaintReq::SignalLength);
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
index 6fceea31150..a93ff4566e7 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
@@ -962,7 +962,8 @@ Dbtup::executeTuxInsertTriggers(Signal* signal,
// fill in constant part
req->tableId = regOperPtr->tableRef;
req->fragId = regOperPtr->fragId;
- req->tupAddr = (regOperPtr->fragPageId << MAX_TUPLES_BITS) | regOperPtr->pageIndex;
+ req->pageId = regOperPtr->realPageId;
+ req->pageOffset = regOperPtr->pageOffset;
req->tupVersion = tupVersion;
req->opInfo = TuxMaintReq::OpAdd;
// loop over index list
@@ -1000,7 +1001,8 @@ Dbtup::executeTuxUpdateTriggers(Signal* signal,
// fill in constant part
req->tableId = regOperPtr->tableRef;
req->fragId = regOperPtr->fragId;
- req->tupAddr = (regOperPtr->fragPageId << MAX_TUPLES_BITS) | regOperPtr->pageIndex;
+ req->pageId = regOperPtr->realPageId;
+ req->pageOffset = regOperPtr->pageOffset;
req->tupVersion = tupVersion;
req->opInfo = TuxMaintReq::OpAdd;
// loop over index list
@@ -1009,7 +1011,6 @@ Dbtup::executeTuxUpdateTriggers(Signal* signal,
triggerList.first(triggerPtr);
while (triggerPtr.i != RNIL) {
ljam();
- req->tupAddr = (regOperPtr->fragPageId << MAX_TUPLES_BITS) | regOperPtr->pageIndex;
req->indexId = triggerPtr.p->indexId;
req->errorCode = RNIL;
EXECUTE_DIRECT(DBTUX, GSN_TUX_MAINT_REQ,
@@ -1074,7 +1075,8 @@ Dbtup::executeTuxCommitTriggers(Signal* signal,
// fill in constant part
req->tableId = regOperPtr->tableRef;
req->fragId = regOperPtr->fragId;
- req->tupAddr = (regOperPtr->fragPageId << MAX_TUPLES_BITS) | regOperPtr->pageIndex;
+ req->pageId = regOperPtr->realPageId;
+ req->pageOffset = regOperPtr->pageOffset;
req->tupVersion = tupVersion;
req->opInfo = TuxMaintReq::OpRemove;
// loop over index list
@@ -1117,7 +1119,8 @@ Dbtup::executeTuxAbortTriggers(Signal* signal,
// fill in constant part
req->tableId = regOperPtr->tableRef;
req->fragId = regOperPtr->fragId;
- req->tupAddr = (regOperPtr->fragPageId << MAX_TUPLES_BITS) | regOperPtr->pageIndex;
+ req->pageId = regOperPtr->realPageId;
+ req->pageOffset = regOperPtr->pageOffset;
req->tupVersion = tupVersion;
req->opInfo = TuxMaintReq::OpRemove;
// loop over index list
diff --git a/ndb/src/kernel/blocks/dbtup/Makefile.am b/ndb/src/kernel/blocks/dbtup/Makefile.am
new file mode 100644
index 00000000000..7e94a01d43b
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbtup/Makefile.am
@@ -0,0 +1,27 @@
+noinst_LIBRARIES = libdbtup.a
+
+libdbtup_a_SOURCES = \
+ DbtupExecQuery.cpp \
+ DbtupBuffer.cpp \
+ DbtupRoutines.cpp \
+ DbtupCommit.cpp \
+ DbtupFixAlloc.cpp \
+ DbtupTrigger.cpp \
+ DbtupAbort.cpp \
+ DbtupLCP.cpp \
+ DbtupUndoLog.cpp \
+ DbtupPageMap.cpp \
+ DbtupPagMan.cpp \
+ DbtupStoredProcDef.cpp \
+ DbtupMeta.cpp \
+ DbtupTabDesMan.cpp \
+ DbtupGen.cpp \
+ DbtupSystemRestart.cpp \
+ DbtupIndex.cpp \
+ DbtupDebug.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/dbtup/Makefile b/ndb/src/kernel/blocks/dbtup/Makefile_old
index 87146f4b441..87146f4b441 100644
--- a/ndb/src/kernel/blocks/dbtup/Makefile
+++ b/ndb/src/kernel/blocks/dbtup/Makefile_old
diff --git a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
index 4737c8422c4..25e85ba9f5f 100644
--- a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
@@ -20,15 +20,18 @@
#include <new>
#include <ndb_limits.h>
#include <SimulatedBlock.hpp>
+#include <AttributeDescriptor.hpp>
#include <AttributeHeader.hpp>
#include <ArrayPool.hpp>
#include <DataBuffer.hpp>
#include <md5_hash.hpp>
+// big brother
+#include <Dbtup.hpp>
+
// signal classes
#include <signaldata/DictTabInfo.hpp>
#include <signaldata/TuxContinueB.hpp>
-#include <signaldata/TuxSizeAltReq.hpp>
#include <signaldata/BuildIndx.hpp>
#include <signaldata/TupFrag.hpp>
#include <signaldata/AlterIndx.hpp>
@@ -82,6 +85,10 @@
#define jam() jamLine(90000 + __LINE__)
#define jamEntry() jamEntryLine(90000 + __LINE__)
#endif
+#ifndef jam
+#define jam() jamLine(__LINE__)
+#define jamEntry() jamEntryLine(__LINE__)
+#endif
#undef max
#undef min
@@ -93,17 +100,17 @@ public:
Dbtux(const Configuration& conf);
virtual ~Dbtux();
+ // pointer to TUP instance in this thread
+ Dbtup* c_tup;
+
private:
// sizes are in words (Uint32)
static const unsigned MaxIndexFragments = 2 * NO_OF_FRAG_PER_NODE;
static const unsigned MaxIndexAttributes = MAX_ATTRIBUTES_IN_INDEX;
-#ifdef VM_TRACE
- static const unsigned MaxNodeHandles = 10000; // More space for printTree
-#else
- static const unsigned MaxNodeHandles = 128; // enough for 1 operation
-#endif
static const unsigned MaxAttrDataSize = 2048;
+public:
static const unsigned DescPageSize = 256;
+private:
static const unsigned MaxTreeNodeSize = MAX_TTREE_NODE_SIZE;
static const unsigned ScanBoundSegmentSize = 7;
static const unsigned MaxAccLockOps = MAX_PARALLEL_OP_PER_SCAN;
@@ -113,7 +120,7 @@ private:
struct DescEnt;
/*
- * Pointer to Uint32 data. Interpretation is context dependent.
+ * Pointer to array of Uint32.
*/
struct Data {
private:
@@ -126,10 +133,13 @@ private:
Data& operator+=(size_t n);
AttributeHeader& ah() const;
};
+ friend class Data;
/*
- * Pointer to constant Uint32 data.
+ * Pointer to array of constant Uint32.
*/
+ struct ConstData;
+ friend struct ConstData;
struct ConstData {
private:
const Uint32* m_data;
@@ -149,8 +159,12 @@ private:
static const unsigned AttributeHeaderSize = 1;
/*
- * Logical tuple address, "local key". Identifies both table tuples
- * and index tuples. The code assumes it is one word.
+ * Array of pointers to TUP table attributes. Always read-on|y.
+ */
+ typedef const Uint32** TableData;
+
+ /*
+ * Logical tuple address, "local key". Identifies table tuples.
*/
typedef Uint32 TupAddr;
static const unsigned NullTupAddr = (Uint32)-1;
@@ -164,20 +178,32 @@ private:
Uint32 m_pageId; // page i-value
Uint16 m_pageOffset; // page offset in words
TupLoc();
+ TupLoc(Uint32 pageId, Uint16 pageOffset);
+ bool operator==(const TupLoc& loc) const;
+ bool operator!=(const TupLoc& loc) const;
};
+ /*
+ * There is no const member NullTupLoc since the compiler may not be
+ * able to optimize it to TupLoc() constants. Instead null values are
+ * constructed on the stack with TupLoc().
+ */
+#define NullTupLoc TupLoc()
+
// tree definitions
/*
- * Tree entry. Points to a tuple in primary table via logical address
- * of "original" tuple and tuple version. Uses 2 words to get correct
- * aligment (one byte is wasted currently).
+ * Tree entry. Points to a tuple in primary table via physical
+ * address of "original" tuple and tuple version.
+ *
+ * ZTUP_VERSION_BITS must be 15 (or less).
*/
+ struct TreeEnt;
+ friend struct TreeEnt;
struct TreeEnt {
- TupAddr m_tupAddr; // address of original tuple
- Uint16 m_tupVersion; // version
- Uint8 m_fragBit; // which duplicated table fragment
- Uint8 unused1;
+ TupLoc m_tupLoc; // address of original tuple
+ unsigned m_tupVersion : 15; // version
+ unsigned m_fragBit : 1; // which duplicated table fragment
TreeEnt();
// methods
int cmp(const TreeEnt ent) const;
@@ -190,7 +216,7 @@ private:
* prefix 3) max and min entries 4) rest of entries 5) one extra entry
* used as work space.
*
- * struct TreeNode part 1
+ * struct TreeNode part 1, size 6 words
* min prefix part 2, size TreeHead::m_prefSize
* max prefix part 2, size TreeHead::m_prefSize
* max entry part 3
@@ -198,16 +224,23 @@ private:
* rest of entries part 4
* work entry part 5
*
+ * There are 3 links to other nodes: left child, right child, parent.
+ * These are in TupLoc format but the pageIds and pageOffsets are
+ * stored in separate arrays (saves 1 word).
+ *
* Occupancy (number of entries) is at least 1 except temporarily when
* a node is about to be removed. If occupancy is 1, only max entry
* is present but both min and max prefixes are set.
*/
+ struct TreeNode;
+ friend struct TreeNode;
struct TreeNode {
- TupAddr m_link[3]; // link to 0-left child 1-right child 2-parent
- Uint8 m_side; // we are 0-left child 1-right child 2-root
+ Uint32 m_linkPI[3]; // link to 0-left child 1-right child 2-parent
+ Uint16 m_linkPO[3]; // page offsets for above real page ids
+ unsigned m_side : 2; // we are 0-left child 1-right child 2-root
+ int m_balance : 2; // balance -1, 0, +1
+ unsigned pad1 : 4;
Uint8 m_occup; // current number of entries
- Int8 m_balance; // balance -1, 0, +1
- Uint8 unused1;
Uint32 m_nodeScan; // list of scans at this node
TreeNode();
};
@@ -228,12 +261,14 @@ private:
* Tree header. There is one in each fragment. Contains tree
* parameters and address of root node.
*/
+ struct TreeHead;
+ friend struct TreeHead;
struct TreeHead {
Uint8 m_nodeSize; // words in tree node
Uint8 m_prefSize; // words in min/max prefix each
Uint8 m_minOccup; // min entries in internal node
Uint8 m_maxOccup; // max entries in node
- TupAddr m_root; // root node
+ TupLoc m_root; // root node
TreeHead();
// methods
unsigned getSize(AccSize acc) const;
@@ -248,9 +283,10 @@ private:
* also represented by position 0 of next node. Includes direction
* and copy of entry used by scan.
*/
+ struct TreePos;
+ friend struct TreePos;
struct TreePos {
- TupAddr m_addr; // logical node address
- TupLoc m_loc; // physical address
+ TupLoc m_loc; // physical node address
Uint16 m_pos; // position 0 to m_occup
Uint8 m_match; // at an existing entry
Uint8 m_dir; // from link (0-2) or within node (3)
@@ -264,6 +300,8 @@ private:
* Descriptor page. The "hot" metadata for an index is stored as
* a contiguous array of words on some page.
*/
+ struct DescPage;
+ friend struct DescPage;
struct DescPage {
Uint32 m_nextPage;
Uint32 m_numFree; // number of free words
@@ -290,10 +328,9 @@ private:
* Attribute metadata. Size must be multiple of word size.
*/
struct DescAttr {
- unsigned m_primaryAttrId : 16;
- unsigned m_typeId : 8;
- unsigned m_nullable : 1;
- unsigned pad1 : 7;
+ Uint32 m_attrDesc; // standard AttributeDescriptor
+ Uint16 m_primaryAttrId;
+ Uint16 m_typeId;
};
static const unsigned DescAttrSize = sizeof(DescAttr) >> 2;
@@ -301,6 +338,8 @@ private:
* Complete metadata for one index. The array of attributes has
* variable size.
*/
+ struct DescEnt;
+ friend struct DescEnt;
struct DescEnt {
DescHead m_descHead;
DescAttr m_descAttr[1]; // variable size data
@@ -329,6 +368,8 @@ private:
* be for an entry we were moved away from. In any case nothing
* happens with current entry before lock wait flag is cleared.
*/
+ struct ScanOp;
+ friend struct ScanOp;
struct ScanOp {
enum {
Undef = 0,
@@ -382,6 +423,8 @@ private:
* Ordered index. Top level data structure. The primary table (table
* being indexed) lives in TUP.
*/
+ struct Index;
+ friend struct Index;
struct Index {
enum State {
NotDefined = 0,
@@ -412,6 +455,8 @@ private:
* duplicate fragments known to LQH/ACC/TUP. Includes tree header.
* There are no maintenance operation records yet.
*/
+ struct Frag;
+ friend struct Frag;
struct Frag {
Uint32 m_tableId; // copy from index level
Uint32 m_indexId;
@@ -421,9 +466,11 @@ private:
Uint16 m_descOff;
Uint16 m_numAttrs;
TreeHead m_tree;
- Uint32 m_nodeList; // node cache of current operation
- Uint32 m_nodeFree; // one node pre-allocated for insert
+ TupLoc m_freeLoc; // one node pre-allocated for insert
DLList<ScanOp> m_scanList; // current scans on this fragment
+ Uint32 m_tupIndexFragPtrI;
+ Uint32 m_tupTableFragPtrI[2];
+ Uint32 m_accTableFragPtrI[2];
union {
Uint32 nextPool;
};
@@ -454,61 +501,39 @@ private:
// node handles
/*
- * A tree operation builds a cache of accessed nodes. This allows
- * different implementations of index memory access. The cache is
- * committed and released at the end of the operation.
+ * A node handle is a reference to a tree node in TUP. It is used to
+ * operate on the node. Node handles are allocated on the stack.
*/
+ struct NodeHandle;
+ friend struct NodeHandle;
struct NodeHandle {
- enum Flags {
- // bits 0,1 mark need for left,right prefix
- DoInsert = (1 << 2),
- DoDelete = (1 << 3),
- DoUpdate = (1 << 4)
- };
- Dbtux& m_tux; // this block
Frag& m_frag; // fragment using the node
- TupAddr m_addr; // logical node address
TupLoc m_loc; // physical node address
- AccSize m_acc; // accessed size
- unsigned m_flags; // flags
- union {
- Uint32 m_next; // next active node under fragment
- Uint32 nextPool;
- };
TreeNode* m_node; // pointer to node storage
- Uint32 m_cache[MaxTreeNodeSize];
- NodeHandle(Dbtux& tux, Frag& frag);
+ AccSize m_acc; // accessed size
+ NodeHandle(Frag& frag);
+ NodeHandle(const NodeHandle& node);
+ NodeHandle& operator=(const NodeHandle& node);
// getters
- TupAddr getLink(unsigned i);
+ TupLoc getLink(unsigned i);
unsigned getChilds(); // cannot spell
unsigned getSide();
unsigned getOccup();
int getBalance();
Uint32 getNodeScan();
- Data getPref(unsigned i);
- TreeEnt getEnt(unsigned pos);
- TreeEnt getMinMax(unsigned i);
// setters
- void setLink(unsigned i, TupAddr addr);
+ void setLink(unsigned i, TupLoc loc);
void setSide(unsigned i);
void setOccup(unsigned n);
void setBalance(int b);
void setNodeScan(Uint32 scanPtrI);
- // operations XXX maybe these should move to Dbtux level
- void pushUp(Signal* signal, unsigned pos, const TreeEnt& ent);
- void popDown(Signal* signal, unsigned pos, TreeEnt& ent);
- void pushDown(Signal* signal, unsigned pos, TreeEnt& ent);
- void popUp(Signal* signal, unsigned pos, TreeEnt& ent);
- void slide(Signal* signal, Ptr<NodeHandle> nodePtr, unsigned i);
- void linkScan(Dbtux::ScanOpPtr scanPtr);
- void unlinkScan(Dbtux::ScanOpPtr scanPtr);
- bool islinkScan(Dbtux::ScanOpPtr scanPtr);
- // for ndbrequire
- void progError(int line, int cause, const char* extra);
+ // access other parts of the node
+ Data getPref(unsigned i);
+ TreeEnt getEnt(unsigned pos);
+ TreeEnt getMinMax(unsigned i);
+ // for ndbrequire and ndbassert
+ void progError(int line, int cause, const char* file);
};
- typedef Ptr<NodeHandle> NodeHandlePtr;
- ArrayPool<NodeHandle> c_nodeHandlePool;
- friend class NodeHandle;
// parameters for methods
@@ -528,6 +553,8 @@ private:
/*
* Read index key attributes.
*/
+ struct ReadPar;
+ friend struct ReadPar;
struct ReadPar {
TreeEnt m_ent; // tuple to read
unsigned m_first; // first index attribute
@@ -538,40 +565,10 @@ private:
};
/*
- * Node storage operation.
- */
- struct StorePar {
- TupStoreTh::OpCode m_opCode;// operation code
- unsigned m_offset; // data offset in words
- unsigned m_size; // number of words
- Uint32 m_errorCode; // terrorCode from TUP
- StorePar();
- };
-
- /*
- * Tree search for entry.
- */
- struct SearchPar {
- ConstData m_data; // input index key values
- TreeEnt m_ent; // input tuple and version
- SearchPar();
- };
-
- /*
- * Attribute data comparison.
- */
- struct CmpPar {
- ConstData m_data1; // full search key
- ConstData m_data2; // full or prefix data
- unsigned m_len2; // words in data2 buffer
- unsigned m_first; // first attribute
- unsigned m_numEq; // number of initial equal attributes
- CmpPar();
- };
-
- /*
* Scan bound comparison.
*/
+ struct BoundPar;
+ friend struct BoundPar;
struct BoundPar {
ConstData m_data1; // full bound data
ConstData m_data2; // full or prefix data
@@ -588,9 +585,12 @@ private:
*/
void execCONTINUEB(Signal* signal);
void execSTTOR(Signal* signal);
- void execSIZEALT_REP(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
// utils
+ void setKeyAttrs(const Frag& frag);
+ void readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, TableData keyData);
void copyAttrs(Data dst, ConstData src, CopyPar& copyPar);
+ void copyAttrs(const Frag& frag, TableData data1, Data data2, unsigned maxlen2 = MaxAttrDataSize);
/*
* DbtuxMeta.cpp
@@ -602,8 +602,6 @@ private:
bool allocDescEnt(IndexPtr indexPtr);
void freeDescEnt(IndexPtr indexPtr);
void dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 senderData);
- // helpers
- DescEnt& getDescEnt(Uint32 descPage, Uint32 descOff);
/*
* DbtuxMaint.cpp
@@ -611,29 +609,35 @@ private:
void execTUX_MAINT_REQ(Signal* signal);
void tupReadAttrs(Signal* signal, const Frag& frag, ReadPar& readPar);
void tupReadKeys(Signal* signal, const Frag& frag, ReadPar& readPar);
- void tupStoreTh(Signal* signal, const Frag& frag, NodeHandlePtr nodePtr, StorePar storePar);
/*
* DbtuxNode.cpp
*/
- void seizeNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr);
- void preallocNode(Signal* signal, Frag& frag, Uint32& errorCode);
- void findNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, TupAddr addr);
- void selectNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, TupAddr addr, AccSize acc);
- void insertNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, AccSize acc);
- void deleteNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr);
- void accessNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, AccSize acc);
- void setNodePref(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, unsigned i);
- void commitNodes(Signal* signal, Frag& frag, bool updateOk);
+ int allocNode(Signal* signal, NodeHandle& node);
+ void accessNode(Signal* signal, NodeHandle& node, AccSize acc);
+ void selectNode(Signal* signal, NodeHandle& node, TupLoc loc, AccSize acc);
+ void insertNode(Signal* signal, NodeHandle& node, AccSize acc);
+ void deleteNode(Signal* signal, NodeHandle& node);
+ void setNodePref(Signal* signal, NodeHandle& node, unsigned i);
+ // node operations
+ void nodePushUp(Signal* signal, NodeHandle& node, unsigned pos, const TreeEnt& ent);
+ void nodePopDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent);
+ void nodePushDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent);
+ void nodePopUp(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent);
+ void nodeSlide(Signal* signal, NodeHandle& dstNode, NodeHandle& srcNode, unsigned i);
+ // scans linked to node
+ void linkScan(NodeHandle& node, ScanOpPtr scanPtr);
+ void unlinkScan(NodeHandle& node, ScanOpPtr scanPtr);
+ bool islinkScan(NodeHandle& node, ScanOpPtr scanPtr);
/*
* DbtuxTree.cpp
*/
- void treeSearch(Signal* signal, Frag& frag, SearchPar searchPar, TreePos& treePos);
+ void treeSearch(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos);
void treeAdd(Signal* signal, Frag& frag, TreePos treePos, TreeEnt ent);
void treeRemove(Signal* signal, Frag& frag, TreePos treePos);
- void treeRotateSingle(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, unsigned i);
- void treeRotateDouble(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, unsigned i);
+ void treeRotateSingle(Signal* signal, Frag& frag, NodeHandle& node, unsigned i);
+ void treeRotateDouble(Signal* signal, Frag& frag, NodeHandle& node, unsigned i);
/*
* DbtuxScan.cpp
@@ -656,7 +660,8 @@ private:
/*
* DbtuxCmp.cpp
*/
- int cmpTreeAttrs(const Frag& frag, CmpPar& cmpPar);
+ int cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstData data2, unsigned maxlen2 = MaxAttrDataSize);
+ int cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableData data2);
int cmpScanBound(const Frag& frag, const BoundPar boundPar);
/*
@@ -667,23 +672,24 @@ private:
struct PrintPar {
char m_path[100]; // LR prefix
unsigned m_side; // expected side
- TupAddr m_parent; // expected parent address
+ TupLoc m_parent; // expected parent address
int m_depth; // returned depth
unsigned m_occup; // returned occupancy
bool m_ok; // returned status
PrintPar();
};
void printTree(Signal* signal, Frag& frag, NdbOut& out);
- void printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar& par);
+ void printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par);
+ friend class NdbOut& operator<<(NdbOut&, const TupLoc&);
friend class NdbOut& operator<<(NdbOut&, const TreeEnt&);
friend class NdbOut& operator<<(NdbOut&, const TreeNode&);
friend class NdbOut& operator<<(NdbOut&, const TreeHead&);
friend class NdbOut& operator<<(NdbOut&, const TreePos&);
friend class NdbOut& operator<<(NdbOut&, const DescAttr&);
+ friend class NdbOut& operator<<(NdbOut&, const ScanOp&);
friend class NdbOut& operator<<(NdbOut&, const Index&);
friend class NdbOut& operator<<(NdbOut&, const Frag&);
friend class NdbOut& operator<<(NdbOut&, const NodeHandle&);
- friend class NdbOut& operator<<(NdbOut&, const ScanOp&);
FILE* debugFile;
NdbOut debugOut;
unsigned debugFlags;
@@ -699,10 +705,25 @@ private:
Uint32 c_internalStartPhase;
Uint32 c_typeOfStart;
- // buffers
- Data c_keyBuffer; // search key or scan bound
+ /*
+ * Array of index key attribute ids in AttributeHeader format.
+ * Includes fixed attribute sizes. This is global data set at
+ * operation start and is not passed as a parameter.
+ */
+ Data c_keyAttrs;
- // small stuff
+ // buffer for search key data as pointers to TUP storage
+ TableData c_searchKey;
+
+ // buffer for current entry key data as pointers to TUP storage
+ TableData c_entryKey;
+
+ // buffer for scan bounds and keyinfo (primary key)
+ Data c_dataBuffer;
+
+ // inlined utils
+ DescEnt& getDescEnt(Uint32 descPage, Uint32 descOff);
+ Uint32 getTupAddr(const Frag& frag, TreeEnt ent);
static unsigned min(unsigned x, unsigned y);
static unsigned max(unsigned x, unsigned y);
};
@@ -800,19 +821,58 @@ Dbtux::ConstData::operator=(Data data)
return *this;
}
+// Dbtux::TupLoc
+
+inline
+Dbtux::TupLoc::TupLoc() :
+ m_pageId(RNIL),
+ m_pageOffset(0)
+{
+}
+
+inline
+Dbtux::TupLoc::TupLoc(Uint32 pageId, Uint16 pageOffset) :
+ m_pageId(pageId),
+ m_pageOffset(pageOffset)
+{
+}
+
+inline bool
+Dbtux::TupLoc::operator==(const TupLoc& loc) const
+{
+ return m_pageId == loc.m_pageId && m_pageOffset == loc.m_pageOffset;
+}
+
+inline bool
+Dbtux::TupLoc::operator!=(const TupLoc& loc) const
+{
+ return ! (*this == loc);
+}
+
// Dbtux::TreeEnt
+inline
+Dbtux::TreeEnt::TreeEnt() :
+ m_tupLoc(),
+ m_tupVersion(0),
+ m_fragBit(0)
+{
+}
+
inline int
Dbtux::TreeEnt::cmp(const TreeEnt ent) const
{
- // compare frags first (not optimal but makes easier to read logs)
if (m_fragBit < ent.m_fragBit)
return -1;
if (m_fragBit > ent.m_fragBit)
return +1;
- if (m_tupAddr < ent.m_tupAddr)
+ if (m_tupLoc.m_pageId < ent.m_tupLoc.m_pageId)
+ return -1;
+ if (m_tupLoc.m_pageId > ent.m_tupLoc.m_pageId)
+ return +1;
+ if (m_tupLoc.m_pageOffset < ent.m_tupLoc.m_pageOffset)
return -1;
- if (m_tupAddr > ent.m_tupAddr)
+ if (m_tupLoc.m_pageOffset > ent.m_tupLoc.m_pageOffset)
return +1;
if (m_tupVersion < ent.m_tupVersion)
return -1;
@@ -821,8 +881,36 @@ Dbtux::TreeEnt::cmp(const TreeEnt ent) const
return 0;
}
+// Dbtux::TreeNode
+
+inline
+Dbtux::TreeNode::TreeNode() :
+ m_side(2),
+ m_balance(0),
+ pad1(0),
+ m_occup(0),
+ m_nodeScan(RNIL)
+{
+ m_linkPI[0] = NullTupLoc.m_pageId;
+ m_linkPO[0] = NullTupLoc.m_pageOffset;
+ m_linkPI[1] = NullTupLoc.m_pageId;
+ m_linkPO[1] = NullTupLoc.m_pageOffset;
+ m_linkPI[2] = NullTupLoc.m_pageId;
+ m_linkPO[2] = NullTupLoc.m_pageOffset;
+}
+
// Dbtux::TreeHead
+inline
+Dbtux::TreeHead::TreeHead() :
+ m_nodeSize(0),
+ m_prefSize(0),
+ m_minOccup(0),
+ m_maxOccup(0),
+ m_root()
+{
+}
+
inline unsigned
Dbtux::TreeHead::getSize(AccSize acc) const
{
@@ -854,52 +942,10 @@ Dbtux::TreeHead::getEntList(TreeNode* node) const
return (TreeEnt*)ptr;
}
-// Dbtux
-
-// constructors
-
-inline
-Dbtux::TupLoc::TupLoc() :
- m_pageId(RNIL),
- m_pageOffset(0)
-{
-}
-
-inline
-Dbtux::TreeEnt::TreeEnt() :
- m_tupAddr(NullTupAddr),
- m_tupVersion(0),
- m_fragBit(255),
- unused1(0)
-{
-}
-
-inline
-Dbtux::TreeNode::TreeNode() :
- m_side(255),
- m_occup(0),
- m_balance(0),
- unused1(0xa1),
- m_nodeScan(RNIL)
-{
- m_link[0] = NullTupAddr;
- m_link[1] = NullTupAddr;
- m_link[2] = NullTupAddr;
-}
-
-inline
-Dbtux::TreeHead::TreeHead() :
- m_nodeSize(0),
- m_prefSize(0),
- m_minOccup(0),
- m_maxOccup(0),
- m_root(0)
-{
-}
+// Dbtux::TreePos
inline
Dbtux::TreePos::TreePos() :
- m_addr(NullTupAddr),
m_loc(),
m_pos(ZNIL),
m_match(false),
@@ -908,6 +954,8 @@ Dbtux::TreePos::TreePos() :
{
}
+// Dbtux::DescPage
+
inline
Dbtux::DescPage::DescPage() :
m_nextPage(RNIL),
@@ -922,6 +970,41 @@ Dbtux::DescPage::DescPage() :
}
}
+// Dbtux::ScanOp
+
+inline
+Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
+ m_state(Undef),
+ m_lockwait(false),
+ m_userPtr(RNIL),
+ m_userRef(RNIL),
+ m_tableId(RNIL),
+ m_indexId(RNIL),
+ m_fragPtrI(RNIL),
+ m_transId1(0),
+ m_transId2(0),
+ m_savePointId(0),
+ m_accLockOp(RNIL),
+ m_readCommitted(0),
+ m_lockMode(0),
+ m_keyInfo(0),
+ m_boundMin(scanBoundPool),
+ m_boundMax(scanBoundPool),
+ m_scanPos(),
+ m_lastEnt(),
+ m_nodeScan(RNIL)
+{
+ m_bound[0] = &m_boundMin;
+ m_bound[1] = &m_boundMax;
+ m_boundCnt[0] = 0;
+ m_boundCnt[1] = 0;
+ for (unsigned i = 0; i < MaxAccLockOps; i++) {
+ m_accLockOps[i] = RNIL;
+ }
+}
+
+// Dbtux::Index
+
inline
Dbtux::Index::Index() :
m_state(NotDefined),
@@ -938,6 +1021,8 @@ Dbtux::Index::Index() :
};
};
+// Dbtux::Frag
+
inline
Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
m_tableId(RNIL),
@@ -948,12 +1033,18 @@ Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
m_descOff(0),
m_numAttrs(ZNIL),
m_tree(),
- m_nodeList(RNIL),
- m_nodeFree(RNIL),
- m_scanList(scanOpPool)
+ m_freeLoc(),
+ m_scanList(scanOpPool),
+ m_tupIndexFragPtrI(RNIL)
{
+ m_tupTableFragPtrI[0] = RNIL;
+ m_tupTableFragPtrI[1] = RNIL;
+ m_accTableFragPtrI[0] = RNIL;
+ m_accTableFragPtrI[1] = RNIL;
}
+// Dbtux::FragOp
+
inline
Dbtux::FragOp::FragOp() :
m_userPtr(RNIL),
@@ -966,160 +1057,107 @@ Dbtux::FragOp::FragOp() :
{
};
+// Dbtux::NodeHandle
+
inline
-Dbtux::NodeHandle::NodeHandle(Dbtux& tux, Frag& frag) :
- m_tux(tux),
+Dbtux::NodeHandle::NodeHandle(Frag& frag) :
m_frag(frag),
- m_addr(NullTupAddr),
m_loc(),
- m_acc(AccNone),
- m_flags(0),
- m_next(RNIL),
- m_node(0)
+ m_node(0),
+ m_acc(AccNone)
{
}
inline
-Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
- m_state(Undef),
- m_lockwait(false),
- m_userPtr(RNIL),
- m_userRef(RNIL),
- m_tableId(RNIL),
- m_indexId(RNIL),
- m_fragPtrI(RNIL),
- m_transId1(0),
- m_transId2(0),
- m_savePointId(0),
- m_accLockOp(RNIL),
- m_readCommitted(0),
- m_lockMode(0),
- m_keyInfo(0),
- m_boundMin(scanBoundPool),
- m_boundMax(scanBoundPool),
- m_scanPos(),
- m_lastEnt(),
- m_nodeScan(RNIL)
+Dbtux::NodeHandle::NodeHandle(const NodeHandle& node) :
+ m_frag(node.m_frag),
+ m_loc(node.m_loc),
+ m_node(node.m_node),
+ m_acc(node.m_acc)
{
- m_bound[0] = &m_boundMin;
- m_bound[1] = &m_boundMax;
- m_boundCnt[0] = 0;
- m_boundCnt[1] = 0;
- for (unsigned i = 0; i < MaxAccLockOps; i++) {
- m_accLockOps[i] = RNIL;
- }
}
-inline
-Dbtux::CopyPar::CopyPar() :
- m_items(0),
- m_headers(true),
- m_maxwords(~0), // max unsigned
- // output
- m_numitems(0),
- m_numwords(0)
+inline Dbtux::NodeHandle&
+Dbtux::NodeHandle::operator=(const NodeHandle& node)
{
+ ndbassert(&m_frag == &node.m_frag);
+ m_loc = node.m_loc;
+ m_node = node.m_node;
+ m_acc = node.m_acc;
+ return *this;
}
-inline
-Dbtux::ReadPar::ReadPar() :
- m_first(0),
- m_count(0),
- m_data(0),
- m_size(0)
+inline Dbtux::TupLoc
+Dbtux::NodeHandle::getLink(unsigned i)
{
+ ndbrequire(i <= 2);
+ return TupLoc(m_node->m_linkPI[i], m_node->m_linkPO[i]);
}
-inline
-Dbtux::StorePar::StorePar() :
- m_opCode(TupStoreTh::OpUndefined),
- m_offset(0),
- m_size(0),
- m_errorCode(0)
+inline unsigned
+Dbtux::NodeHandle::getChilds()
{
+ return (getLink(0) != NullTupLoc) + (getLink(1) != NullTupLoc);
}
-inline
-Dbtux::SearchPar::SearchPar() :
- m_data(0),
- m_ent()
+inline unsigned
+Dbtux::NodeHandle::getSide()
{
+ return m_node->m_side;
}
-inline
-Dbtux::CmpPar::CmpPar() :
- m_data1(0),
- m_data2(0),
- m_len2(0),
- m_first(0),
- m_numEq(0)
+inline unsigned
+Dbtux::NodeHandle::getOccup()
{
+ return m_node->m_occup;
}
-inline
-Dbtux::BoundPar::BoundPar() :
- m_data1(0),
- m_data2(0),
- m_count1(0),
- m_len2(0),
- m_dir(255)
+inline int
+Dbtux::NodeHandle::getBalance()
{
+ return m_node->m_balance;
}
-#ifdef VM_TRACE
-inline
-Dbtux::PrintPar::PrintPar() :
- // caller fills in
- m_path(),
- m_side(255),
- m_parent(NullTupAddr),
- // default return values
- m_depth(0),
- m_occup(0),
- m_ok(true)
+inline Uint32
+Dbtux::NodeHandle::getNodeScan()
{
+ return m_node->m_nodeScan;
}
-#endif
-// node handles
-
-inline Dbtux::TupAddr
-Dbtux::NodeHandle::getLink(unsigned i)
+inline void
+Dbtux::NodeHandle::setLink(unsigned i, TupLoc loc)
{
ndbrequire(i <= 2);
- return m_node->m_link[i];
-}
-
-inline unsigned
-Dbtux::NodeHandle::getChilds()
-{
- return
- (m_node->m_link[0] != NullTupAddr) +
- (m_node->m_link[1] != NullTupAddr);
+ m_node->m_linkPI[i] = loc.m_pageId;
+ m_node->m_linkPO[i] = loc.m_pageOffset;
}
-inline Dbtux::TupAddr
-Dbtux::NodeHandle::getSide()
+inline void
+Dbtux::NodeHandle::setSide(unsigned i)
{
- return m_node->m_side;
+ ndbrequire(i <= 2);
+ m_node->m_side = i;
}
-inline unsigned
-Dbtux::NodeHandle::getOccup()
+inline void
+Dbtux::NodeHandle::setOccup(unsigned n)
{
- return m_node->m_occup;
+ TreeHead& tree = m_frag.m_tree;
+ ndbrequire(n <= tree.m_maxOccup);
+ m_node->m_occup = n;
}
-inline int
-Dbtux::NodeHandle::getBalance()
+inline void
+Dbtux::NodeHandle::setBalance(int b)
{
- return m_node->m_balance;
+ ndbrequire(abs(b) <= 1);
+ m_node->m_balance = b;
}
-inline Uint32
-Dbtux::NodeHandle::getNodeScan()
+inline void
+Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI)
{
- return m_node->m_nodeScan;
+ m_node->m_nodeScan = scanPtrI;
}
inline Dbtux::Data
@@ -1153,47 +1191,54 @@ Dbtux::NodeHandle::getMinMax(unsigned i)
return getEnt(i == 0 ? 0 : occup - 1);
}
-inline void
-Dbtux::NodeHandle::setLink(unsigned i, TupAddr addr)
-{
- ndbrequire(i <= 2);
- m_node->m_link[i] = addr;
- m_flags |= DoUpdate;
-}
+// parameters for methods
-inline void
-Dbtux::NodeHandle::setSide(unsigned i)
+inline
+Dbtux::CopyPar::CopyPar() :
+ m_items(0),
+ m_headers(true),
+ m_maxwords(~0), // max unsigned
+ // output
+ m_numitems(0),
+ m_numwords(0)
{
- // ndbrequire(i <= 1);
- m_node->m_side = i;
- m_flags |= DoUpdate;
}
-inline void
-Dbtux::NodeHandle::setOccup(unsigned n)
+inline
+Dbtux::ReadPar::ReadPar() :
+ m_first(0),
+ m_count(0),
+ m_data(0),
+ m_size(0)
{
- TreeHead& tree = m_frag.m_tree;
- ndbrequire(n <= tree.m_maxOccup);
- m_node->m_occup = n;
- m_flags |= DoUpdate;
}
-inline void
-Dbtux::NodeHandle::setBalance(int b)
+inline
+Dbtux::BoundPar::BoundPar() :
+ m_data1(0),
+ m_data2(0),
+ m_count1(0),
+ m_len2(0),
+ m_dir(255)
{
- ndbrequire(abs(b) <= 1);
- m_node->m_balance = b;
- m_flags |= DoUpdate;
}
-inline void
-Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI)
+#ifdef VM_TRACE
+inline
+Dbtux::PrintPar::PrintPar() :
+ // caller fills in
+ m_path(),
+ m_side(255),
+ m_parent(),
+ // default return values
+ m_depth(0),
+ m_occup(0),
+ m_ok(true)
{
- m_node->m_nodeScan = scanPtrI;
- m_flags |= DoUpdate;
}
+#endif
-// other methods
+// utils
inline Dbtux::DescEnt&
Dbtux::getDescEnt(Uint32 descPage, Uint32 descOff)
@@ -1206,6 +1251,17 @@ Dbtux::getDescEnt(Uint32 descPage, Uint32 descOff)
return *descEnt;
}
+inline Uint32
+Dbtux::getTupAddr(const Frag& frag, TreeEnt ent)
+{
+ const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
+ const TupLoc tupLoc = ent.m_tupLoc;
+ Uint32 tupAddr = NullTupAddr;
+ c_tup->tuxGetTupAddr(tableFragPtrI, tupLoc.m_pageId, tupLoc.m_pageOffset, tupAddr);
+ jamEntry();
+ return tupAddr;
+}
+
inline unsigned
Dbtux::min(unsigned x, unsigned y)
{
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
index 6404cc66213..7601a14a242 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
@@ -18,50 +18,42 @@
#include "Dbtux.hpp"
/*
- * Search key vs tree entry.
+ * Search key vs node prefix.
*
- * Compare search key and index attribute data. The attribute data may
- * be partial in which case CmpUnknown may be returned. Also counts how
- * many (additional) initial attributes were equal.
+ * The comparison starts at given attribute position (in fact 0). The
+ * position is updated by number of equal initial attributes found. The
+ * prefix may be partial in which case CmpUnknown may be returned.
*/
int
-Dbtux::cmpTreeAttrs(const Frag& frag, CmpPar& cmpPar)
+Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstData data2, unsigned maxlen2)
{
+ const unsigned numAttrs = frag.m_numAttrs;
const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
- ConstData data1 = cmpPar.m_data1;
- ConstData data2 = cmpPar.m_data2;
// number of words of attribute data left
- unsigned len2 = cmpPar.m_len2;
- const unsigned numAttrs = frag.m_numAttrs;
- unsigned index = cmpPar.m_first;
- ndbrequire(index < numAttrs);
- // skip to right position in search key XXX do it before the call
- for (unsigned i = 0; i < index; i++) {
- jam();
- data1 += AttributeHeaderSize + data1.ah().getDataSize();
- }
- unsigned numEq = 0;
+ unsigned len2 = maxlen2;
+ // skip to right position in search key
+ data1 += start;
int ret = 0;
- while (index < numAttrs) {
+ while (start < numAttrs) {
if (len2 < AttributeHeaderSize) {
jam();
ret = NdbSqlUtil::CmpUnknown;
break;
}
len2 -= AttributeHeaderSize;
- if (! data1.ah().isNULL()) {
+ if (*data1 != 0) {
if (! data2.ah().isNULL()) {
jam();
// current attribute
- const DescAttr& descAttr = descEnt.m_descAttr[index];
+ const DescAttr& descAttr = descEnt.m_descAttr[start];
const unsigned typeId = descAttr.m_typeId;
// full data size
- const unsigned size1 = data1.ah().getDataSize();
+ const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
ndbrequire(size1 != 0 && size1 == data2.ah().getDataSize());
const unsigned size2 = min(size1, len2);
len2 -= size2;
// compare
- const Uint32* const p1 = &data1[AttributeHeaderSize];
+ const Uint32* const p1 = *data1;
const Uint32* const p2 = &data2[AttributeHeaderSize];
ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size2);
if (ret != 0) {
@@ -82,18 +74,71 @@ Dbtux::cmpTreeAttrs(const Frag& frag, CmpPar& cmpPar)
break;
}
}
- data1 += AttributeHeaderSize + data1.ah().getDataSize();
+ data1 += 1;
data2 += AttributeHeaderSize + data2.ah().getDataSize();
- numEq++;
- index++;
+ start++;
}
// XXX until data format errors are handled
ndbrequire(ret != NdbSqlUtil::CmpError);
- cmpPar.m_numEq += numEq; // add to previous count
return ret;
}
/*
+ * Search key vs tree entry.
+ *
+ * Start position is updated as in previous routine.
+ */
+int
+Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableData data2)
+{
+ const unsigned numAttrs = frag.m_numAttrs;
+ const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
+ // skip to right position
+ data1 += start;
+ data2 += start;
+ int ret = 0;
+ while (start < numAttrs) {
+ if (*data1 != 0) {
+ if (*data2 != 0) {
+ jam();
+ // current attribute
+ const DescAttr& descAttr = descEnt.m_descAttr[start];
+ const unsigned typeId = descAttr.m_typeId;
+ // full data size
+ const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
+ // compare
+ const Uint32* const p1 = *data1;
+ const Uint32* const p2 = *data2;
+ ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size1);
+ if (ret != 0) {
+ jam();
+ break;
+ }
+ } else {
+ jam();
+ // not NULL < NULL
+ ret = -1;
+ break;
+ }
+ } else {
+ if (*data2 != 0) {
+ jam();
+ // NULL > not NULL
+ ret = +1;
+ break;
+ }
+ }
+ data1 += 1;
+ data2 += 1;
+ start++;
+ }
+ // XXX until data format errors are handled
+ ndbrequire(ret != NdbSqlUtil::CmpError);
+ return ret;
+}
+
+
+/*
* Scan bound vs tree entry.
*
* Compare lower or upper bound and index attribute data. The attribute
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
index c5d24205d1a..c4931685305 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
@@ -97,7 +97,7 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
PrintPar par;
strcpy(par.m_path, ".");
par.m_side = 2;
- par.m_parent = NullTupAddr;
+ par.m_parent = NullTupLoc;
printNode(signal, frag, out, tree.m_root, par);
out.m_out->flush();
if (! par.m_ok) {
@@ -106,26 +106,24 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
signal->theData[1] = 1;
execDUMP_STATE_ORD(signal);
if (debugFile != 0) {
- commitNodes(signal, frag, false);
printTree(signal, frag, debugOut);
}
}
ndbrequire(false);
}
- commitNodes(signal, frag, false);
}
void
-Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar& par)
+Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par)
{
- if (addr == NullTupAddr) {
+ if (loc == NullTupLoc) {
par.m_depth = 0;
return;
}
TreeHead& tree = frag.m_tree;
- NodeHandlePtr nodePtr;
- selectNode(signal, frag, nodePtr, addr, AccFull);
- out << par.m_path << " " << *nodePtr.p << endl;
+ NodeHandle node(frag);
+ selectNode(signal, node, loc, AccFull);
+ out << par.m_path << " " << node << endl;
// check children
PrintPar cpar[2];
ndbrequire(strlen(par.m_path) + 1 < sizeof(par.m_path));
@@ -133,57 +131,57 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
sprintf(cpar[i].m_path, "%s%c", par.m_path, "LR"[i]);
cpar[i].m_side = i;
cpar[i].m_depth = 0;
- cpar[i].m_parent = addr;
- printNode(signal, frag, out, nodePtr.p->getLink(i), cpar[i]);
+ cpar[i].m_parent = loc;
+ printNode(signal, frag, out, node.getLink(i), cpar[i]);
if (! cpar[i].m_ok) {
par.m_ok = false;
}
}
// check child-parent links
- if (nodePtr.p->getLink(2) != par.m_parent) {
+ if (node.getLink(2) != par.m_parent) {
par.m_ok = false;
out << par.m_path << " *** ";
- out << "parent addr " << hex << nodePtr.p->getLink(2);
+ out << "parent loc " << hex << node.getLink(2);
out << " should be " << hex << par.m_parent << endl;
}
- if (nodePtr.p->getSide() != par.m_side) {
+ if (node.getSide() != par.m_side) {
par.m_ok = false;
out << par.m_path << " *** ";
- out << "side " << dec << nodePtr.p->getSide();
+ out << "side " << dec << node.getSide();
out << " should be " << dec << par.m_side << endl;
}
// check balance
const int balance = -cpar[0].m_depth + cpar[1].m_depth;
- if (nodePtr.p->getBalance() != balance) {
+ if (node.getBalance() != balance) {
par.m_ok = false;
out << par.m_path << " *** ";
- out << "balance " << nodePtr.p->getBalance();
+ out << "balance " << node.getBalance();
out << " should be " << balance << endl;
}
- if (abs(nodePtr.p->getBalance()) > 1) {
+ if (abs(node.getBalance()) > 1) {
par.m_ok = false;
out << par.m_path << " *** ";
- out << "balance " << nodePtr.p->getBalance() << " is invalid" << endl;
+ out << "balance " << node.getBalance() << " is invalid" << endl;
}
// check occupancy
- if (nodePtr.p->getOccup() > tree.m_maxOccup) {
+ if (node.getOccup() > tree.m_maxOccup) {
par.m_ok = false;
out << par.m_path << " *** ";
- out << "occupancy " << nodePtr.p->getOccup();
+ out << "occupancy " << node.getOccup();
out << " greater than max " << tree.m_maxOccup << endl;
}
// check for occupancy of interior node
- if (nodePtr.p->getChilds() == 2 && nodePtr.p->getOccup() < tree.m_minOccup) {
+ if (node.getChilds() == 2 && node.getOccup() < tree.m_minOccup) {
par.m_ok = false;
out << par.m_path << " *** ";
- out << "occupancy " << nodePtr.p->getOccup() << " of interior node";
+ out << "occupancy " << node.getOccup() << " of interior node";
out << " less than min " << tree.m_minOccup << endl;
}
// check missed half-leaf/leaf merge
for (unsigned i = 0; i <= 1; i++) {
- if (nodePtr.p->getLink(i) != NullTupAddr &&
- nodePtr.p->getLink(1 - i) == NullTupAddr &&
- nodePtr.p->getOccup() + cpar[i].m_occup <= tree.m_maxOccup) {
+ if (node.getLink(i) != NullTupLoc &&
+ node.getLink(1 - i) == NullTupLoc &&
+ node.getOccup() + cpar[i].m_occup <= tree.m_maxOccup) {
par.m_ok = false;
out << par.m_path << " *** ";
out << "missed merge with child " << i << endl;
@@ -191,14 +189,26 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
}
// return values
par.m_depth = 1 + max(cpar[0].m_depth, cpar[1].m_depth);
- par.m_occup = nodePtr.p->getOccup();
+ par.m_occup = node.getOccup();
+}
+
+NdbOut&
+operator<<(NdbOut& out, const Dbtux::TupLoc& loc)
+{
+ if (loc == Dbtux::NullTupLoc) {
+ out << "null";
+ } else {
+ out << dec << loc.m_pageId;
+ out << "." << dec << loc.m_pageOffset;
+ }
+ return out;
}
NdbOut&
operator<<(NdbOut& out, const Dbtux::TreeEnt& ent)
{
out << dec << ent.m_fragBit;
- out << "-" << hex << ent.m_tupAddr;
+ out << "-" << ent.m_tupLoc;
out << "-" << dec << ent.m_tupVersion;
return out;
}
@@ -206,10 +216,13 @@ operator<<(NdbOut& out, const Dbtux::TreeEnt& ent)
NdbOut&
operator<<(NdbOut& out, const Dbtux::TreeNode& node)
{
+ Dbtux::TupLoc link0(node.m_linkPI[0], node.m_linkPO[0]);
+ Dbtux::TupLoc link1(node.m_linkPI[1], node.m_linkPO[1]);
+ Dbtux::TupLoc link2(node.m_linkPI[2], node.m_linkPO[2]);
out << "[TreeNode " << hex << &node;
- out << " [left " << hex << node.m_link[0] << "]";
- out << " [right " << hex << node.m_link[1] << "]";
- out << " [up " << hex << node.m_link[2] << "]";
+ out << " [left " << link0 << "]";
+ out << " [right " << link1 << "]";
+ out << " [up " << link2 << "]";
out << " [side " << dec << node.m_side << "]";
out << " [occup " << dec << node.m_occup << "]";
out << " [balance " << dec << (int)node.m_balance << "]";
@@ -238,7 +251,7 @@ NdbOut&
operator<<(NdbOut& out, const Dbtux::TreePos& pos)
{
out << "[TreePos " << hex << &pos;
- out << " [addr " << hex << pos.m_addr << "]";
+ out << " [loc " << pos.m_loc << "]";
out << " [pos " << dec << pos.m_pos << "]";
out << " [match " << dec << pos.m_match << "]";
out << " [dir " << dec << pos.m_dir << "]";
@@ -251,9 +264,9 @@ NdbOut&
operator<<(NdbOut& out, const Dbtux::DescAttr& descAttr)
{
out << "[DescAttr " << hex << &descAttr;
+ out << " [attrDesc " << hex << descAttr.m_attrDesc;
out << " [primaryAttrId " << dec << descAttr.m_primaryAttrId << "]";
out << " [typeId " << dec << descAttr.m_typeId << "]";
- out << " [nullable " << dec << descAttr.m_nullable << "]";
out << "]";
return out;
}
@@ -338,9 +351,8 @@ operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
const Dbtux::Frag& frag = node.m_frag;
const Dbtux::TreeHead& tree = frag.m_tree;
out << "[NodeHandle " << hex << &node;
- out << " [addr " << hex << node.m_addr << "]";
+ out << " [loc " << node.m_loc << "]";
out << " [acc " << dec << node.m_acc << "]";
- out << " [flags " << hex << node.m_flags << "]";
out << " [node " << *node.m_node << "]";
if (node.m_acc >= Dbtux::AccPref) {
for (unsigned i = 0; i <= 1; i++) {
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
index 32d66422d5c..93a5c78338c 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
@@ -16,9 +16,12 @@
#define DBTUX_GEN_CPP
#include "Dbtux.hpp"
+#include <signaldata/TuxContinueB.hpp>
+#include <signaldata/TuxContinueB.hpp>
Dbtux::Dbtux(const Configuration& conf) :
SimulatedBlock(DBTUX, conf),
+ c_tup(0),
c_descPageList(RNIL),
#ifdef VM_TRACE
debugFile(0),
@@ -27,22 +30,22 @@ Dbtux::Dbtux(const Configuration& conf) :
#endif
c_internalStartPhase(0),
c_typeOfStart(NodeState::ST_ILLEGAL_TYPE),
- c_keyBuffer(0)
+ c_dataBuffer(0)
{
BLOCK_CONSTRUCTOR(Dbtux);
// verify size assumptions (also when release-compiled)
ndbrequire(
- (sizeof(DescHead) & 0x3) == 0 &&
- (sizeof(DescAttr) & 0x3) == 0 &&
(sizeof(TreeEnt) & 0x3) == 0 &&
- (sizeof(TreeNode) & 0x3) == 0
+ (sizeof(TreeNode) & 0x3) == 0 &&
+ (sizeof(DescHead) & 0x3) == 0 &&
+ (sizeof(DescAttr) & 0x3) == 0
);
/*
* DbtuxGen.cpp
*/
addRecSignal(GSN_CONTINUEB, &Dbtux::execCONTINUEB);
addRecSignal(GSN_STTOR, &Dbtux::execSTTOR);
- addRecSignal(GSN_SIZEALT_REP, &Dbtux::execSIZEALT_REP);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Dbtux::execREAD_CONFIG_REQ, true);
/*
* DbtuxMeta.cpp
*/
@@ -121,6 +124,8 @@ Dbtux::execSTTOR(Signal* signal)
case 1:
jam();
CLEAR_ERROR_INSERT_VALUE;
+ c_tup = (Dbtup*)globalData.getBlock(DBTUP);
+ ndbrequire(c_tup != 0);
break;
case 3:
jam();
@@ -143,28 +148,41 @@ Dbtux::execSTTOR(Signal* signal)
}
void
-Dbtux::execSIZEALT_REP(Signal* signal)
+Dbtux::execREAD_CONFIG_REQ(Signal* signal)
{
jamEntry();
- const Uint32* data = signal->getDataPtr();
- BlockReference sender = data[TuxSizeAltReq::IND_BLOCK_REF];
- const Uint32 nIndex = data[TuxSizeAltReq::IND_INDEX];
- const Uint32 nFragment = data[TuxSizeAltReq::IND_FRAGMENT];
- const Uint32 nAttribute = data[TuxSizeAltReq::IND_ATTRIBUTE];
+
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+ ndbrequire(req->noOfParameters == 0);
+
+ Uint32 nIndex;
+ Uint32 nFragment;
+ Uint32 nAttribute;
+ Uint32 nScanOp;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_INDEX, &nIndex));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_FRAGMENT, &nFragment));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_ATTRIBUTE, &nAttribute));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
+
const Uint32 nDescPage = (nIndex + nAttribute + DescPageSize - 1) / DescPageSize;
- const Uint32 nScanOp = data[TuxSizeAltReq::IND_SCAN];
const Uint32 nScanBoundWords = nScanOp * ScanBoundSegmentSize * 4;
- // allocate records
+
c_indexPool.setSize(nIndex);
c_fragPool.setSize(nFragment);
c_descPagePool.setSize(nDescPage);
c_fragOpPool.setSize(MaxIndexFragments);
- c_nodeHandlePool.setSize(MaxNodeHandles);
c_scanOpPool.setSize(nScanOp);
c_scanBoundPool.setSize(nScanBoundWords);
/*
* Index id is physical array index. We seize and initialize all
- * index records now. This assumes ArrayPool is an array.
+ * index records now.
*/
IndexPtr indexPtr;
while (1) {
@@ -177,14 +195,52 @@ Dbtux::execSIZEALT_REP(Signal* signal)
new (indexPtr.p) Index();
}
// allocate buffers
- c_keyBuffer = (Uint32*)allocRecord("c_keyBuffer", sizeof(Uint64), (MaxAttrDataSize + 1) >> 1);
+ c_keyAttrs = (Uint32*)allocRecord("c_keyAttrs", sizeof(Uint32), MaxIndexAttributes);
+ c_searchKey = (TableData)allocRecord("c_searchKey", sizeof(Uint32*), MaxIndexAttributes);
+ c_entryKey = (TableData)allocRecord("c_entryKey", sizeof(Uint32*), MaxIndexAttributes);
+ c_dataBuffer = (Uint32*)allocRecord("c_dataBuffer", sizeof(Uint64), (MaxAttrDataSize + 1) >> 1);
// ack
- sendSignal(sender, GSN_SIZEALT_ACK, signal, 1, JBB);
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
}
// utils
void
+Dbtux::setKeyAttrs(const Frag& frag)
+{
+ Data keyAttrs = c_keyAttrs; // global
+ const unsigned numAttrs = frag.m_numAttrs;
+ const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
+ for (unsigned i = 0; i < numAttrs; i++) {
+ const DescAttr& descAttr = descEnt.m_descAttr[i];
+ Uint32 size = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
+ // set attr id and fixed size
+ keyAttrs.ah() = AttributeHeader(descAttr.m_primaryAttrId, size);
+ keyAttrs += 1;
+ }
+}
+
+void
+Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, TableData keyData)
+{
+ ConstData keyAttrs = c_keyAttrs; // global
+ const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
+ const TupLoc tupLoc = ent.m_tupLoc;
+ const Uint32 tupVersion = ent.m_tupVersion;
+ ndbrequire(start < frag.m_numAttrs);
+ const unsigned numAttrs = frag.m_numAttrs - start;
+ // start applies to both keys and output data
+ keyAttrs += start;
+ keyData += start;
+ c_tup->tuxReadAttrs(tableFragPtrI, tupLoc.m_pageId, tupLoc.m_pageOffset, tupVersion, numAttrs, keyAttrs, keyData);
+ jamEntry();
+}
+
+void
Dbtux::copyAttrs(Data dst, ConstData src, CopyPar& copyPar)
{
CopyPar c = copyPar;
@@ -218,4 +274,46 @@ Dbtux::copyAttrs(Data dst, ConstData src, CopyPar& copyPar)
copyPar = c;
}
+/*
+ * Input is pointers to table attributes. Output is array of attribute
+ * data with headers. Copies whatever fits.
+ */
+void
+Dbtux::copyAttrs(const Frag& frag, TableData data1, Data data2, unsigned maxlen2)
+{
+ ConstData keyAttrs = c_keyAttrs; // global
+ const unsigned numAttrs = frag.m_numAttrs;
+ unsigned len2 = maxlen2;
+ for (unsigned n = 0; n < numAttrs; n++) {
+ jam();
+ const unsigned attrId = keyAttrs.ah().getAttributeId();
+ const unsigned dataSize = keyAttrs.ah().getDataSize();
+ const Uint32* const p1 = *data1;
+ if (p1 != 0) {
+ if (len2 == 0)
+ return;
+ data2.ah() = AttributeHeader(attrId, dataSize);
+ data2 += 1;
+ len2 -= 1;
+ unsigned n = dataSize;
+ for (unsigned i = 0; i < dataSize; i++) {
+ if (len2 == 0)
+ return;
+ *data2 = p1[i];
+ data2 += 1;
+ len2 -= 1;
+ }
+ } else {
+ if (len2 == 0)
+ return;
+ data2.ah() = AttributeHeader(attrId, 0);
+ data2.ah().setNULL();
+ data2 += 1;
+ len2 -= 1;
+ }
+ keyAttrs += 1;
+ data1 += 1;
+ }
+}
+
BLOCK_FUNCTIONS(Dbtux);
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
index a6b2485067c..fc72611a273 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
@@ -33,11 +33,12 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
jam();
#ifdef VM_TRACE
if (debugFlags & DebugMaint) {
+ TupLoc tupLoc(sig->pageId, sig->pageOffset);
debugOut << "opInfo=" << hex << sig->opInfo;
debugOut << " tableId=" << dec << sig->tableId;
debugOut << " indexId=" << dec << sig->indexId;
debugOut << " fragId=" << dec << sig->fragId;
- debugOut << " tupAddr=" << hex << sig->tupAddr;
+ debugOut << " tupLoc=" << tupLoc;
debugOut << " tupVersion=" << dec << sig->tupVersion;
debugOut << " -- ignored at ISP=" << dec << c_internalStartPhase;
debugOut << " TOS=" << dec << c_typeOfStart;
@@ -72,31 +73,25 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
}
ndbrequire(fragPtr.i != RNIL);
Frag& frag = *fragPtr.p;
- ndbrequire(frag.m_nodeList == RNIL);
- // set up index entry
+ // set up index keys for this operation
+ setKeyAttrs(frag);
+ // set up search entry
TreeEnt ent;
- ent.m_tupAddr = req->tupAddr;
+ ent.m_tupLoc = TupLoc(req->pageId, req->pageOffset);
ent.m_tupVersion = req->tupVersion;
ent.m_fragBit = fragBit;
// read search key
- ReadPar readPar;
- readPar.m_ent = ent;
- readPar.m_first = 0;
- readPar.m_count = frag.m_numAttrs;
- // output goes here
- readPar.m_data = c_keyBuffer;
- tupReadAttrs(signal, frag, readPar);
+ readKeyAttrs(frag, ent, 0, c_searchKey);
// check if all keys are null
{
+ const unsigned numAttrs = frag.m_numAttrs;
bool allNull = true;
- ConstData data = readPar.m_data;
- for (unsigned i = 0; i < frag.m_numAttrs; i++) {
- if (! data.ah().isNULL()) {
+ for (unsigned i = 0; i < numAttrs; i++) {
+ if (c_searchKey[i] != 0) {
jam();
allNull = false;
break;
}
- data += AttributeHeaderSize + data.ah().getDataSize();
}
if (allNull) {
jam();
@@ -105,11 +100,6 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
return;
}
}
- // find position in tree
- SearchPar searchPar;
- searchPar.m_data = c_keyBuffer;
- searchPar.m_ent = ent;
- TreePos treePos;
#ifdef VM_TRACE
if (debugFlags & DebugMaint) {
debugOut << "opCode=" << dec << opCode;
@@ -121,7 +111,9 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
debugOut << endl;
}
#endif
- treeSearch(signal, frag, searchPar, treePos);
+ // find position in tree
+ TreePos treePos;
+ treeSearch(signal, frag, c_searchKey, ent, treePos);
#ifdef VM_TRACE
if (debugFlags & DebugMaint) {
debugOut << treePos << endl;
@@ -143,17 +135,18 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
}
/*
* At most one new node is inserted in the operation. We keep one
- * free node pre-allocated so the operation cannot fail. This also
- * gives a real TupAddr for links to the new node.
+ * free node pre-allocated so the operation cannot fail.
*/
- if (frag.m_nodeFree == RNIL) {
+ if (frag.m_freeLoc == NullTupLoc) {
jam();
- preallocNode(signal, frag, req->errorCode);
+ NodeHandle node(frag);
+ req->errorCode = allocNode(signal, node);
if (req->errorCode != 0) {
jam();
break;
}
- ndbrequire(frag.m_nodeFree != RNIL);
+ frag.m_freeLoc = node.m_loc;
+ ndbrequire(frag.m_freeLoc != NullTupLoc);
}
treeAdd(signal, frag, treePos, ent);
break;
@@ -175,7 +168,6 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
break;
}
// commit and release nodes
- commitNodes(signal, frag, req->errorCode == 0);
#ifdef VM_TRACE
if (debugFlags & DebugTree) {
printTree(signal, frag, debugOut);
@@ -199,11 +191,11 @@ Dbtux::tupReadAttrs(Signal* signal, const Frag& frag, ReadPar& readPar)
req->requestInfo = 0;
req->tableId = frag.m_tableId;
req->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
- req->fragPtrI = RNIL;
- req->tupAddr = ent.m_tupAddr;
+ req->fragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
+ req->tupAddr = (Uint32)-1;
req->tupVersion = ent.m_tupVersion;
- req->pageId = RNIL;
- req->pageOffset = 0;
+ req->pageId = ent.m_tupLoc.m_pageId;
+ req->pageOffset = ent.m_tupLoc.m_pageOffset;
req->bufferId = 0;
// add count and list of attribute ids
Data data = (Uint32*)req + TupReadAttrs::SignalLength;
@@ -246,11 +238,11 @@ Dbtux::tupReadKeys(Signal* signal, const Frag& frag, ReadPar& readPar)
req->requestInfo = TupReadAttrs::ReadKeys;
req->tableId = frag.m_tableId;
req->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
- req->fragPtrI = RNIL;
- req->tupAddr = ent.m_tupAddr;
+ req->fragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
+ req->tupAddr = (Uint32)-1;
req->tupVersion = RNIL; // not used
- req->pageId = RNIL;
- req->pageOffset = 0;
+ req->pageId = ent.m_tupLoc.m_pageId;
+ req->pageOffset = ent.m_tupLoc.m_pageOffset;
req->bufferId = 0;
// execute
EXECUTE_DIRECT(DBTUP, GSN_TUP_READ_ATTRS, signal, TupReadAttrs::SignalLength);
@@ -270,100 +262,3 @@ Dbtux::tupReadKeys(Signal* signal, const Frag& frag, ReadPar& readPar)
readPar.m_count = numKeys;
readPar.m_size = copyPar.m_numwords;
}
-
-/*
- * Operate on index node tuple in TUP. The data is copied between node
- * cache and index storage via signal data.
- */
-void
-Dbtux::tupStoreTh(Signal* signal, const Frag& frag, NodeHandlePtr nodePtr, StorePar storePar)
-{
- const TreeHead& tree = frag.m_tree;
- // define the direct signal
- TupStoreTh* req = (TupStoreTh*)signal->getDataPtrSend();
- req->errorCode = RNIL;
- req->tableId = frag.m_indexId;
- req->fragId = frag.m_fragId;
- req->fragPtrI = RNIL;
- req->tupAddr = nodePtr.p->m_addr;
- req->tupVersion = 0;
- req->pageId = nodePtr.p->m_loc.m_pageId;
- req->pageOffset = nodePtr.p->m_loc.m_pageOffset;
- req->bufferId = 0;
- req->opCode = storePar.m_opCode;
- ndbrequire(storePar.m_offset + storePar.m_size <= tree.m_nodeSize);
- req->dataOffset = storePar.m_offset;
- req->dataSize = storePar.m_size;
- // the node cache
- ndbrequire(nodePtr.p->m_node != 0);
- // the buffer in signal data
- Uint32* const buffer = (Uint32*)req + TupStoreTh::SignalLength;
- // copy in data
- switch (storePar.m_opCode) {
- case TupStoreTh::OpRead:
- jam();
- #ifdef VM_TRACE
- {
- Uint32* dst = buffer + storePar.m_offset;
- memset(dst, 0xa9, storePar.m_size << 2);
- }
- #endif
- break;
- case TupStoreTh::OpInsert:
- jam();
- // fallthru
- case TupStoreTh::OpUpdate:
- jam();
- // copy from cache to signal data
- {
- Uint32* dst = buffer + storePar.m_offset;
- const Uint32* src = (const Uint32*)nodePtr.p->m_node + storePar.m_offset;
- memcpy(dst, src, storePar.m_size << 2);
- }
- break;
- case TupStoreTh::OpDelete:
- jam();
- break;
- default:
- ndbrequire(false);
- break;
- }
- // execute
- EXECUTE_DIRECT(DBTUP, GSN_TUP_STORE_TH, signal, TupStoreTh::SignalLength);
- jamEntry();
- if (req->errorCode != 0) {
- jam();
- storePar.m_errorCode = req->errorCode;
- return;
- }
- ndbrequire(req->errorCode == 0);
- // copy out data
- switch (storePar.m_opCode) {
- case TupStoreTh::OpRead:
- jam();
- {
- Uint32* dst = (Uint32*)nodePtr.p->m_node + storePar.m_offset;
- const Uint32* src = (const Uint32*)buffer + storePar.m_offset;
- memcpy(dst, src, storePar.m_size << 2);
- }
- // fallthru
- case TupStoreTh::OpInsert:
- jam();
- // fallthru
- case TupStoreTh::OpUpdate:
- jam();
- nodePtr.p->m_addr = req->tupAddr;
- nodePtr.p->m_loc.m_pageId = req->pageId;
- nodePtr.p->m_loc.m_pageOffset = req->pageOffset;
- break;
- case TupStoreTh::OpDelete:
- jam();
- nodePtr.p->m_addr = NullTupAddr;
- nodePtr.p->m_loc.m_pageId = RNIL;
- nodePtr.p->m_loc.m_pageOffset = 0;
- break;
- default:
- ndbrequire(false);
- break;
- }
-}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
index 2ffd599429c..0612f191830 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
@@ -85,6 +85,11 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
fragPtr.p->m_fragOff = req->fragOff;
fragPtr.p->m_fragId = req->fragId;
fragPtr.p->m_numAttrs = req->noOfAttr;
+ fragPtr.p->m_tupIndexFragPtrI = req->tupIndexFragPtrI;
+ fragPtr.p->m_tupTableFragPtrI[0] = req->tupTableFragPtrI[0];
+ fragPtr.p->m_tupTableFragPtrI[1] = req->tupTableFragPtrI[1];
+ fragPtr.p->m_accTableFragPtrI[0] = req->accTableFragPtrI[0];
+ fragPtr.p->m_accTableFragPtrI[1] = req->accTableFragPtrI[1];
// add the fragment to the index
indexPtr.p->m_fragId[indexPtr.p->m_numFrags] = req->fragId;
indexPtr.p->m_fragPtrI[indexPtr.p->m_numFrags] = fragPtr.i;
@@ -176,10 +181,9 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
// define the attribute
DescEnt& descEnt = getDescEnt(indexPtr.p->m_descPage, indexPtr.p->m_descOff);
DescAttr& descAttr = descEnt.m_descAttr[attrId];
+ descAttr.m_attrDesc = req->attrDescriptor;
descAttr.m_primaryAttrId = req->primaryAttrId;
descAttr.m_typeId = req->extTypeInfo & 0xFF;
- descAttr.m_nullable = AttributeDescriptor::getNullable(req->attrDescriptor);
- descAttr.pad1 = 0;
#ifdef VM_TRACE
if (debugFlags & DebugMeta) {
debugOut << "Add frag " << fragPtr.i << " attr " << attrId << " " << descAttr << endl;
@@ -197,6 +201,7 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
jam();
// initialize tree header
TreeHead& tree = fragPtr.p->m_tree;
+ new (&tree) TreeHead();
// make these configurable later
tree.m_nodeSize = MAX_TTREE_NODE_SIZE;
tree.m_prefSize = MAX_TTREE_PREF_SIZE;
@@ -222,8 +227,8 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
break;
}
tree.m_minOccup = tree.m_maxOccup - maxSlack;
- // root node does not exist
- tree.m_root = NullTupAddr;
+ // root node does not exist (also set by ctor)
+ tree.m_root = NullTupLoc;
// fragment is defined
c_fragOpPool.release(fragOpPtr);
}
@@ -310,12 +315,6 @@ Dbtux::dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 sen
unsigned i = --indexPtr.p->m_numFrags;
FragPtr fragPtr;
c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
- Frag& frag = *fragPtr.p;
- ndbrequire(frag.m_nodeList == RNIL);
- if (frag.m_nodeFree != RNIL) {
- c_nodeHandlePool.release(frag.m_nodeFree);
- frag.m_nodeFree = RNIL;
- }
c_fragPool.release(fragPtr);
// the real time break is not used for anything currently
signal->theData[0] = TuxContinueB::DropIndex;
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
index 6733a87da97..c969e35dc82 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
@@ -18,241 +18,113 @@
#include "Dbtux.hpp"
/*
- * Node handles.
- *
- * We use the "cache" implementation. Node operations are done on
- * cached copies. Index memory is updated at the end of the operation.
- * At most one node is inserted and it is always pre-allocated.
- *
- * An alternative "pointer" implementation which writes directly into
- * index memory is planned for later.
+ * Allocate index node in TUP.
*/
-
-// Dbtux
-
-void
-Dbtux::seizeNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr)
-{
- if (! c_nodeHandlePool.seize(nodePtr)) {
- jam();
- return;
- }
- new (nodePtr.p) NodeHandle(*this, frag);
- nodePtr.p->m_next = frag.m_nodeList;
- frag.m_nodeList = nodePtr.i;
- // node cache used always
- nodePtr.p->m_node = (TreeNode*)nodePtr.p->m_cache;
- new (nodePtr.p->m_node) TreeNode();
-#ifdef VM_TRACE
- TreeHead& tree = frag.m_tree;
- TreeNode* node = nodePtr.p->m_node;
- memset(tree.getPref(node, 0), 0xa2, tree.m_prefSize << 2);
- memset(tree.getPref(node, 1), 0xa2, tree.m_prefSize << 2);
- TreeEnt* entList = tree.getEntList(node);
- memset(entList, 0xa4, (tree.m_maxOccup + 1) * (TreeEntSize << 2));
-#endif
-}
-
-void
-Dbtux::preallocNode(Signal* signal, Frag& frag, Uint32& errorCode)
-{
- ndbrequire(frag.m_nodeFree == RNIL);
- NodeHandlePtr nodePtr;
- seizeNode(signal, frag, nodePtr);
- ndbrequire(nodePtr.i != RNIL);
- // remove from cache XXX ugly
- frag.m_nodeFree = frag.m_nodeList;
- frag.m_nodeList = nodePtr.p->m_next;
- StorePar storePar;
- storePar.m_opCode = TupStoreTh::OpInsert;
- storePar.m_offset = 0;
- storePar.m_size = 0;
- tupStoreTh(signal, frag, nodePtr, storePar);
- if (storePar.m_errorCode != 0) {
- jam();
- errorCode = storePar.m_errorCode;
- c_nodeHandlePool.release(nodePtr);
- frag.m_nodeFree = RNIL;
- }
-}
-
-/*
- * Find node in the cache. XXX too slow, use direct links instead
- */
-void
-Dbtux::findNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, TupAddr addr)
-{
- NodeHandlePtr tmpPtr;
- tmpPtr.i = frag.m_nodeList;
- while (tmpPtr.i != RNIL) {
- jam();
- c_nodeHandlePool.getPtr(tmpPtr);
- if (tmpPtr.p->m_addr == addr) {
- jam();
- nodePtr = tmpPtr;
- return;
- }
- tmpPtr.i = tmpPtr.p->m_next;
- }
- nodePtr.i = RNIL;
- nodePtr.p = 0;
-}
-
-/*
- * Get handle for existing node.
- */
-void
-Dbtux::selectNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, TupAddr addr, AccSize acc)
+int
+Dbtux::allocNode(Signal* signal, NodeHandle& node)
{
- ndbrequire(addr != NullTupAddr && acc > AccNone);
- NodeHandlePtr tmpPtr;
- // search in cache
- findNode(signal, frag, tmpPtr, addr);
- if (tmpPtr.i == RNIL) {
+ Frag& frag = node.m_frag;
+ Uint32 pageId = NullTupLoc.m_pageId;
+ Uint32 pageOffset = NullTupLoc.m_pageOffset;
+ Uint32* node32 = 0;
+ int errorCode = c_tup->tuxAllocNode(signal, frag.m_tupIndexFragPtrI, pageId, pageOffset, node32);
+ jamEntry();
+ if (errorCode == 0) {
jam();
- // add new node
- seizeNode(signal, frag, tmpPtr);
- ndbrequire(tmpPtr.i != RNIL);
- tmpPtr.p->m_addr = addr;
+ node.m_loc = TupLoc(pageId, pageOffset);
+ node.m_node = reinterpret_cast<TreeNode*>(node32);
+ node.m_acc = AccNone;
+ ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
}
- if (tmpPtr.p->m_acc < acc) {
- jam();
- accessNode(signal, frag, tmpPtr, acc);
- }
- nodePtr = tmpPtr;
+ return errorCode;
}
/*
- * Create new node in the cache and mark it for insert.
+ * Access more of the node.
*/
void
-Dbtux::insertNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, AccSize acc)
+Dbtux::accessNode(Signal* signal, NodeHandle& node, AccSize acc)
{
- ndbrequire(acc > AccNone);
- NodeHandlePtr tmpPtr;
- // use the pre-allocated node
- tmpPtr.i = frag.m_nodeFree;
- frag.m_nodeFree = RNIL;
- c_nodeHandlePool.getPtr(tmpPtr);
- // move it to the cache
- tmpPtr.p->m_next = frag.m_nodeList;
- frag.m_nodeList = tmpPtr.i;
- tmpPtr.p->m_acc = acc;
- tmpPtr.p->m_flags |= NodeHandle::DoInsert;
- nodePtr = tmpPtr;
+ ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
+ if (node.m_acc >= acc)
+ return;
+ // XXX could do prefetch
+ node.m_acc = acc;
}
/*
- * Mark existing node for deletion.
+ * Set handle to point to existing node.
*/
void
-Dbtux::deleteNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr)
+Dbtux::selectNode(Signal* signal, NodeHandle& node, TupLoc loc, AccSize acc)
{
- NodeHandlePtr tmpPtr = nodePtr;
- ndbrequire(tmpPtr.p->getOccup() == 0);
- tmpPtr.p->m_flags |= NodeHandle::DoDelete;
- // scans have already been moved by popDown or popUp
+ Frag& frag = node.m_frag;
+ ndbrequire(loc != NullTupLoc);
+ Uint32 pageId = loc.m_pageId;
+ Uint32 pageOffset = loc.m_pageOffset;
+ Uint32* node32 = 0;
+ c_tup->tuxGetNode(frag.m_tupIndexFragPtrI, pageId, pageOffset, node32);
+ jamEntry();
+ node.m_loc = loc;
+ node.m_node = reinterpret_cast<TreeNode*>(node32);
+ node.m_acc = AccNone;
+ ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
+ accessNode(signal, node, acc);
}
/*
- * Access more of the node.
+ * Set handle to point to new node. Uses the pre-allocated node.
*/
void
-Dbtux::accessNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, AccSize acc)
+Dbtux::insertNode(Signal* signal, NodeHandle& node, AccSize acc)
{
+ Frag& frag = node.m_frag;
+ TupLoc loc = frag.m_freeLoc;
+ frag.m_freeLoc = NullTupLoc;
+ selectNode(signal, node, loc, acc);
+ new (node.m_node) TreeNode();
+#ifdef VM_TRACE
TreeHead& tree = frag.m_tree;
- NodeHandlePtr tmpPtr = nodePtr;
- if (tmpPtr.p->m_acc >= acc)
- return;
- if (! (tmpPtr.p->m_flags & NodeHandle::DoInsert)) {
- jam();
- StorePar storePar;
- storePar.m_opCode = TupStoreTh::OpRead;
- storePar.m_offset = tree.getSize(tmpPtr.p->m_acc);
- storePar.m_size = tree.getSize(acc) - tree.getSize(tmpPtr.p->m_acc);
- tmpPtr.p->m_tux.tupStoreTh(signal, frag, tmpPtr, storePar);
- ndbrequire(storePar.m_errorCode == 0);
- }
- tmpPtr.p->m_acc = acc;
+ memset(node.getPref(0), 0xa2, tree.m_prefSize << 2);
+ memset(node.getPref(1), 0xa2, tree.m_prefSize << 2);
+ TreeEnt* entList = tree.getEntList(node.m_node);
+ memset(entList, 0xa4, (tree.m_maxOccup + 1) * (TreeEntSize << 2));
+#endif
}
/*
- * Set prefix.
+ * Delete existing node.
*/
void
-Dbtux::setNodePref(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, unsigned i)
+Dbtux::deleteNode(Signal* signal, NodeHandle& node)
{
- TreeHead& tree = frag.m_tree;
- NodeHandlePtr tmpPtr = nodePtr;
- ReadPar readPar;
- ndbrequire(i <= 1);
- readPar.m_ent = tmpPtr.p->getMinMax(i);
- readPar.m_first = 0;
- readPar.m_count = frag.m_numAttrs;
- // leave in signal data
- readPar.m_data = 0;
- // XXX implement max words to read
- tupReadAttrs(signal, frag, readPar);
- // copy whatever fits
- CopyPar copyPar;
- copyPar.m_items = readPar.m_count;
- copyPar.m_headers = true;
- copyPar.m_maxwords = tree.m_prefSize;
- Data pref = tmpPtr.p->getPref(i);
- copyAttrs(pref, readPar.m_data, copyPar);
- nodePtr.p->m_flags |= NodeHandle::DoUpdate;
+ Frag& frag = node.m_frag;
+ ndbrequire(node.getOccup() == 0);
+ TupLoc loc = node.m_loc;
+ Uint32 pageId = loc.m_pageId;
+ Uint32 pageOffset = loc.m_pageOffset;
+ Uint32* node32 = reinterpret_cast<Uint32*>(node.m_node);
+ c_tup->tuxFreeNode(signal, frag.m_tupIndexFragPtrI, pageId, pageOffset, node32);
+ jamEntry();
+ // invalidate handle and storage
+ node.m_loc = NullTupLoc;
+ node.m_node = 0;
}
/*
- * Commit and release nodes at the end of an operation. Used also on
- * error since no changes have been made (updateOk false).
+ * Set prefix. Copies the number of words that fits. Includes
+ * attribute headers for now. XXX use null mask instead
*/
void
-Dbtux::commitNodes(Signal* signal, Frag& frag, bool updateOk)
+Dbtux::setNodePref(Signal* signal, NodeHandle& node, unsigned i)
{
- TreeHead& tree = frag.m_tree;
- NodeHandlePtr nodePtr;
- nodePtr.i = frag.m_nodeList;
- frag.m_nodeList = RNIL;
- while (nodePtr.i != RNIL) {
- c_nodeHandlePool.getPtr(nodePtr);
- const unsigned flags = nodePtr.p->m_flags;
- if (flags & NodeHandle::DoDelete) {
- jam();
- ndbrequire(updateOk);
- // delete
- StorePar storePar;
- storePar.m_opCode = TupStoreTh::OpDelete;
- nodePtr.p->m_tux.tupStoreTh(signal, frag, nodePtr, storePar);
- ndbrequire(storePar.m_errorCode == 0);
- } else if (flags & NodeHandle::DoUpdate) {
- jam();
- ndbrequire(updateOk);
- // set prefixes
- if (flags & (1 << 0)) {
- jam();
- setNodePref(signal, frag, nodePtr, 0);
- }
- if (flags & (1 << 1)) {
- jam();
- setNodePref(signal, frag, nodePtr, 1);
- }
- // update
- StorePar storePar;
- storePar.m_opCode = TupStoreTh::OpUpdate;
- storePar.m_offset = 0;
- storePar.m_size = tree.getSize(nodePtr.p->m_acc);
- nodePtr.p->m_tux.tupStoreTh(signal, frag, nodePtr, storePar);
- ndbrequire(storePar.m_errorCode == 0);
- }
- // release
- NodeHandlePtr tmpPtr = nodePtr;
- nodePtr.i = nodePtr.p->m_next;
- c_nodeHandlePool.release(tmpPtr);
- }
+ const Frag& frag = node.m_frag;
+ const TreeHead& tree = frag.m_tree;
+ readKeyAttrs(frag, node.getMinMax(i), 0, c_entryKey);
+ copyAttrs(frag, c_entryKey, node.getPref(i), tree.m_prefSize);
}
-// Dbtux::NodeHandle
+// node operations
/*
* Add entry at position. Move entries greater than or equal to the old
@@ -264,25 +136,26 @@ Dbtux::commitNodes(Signal* signal, Frag& frag, bool updateOk)
* 0 1 2 3 4 5 6 0 1 2 3 4 5 6
*/
void
-Dbtux::NodeHandle::pushUp(Signal* signal, unsigned pos, const TreeEnt& ent)
+Dbtux::nodePushUp(Signal* signal, NodeHandle& node, unsigned pos, const TreeEnt& ent)
{
- TreeHead& tree = m_frag.m_tree;
- const unsigned occup = getOccup();
+ Frag& frag = node.m_frag;
+ TreeHead& tree = frag.m_tree;
+ const unsigned occup = node.getOccup();
ndbrequire(occup < tree.m_maxOccup && pos <= occup);
// fix scans
ScanOpPtr scanPtr;
- scanPtr.i = getNodeScan();
+ scanPtr.i = node.getNodeScan();
while (scanPtr.i != RNIL) {
jam();
- m_tux.c_scanOpPool.getPtr(scanPtr);
+ c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_addr == m_addr && scanPos.m_pos < occup);
+ ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
if (scanPos.m_pos >= pos) {
jam();
#ifdef VM_TRACE
- if (m_tux.debugFlags & m_tux.DebugScan) {
- m_tux.debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
- m_tux.debugOut << "At pushUp pos=" << pos << " " << *this << endl;
+ if (debugFlags & DebugScan) {
+ debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "At pushUp pos=" << pos << " " << node << endl;
}
#endif
scanPos.m_pos++;
@@ -290,7 +163,7 @@ Dbtux::NodeHandle::pushUp(Signal* signal, unsigned pos, const TreeEnt& ent)
scanPtr.i = scanPtr.p->m_nodeScan;
}
// fix node
- TreeEnt* const entList = tree.getEntList(m_node);
+ TreeEnt* const entList = tree.getEntList(node.m_node);
entList[occup] = entList[0];
TreeEnt* const tmpList = entList + 1;
for (unsigned i = occup; i > pos; i--) {
@@ -298,18 +171,18 @@ Dbtux::NodeHandle::pushUp(Signal* signal, unsigned pos, const TreeEnt& ent)
tmpList[i] = tmpList[i - 1];
}
tmpList[pos] = ent;
+ entList[0] = entList[occup + 1];
+ node.setOccup(occup + 1);
+ // fix prefixes
if (occup == 0 || pos == 0)
- m_flags |= (1 << 0);
+ setNodePref(signal, node, 0);
if (occup == 0 || pos == occup)
- m_flags |= (1 << 1);
- entList[0] = entList[occup + 1];
- setOccup(occup + 1);
- m_flags |= DoUpdate;
+ setNodePref(signal, node, 1);
}
/*
* Remove and return entry at position. Move entries greater than the
- * removed one to the left. This is the opposite of pushUp.
+ * removed one to the left. This is the opposite of nodePushUp.
*
* D
* ^ ^
@@ -317,46 +190,47 @@ Dbtux::NodeHandle::pushUp(Signal* signal, unsigned pos, const TreeEnt& ent)
* 0 1 2 3 4 5 6 0 1 2 3 4 5 6
*/
void
-Dbtux::NodeHandle::popDown(Signal* signal, unsigned pos, TreeEnt& ent)
+Dbtux::nodePopDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
{
- TreeHead& tree = m_frag.m_tree;
- const unsigned occup = getOccup();
+ Frag& frag = node.m_frag;
+ TreeHead& tree = frag.m_tree;
+ const unsigned occup = node.getOccup();
ndbrequire(occup <= tree.m_maxOccup && pos < occup);
ScanOpPtr scanPtr;
// move scans whose entry disappears
- scanPtr.i = getNodeScan();
+ scanPtr.i = node.getNodeScan();
while (scanPtr.i != RNIL) {
jam();
- m_tux.c_scanOpPool.getPtr(scanPtr);
+ c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_addr == m_addr && scanPos.m_pos < occup);
+ ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
if (scanPos.m_pos == pos) {
jam();
#ifdef VM_TRACE
- if (m_tux.debugFlags & m_tux.DebugScan) {
- m_tux.debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
- m_tux.debugOut << "At popDown pos=" << pos << " " << *this << endl;
+ if (debugFlags & DebugScan) {
+ debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "At popDown pos=" << pos << " " << node << endl;
}
#endif
- m_tux.scanNext(signal, scanPtr);
+ scanNext(signal, scanPtr);
}
scanPtr.i = nextPtrI;
}
// fix other scans
- scanPtr.i = getNodeScan();
+ scanPtr.i = node.getNodeScan();
while (scanPtr.i != RNIL) {
jam();
- m_tux.c_scanOpPool.getPtr(scanPtr);
+ c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_addr == m_addr && scanPos.m_pos < occup);
+ ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
ndbrequire(scanPos.m_pos != pos);
if (scanPos.m_pos > pos) {
jam();
#ifdef VM_TRACE
- if (m_tux.debugFlags & m_tux.DebugScan) {
- m_tux.debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
- m_tux.debugOut << "At popDown pos=" << pos << " " << *this << endl;
+ if (debugFlags & DebugScan) {
+ debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "At popDown pos=" << pos << " " << node << endl;
}
#endif
scanPos.m_pos--;
@@ -364,7 +238,7 @@ Dbtux::NodeHandle::popDown(Signal* signal, unsigned pos, TreeEnt& ent)
scanPtr.i = scanPtr.p->m_nodeScan;
}
// fix node
- TreeEnt* const entList = tree.getEntList(m_node);
+ TreeEnt* const entList = tree.getEntList(node.m_node);
entList[occup] = entList[0];
TreeEnt* const tmpList = entList + 1;
ent = tmpList[pos];
@@ -372,13 +246,13 @@ Dbtux::NodeHandle::popDown(Signal* signal, unsigned pos, TreeEnt& ent)
jam();
tmpList[i] = tmpList[i + 1];
}
+ entList[0] = entList[occup - 1];
+ node.setOccup(occup - 1);
+ // fix prefixes
if (occup != 1 && pos == 0)
- m_flags |= (1 << 0);
+ setNodePref(signal, node, 0);
if (occup != 1 && pos == occup - 1)
- m_flags |= (1 << 1);
- entList[0] = entList[occup - 1];
- setOccup(occup - 1);
- m_flags |= DoUpdate;
+ setNodePref(signal, node, 1);
}
/*
@@ -391,47 +265,48 @@ Dbtux::NodeHandle::popDown(Signal* signal, unsigned pos, TreeEnt& ent)
* 0 1 2 3 4 5 6 0 1 2 3 4 5 6
*/
void
-Dbtux::NodeHandle::pushDown(Signal* signal, unsigned pos, TreeEnt& ent)
+Dbtux::nodePushDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
{
- TreeHead& tree = m_frag.m_tree;
- const unsigned occup = getOccup();
+ Frag& frag = node.m_frag;
+ TreeHead& tree = frag.m_tree;
+ const unsigned occup = node.getOccup();
ndbrequire(occup <= tree.m_maxOccup && pos < occup);
ScanOpPtr scanPtr;
// move scans whose entry disappears
- scanPtr.i = getNodeScan();
+ scanPtr.i = node.getNodeScan();
while (scanPtr.i != RNIL) {
jam();
- m_tux.c_scanOpPool.getPtr(scanPtr);
+ c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_addr == m_addr && scanPos.m_pos < occup);
+ ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
if (scanPos.m_pos == 0) {
jam();
#ifdef VM_TRACE
- if (m_tux.debugFlags & m_tux.DebugScan) {
- m_tux.debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
- m_tux.debugOut << "At pushDown pos=" << pos << " " << *this << endl;
+ if (debugFlags & DebugScan) {
+ debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "At pushDown pos=" << pos << " " << node << endl;
}
#endif
// here we may miss a valid entry "X" XXX known bug
- m_tux.scanNext(signal, scanPtr);
+ scanNext(signal, scanPtr);
}
scanPtr.i = nextPtrI;
}
// fix other scans
- scanPtr.i = getNodeScan();
+ scanPtr.i = node.getNodeScan();
while (scanPtr.i != RNIL) {
jam();
- m_tux.c_scanOpPool.getPtr(scanPtr);
+ c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_addr == m_addr && scanPos.m_pos < occup);
+ ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
ndbrequire(scanPos.m_pos != 0);
if (scanPos.m_pos <= pos) {
jam();
#ifdef VM_TRACE
- if (m_tux.debugFlags & m_tux.DebugScan) {
- m_tux.debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
- m_tux.debugOut << "At pushDown pos=" << pos << " " << *this << endl;
+ if (debugFlags & DebugScan) {
+ debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "At pushDown pos=" << pos << " " << node << endl;
}
#endif
scanPos.m_pos--;
@@ -439,7 +314,7 @@ Dbtux::NodeHandle::pushDown(Signal* signal, unsigned pos, TreeEnt& ent)
scanPtr.i = scanPtr.p->m_nodeScan;
}
// fix node
- TreeEnt* const entList = tree.getEntList(m_node);
+ TreeEnt* const entList = tree.getEntList(node.m_node);
entList[occup] = entList[0];
TreeEnt* const tmpList = entList + 1;
TreeEnt oldMin = tmpList[0];
@@ -449,18 +324,18 @@ Dbtux::NodeHandle::pushDown(Signal* signal, unsigned pos, TreeEnt& ent)
}
tmpList[pos] = ent;
ent = oldMin;
+ entList[0] = entList[occup];
+ // fix prefixes
if (true)
- m_flags |= (1 << 0);
+ setNodePref(signal, node, 0);
if (occup == 1 || pos == occup - 1)
- m_flags |= (1 << 1);
- entList[0] = entList[occup];
- m_flags |= DoUpdate;
+ setNodePref(signal, node, 1);
}
/*
* Remove and return entry at position. Move entries less than the
* removed one to the right. Replace min entry by the input entry.
- * This is the opposite of pushDown.
+ * This is the opposite of nodePushDown.
*
* X D
* v ^ ^
@@ -468,47 +343,48 @@ Dbtux::NodeHandle::pushDown(Signal* signal, unsigned pos, TreeEnt& ent)
* 0 1 2 3 4 5 6 0 1 2 3 4 5 6
*/
void
-Dbtux::NodeHandle::popUp(Signal* signal, unsigned pos, TreeEnt& ent)
+Dbtux::nodePopUp(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
{
- TreeHead& tree = m_frag.m_tree;
- const unsigned occup = getOccup();
+ Frag& frag = node.m_frag;
+ TreeHead& tree = frag.m_tree;
+ const unsigned occup = node.getOccup();
ndbrequire(occup <= tree.m_maxOccup && pos < occup);
ScanOpPtr scanPtr;
// move scans whose entry disappears
- scanPtr.i = getNodeScan();
+ scanPtr.i = node.getNodeScan();
while (scanPtr.i != RNIL) {
jam();
- m_tux.c_scanOpPool.getPtr(scanPtr);
+ c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_addr == m_addr && scanPos.m_pos < occup);
+ ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
if (scanPos.m_pos == pos) {
jam();
#ifdef VM_TRACE
- if (m_tux.debugFlags & m_tux.DebugScan) {
- m_tux.debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
- m_tux.debugOut << "At popUp pos=" << pos << " " << *this << endl;
+ if (debugFlags & DebugScan) {
+ debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "At popUp pos=" << pos << " " << node << endl;
}
#endif
// here we may miss a valid entry "X" XXX known bug
- m_tux.scanNext(signal, scanPtr);
+ scanNext(signal, scanPtr);
}
scanPtr.i = nextPtrI;
}
// fix other scans
- scanPtr.i = getNodeScan();
+ scanPtr.i = node.getNodeScan();
while (scanPtr.i != RNIL) {
jam();
- m_tux.c_scanOpPool.getPtr(scanPtr);
+ c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_addr == m_addr && scanPos.m_pos < occup);
+ ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
ndbrequire(scanPos.m_pos != pos);
if (scanPos.m_pos < pos) {
jam();
#ifdef VM_TRACE
- if (m_tux.debugFlags & m_tux.DebugScan) {
- m_tux.debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
- m_tux.debugOut << "At popUp pos=" << pos << " " << *this << endl;
+ if (debugFlags & DebugScan) {
+ debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "At popUp pos=" << pos << " " << node << endl;
}
#endif
scanPos.m_pos++;
@@ -516,7 +392,7 @@ Dbtux::NodeHandle::popUp(Signal* signal, unsigned pos, TreeEnt& ent)
scanPtr.i = scanPtr.p->m_nodeScan;
}
// fix node
- TreeEnt* const entList = tree.getEntList(m_node);
+ TreeEnt* const entList = tree.getEntList(node.m_node);
entList[occup] = entList[0];
TreeEnt* const tmpList = entList + 1;
TreeEnt newMin = ent;
@@ -526,12 +402,12 @@ Dbtux::NodeHandle::popUp(Signal* signal, unsigned pos, TreeEnt& ent)
tmpList[i] = tmpList[i - 1];
}
tmpList[0] = newMin;
+ entList[0] = entList[occup];
+ // fix prefixes
if (true)
- m_flags |= (1 << 0);
+ setNodePref(signal, node, 0);
if (occup == 1 || pos == occup - 1)
- m_flags |= (1 << 1);
- entList[0] = entList[occup];
- m_flags |= DoUpdate;
+ setNodePref(signal, node, 1);
}
/*
@@ -539,14 +415,15 @@ Dbtux::NodeHandle::popUp(Signal* signal, unsigned pos, TreeEnt& ent)
* after the max (i=1). XXX can be optimized
*/
void
-Dbtux::NodeHandle::slide(Signal* signal, NodeHandlePtr nodePtr, unsigned i)
+Dbtux::nodeSlide(Signal* signal, NodeHandle& dstNode, NodeHandle& srcNode, unsigned i)
{
+ Frag& frag = dstNode.m_frag;
+ TreeHead& tree = frag.m_tree;
ndbrequire(i <= 1);
- TreeHead& tree = m_frag.m_tree;
- while (getOccup() < tree.m_maxOccup && nodePtr.p->getOccup() != 0) {
+ while (dstNode.getOccup() < tree.m_maxOccup && srcNode.getOccup() != 0) {
TreeEnt ent;
- nodePtr.p->popDown(signal, i == 0 ? nodePtr.p->getOccup() - 1 : 0, ent);
- pushUp(signal, i == 0 ? 0 : getOccup(), ent);
+ nodePopDown(signal, srcNode, i == 0 ? srcNode.getOccup() - 1 : 0, ent);
+ nodePushUp(signal, dstNode, i == 0 ? 0 : dstNode.getOccup(), ent);
}
}
@@ -555,50 +432,50 @@ Dbtux::NodeHandle::slide(Signal* signal, NodeHandlePtr nodePtr, unsigned i)
* ordering does not matter.
*/
void
-Dbtux::NodeHandle::linkScan(Dbtux::ScanOpPtr scanPtr)
+Dbtux::linkScan(NodeHandle& node, ScanOpPtr scanPtr)
{
#ifdef VM_TRACE
- if (m_tux.debugFlags & m_tux.DebugScan) {
- m_tux.debugOut << "Link scan " << scanPtr.i << " " << *scanPtr.p << endl;
- m_tux.debugOut << "To node " << *this << endl;
+ if (debugFlags & DebugScan) {
+ debugOut << "Link scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "To node " << node << endl;
}
#endif
- ndbrequire(! islinkScan(scanPtr) && scanPtr.p->m_nodeScan == RNIL);
- scanPtr.p->m_nodeScan = getNodeScan();
- setNodeScan(scanPtr.i);
+ ndbrequire(! islinkScan(node, scanPtr) && scanPtr.p->m_nodeScan == RNIL);
+ scanPtr.p->m_nodeScan = node.getNodeScan();
+ node.setNodeScan(scanPtr.i);
}
/*
* Unlink a scan from the list under the node.
*/
void
-Dbtux::NodeHandle::unlinkScan(Dbtux::ScanOpPtr scanPtr)
+Dbtux::unlinkScan(NodeHandle& node, ScanOpPtr scanPtr)
{
#ifdef VM_TRACE
- if (m_tux.debugFlags & m_tux.DebugScan) {
- m_tux.debugOut << "Unlink scan " << scanPtr.i << " " << *scanPtr.p << endl;
- m_tux.debugOut << "From node " << *this << endl;
+ if (debugFlags & DebugScan) {
+ debugOut << "Unlink scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "From node " << node << endl;
}
#endif
- Dbtux::ScanOpPtr currPtr;
- currPtr.i = getNodeScan();
- Dbtux::ScanOpPtr prevPtr;
+ ScanOpPtr currPtr;
+ currPtr.i = node.getNodeScan();
+ ScanOpPtr prevPtr;
prevPtr.i = RNIL;
while (true) {
jam();
- m_tux.c_scanOpPool.getPtr(currPtr);
+ c_scanOpPool.getPtr(currPtr);
Uint32 nextPtrI = currPtr.p->m_nodeScan;
if (currPtr.i == scanPtr.i) {
jam();
if (prevPtr.i == RNIL) {
- setNodeScan(nextPtrI);
+ node.setNodeScan(nextPtrI);
} else {
jam();
prevPtr.p->m_nodeScan = nextPtrI;
}
scanPtr.p->m_nodeScan = RNIL;
// check for duplicates
- ndbrequire(! islinkScan(scanPtr));
+ ndbrequire(! islinkScan(node, scanPtr));
return;
}
prevPtr = currPtr;
@@ -610,13 +487,13 @@ Dbtux::NodeHandle::unlinkScan(Dbtux::ScanOpPtr scanPtr)
* Check if a scan is linked to this node. Only for ndbrequire.
*/
bool
-Dbtux::NodeHandle::islinkScan(Dbtux::ScanOpPtr scanPtr)
+Dbtux::islinkScan(NodeHandle& node, ScanOpPtr scanPtr)
{
- Dbtux::ScanOpPtr currPtr;
- currPtr.i = getNodeScan();
+ ScanOpPtr currPtr;
+ currPtr.i = node.getNodeScan();
while (currPtr.i != RNIL) {
jam();
- m_tux.c_scanOpPool.getPtr(currPtr);
+ c_scanOpPool.getPtr(currPtr);
if (currPtr.i == scanPtr.i) {
jam();
return true;
@@ -627,7 +504,7 @@ Dbtux::NodeHandle::islinkScan(Dbtux::ScanOpPtr scanPtr)
}
void
-Dbtux::NodeHandle::progError(int line, int cause, const char* extra)
+Dbtux::NodeHandle::progError(int line, int cause, const char* file)
{
- m_tux.progError(line, cause, extra);
+ ErrorReporter::handleAssert("Dbtux::NodeHandle: assert failed", file, line);
}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
index eaa539d9cfc..703b0abb683 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
@@ -42,12 +42,11 @@ Dbtux::execACC_SCANREQ(Signal* signal)
}
ndbrequire(fragPtr.i != RNIL);
Frag& frag = *fragPtr.p;
- ndbrequire(frag.m_nodeList == RNIL);
// must be normal DIH/TC fragment
ndbrequire(frag.m_fragId < (1 << frag.m_fragOff));
TreeHead& tree = frag.m_tree;
// check for empty fragment
- if (tree.m_root == NullTupAddr) {
+ if (tree.m_root == NullTupLoc) {
jam();
AccScanConf* const conf = (AccScanConf*)signal->getDataPtrSend();
conf->scanPtr = req->senderData;
@@ -241,7 +240,6 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
debugOut << "NEXT_SCANREQ scan " << scanPtr.i << " " << scan << endl;
}
#endif
- ndbrequire(frag.m_nodeList == RNIL);
// handle unlock previous and close scan
switch (req->scanFlag) {
case NextScanReq::ZSCAN_NEXT:
@@ -275,13 +273,13 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
case NextScanReq::ZSCAN_CLOSE:
jam();
// unlink from tree node first to avoid state changes
- if (scan.m_scanPos.m_addr != NullTupAddr) {
+ if (scan.m_scanPos.m_loc != NullTupLoc) {
jam();
- const TupAddr addr = scan.m_scanPos.m_addr;
- NodeHandlePtr nodePtr;
- selectNode(signal, frag, nodePtr, addr, AccHead);
- nodePtr.p->unlinkScan(scanPtr);
- scan.m_scanPos.m_addr = NullTupAddr;
+ const TupLoc loc = scan.m_scanPos.m_loc;
+ NodeHandle node(frag);
+ selectNode(signal, node, loc, AccHead);
+ unlinkScan(node, scanPtr);
+ scan.m_scanPos.m_loc = NullTupLoc;
}
if (scan.m_lockwait) {
jam();
@@ -295,7 +293,6 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
jamEntry();
ndbrequire(lockReq->returnCode == AccLockReq::Success);
scan.m_state = ScanOp::Aborting;
- commitNodes(signal, frag, true);
return;
}
if (scan.m_state == ScanOp::Locked) {
@@ -350,7 +347,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
signal->theData[1] = true;
EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
jamEntry();
- commitNodes(signal, frag, true);
return; // stop
}
if (scan.m_lockwait) {
@@ -365,7 +361,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
// if TC has ordered scan close, it will be detected here
sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB);
- commitNodes(signal, frag, true);
return; // stop
}
if (scan.m_state == ScanOp::First) {
@@ -395,7 +390,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
const TreeEnt ent = scan.m_scanPos.m_ent;
// read tuple key
keyPar.m_ent = ent;
- keyPar.m_data = c_keyBuffer;
+ keyPar.m_data = c_dataBuffer;
tupReadKeys(signal, frag, keyPar);
// get read lock or exclusive lock
AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
@@ -407,12 +402,11 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
lockReq->userRef = reference();
lockReq->tableId = scan.m_tableId;
lockReq->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
- // should cache this at fragment create
- lockReq->fragPtrI = RNIL;
+ lockReq->fragPtrI = frag.m_accTableFragPtrI[ent.m_fragBit];
const Uint32* const buf32 = static_cast<Uint32*>(keyPar.m_data);
const Uint64* const buf64 = reinterpret_cast<const Uint64*>(buf32);
lockReq->hashValue = md5_hash(buf64, keyPar.m_size);
- lockReq->tupAddr = ent.m_tupAddr;
+ lockReq->tupAddr = getTupAddr(frag, ent);
lockReq->transId1 = scan.m_transId1;
lockReq->transId2 = scan.m_transId2;
// execute
@@ -445,7 +439,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
signal->theData[1] = true;
EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
jamEntry();
- commitNodes(signal, frag, true);
return; // stop
break;
case AccLockReq::Refused:
@@ -458,7 +451,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
signal->theData[1] = true;
EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
jamEntry();
- commitNodes(signal, frag, true);
return; // stop
break;
case AccLockReq::NoFreeOp:
@@ -471,7 +463,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
signal->theData[1] = true;
EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
jamEntry();
- commitNodes(signal, frag, true);
return; // stop
break;
default:
@@ -492,7 +483,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
if (keyPar.m_data == 0) {
jam();
keyPar.m_ent = ent;
- keyPar.m_data = c_keyBuffer;
+ keyPar.m_data = c_dataBuffer;
tupReadKeys(signal, frag, keyPar);
}
}
@@ -512,7 +503,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
}
conf->accOperationPtr = accLockOp;
conf->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
- conf->localKey[0] = ent.m_tupAddr;
+ conf->localKey[0] = getTupAddr(frag, ent);
conf->localKey[1] = 0;
conf->localKeyLength = 1;
unsigned signalLength = 6;
@@ -555,7 +546,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
scan.m_lastEnt = ent;
// next time look for next entry
scan.m_state = ScanOp::Next;
- commitNodes(signal, frag, true);
return;
}
// XXX in ACC this is checked before req->checkLcpStop
@@ -569,7 +559,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
unsigned signalLength = 3;
sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB);
- commitNodes(signal, frag, true);
return;
}
ndbrequire(false);
@@ -700,45 +689,45 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
ScanOp& scan = *scanPtr.p;
Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
TreeHead& tree = frag.m_tree;
- if (tree.m_root == NullTupAddr) {
+ if (tree.m_root == NullTupLoc) {
// tree may have become empty
jam();
scan.m_state = ScanOp::Last;
return;
}
TreePos pos;
- pos.m_addr = tree.m_root;
- NodeHandlePtr nodePtr;
+ pos.m_loc = tree.m_root;
+ NodeHandle node(frag);
// unpack lower bound
const ScanBound& bound = *scan.m_bound[0];
ScanBoundIterator iter;
bound.first(iter);
for (unsigned j = 0; j < bound.getSize(); j++) {
jam();
- c_keyBuffer[j] = *iter.data;
+ c_dataBuffer[j] = *iter.data;
bound.next(iter);
}
// comparison parameters
BoundPar boundPar;
- boundPar.m_data1 = c_keyBuffer;
+ boundPar.m_data1 = c_dataBuffer;
boundPar.m_count1 = scan.m_boundCnt[0];
boundPar.m_dir = 0;
loop: {
jam();
- selectNode(signal, frag, nodePtr, pos.m_addr, AccPref);
- const unsigned occup = nodePtr.p->getOccup();
+ selectNode(signal, node, pos.m_loc, AccPref);
+ const unsigned occup = node.getOccup();
ndbrequire(occup != 0);
for (unsigned i = 0; i <= 1; i++) {
jam();
// compare prefix
- boundPar.m_data2 = nodePtr.p->getPref(i);
+ boundPar.m_data2 = node.getPref(i);
boundPar.m_len2 = tree.m_prefSize;
int ret = cmpScanBound(frag, boundPar);
if (ret == NdbSqlUtil::CmpUnknown) {
jam();
// read full value
ReadPar readPar;
- readPar.m_ent = nodePtr.p->getMinMax(i);
+ readPar.m_ent = node.getMinMax(i);
readPar.m_first = 0;
readPar.m_count = frag.m_numAttrs;
readPar.m_data = 0; // leave in signal data
@@ -751,11 +740,11 @@ loop: {
}
if (i == 0 && ret < 0) {
jam();
- const TupAddr tupAddr = nodePtr.p->getLink(i);
- if (tupAddr != NullTupAddr) {
+ const TupLoc loc = node.getLink(i);
+ if (loc != NullTupLoc) {
jam();
// continue to left subtree
- pos.m_addr = tupAddr;
+ pos.m_loc = loc;
goto loop;
}
// start scanning this node
@@ -764,34 +753,34 @@ loop: {
pos.m_dir = 3;
scan.m_scanPos = pos;
scan.m_state = ScanOp::Next;
- nodePtr.p->linkScan(scanPtr);
+ linkScan(node, scanPtr);
return;
}
if (i == 1 && ret > 0) {
jam();
- const TupAddr tupAddr = nodePtr.p->getLink(i);
- if (tupAddr != NullTupAddr) {
+ const TupLoc loc = node.getLink(i);
+ if (loc != NullTupLoc) {
jam();
// continue to right subtree
- pos.m_addr = tupAddr;
+ pos.m_loc = loc;
goto loop;
}
// start scanning upwards
pos.m_dir = 1;
scan.m_scanPos = pos;
scan.m_state = ScanOp::Next;
- nodePtr.p->linkScan(scanPtr);
+ linkScan(node, scanPtr);
return;
}
}
// read rest of current node
- accessNode(signal, frag, nodePtr, AccFull);
+ accessNode(signal, node, AccFull);
// look for first entry
ndbrequire(occup >= 2);
for (unsigned j = 1; j < occup; j++) {
jam();
ReadPar readPar;
- readPar.m_ent = nodePtr.p->getEnt(j);
+ readPar.m_ent = node.getEnt(j);
readPar.m_first = 0;
readPar.m_count = frag.m_numAttrs;
readPar.m_data = 0; // leave in signal data
@@ -809,7 +798,7 @@ loop: {
pos.m_dir = 3;
scan.m_scanPos = pos;
scan.m_state = ScanOp::Next;
- nodePtr.p->linkScan(scanPtr);
+ linkScan(node, scanPtr);
return;
}
}
@@ -858,42 +847,42 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
bound.first(iter);
for (unsigned j = 0; j < bound.getSize(); j++) {
jam();
- c_keyBuffer[j] = *iter.data;
+ c_dataBuffer[j] = *iter.data;
bound.next(iter);
}
// comparison parameters
BoundPar boundPar;
- boundPar.m_data1 = c_keyBuffer;
+ boundPar.m_data1 = c_dataBuffer;
boundPar.m_count1 = scan.m_boundCnt[1];
boundPar.m_dir = 1;
// use copy of position
TreePos pos = scan.m_scanPos;
// get and remember original node
- NodeHandlePtr origNodePtr;
- selectNode(signal, frag, origNodePtr, pos.m_addr, AccHead);
- ndbrequire(origNodePtr.p->islinkScan(scanPtr));
+ NodeHandle origNode(frag);
+ selectNode(signal, origNode, pos.m_loc, AccHead);
+ ndbrequire(islinkScan(origNode, scanPtr));
// current node in loop
- NodeHandlePtr nodePtr = origNodePtr;
+ NodeHandle node = origNode;
while (true) {
jam();
if (pos.m_dir == 2) {
// coming up from root ends the scan
jam();
- pos.m_addr = NullTupAddr;
+ pos.m_loc = NullTupLoc;
scan.m_state = ScanOp::Last;
break;
}
- if (nodePtr.p->m_addr != pos.m_addr) {
+ if (node.m_loc != pos.m_loc) {
jam();
- selectNode(signal, frag, nodePtr, pos.m_addr, AccHead);
+ selectNode(signal, node, pos.m_loc, AccHead);
}
if (pos.m_dir == 4) {
// coming down from parent proceed to left child
jam();
- TupAddr addr = nodePtr.p->getLink(0);
- if (addr != NullTupAddr) {
+ TupLoc loc = node.getLink(0);
+ if (loc != NullTupLoc) {
jam();
- pos.m_addr = addr;
+ pos.m_loc = loc;
pos.m_dir = 4; // unchanged
continue;
}
@@ -910,10 +899,10 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
if (pos.m_dir == 3) {
// within node
jam();
- unsigned occup = nodePtr.p->getOccup();
+ unsigned occup = node.getOccup();
ndbrequire(occup >= 1);
// access full node
- accessNode(signal, frag, nodePtr, AccFull);
+ accessNode(signal, node, AccFull);
// advance position
if (! pos.m_match)
pos.m_match = true;
@@ -921,7 +910,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
pos.m_pos++;
if (pos.m_pos < occup) {
jam();
- pos.m_ent = nodePtr.p->getEnt(pos.m_pos);
+ pos.m_ent = node.getEnt(pos.m_pos);
pos.m_dir = 3; // unchanged
// XXX implement prefix optimization
ReadPar readPar;
@@ -938,7 +927,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
if (ret < 0) {
jam();
// hit upper bound of single range scan
- pos.m_addr = NullTupAddr;
+ pos.m_loc = NullTupLoc;
scan.m_state = ScanOp::Last;
break;
}
@@ -952,10 +941,10 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
break;
}
// after node proceed to right child
- TupAddr addr = nodePtr.p->getLink(1);
- if (addr != NullTupAddr) {
+ TupLoc loc = node.getLink(1);
+ if (loc != NullTupLoc) {
jam();
- pos.m_addr = addr;
+ pos.m_loc = loc;
pos.m_dir = 4;
continue;
}
@@ -965,8 +954,8 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
if (pos.m_dir == 1) {
// coming from right child proceed to parent
jam();
- pos.m_addr = nodePtr.p->getLink(2);
- pos.m_dir = nodePtr.p->getSide();
+ pos.m_loc = node.getLink(2);
+ pos.m_dir = node.getSide();
continue;
}
ndbrequire(false);
@@ -975,16 +964,16 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
scan.m_scanPos = pos;
// relink
if (scan.m_state == ScanOp::Current) {
- ndbrequire(pos.m_addr == nodePtr.p->m_addr);
- if (origNodePtr.i != nodePtr.i) {
+ ndbrequire(pos.m_loc == node.m_loc);
+ if (origNode.m_loc != node.m_loc) {
jam();
- origNodePtr.p->unlinkScan(scanPtr);
- nodePtr.p->linkScan(scanPtr);
+ unlinkScan(origNode, scanPtr);
+ linkScan(node, scanPtr);
}
} else if (scan.m_state == ScanOp::Last) {
jam();
- ndbrequire(pos.m_addr == NullTupAddr);
- origNodePtr.p->unlinkScan(scanPtr);
+ ndbrequire(pos.m_loc == NullTupLoc);
+ unlinkScan(origNode, scanPtr);
} else {
ndbrequire(false);
}
@@ -1012,10 +1001,10 @@ Dbtux::scanVisible(Signal* signal, ScanOpPtr scanPtr, TreeEnt ent)
Uint32 tableId = frag.m_tableId;
Uint32 fragBit = ent.m_fragBit;
Uint32 fragId = frag.m_fragId | (fragBit << frag.m_fragOff);
- Uint32 tupAddr = ent.m_tupAddr;
+ Uint32 tupAddr = getTupAddr(frag, ent);
Uint32 tupVersion = ent.m_tupVersion;
/* Check for same tuple twice in row */
- if (scan.m_lastEnt.m_tupAddr == tupAddr &&
+ if (scan.m_lastEnt.m_tupLoc == ent.m_tupLoc &&
scan.m_lastEnt.m_fragBit == fragBit) {
jam();
return false;
@@ -1044,7 +1033,6 @@ void
Dbtux::scanClose(Signal* signal, ScanOpPtr scanPtr)
{
ScanOp& scan = *scanPtr.p;
- Frag& frag = *c_fragPool.getPtr(scanPtr.p->m_fragPtrI);
ndbrequire(! scan.m_lockwait && scan.m_accLockOp == RNIL);
// unlock all not unlocked by LQH
for (unsigned i = 0; i < MaxAccLockOps; i++) {
@@ -1069,7 +1057,6 @@ Dbtux::scanClose(Signal* signal, ScanOpPtr scanPtr)
sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB);
releaseScanOp(scanPtr);
- commitNodes(signal, frag, true);
}
void
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
index 860aa65414f..7c3f5fa36b8 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
@@ -26,71 +26,55 @@
* same in min/max need not be checked.
*/
void
-Dbtux::treeSearch(Signal* signal, Frag& frag, SearchPar searchPar, TreePos& treePos)
+Dbtux::treeSearch(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos)
{
const TreeHead& tree = frag.m_tree;
const unsigned numAttrs = frag.m_numAttrs;
- treePos.m_addr = tree.m_root;
- NodeHandlePtr nodePtr;
- if (treePos.m_addr == NullTupAddr) {
+ treePos.m_loc = tree.m_root;
+ if (treePos.m_loc == NullTupLoc) {
// empty tree
jam();
treePos.m_pos = 0;
treePos.m_match = false;
return;
}
+ NodeHandle node(frag);
loop: {
jam();
- selectNode(signal, frag, nodePtr, treePos.m_addr, AccPref);
- const unsigned occup = nodePtr.p->getOccup();
+ selectNode(signal, node, treePos.m_loc, AccPref);
+ const unsigned occup = node.getOccup();
ndbrequire(occup != 0);
// number of equal initial attributes in bounding node
- unsigned numEq = ZNIL;
+ unsigned start = ZNIL;
for (unsigned i = 0; i <= 1; i++) {
jam();
+ unsigned start1 = 0;
// compare prefix
- CmpPar cmpPar;
- cmpPar.m_data1 = searchPar.m_data;
- cmpPar.m_data2 = nodePtr.p->getPref(i);
- cmpPar.m_len2 = tree.m_prefSize;
- cmpPar.m_first = 0;
- cmpPar.m_numEq = 0;
- int ret = cmpTreeAttrs(frag, cmpPar);
+ int ret = cmpSearchKey(frag, start1, searchKey, node.getPref(i), tree.m_prefSize);
if (ret == NdbSqlUtil::CmpUnknown) {
jam();
- // read full value
- ReadPar readPar;
- readPar.m_ent = nodePtr.p->getMinMax(i);
- ndbrequire(cmpPar.m_numEq < numAttrs);
- readPar.m_first = cmpPar.m_numEq;
- readPar.m_count = numAttrs - cmpPar.m_numEq;
- readPar.m_data = 0; // leave in signal data
- tupReadAttrs(signal, frag, readPar);
- // compare full value
- cmpPar.m_data2 = readPar.m_data;
- cmpPar.m_len2 = ZNIL; // big
- cmpPar.m_first = readPar.m_first;
- ret = cmpTreeAttrs(frag, cmpPar);
+ // read and compare remaining attributes
+ readKeyAttrs(frag, node.getMinMax(i), start1, c_entryKey);
+ ret = cmpSearchKey(frag, start1, searchKey, c_entryKey);
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
}
- if (numEq > cmpPar.m_numEq)
- numEq = cmpPar.m_numEq;
+ if (start > start1)
+ start = start1;
if (ret == 0) {
jam();
// keys are equal, compare entry values
- ret = searchPar.m_ent.cmp(nodePtr.p->getMinMax(i));
+ ret = searchEnt.cmp(node.getMinMax(i));
}
if (i == 0 ? (ret < 0) : (ret > 0)) {
jam();
- const TupAddr tupAddr = nodePtr.p->getLink(i);
- if (tupAddr != NullTupAddr) {
+ const TupLoc loc = node.getLink(i);
+ if (loc != NullTupLoc) {
jam();
// continue to left/right subtree
- treePos.m_addr = tupAddr;
+ treePos.m_loc = loc;
goto loop;
}
// position is immediately before/after this node
- // XXX disallow second case
treePos.m_pos = (i == 0 ? 0 : occup);
treePos.m_match = false;
return;
@@ -103,36 +87,26 @@ loop: {
return;
}
}
- // read rest of the bounding node
- accessNode(signal, frag, nodePtr, AccFull);
+ // access rest of the bounding node
+ accessNode(signal, node, AccFull);
// position is strictly within the node
ndbrequire(occup >= 2);
const unsigned numWithin = occup - 2;
for (unsigned j = 1; j <= numWithin; j++) {
jam();
int ret = 0;
- // compare remaining attributes
- if (numEq < numAttrs) {
+ if (start < numAttrs) {
jam();
- ReadPar readPar;
- readPar.m_ent = nodePtr.p->getEnt(j);
- readPar.m_first = numEq;
- readPar.m_count = numAttrs - numEq;
- readPar.m_data = 0; // leave in signal data
- tupReadAttrs(signal, frag, readPar);
- // compare
- CmpPar cmpPar;
- cmpPar.m_data1 = searchPar.m_data;
- cmpPar.m_data2 = readPar.m_data;
- cmpPar.m_len2 = ZNIL; // big
- cmpPar.m_first = readPar.m_first;
- ret = cmpTreeAttrs(frag, cmpPar);
+ // read and compare remaining attributes
+ unsigned start1 = start;
+ readKeyAttrs(frag, node.getEnt(j), start1, c_entryKey);
+ ret = cmpSearchKey(frag, start1, searchKey, c_entryKey);
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
}
if (ret == 0) {
jam();
// keys are equal, compare entry values
- ret = searchPar.m_ent.cmp(nodePtr.p->getEnt(j));
+ ret = searchEnt.cmp(node.getEnt(j));
}
if (ret <= 0) {
jam();
@@ -157,94 +131,94 @@ Dbtux::treeAdd(Signal* signal, Frag& frag, TreePos treePos, TreeEnt ent)
{
TreeHead& tree = frag.m_tree;
unsigned pos = treePos.m_pos;
- NodeHandlePtr nodePtr;
+ NodeHandle node(frag);
// check for empty tree
- if (treePos.m_addr == NullTupAddr) {
+ if (treePos.m_loc == NullTupLoc) {
jam();
- insertNode(signal, frag, nodePtr, AccPref);
- nodePtr.p->pushUp(signal, 0, ent);
- nodePtr.p->setSide(2);
- tree.m_root = nodePtr.p->m_addr;
+ insertNode(signal, node, AccPref);
+ nodePushUp(signal, node, 0, ent);
+ node.setSide(2);
+ tree.m_root = node.m_loc;
return;
}
// access full node
- selectNode(signal, frag, nodePtr, treePos.m_addr, AccFull);
+ selectNode(signal, node, treePos.m_loc, AccFull);
// check if it is bounding node
- if (pos != 0 && pos != nodePtr.p->getOccup()) {
+ if (pos != 0 && pos != node.getOccup()) {
jam();
// check if room for one more
- if (nodePtr.p->getOccup() < tree.m_maxOccup) {
+ if (node.getOccup() < tree.m_maxOccup) {
jam();
- nodePtr.p->pushUp(signal, pos, ent);
+ nodePushUp(signal, node, pos, ent);
return;
}
// returns min entry
- nodePtr.p->pushDown(signal, pos - 1, ent);
+ nodePushDown(signal, node, pos - 1, ent);
// find position to add the removed min entry
- TupAddr childAddr = nodePtr.p->getLink(0);
- if (childAddr == NullTupAddr) {
+ TupLoc childLoc = node.getLink(0);
+ if (childLoc == NullTupLoc) {
jam();
// left child will be added
pos = 0;
} else {
jam();
// find glb node
- while (childAddr != NullTupAddr) {
+ while (childLoc != NullTupLoc) {
jam();
- selectNode(signal, frag, nodePtr, childAddr, AccHead);
- childAddr = nodePtr.p->getLink(1);
+ selectNode(signal, node, childLoc, AccHead);
+ childLoc = node.getLink(1);
}
// access full node again
- accessNode(signal, frag, nodePtr, AccFull);
- pos = nodePtr.p->getOccup();
+ accessNode(signal, node, AccFull);
+ pos = node.getOccup();
}
// fall thru to next case
}
// adding new min or max
unsigned i = (pos == 0 ? 0 : 1);
- ndbrequire(nodePtr.p->getLink(i) == NullTupAddr);
+ ndbrequire(node.getLink(i) == NullTupLoc);
// check if the half-leaf/leaf has room for one more
- if (nodePtr.p->getOccup() < tree.m_maxOccup) {
+ if (node.getOccup() < tree.m_maxOccup) {
jam();
- nodePtr.p->pushUp(signal, pos, ent);
+ nodePushUp(signal, node, pos, ent);
return;
}
// add a new node
- NodeHandlePtr childPtr;
- insertNode(signal, frag, childPtr, AccPref);
- childPtr.p->pushUp(signal, 0, ent);
+ NodeHandle childNode(frag);
+ insertNode(signal, childNode, AccPref);
+ nodePushUp(signal, childNode, 0, ent);
// connect parent and child
- nodePtr.p->setLink(i, childPtr.p->m_addr);
- childPtr.p->setLink(2, nodePtr.p->m_addr);
- childPtr.p->setSide(i);
+ node.setLink(i, childNode.m_loc);
+ childNode.setLink(2, node.m_loc);
+ childNode.setSide(i);
// re-balance tree at each node
while (true) {
// height of subtree i has increased by 1
int j = (i == 0 ? -1 : +1);
- int b = nodePtr.p->getBalance();
+ int b = node.getBalance();
if (b == 0) {
// perfectly balanced
jam();
- nodePtr.p->setBalance(j);
+ node.setBalance(j);
// height change propagates up
} else if (b == -j) {
// height of shorter subtree increased
jam();
- nodePtr.p->setBalance(0);
+ node.setBalance(0);
// height of tree did not change - done
break;
} else if (b == j) {
// height of longer subtree increased
jam();
- NodeHandlePtr childPtr;
- selectNode(signal, frag, childPtr, nodePtr.p->getLink(i), AccHead);
- int b2 = childPtr.p->getBalance();
+ NodeHandle childNode(frag);
+ selectNode(signal, childNode, node.getLink(i), AccHead);
+ int b2 = childNode.getBalance();
if (b2 == b) {
jam();
- treeRotateSingle(signal, frag, nodePtr, i);
+ treeRotateSingle(signal, frag, node, i);
} else if (b2 == -b) {
jam();
- treeRotateDouble(signal, frag, nodePtr, i);
+ treeRotateDouble(signal, frag, node, i);
} else {
// height of subtree increased so it cannot be perfectly balanced
ndbrequire(false);
@@ -254,14 +228,14 @@ Dbtux::treeAdd(Signal* signal, Frag& frag, TreePos treePos, TreeEnt ent)
} else {
ndbrequire(false);
}
- TupAddr parentAddr = nodePtr.p->getLink(2);
- if (parentAddr == NullTupAddr) {
+ TupLoc parentLoc = node.getLink(2);
+ if (parentLoc == NullTupLoc) {
jam();
// root node - done
break;
}
- i = nodePtr.p->getSide();
- selectNode(signal, frag, nodePtr, parentAddr, AccHead);
+ i = node.getSide();
+ selectNode(signal, node, parentLoc, AccHead);
}
}
@@ -273,101 +247,101 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos)
{
TreeHead& tree = frag.m_tree;
unsigned pos = treePos.m_pos;
- NodeHandlePtr nodePtr;
+ NodeHandle node(frag);
// access full node
- selectNode(signal, frag, nodePtr, treePos.m_addr, AccFull);
+ selectNode(signal, node, treePos.m_loc, AccFull);
TreeEnt ent;
// check interior node first
- if (nodePtr.p->getChilds() == 2) {
+ if (node.getChilds() == 2) {
jam();
- ndbrequire(nodePtr.p->getOccup() >= tree.m_minOccup);
+ ndbrequire(node.getOccup() >= tree.m_minOccup);
// check if no underflow
- if (nodePtr.p->getOccup() > tree.m_minOccup) {
+ if (node.getOccup() > tree.m_minOccup) {
jam();
- nodePtr.p->popDown(signal, pos, ent);
+ nodePopDown(signal, node, pos, ent);
return;
}
// save current handle
- NodeHandlePtr parentPtr = nodePtr;
+ NodeHandle parentNode = node;
// find glb node
- TupAddr childAddr = nodePtr.p->getLink(0);
- while (childAddr != NullTupAddr) {
+ TupLoc childLoc = node.getLink(0);
+ while (childLoc != NullTupLoc) {
jam();
- selectNode(signal, frag, nodePtr, childAddr, AccHead);
- childAddr = nodePtr.p->getLink(1);
+ selectNode(signal, node, childLoc, AccHead);
+ childLoc = node.getLink(1);
}
// access full node again
- accessNode(signal, frag, nodePtr, AccFull);
+ accessNode(signal, node, AccFull);
// use glb max as new parent min
- ent = nodePtr.p->getEnt(nodePtr.p->getOccup() - 1);
- parentPtr.p->popUp(signal, pos, ent);
+ ent = node.getEnt(node.getOccup() - 1);
+ nodePopUp(signal, parentNode, pos, ent);
// set up to remove glb max
- pos = nodePtr.p->getOccup() - 1;
+ pos = node.getOccup() - 1;
// fall thru to next case
}
// remove the element
- nodePtr.p->popDown(signal, pos, ent);
- ndbrequire(nodePtr.p->getChilds() <= 1);
+ nodePopDown(signal, node, pos, ent);
+ ndbrequire(node.getChilds() <= 1);
// handle half-leaf
for (unsigned i = 0; i <= 1; i++) {
jam();
- TupAddr childAddr = nodePtr.p->getLink(i);
- if (childAddr != NullTupAddr) {
+ TupLoc childLoc = node.getLink(i);
+ if (childLoc != NullTupLoc) {
// move to child
- selectNode(signal, frag, nodePtr, childAddr, AccFull);
+ selectNode(signal, node, childLoc, AccFull);
// balance of half-leaf parent requires child to be leaf
break;
}
}
- ndbrequire(nodePtr.p->getChilds() == 0);
+ ndbrequire(node.getChilds() == 0);
// get parent if any
- TupAddr parentAddr = nodePtr.p->getLink(2);
- NodeHandlePtr parentPtr;
- unsigned i = nodePtr.p->getSide();
+ TupLoc parentLoc = node.getLink(2);
+ NodeHandle parentNode(frag);
+ unsigned i = node.getSide();
// move all that fits into parent
- if (parentAddr != NullTupAddr) {
+ if (parentLoc != NullTupLoc) {
jam();
- selectNode(signal, frag, parentPtr, nodePtr.p->getLink(2), AccFull);
- parentPtr.p->slide(signal, nodePtr, i);
+ selectNode(signal, parentNode, node.getLink(2), AccFull);
+ nodeSlide(signal, parentNode, node, i);
// fall thru to next case
}
// non-empty leaf
- if (nodePtr.p->getOccup() >= 1) {
+ if (node.getOccup() >= 1) {
jam();
return;
}
// remove empty leaf
- deleteNode(signal, frag, nodePtr);
- if (parentAddr == NullTupAddr) {
+ deleteNode(signal, node);
+ if (parentLoc == NullTupLoc) {
jam();
// tree is now empty
- tree.m_root = NullTupAddr;
+ tree.m_root = NullTupLoc;
return;
}
- nodePtr = parentPtr;
- nodePtr.p->setLink(i, NullTupAddr);
+ node = parentNode;
+ node.setLink(i, NullTupLoc);
#ifdef dbtux_min_occup_less_max_occup
// check if we created a half-leaf
- if (nodePtr.p->getBalance() == 0) {
+ if (node.getBalance() == 0) {
jam();
// move entries from the other child
- TupAddr childAddr = nodePtr.p->getLink(1 - i);
- NodeHandlePtr childPtr;
- selectNode(signal, frag, childPtr, childAddr, AccFull);
- nodePtr.p->slide(signal, childPtr, 1 - i);
- if (childPtr.p->getOccup() == 0) {
+ TupLoc childLoc = node.getLink(1 - i);
+ NodeHandle childNode(frag);
+ selectNode(signal, childNode, childLoc, AccFull);
+ nodeSlide(signal, node, childNode, 1 - i);
+ if (childNode.getOccup() == 0) {
jam();
- deleteNode(signal, frag, childPtr);
- nodePtr.p->setLink(1 - i, NullTupAddr);
+ deleteNode(signal, childNode);
+ node.setLink(1 - i, NullTupLoc);
// we are balanced again but our parent balance changes by -1
- parentAddr = nodePtr.p->getLink(2);
- if (parentAddr == NullTupAddr) {
+ parentLoc = node.getLink(2);
+ if (parentLoc == NullTupLoc) {
jam();
return;
}
// fix side and become parent
- i = nodePtr.p->getSide();
- selectNode(signal, frag, nodePtr, parentAddr, AccHead);
+ i = node.getSide();
+ selectNode(signal, node, parentLoc, AccHead);
}
}
#endif
@@ -375,50 +349,50 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos)
while (true) {
// height of subtree i has decreased by 1
int j = (i == 0 ? -1 : +1);
- int b = nodePtr.p->getBalance();
+ int b = node.getBalance();
if (b == 0) {
// perfectly balanced
jam();
- nodePtr.p->setBalance(-j);
+ node.setBalance(-j);
// height of tree did not change - done
return;
} else if (b == j) {
// height of longer subtree has decreased
jam();
- nodePtr.p->setBalance(0);
+ node.setBalance(0);
// height change propagates up
} else if (b == -j) {
// height of shorter subtree has decreased
jam();
- NodeHandlePtr childPtr;
// child on the other side
- selectNode(signal, frag, childPtr, nodePtr.p->getLink(1 - i), AccHead);
- int b2 = childPtr.p->getBalance();
+ NodeHandle childNode(frag);
+ selectNode(signal, childNode, node.getLink(1 - i), AccHead);
+ int b2 = childNode.getBalance();
if (b2 == b) {
jam();
- treeRotateSingle(signal, frag, nodePtr, 1 - i);
+ treeRotateSingle(signal, frag, node, 1 - i);
// height of tree decreased and propagates up
} else if (b2 == -b) {
jam();
- treeRotateDouble(signal, frag, nodePtr, 1 - i);
+ treeRotateDouble(signal, frag, node, 1 - i);
// height of tree decreased and propagates up
} else {
jam();
- treeRotateSingle(signal, frag, nodePtr, 1 - i);
+ treeRotateSingle(signal, frag, node, 1 - i);
// height of tree did not change - done
return;
}
} else {
ndbrequire(false);
}
- TupAddr parentAddr = nodePtr.p->getLink(2);
- if (parentAddr == NullTupAddr) {
+ TupLoc parentLoc = node.getLink(2);
+ if (parentLoc == NullTupLoc) {
jam();
// root node - done
return;
}
- i = nodePtr.p->getSide();
- selectNode(signal, frag, nodePtr, parentAddr, AccHead);
+ i = node.getSide();
+ selectNode(signal, node, parentLoc, AccHead);
}
}
@@ -441,55 +415,55 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos)
void
Dbtux::treeRotateSingle(Signal* signal,
Frag& frag,
- NodeHandlePtr& nodePtr,
+ NodeHandle& node,
unsigned i)
{
ndbrequire(i <= 1);
/*
5 is the old top node that have been unbalanced due to an insert or
delete. The balance is still the old balance before the update.
- Verify that n5Bal is 1 if RR rotate and -1 if LL rotate.
+ Verify that bal5 is 1 if RR rotate and -1 if LL rotate.
*/
- NodeHandlePtr n5Ptr = nodePtr;
- const TupAddr n5Addr = n5Ptr.p->m_addr;
- const int n5Bal = n5Ptr.p->getBalance();
- const int n5side = n5Ptr.p->getSide();
- ndbrequire(n5Bal + (1 - i) == i);
+ NodeHandle node5 = node;
+ const TupLoc loc5 = node5.m_loc;
+ const int bal5 = node5.getBalance();
+ const int side5 = node5.getSide();
+ ndbrequire(bal5 + (1 - i) == i);
/*
3 is the new root of this part of the tree which is to swap place with
node 5. For an insert to cause this it must have the same balance as 5.
For deletes it can have the balance 0.
*/
- TupAddr n3Addr = n5Ptr.p->getLink(i);
- NodeHandlePtr n3Ptr;
- selectNode(signal, frag, n3Ptr, n3Addr, AccHead);
- const int n3Bal = n3Ptr.p->getBalance();
+ TupLoc loc3 = node5.getLink(i);
+ NodeHandle node3(frag);
+ selectNode(signal, node3, loc3, AccHead);
+ const int bal3 = node3.getBalance();
/*
2 must always be there but is not changed. Thus we mereley check that it
exists.
*/
- ndbrequire(n3Ptr.p->getLink(i) != NullTupAddr);
+ ndbrequire(node3.getLink(i) != NullTupLoc);
/*
4 is not necessarily there but if it is there it will move from one
side of 3 to the other side of 5. For LL it moves from the right side
to the left side and for RR it moves from the left side to the right
side. This means that it also changes parent from 3 to 5.
*/
- TupAddr n4Addr = n3Ptr.p->getLink(1 - i);
- NodeHandlePtr n4Ptr;
- if (n4Addr != NullTupAddr) {
+ TupLoc loc4 = node3.getLink(1 - i);
+ NodeHandle node4(frag);
+ if (loc4 != NullTupLoc) {
jam();
- selectNode(signal, frag, n4Ptr, n4Addr, AccHead);
- ndbrequire(n4Ptr.p->getSide() == (1 - i) &&
- n4Ptr.p->getLink(2) == n3Addr);
- n4Ptr.p->setSide(i);
- n4Ptr.p->setLink(2, n5Addr);
+ selectNode(signal, node4, loc4, AccHead);
+ ndbrequire(node4.getSide() == (1 - i) &&
+ node4.getLink(2) == loc3);
+ node4.setSide(i);
+ node4.setLink(2, loc5);
}//if
/*
Retrieve the address of 5's parent before it is destroyed
*/
- TupAddr n0Addr = n5Ptr.p->getLink(2);
+ TupLoc loc0 = node5.getLink(2);
/*
The next step is to perform the rotation. 3 will inherit 5's parent
@@ -503,22 +477,22 @@ Dbtux::treeRotateSingle(Signal* signal,
1. 3 must have had 5 as parent before the change.
2. 3's side is left for LL and right for RR before change.
*/
- ndbrequire(n3Ptr.p->getLink(2) == n5Addr);
- ndbrequire(n3Ptr.p->getSide() == i);
- n3Ptr.p->setLink(1 - i, n5Addr);
- n3Ptr.p->setLink(2, n0Addr);
- n3Ptr.p->setSide(n5side);
- n5Ptr.p->setLink(i, n4Addr);
- n5Ptr.p->setLink(2, n3Addr);
- n5Ptr.p->setSide(1 - i);
- if (n0Addr != NullTupAddr) {
+ ndbrequire(node3.getLink(2) == loc5);
+ ndbrequire(node3.getSide() == i);
+ node3.setLink(1 - i, loc5);
+ node3.setLink(2, loc0);
+ node3.setSide(side5);
+ node5.setLink(i, loc4);
+ node5.setLink(2, loc3);
+ node5.setSide(1 - i);
+ if (loc0 != NullTupLoc) {
jam();
- NodeHandlePtr n0Ptr;
- selectNode(signal, frag, n0Ptr, n0Addr, AccHead);
- n0Ptr.p->setLink(n5side, n3Addr);
+ NodeHandle node0(frag);
+ selectNode(signal, node0, loc0, AccHead);
+ node0.setLink(side5, loc3);
} else {
jam();
- frag.m_tree.m_root = n3Addr;
+ frag.m_tree.m_root = loc3;
}//if
/* The final step of the change is to update the balance of 3 and
5 that changed places. There are two cases here. The first case is
@@ -531,22 +505,22 @@ Dbtux::treeRotateSingle(Signal* signal,
In this case 5 will change balance but still be unbalanced and 3 will
be unbalanced in the opposite direction of 5.
*/
- if (n3Bal == n5Bal) {
+ if (bal3 == bal5) {
jam();
- n3Ptr.p->setBalance(0);
- n5Ptr.p->setBalance(0);
- } else if (n3Bal == 0) {
+ node3.setBalance(0);
+ node5.setBalance(0);
+ } else if (bal3 == 0) {
jam();
- n3Ptr.p->setBalance(-n5Bal);
- n5Ptr.p->setBalance(n5Bal);
+ node3.setBalance(-bal5);
+ node5.setBalance(bal5);
} else {
ndbrequire(false);
}//if
/*
- Set nodePtr to 3 as return parameter for enabling caller to continue
+ Set node to 3 as return parameter for enabling caller to continue
traversing the tree.
*/
- nodePtr = n3Ptr;
+ node = node3;
}
/*
@@ -651,105 +625,105 @@ Dbtux::treeRotateSingle(Signal* signal,
*
*/
void
-Dbtux::treeRotateDouble(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, unsigned i)
+Dbtux::treeRotateDouble(Signal* signal, Frag& frag, NodeHandle& node, unsigned i)
{
// old top node
- NodeHandlePtr n6Ptr = nodePtr;
- const TupAddr n6Addr = n6Ptr.p->m_addr;
+ NodeHandle node6 = node;
+ const TupLoc loc6 = node6.m_loc;
// the un-updated balance
- const int n6Bal = n6Ptr.p->getBalance();
- const unsigned n6Side = n6Ptr.p->getSide();
+ const int bal6 = node6.getBalance();
+ const unsigned side6 = node6.getSide();
// level 1
- TupAddr n2Addr = n6Ptr.p->getLink(i);
- NodeHandlePtr n2Ptr;
- selectNode(signal, frag, n2Ptr, n2Addr, AccHead);
- const int n2Bal = n2Ptr.p->getBalance();
+ TupLoc loc2 = node6.getLink(i);
+ NodeHandle node2(frag);
+ selectNode(signal, node2, loc2, AccHead);
+ const int bal2 = node2.getBalance();
// level 2
- TupAddr n4Addr = n2Ptr.p->getLink(1 - i);
- NodeHandlePtr n4Ptr;
- selectNode(signal, frag, n4Ptr, n4Addr, AccHead);
- const int n4Bal = n4Ptr.p->getBalance();
+ TupLoc loc4 = node2.getLink(1 - i);
+ NodeHandle node4(frag);
+ selectNode(signal, node4, loc4, AccHead);
+ const int bal4 = node4.getBalance();
ndbrequire(i <= 1);
- ndbrequire(n6Bal + (1 - i) == i);
- ndbrequire(n2Bal == -n6Bal);
- ndbrequire(n2Ptr.p->getLink(2) == n6Addr);
- ndbrequire(n2Ptr.p->getSide() == i);
- ndbrequire(n4Ptr.p->getLink(2) == n2Addr);
+ ndbrequire(bal6 + (1 - i) == i);
+ ndbrequire(bal2 == -bal6);
+ ndbrequire(node2.getLink(2) == loc6);
+ ndbrequire(node2.getSide() == i);
+ ndbrequire(node4.getLink(2) == loc2);
// level 3
- TupAddr n3Addr = n4Ptr.p->getLink(i);
- TupAddr n5Addr = n4Ptr.p->getLink(1 - i);
+ TupLoc loc3 = node4.getLink(i);
+ TupLoc loc5 = node4.getLink(1 - i);
// fill up leaf before it becomes internal
- if (n3Addr == NullTupAddr && n5Addr == NullTupAddr) {
+ if (loc3 == NullTupLoc && loc5 == NullTupLoc) {
jam();
TreeHead& tree = frag.m_tree;
- accessNode(signal, frag, n2Ptr, AccFull);
- accessNode(signal, frag, n4Ptr, AccFull);
- n4Ptr.p->slide(signal, n2Ptr, i);
+ accessNode(signal, node2, AccFull);
+ accessNode(signal, node4, AccFull);
+ nodeSlide(signal, node4, node2, i);
// implied by rule of merging half-leaves with leaves
- ndbrequire(n4Ptr.p->getOccup() >= tree.m_minOccup);
- ndbrequire(n2Ptr.p->getOccup() != 0);
+ ndbrequire(node4.getOccup() >= tree.m_minOccup);
+ ndbrequire(node2.getOccup() != 0);
} else {
- if (n3Addr != NullTupAddr) {
+ if (loc3 != NullTupLoc) {
jam();
- NodeHandlePtr n3Ptr;
- selectNode(signal, frag, n3Ptr, n3Addr, AccHead);
- n3Ptr.p->setLink(2, n2Addr);
- n3Ptr.p->setSide(1 - i);
+ NodeHandle node3(frag);
+ selectNode(signal, node3, loc3, AccHead);
+ node3.setLink(2, loc2);
+ node3.setSide(1 - i);
}
- if (n5Addr != NullTupAddr) {
+ if (loc5 != NullTupLoc) {
jam();
- NodeHandlePtr n5Ptr;
- selectNode(signal, frag, n5Ptr, n5Addr, AccHead);
- n5Ptr.p->setLink(2, n6Ptr.p->m_addr);
- n5Ptr.p->setSide(i);
+ NodeHandle node5(frag);
+ selectNode(signal, node5, loc5, AccHead);
+ node5.setLink(2, node6.m_loc);
+ node5.setSide(i);
}
}
// parent
- TupAddr n0Addr = n6Ptr.p->getLink(2);
- NodeHandlePtr n0Ptr;
+ TupLoc loc0 = node6.getLink(2);
+ NodeHandle node0(frag);
// perform the rotation
- n6Ptr.p->setLink(i, n5Addr);
- n6Ptr.p->setLink(2, n4Addr);
- n6Ptr.p->setSide(1 - i);
+ node6.setLink(i, loc5);
+ node6.setLink(2, loc4);
+ node6.setSide(1 - i);
- n2Ptr.p->setLink(1 - i, n3Addr);
- n2Ptr.p->setLink(2, n4Addr);
+ node2.setLink(1 - i, loc3);
+ node2.setLink(2, loc4);
- n4Ptr.p->setLink(i, n2Addr);
- n4Ptr.p->setLink(1 - i, n6Addr);
- n4Ptr.p->setLink(2, n0Addr);
- n4Ptr.p->setSide(n6Side);
+ node4.setLink(i, loc2);
+ node4.setLink(1 - i, loc6);
+ node4.setLink(2, loc0);
+ node4.setSide(side6);
- if (n0Addr != NullTupAddr) {
+ if (loc0 != NullTupLoc) {
jam();
- selectNode(signal, frag, n0Ptr, n0Addr, AccHead);
- n0Ptr.p->setLink(n6Side, n4Addr);
+ selectNode(signal, node0, loc0, AccHead);
+ node0.setLink(side6, loc4);
} else {
jam();
- frag.m_tree.m_root = n4Addr;
+ frag.m_tree.m_root = loc4;
}
// set balance of changed nodes
- n4Ptr.p->setBalance(0);
- if (n4Bal == 0) {
+ node4.setBalance(0);
+ if (bal4 == 0) {
jam();
- n2Ptr.p->setBalance(0);
- n6Ptr.p->setBalance(0);
- } else if (n4Bal == -n2Bal) {
+ node2.setBalance(0);
+ node6.setBalance(0);
+ } else if (bal4 == -bal2) {
jam();
- n2Ptr.p->setBalance(0);
- n6Ptr.p->setBalance(n2Bal);
- } else if (n4Bal == n2Bal) {
+ node2.setBalance(0);
+ node6.setBalance(bal2);
+ } else if (bal4 == bal2) {
jam();
- n2Ptr.p->setBalance(-n2Bal);
- n6Ptr.p->setBalance(0);
+ node2.setBalance(-bal2);
+ node6.setBalance(0);
} else {
ndbrequire(false);
}
// new top node
- nodePtr = n4Ptr;
+ node = node4;
}
diff --git a/ndb/src/kernel/blocks/dbtux/Makefile.am b/ndb/src/kernel/blocks/dbtux/Makefile.am
new file mode 100644
index 00000000000..0b48ad5724f
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbtux/Makefile.am
@@ -0,0 +1,19 @@
+noinst_LIBRARIES = libdbtux.a
+
+libdbtux_a_SOURCES = \
+ DbtuxGen.cpp \
+ DbtuxMeta.cpp \
+ DbtuxMaint.cpp \
+ DbtuxNode.cpp \
+ DbtuxTree.cpp \
+ DbtuxScan.cpp \
+ DbtuxCmp.cpp \
+ DbtuxDebug.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/kernel/blocks/dbtup
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/dbtux/Makefile b/ndb/src/kernel/blocks/dbtux/Makefile_old
index 30927c31848..30927c31848 100644
--- a/ndb/src/kernel/blocks/dbtux/Makefile
+++ b/ndb/src/kernel/blocks/dbtux/Makefile_old
diff --git a/ndb/src/kernel/blocks/dbtux/Times.txt b/ndb/src/kernel/blocks/dbtux/Times.txt
new file mode 100644
index 00000000000..16c4102249b
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbtux/Times.txt
@@ -0,0 +1,52 @@
+index maintenance overhead
+==========================
+
+"mc02" 2x1700 MHz linux-2.4.9 gcc-2.96 -O3 one db-node
+
+case a: index on Unsigned
+testOIBasic -case u -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
+
+case b: index on Varchar(5) + Varchar(5) + Varchar(20) + Unsigned
+testOIBasic -case u -table 2 -index 4 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
+
+1 million rows, pk update without index, pk update with index
+shows ms / 1000 rows for each and pct overhead
+the figures are based on single run on idle machine
+
+040616 mc02/a 40 ms 87 ms 114 pct
+ mc02/b 51 ms 128 ms 148 pct
+
+optim 1 mc02/a 38 ms 85 ms 124 pct
+ mc02/b 51 ms 123 ms 140 pct
+
+optim 2 mc02/a 41 ms 80 ms 96 pct
+ mc02/b 51 ms 117 ms 128 pct
+
+optim 3 mc02/a 43 ms 80 ms 85 pct
+ mc02/b 54 ms 118 ms 117 pct
+
+optim 4 mc02/a 42 ms 80 ms 87 pct
+ mc02/b 51 ms 119 ms 129 pct
+
+optim 5 mc02/a 43 ms 77 ms 77 pct
+ mc02/b 54 ms 118 ms 117 pct
+
+optim 6 mc02/a 42 ms 70 ms 66 pct
+ mc02/b 53 ms 109 ms 105 pct
+
+optim 7 mc02/a 42 ms 69 ms 61 pct
+ mc02/b 52 ms 106 ms 101 pct
+
+optim 8 mc02/a 42 ms 69 ms 62 pct
+ mc02/b 54 ms 104 ms 92 pct
+
+optim 9 mc02/a 43 ms 67 ms 54 pct
+ mc02/b 53 ms 102 ms 91 pct
+
+optim 10 mc02/a 44 ms 65 ms 46 pct
+ mc02/b 53 ms 88 ms 66 pct
+
+optim 11 mc02/a 43 ms 63 ms 46 pct
+ mc02/b 52 ms 86 ms 63 pct
+
+vim: set et:
diff --git a/ndb/src/kernel/blocks/dbutil/Makefile.am b/ndb/src/kernel/blocks/dbutil/Makefile.am
new file mode 100644
index 00000000000..763875d578f
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbutil/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libdbutil.a
+
+libdbutil_a_SOURCES = DbUtil.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/dbutil/Makefile b/ndb/src/kernel/blocks/dbutil/Makefile_old
index 54b7326e4e5..54b7326e4e5 100644
--- a/ndb/src/kernel/blocks/dbutil/Makefile
+++ b/ndb/src/kernel/blocks/dbutil/Makefile_old
diff --git a/ndb/src/kernel/blocks/grep/Makefile.am b/ndb/src/kernel/blocks/grep/Makefile.am
new file mode 100644
index 00000000000..31081c7b6a0
--- /dev/null
+++ b/ndb/src/kernel/blocks/grep/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libgrep.a
+
+libgrep_a_SOURCES = Grep.cpp GrepInit.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/grep/Makefile b/ndb/src/kernel/blocks/grep/Makefile_old
index 5ad5a0bce3b..5ad5a0bce3b 100644
--- a/ndb/src/kernel/blocks/grep/Makefile
+++ b/ndb/src/kernel/blocks/grep/Makefile_old
diff --git a/ndb/src/kernel/blocks/ndbcntr/Makefile.am b/ndb/src/kernel/blocks/ndbcntr/Makefile.am
new file mode 100644
index 00000000000..9230b55b374
--- /dev/null
+++ b/ndb/src/kernel/blocks/ndbcntr/Makefile.am
@@ -0,0 +1,12 @@
+noinst_LIBRARIES = libndbcntr.a
+
+libndbcntr_a_SOURCES = \
+ NdbcntrInit.cpp \
+ NdbcntrSysTable.cpp \
+ NdbcntrMain.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/ndbcntr/Makefile b/ndb/src/kernel/blocks/ndbcntr/Makefile_old
index 8e9c4f01027..8e9c4f01027 100644
--- a/ndb/src/kernel/blocks/ndbcntr/Makefile
+++ b/ndb/src/kernel/blocks/ndbcntr/Makefile_old
diff --git a/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp b/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp
index a481573e370..639d300d6df 100644
--- a/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp
+++ b/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp
@@ -21,10 +21,13 @@
#include <pc.hpp>
#include <SimulatedBlock.hpp>
#include <ndb_limits.h>
-#include <signaldata/CmvmiCfgConf.hpp>
#include <signaldata/StopReq.hpp>
#include <signaldata/ResumeReq.hpp>
#include <signaldata/DictTabInfo.hpp>
+#include <signaldata/CntrStart.hpp>
+#include <signaldata/CheckNodeGroups.hpp>
+
+#include <signaldata/UpgradeStartup.hpp>
#include <NodeState.hpp>
#include <NdbTick.h>
@@ -39,70 +42,13 @@
-----------------
*/
#define ZNO_NDB_BLOCKS 6 /* ACC, DICT, DIH, LQH, TC, TUP */
-#define ZDELAY_NODERESTART 5 /* MASTER REFUSED NODERESTART, WAIT SEC */
-#define ZDELAY_START 25 /* WAIT SECONDS FOR OTHER NODES, RESTART*/
-#define ZHB_INTERVAL 10 /* HEART BEAT INTERVAL TIME MS */
-#define ZNO_NDB_NODES 1
-#define ZHB_TYPE 1
-
-//------- ERROR CODES -----------------------------------------
-#define ZERROR_ALREADY_EXISTS 901
-#define ZERROR_DOESNT_EXIST 902
-#define ZERROR_VALUE_OUT_OF_RANGE 903
-#define ZERROR_NOT_STARTED 904
-#define ZERROR_NODE_RESTART 905
-#define ZERROR_NO_RESTART_NODES 906
-#define ZERROR_STARTPHASE_VALUE 907
-#define ZERROR_CNTR_MASTERREQ 908
-#define ZERROR_CNTR_MASTERREF 909
-#define ZERROR_CNTR_MASTERCONF 910
-#define ZERROR_NOT_RUNNING 911
-#define ZERROR_CNTR_WAITREP 912
+
#define ZNOT_AVAILABLE 913
-#define ZERROR_DISK_FAILURE 914
-#define ZERROR_TOO_MANY_NODES 915
-#define ZERROR_TYPEOFSTART 916
-#define ZERROR_CTYPE_OF_START 917
-#define ZERROR_ZSTART 918
-#define ZERROR_AT_SELECT_START 919
-#define ZERROR_CNTR_CHANGEREP 920
-#define ZERR_DETECT_NODERESTART_1 921
-#define ZERR_DETECT_NODERESTART_2 922
-#define ZERROR_CONTINUEB 923
-#define ZERR_APPL_REGREF 924
-#define ZERR_DICTADDATTRREF 925
-#define ZERR_DICTPREPAREREF 926
-#define ZERR_DICTRELEASEREF 927
-#define ZERR_DICTTABREF 928
-#define ZERR_DICTSEIZEREF 929
-#define ZERR_NDB_STARTREF 930
-#define ZERR_NODE_STATESREF 931
-#define ZERR_READ_NODESREF 932
-#define ZERR_TCKEYREF 933
-#define ZERR_TCRELEASEREF 934
-#define ZERR_TCSEIZEREF 935
-#define ZNOTVALIDSTATE_1 936
-#define ZNOTVALIDSTATE_2 937
-#define ZNODE_FAILURE_DURING_RESTART 938
-#define ZSTART_IN_PROGRESS_ERROR 939
-#define ZCOULD_NOT_OCCUR_ERROR 940
-#define ZTOO_MANY_NODES_ERROR 941
-#define ZNODE_RESTART_ONGOING_ERROR 942
-#define ZWE_ARE_DECLARED_DEAD_ERROR 943
-#define ZTIME_OUT_ERROR 944
-#define ZTYPE_OF_START_ERROR 945
-#define ZMASTER_CONFLICT_ERROR 946
-#define ZNODE_CONFLICT_ERROR 947
//------- OTHERS ---------------------------------------------
-#define ZCONTINUEB_1 1
-#define ZCONTINUEB_2 2
-#define ZSHUTDOWN 3
-
-#define ZAPPL_SUBTYPE 0
-#define ZNAME_OF_APPL "NDB"
-#define ZVOTING 2
-#define ZSIZE_CFG_BLOCK_REC 8
+#define ZSTARTUP 1
+#define ZSHUTDOWN 2
+
#define ZSIZE_NDB_BLOCKS_REC 16 /* MAX BLOCKS IN NDB */
#define ZSIZE_SYSTAB 2048
#define ZSTART_PHASE_1 1
@@ -124,28 +70,10 @@
#define ZWAITPOINT_7_1 7
#define ZWAITPOINT_7_2 8
#define ZSYSTAB_VERSION 1
-/*
-------- SIGNAL CONSTANTS -----------------------------------
-*/
-#define ZNOT_MASTER 0
-/* REASON OF CNTR_MASTERREF */
-#define ZTOO_FEW_NODES 1
-#define ZNEW_MASTER 0
-#define ZDELETE_NODE 1
-#define ZSYSTAB_EXIST 3
-#define ZVOTE_NEW_NODE 4
-#define ZVARIABLE_NO 1
-#define ZAMOUNT_PAGES 8
#endif
class Ndbcntr: public SimulatedBlock {
public:
- // State values
- enum State {
- NOT_ACTIVE = 0,
- ACTIVE = 1
- };
-
// Records
/* FSREADREQ FSWRITEREQ */
@@ -154,59 +82,27 @@ public:
* ------------------------------------------------------------
*/
-/**
- * CFG_BLOCK_REC CONTAINS ALL CONFIG DATA SENT IN EACH NDB_STTOR
- * SOME OTHER CONFIG DATA IS STORED IN RECORD 0
- *
- * WHEN CFG_BLOCK_PTR = ZSTART_PHASE_X ( CINTERNAL_STARTPHASE )
- * WORD 0 DICT_1
- * WORD 1 DICT_2
- * WORD 2 DIH_1
- * WORD 3 DIH_2
- * WORD 4 LQH_1
- * WORD 5 LQH_2
- * WORD 6 TC_1
- * WORD 7 TC_2
- * WORD 8 TUP_1
- * WORD 9 TUP_2
- * WORD 10 ACC_1
- * WORD 11 ACC_2
- *
- * CFG_BLOCK_PTR = 0
- * WORD 0 CDELAY_START
- * WORD 1 CDELAY_NODERESTART
- *------------------------------------------------------------------------*/
- struct CfgBlockRec {
- UintR cfgData[CmvmiCfgConf::NO_OF_WORDS];
- }; /* p2c: size = 64 bytes */
+ struct StartRecord {
+ Uint64 m_startTime;
+
+ void reset();
+ NdbNodeBitmask m_starting;
+ NdbNodeBitmask m_waiting; // == (m_withLog | m_withoutLog)
+ NdbNodeBitmask m_withLog;
+ NdbNodeBitmask m_withoutLog;
+ Uint32 m_lastGci;
+ Uint32 m_lastGciNodeId;
+
+ Uint64 m_startPartialTimeout;
+ Uint64 m_startPartitionedTimeout;
+ Uint64 m_startFailureTimeout;
+ struct {
+ Uint32 m_nodeId;
+ Uint32 m_lastGci;
+ } m_logNodes[MAX_NDB_NODES];
+ Uint32 m_logNodesCount;
+ } c_start;
- typedef Ptr<CfgBlockRec> CfgBlockRecPtr;
-
-/*------------------------------------------------------------------------*/
-// CONTAIN INFO ABOUT ALL NODES IN CLUSTER. NODE_PTR ARE USED AS NODE NUMBER.
-// IF THE STATE ARE ZDELETE THEN THE NODE DOESN'T EXIST. NODES ARE ALLOWED
-// TO REGISTER (ZADD) DURING RESTART.
-// WHEN THE SYSTEM IS RUNNING THE MASTER WILL CHECK IF ANY NODE HAS MADE A
-// CNTR_MASTERREQ AND TAKE CARE OF THE
-// REQUEST. TO CONFIRM THE REQ, THE MASTER DEMANDS THAT ALL RUNNING NODES HAS
-// VOTED FOR THE NEW NODE.
-// NODE_PTR:MASTER_REQ IS USED DURING RESTART TO LOG POSTPONED
-// CNTR_MASTERREQ'S
-/*------------------------------------------------------------------------*/
- struct NodeRec {
- UintR dynamicId;
- BlockReference cntrBlockref;
- Uint16 masterReq;
- Uint16 state;
- Uint16 ndbVersion;
- Uint16 subType;
- Uint8 votes;
- Uint8 voter;
- UintR nodeDefined;
- }; /* p2c: size = 16 bytes */
-
- typedef Ptr<NodeRec> NodeRecPtr;
-
struct NdbBlocksRec {
BlockReference blockref;
}; /* p2c: size = 2 bytes */
@@ -266,16 +162,14 @@ private:
void execCONTINUEB(Signal* signal);
void execREAD_NODESCONF(Signal* signal);
void execREAD_NODESREF(Signal* signal);
- void execCNTR_MASTERREQ(Signal* signal);
- void execCNTR_MASTERCONF(Signal* signal);
- void execCNTR_MASTERREF(Signal* signal);
+ void execCM_ADD_REP(Signal* signal);
+ void execCNTR_START_REQ(Signal* signal);
+ void execCNTR_START_REF(Signal* signal);
+ void execCNTR_START_CONF(Signal* signal);
+ void execCNTR_START_REP(Signal* signal);
void execCNTR_WAITREP(Signal* signal);
- void execNODE_STATESREQ(Signal* signal);
- void execNODE_STATESCONF(Signal* signal);
- void execNODE_STATESREF(Signal* signal);
void execNODE_FAILREP(Signal* signal);
void execSYSTEM_ERROR(Signal* signal);
- void execVOTE_MASTERORD(Signal* signal);
// Received signals
void execDUMP_STATE_ORD(Signal* signal);
@@ -295,12 +189,7 @@ private:
void execNDB_STTORRY(Signal* signal);
void execNDB_STARTCONF(Signal* signal);
void execREAD_NODESREQ(Signal* signal);
- void execAPPL_REGCONF(Signal* signal);
- void execAPPL_REGREF(Signal* signal);
- void execAPPL_CHANGEREP(Signal* signal);
- void execAPPL_STARTCONF(Signal* signal);
void execNDB_STARTREF(Signal* signal);
- void execCMVMI_CFGCONF(Signal* signal);
void execSET_VAR_REQ(Signal* signal);
void execSTOP_PERM_REF(Signal* signal);
@@ -323,19 +212,17 @@ private:
// Statement blocks
void sendCreateTabReq(Signal* signal, const char* buffer, Uint32 bufLen);
void startInsertTransactions(Signal* signal);
- UintR checkNodelist(Signal* signal, Uint16 TnoRestartNodes);
- void chooseRestartNodes(Signal* signal);
- void copyCfgVariables(Signal* signal);
- void deleteNode(Signal* signal);
- void detectNoderestart(Signal* signal);
- void getStartNodes(Signal* signal);
void initData(Signal* signal);
- void replyMasterconfToAll(Signal* signal);
void resetStartVariables(Signal* signal);
- void sendCntrMasterreq(Signal* signal);
+ void sendCntrStartReq(Signal* signal);
+ void sendCntrStartRef(Signal*, Uint32 nodeId, CntrStartRef::ErrorCode);
void sendNdbSttor(Signal* signal);
void sendSttorry(Signal* signal);
+ bool trySystemRestart(Signal* signal);
+ void startWaitingNodes(Signal* signal);
+ CheckNodeGroups::Output checkNodeGroups(Signal*, const NdbNodeBitmask &);
+
// Generated statement blocks
void systemErrorLab(Signal* signal);
@@ -367,13 +254,6 @@ private:
void ph7ALab(Signal* signal);
void ph8ALab(Signal* signal);
- void masterreq010Lab(Signal* signal,
- Uint16 TnoRestartNodes,
- Uint16 TuserNodeId);
- void masterreq020Lab(Signal* signal);
- void masterreq030Lab(Signal* signal,
- Uint16 TnoRestartNodes,
- Uint16 TuserNodeId);
void waitpoint41Lab(Signal* signal);
void waitpoint51Lab(Signal* signal);
@@ -401,62 +281,40 @@ private:
* NODE_PTR:MASTER_REQ IS USED DURING RESTART TO LOG
* POSTPONED CNTR_MASTERREQ'S
*------------------------------------------------------------------------*/
- CfgBlockRec *cfgBlockRec;
- NodeRec *nodeRec;
NdbBlocksRec *ndbBlocksRec;
- NodeRecPtr nodePtr;
-/*
-2.4 COMMON STORED VARIABLES
-*/
- Uint16 cstartNodes[MAX_NDB_NODES];
- BlockReference ccmvmiBlockref;
- BlockReference cqmgrBlockref;
- BlockReference cdictBlockref;
- BlockReference cdihBlockref;
- BlockReference clqhBlockref;
- BlockReference cownBlockref;
- BlockReference ctcBlockref;
- UintR cnoNdbNodes;
- UintR capplStartconfFlag;
+
+ /*
+ 2.4 COMMON STORED VARIABLES
+ */
UintR cgciSystab;
UintR ckey;
- UintR cnoRegNodes;
- UintR cnoRunNodes;
- UintR cnoNeedNodes;
- UintR cnoWaitrep;
+ //UintR csystabId;
UintR cnoWaitrep6;
UintR cnoWaitrep7;
- //UintR csystabId;
UintR ctcConnectionP;
UintR ctcReqInfo;
- UintR clastGci;
- UintR cmasterLastGci;
- UintR cmasterCurrentId;
- Uint16 cmasterDihId;
+ Uint8 ctransidPhase;
Uint16 cresponses;
- Uint16 cdelayStart;
+ Uint8 cstartPhase;
Uint16 cinternalStartphase;
+
Uint16 cmasterNodeId;
- Uint16 cmasterCandidateId;
Uint16 cndbBlocksCount;
Uint16 cnoStartNodes;
- Uint16 cnoVoters;
- Uint16 cstartProgressFlag;
- Uint16 cqmgrConnectionP;
- Uint16 csignalKey;
+ UintR cnoWaitrep;
NodeState::StartType ctypeOfStart;
- Uint16 cmasterVoters;
Uint16 cdynamicNodeId;
- Uint8 cwaitContinuebFlag;
- Uint8 cstartPhase;
- Uint8 ctransidPhase;
Uint32 c_fsRemoveCount;
Uint32 c_nodeGroup;
void clearFilesystem(Signal* signal);
void execFSREMOVEREF(Signal* signal);
void execFSREMOVECONF(Signal* signal);
+
+ NdbNodeBitmask c_allDefinedNodes;
+ NdbNodeBitmask c_clusterNodes; // All members of qmgr cluster
+ NdbNodeBitmask c_startedNodes; // All cntr started nodes
public:
struct StopRecord {
@@ -495,6 +353,8 @@ private:
void execSTART_ORD(Signal* signal);
void execSTTORRY(Signal* signal);
void sendNextSTTOR(Signal* signal);
+ void execREAD_CONFIG_CONF(Signal* signal);
+ void sendNextREAD_CONFIG_REQ(Signal* signal);
BlockNumber number() const { return cntr.number(); }
void progError(int line, int cause, const char * extra) {
@@ -508,6 +368,9 @@ private:
void execSTTORRY(Signal* signal);
void execSTART_ORD(Signal* signal);
+ void execREAD_CONFIG_CONF(Signal*);
+
+ friend struct UpgradeStartup;
};
#endif
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
index 9af6359876b..1069cf93b06 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
@@ -27,8 +27,6 @@ void Ndbcntr::initData()
{
// Records with constant sizes
- cfgBlockRec = new CfgBlockRec[ZSIZE_CFG_BLOCK_REC];
- nodeRec = new NodeRec[MAX_NDB_NODES];
ndbBlocksRec = new NdbBlocksRec[ZSIZE_NDB_BLOCKS_REC];
}//Ndbcntr::initData()
@@ -51,17 +49,15 @@ Ndbcntr::Ndbcntr(const class Configuration & conf):
addRecSignal(GSN_CONTINUEB, &Ndbcntr::execCONTINUEB);
addRecSignal(GSN_READ_NODESCONF, &Ndbcntr::execREAD_NODESCONF);
addRecSignal(GSN_READ_NODESREF, &Ndbcntr::execREAD_NODESREF);
- addRecSignal(GSN_CNTR_MASTERREQ, &Ndbcntr::execCNTR_MASTERREQ);
- addRecSignal(GSN_CNTR_MASTERCONF, &Ndbcntr::execCNTR_MASTERCONF);
- addRecSignal(GSN_CNTR_MASTERREF, &Ndbcntr::execCNTR_MASTERREF);
+ addRecSignal(GSN_CM_ADD_REP, &Ndbcntr::execCM_ADD_REP);
+ addRecSignal(GSN_CNTR_START_REQ, &Ndbcntr::execCNTR_START_REQ);
+ addRecSignal(GSN_CNTR_START_REF, &Ndbcntr::execCNTR_START_REF);
+ addRecSignal(GSN_CNTR_START_CONF, &Ndbcntr::execCNTR_START_CONF);
addRecSignal(GSN_CNTR_WAITREP, &Ndbcntr::execCNTR_WAITREP);
- addRecSignal(GSN_NODE_STATESREQ, &Ndbcntr::execNODE_STATESREQ);
- addRecSignal(GSN_NODE_STATESCONF, &Ndbcntr::execNODE_STATESCONF);
- addRecSignal(GSN_NODE_STATESREF, &Ndbcntr::execNODE_STATESREF);
+ addRecSignal(GSN_CNTR_START_REP, &Ndbcntr::execCNTR_START_REP);
addRecSignal(GSN_NODE_FAILREP, &Ndbcntr::execNODE_FAILREP);
addRecSignal(GSN_SYSTEM_ERROR , &Ndbcntr::execSYSTEM_ERROR);
- addRecSignal(GSN_VOTE_MASTERORD, &Ndbcntr::execVOTE_MASTERORD);
-
+
// Received signals
addRecSignal(GSN_DUMP_STATE_ORD, &Ndbcntr::execDUMP_STATE_ORD);
addRecSignal(GSN_STTOR, &Ndbcntr::execSTTOR);
@@ -80,12 +76,7 @@ Ndbcntr::Ndbcntr(const class Configuration & conf):
addRecSignal(GSN_NDB_STTORRY, &Ndbcntr::execNDB_STTORRY);
addRecSignal(GSN_NDB_STARTCONF, &Ndbcntr::execNDB_STARTCONF);
addRecSignal(GSN_READ_NODESREQ, &Ndbcntr::execREAD_NODESREQ);
- addRecSignal(GSN_APPL_REGCONF, &Ndbcntr::execAPPL_REGCONF);
- addRecSignal(GSN_APPL_REGREF, &Ndbcntr::execAPPL_REGREF);
- addRecSignal(GSN_APPL_CHANGEREP, &Ndbcntr::execAPPL_CHANGEREP);
- addRecSignal(GSN_APPL_STARTCONF, &Ndbcntr::execAPPL_STARTCONF);
addRecSignal(GSN_NDB_STARTREF, &Ndbcntr::execNDB_STARTREF);
- addRecSignal(GSN_CMVMI_CFGCONF, &Ndbcntr::execCMVMI_CFGCONF);
addRecSignal(GSN_SET_VAR_REQ, &Ndbcntr::execSET_VAR_REQ);
addRecSignal(GSN_STOP_PERM_REF, &Ndbcntr::execSTOP_PERM_REF);
@@ -107,18 +98,18 @@ Ndbcntr::Ndbcntr(const class Configuration & conf):
addRecSignal(GSN_START_ORD, &Ndbcntr::execSTART_ORD);
addRecSignal(GSN_STTORRY, &Ndbcntr::execSTTORRY);
+ addRecSignal(GSN_READ_CONFIG_CONF, &Ndbcntr::execREAD_CONFIG_CONF);
addRecSignal(GSN_FSREMOVEREF, &Ndbcntr::execFSREMOVEREF);
addRecSignal(GSN_FSREMOVECONF, &Ndbcntr::execFSREMOVECONF);
initData();
ctypeOfStart = NodeState::ST_ILLEGAL_TYPE;
+ c_start.m_startTime = NdbTick_CurrentMillisecond();
}//Ndbcntr::Ndbcntr()
Ndbcntr::~Ndbcntr()
{
- delete []cfgBlockRec;
- delete []nodeRec;
delete []ndbBlocksRec;
}//Ndbcntr::~Ndbcntr()
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index 4211645ace6..06453155f33 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -23,13 +23,10 @@
#include <signaldata/DictTabInfo.hpp>
#include <signaldata/CreateTable.hpp>
#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/CntrMasterReq.hpp>
-#include <signaldata/CntrMasterConf.hpp>
#include <signaldata/NodeFailRep.hpp>
#include <signaldata/TcKeyReq.hpp>
#include <signaldata/TcKeyConf.hpp>
#include <signaldata/EventReport.hpp>
-#include <signaldata/SetVarReq.hpp>
#include <signaldata/NodeStateSignalData.hpp>
#include <signaldata/StopPerm.hpp>
#include <signaldata/StopMe.hpp>
@@ -39,9 +36,11 @@
#include <signaldata/AbortAll.hpp>
#include <signaldata/SystemError.hpp>
#include <signaldata/NdbSttor.hpp>
+#include <signaldata/CntrStart.hpp>
#include <signaldata/DumpStateOrd.hpp>
#include <signaldata/FsRemoveReq.hpp>
+#include <signaldata/ReadConfig.hpp>
#include <AttributeHeader.hpp>
#include <Configuration.hpp>
@@ -50,8 +49,6 @@
#include <NdbOut.hpp>
#include <NdbTick.h>
-#define ZSYSTEM_RUN 256
-
/**
* ALL_BLOCKS Used during start phases and while changing node state
*
@@ -60,25 +57,27 @@
struct BlockInfo {
BlockReference Ref; // BlockReference
Uint32 NextSP; // Next start phase
+ Uint32 ErrorInsertStart;
+ Uint32 ErrorInsertStop;
};
static BlockInfo ALL_BLOCKS[] = {
- { DBTC_REF, 1 },
- { DBDIH_REF, 1 },
- { DBLQH_REF, 1 },
- { DBACC_REF, 1 },
- { DBTUP_REF, 1 },
- { DBDICT_REF, 1 },
- { NDBFS_REF, 0 },
- { NDBCNTR_REF, 0 },
- { QMGR_REF, 1 },
- { CMVMI_REF, 1 },
- { TRIX_REF, 1 },
- { BACKUP_REF, 1 },
- { DBUTIL_REF, 1 },
- { SUMA_REF, 1 },
- { GREP_REF, 1 },
- { DBTUX_REF, 1 }
+ { DBTC_REF, 1 , 8000, 8035 },
+ { DBDIH_REF, 1 , 7000, 7173 },
+ { DBLQH_REF, 1 , 5000, 5030 },
+ { DBACC_REF, 1 , 3000, 3999 },
+ { DBTUP_REF, 1 , 4000, 4007 },
+ { DBDICT_REF, 1 , 6000, 6003 },
+ { NDBFS_REF, 0 , 2000, 2999 },
+ { NDBCNTR_REF, 0 , 1000, 1999 },
+ { QMGR_REF, 1 , 1, 999 },
+ { CMVMI_REF, 1 , 9000, 9999 },
+ { TRIX_REF, 1 , 0, 0 },
+ { BACKUP_REF, 1 , 10000, 10999 },
+ { DBUTIL_REF, 1 , 11000, 11999 },
+ { SUMA_REF, 1 , 13000, 13999 },
+ { GREP_REF, 1 , 0, 0 },
+ { DBTUX_REF, 1 , 12000, 12999 }
};
static const Uint32 ALL_BLOCKS_SZ = sizeof(ALL_BLOCKS)/sizeof(BlockInfo);
@@ -91,33 +90,27 @@ void Ndbcntr::execCONTINUEB(Signal* signal)
jamEntry();
UintR Ttemp1 = signal->theData[0];
switch (Ttemp1) {
- case ZCONTINUEB_1:
- jam();
- if (cwaitContinuebFlag == ZFALSE) {
- jam();
-/*******************************/
-/* SIGNAL NOT WANTED ANYMORE */
-/*******************************/
- return;
- } else {
+ case ZSTARTUP:{
+ if(getNodeState().startLevel == NodeState::SL_STARTED){
jam();
-/*******************************/
-/* START ALREADY IN PROGRESS */
-/*******************************/
- if (cstartProgressFlag == ZVOTING) {
- jam();
- systemErrorLab(signal);
- return;
- }//if
- if (ctypeOfStart == NodeState::ST_NODE_RESTART) {
- jam();
- systemErrorLab(signal);
- return;
- }//if
- ph2ELab(signal);
return;
- }//if
+ }
+
+ if(cmasterNodeId == getOwnNodeId() && c_start.m_starting.isclear()){
+ jam();
+ trySystemRestart(signal);
+ // Fall-through
+ }
+
+ Uint64 now = NdbTick_CurrentMillisecond();
+ if(c_start.m_startFailureTimeout > now){
+ ndbrequire(false);
+ }
+
+ signal->theData[0] = ZSTARTUP;
+ sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 1);
break;
+ }
case ZSHUTDOWN:
jam();
c_stopRec.checkTimeout(signal);
@@ -189,28 +182,18 @@ void Ndbcntr::execSYSTEM_ERROR(Signal* signal)
return;
}//Ndbcntr::execSYSTEM_ERROR()
-/*---------------------------------------------------------------------------*/
-/* The STTOR signal is on level C, we use CONTINUEB to get into level B */
-/*---------------------------------------------------------------------------*/
-/**************************** >----------------------------------------------*/
-/* STTOR > SENDER : MISSRA */
-/**************************** >------------------+ RECEIVER : NDBCNTR */
- /* INPUT : CSTART_PHASE */
- /* CSIGNAL_KEY */
- /*---------------------------*/
-/*******************************/
-/* STTOR */
-/*******************************/
void Ndbcntr::execSTTOR(Signal* signal)
{
jamEntry();
cstartPhase = signal->theData[1];
- csignalKey = signal->theData[6];
NodeState newState(NodeState::SL_STARTING, cstartPhase,
(NodeState::StartType)ctypeOfStart);
updateNodeState(signal, newState);
+ cndbBlocksCount = 0;
+ cinternalStartphase = cstartPhase - 1;
+
switch (cstartPhase) {
case 0:
if(theConfiguration.getInitialStart()){
@@ -244,6 +227,7 @@ void Ndbcntr::execSTTOR(Signal* signal)
case 6:
jam();
getNodeGroup(signal);
+ // Fall through
break;
case ZSTART_PHASE_8:
jam();
@@ -327,80 +311,37 @@ void Ndbcntr::execNDB_STTORRY(Signal* signal)
}//switch
}//Ndbcntr::execNDB_STTORRY()
-/*
-4.2 START PHASE 1 */
-/*###########################################################################*/
-/*LOAD OUR BLOCK REFERENCE AND OUR NODE ID. LOAD NODE IDS OF ALL NODES IN */
-/* CLUSTER CALCULATE BLOCK REFERENCES OF ALL BLOCKS IN THIS NODE */
-/*---------------------------------------------------------------------------*/
-/*******************************/
-/* STTOR */
-/*******************************/
void Ndbcntr::startPhase1Lab(Signal* signal)
{
jamEntry();
initData(signal);
- cownBlockref = calcNdbCntrBlockRef(0);
- cnoRunNodes = 0;
- cnoRegNodes = 0;
-
- NdbBlocksRecPtr ndbBlocksPtr;
cdynamicNodeId = 0;
- cownBlockref = calcNdbCntrBlockRef(getOwnNodeId());
- cqmgrBlockref = calcQmgrBlockRef(getOwnNodeId());
- cdictBlockref = calcDictBlockRef(getOwnNodeId());
- cdihBlockref = calcDihBlockRef(getOwnNodeId());
- clqhBlockref = calcLqhBlockRef(getOwnNodeId());
- ctcBlockref = calcTcBlockRef(getOwnNodeId());
- ccmvmiBlockref = numberToRef(CMVMI, getOwnNodeId());
+ NdbBlocksRecPtr ndbBlocksPtr;
ndbBlocksPtr.i = 0;
ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = clqhBlockref;
+ ndbBlocksPtr.p->blockref = DBLQH_REF;
ndbBlocksPtr.i = 1;
ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = cdictBlockref;
+ ndbBlocksPtr.p->blockref = DBDICT_REF;
ndbBlocksPtr.i = 2;
ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = calcTupBlockRef(getOwnNodeId());
+ ndbBlocksPtr.p->blockref = DBTUP_REF;
ndbBlocksPtr.i = 3;
ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = calcAccBlockRef(getOwnNodeId());
+ ndbBlocksPtr.p->blockref = DBACC_REF;
ndbBlocksPtr.i = 4;
ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = ctcBlockref;
+ ndbBlocksPtr.p->blockref = DBTC_REF;
ndbBlocksPtr.i = 5;
ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = cdihBlockref;
+ ndbBlocksPtr.p->blockref = DBDIH_REF;
sendSttorry(signal);
return;
}
-/*
-4.3 START PHASE 2 */
-/*###########################################################################*/
-// SEND A REGISTATION REQUEST TO QMGR AND WAIT FOR REPLY APPL_REGCONF OR
-// APPL_REGREF COLLECT ALL OTHER NDB NODES
-// AND THEIR STATES FIND OUT WHAT KIND OF START THIS NODE ARE GOING TO PERFORM
-// IF THIS IS A SYSTEM OR INITIAL
-// RESTART THEN FIND OUT WHO IS THE MASTER IF THIS NODE BECOME THE CNTR MASTER
-// THEN COLLECT CNTR_MASTERREQ FROM
-// ALL OTHER REGISTRATED CNTR THE MASTER WILL SEND BACK A CNTR_MASTERCONF WITH
-// FINAL DECISSION ABOUT WHAT TYPE
-// OF START AND WHICH NODES ARE APPROVED TO PARTICIPATE IN THE START IF THE
-// RECEIVER OF CNTR_MASTERREQ HAVE A
-// BETTER CHOICE OF MASTER THEN SEND CNTR_MASTERREF. NEW NODES ARE ALWAYS
-// ALLOWED TO REGISTER, EVEN DURING
-// RESTART BUT THEY WILL BE IGNORED UNTIL THE START HAVE FINISHED.
-// SEND SIGNAL NDBSTTOR TO ALL BLOCKS, ACC, DICT, DIH, LQH, TC AND TUP
-// SEND SIGNAL APPL_REGREQ TO QMGR IN THIS NODE AND WAIT FOR REPLY
-// APPL_REGCONF OR APPL_REGREF */
-/*--------------------------------------------------------------------------*/
-/*******************************/
-/* READ_NODESREF */
-/*******************************/
void Ndbcntr::execREAD_NODESREF(Signal* signal)
{
jamEntry();
@@ -408,25 +349,6 @@ void Ndbcntr::execREAD_NODESREF(Signal* signal)
return;
}//Ndbcntr::execREAD_NODESREF()
-/*******************************/
-/* APPL_REGREF */
-/*******************************/
-void Ndbcntr::execAPPL_REGREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal);
- return;
-}//Ndbcntr::execAPPL_REGREF()
-
-/*******************************/
-/* CNTR_MASTERREF */
-/*******************************/
-void Ndbcntr::execCNTR_MASTERREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal);
- return;
-}//Ndbcntr::execCNTR_MASTERREF()
/*******************************/
/* NDB_STARTREF */
@@ -443,17 +365,11 @@ void Ndbcntr::execNDB_STARTREF(Signal* signal)
/*******************************/
void Ndbcntr::startPhase2Lab(Signal* signal)
{
- cinternalStartphase = cstartPhase - 1;
-/*--------------------------------------*/
-/* CASE: CSTART_PHASE = ZSTART_PHASE_2 */
-/*--------------------------------------*/
- cndbBlocksCount = 0;
- cwaitContinuebFlag = ZFALSE;
-/* NOT WAITING FOR SIGNAL CONTINUEB */
-
- clastGci = 0;
- signal->theData[0] = cownBlockref;
- sendSignal(cdihBlockref, GSN_DIH_RESTARTREQ, signal, 1, JBB);
+ c_start.m_lastGci = 0;
+ c_start.m_lastGciNodeId = getOwnNodeId();
+
+ signal->theData[0] = reference();
+ sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal, 1, JBB);
return;
}//Ndbcntr::startPhase2Lab()
@@ -463,8 +379,8 @@ void Ndbcntr::startPhase2Lab(Signal* signal)
void Ndbcntr::execDIH_RESTARTCONF(Signal* signal)
{
jamEntry();
- cmasterDihId = signal->theData[0];
- clastGci = signal->theData[1];
+ //cmasterDihId = signal->theData[0];
+ c_start.m_lastGci = signal->theData[1];
ctypeOfStart = NodeState::ST_SYSTEM_RESTART;
ph2ALab(signal);
return;
@@ -488,370 +404,443 @@ void Ndbcntr::ph2ALab(Signal* signal)
/* from QMGR */
/* READ_NODESREQ */
/******************************/
- signal->theData[0] = cownBlockref;
- sendSignal(cqmgrBlockref, GSN_READ_NODESREQ, signal, 1, JBB);
+ signal->theData[0] = reference();
+ sendSignal(QMGR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
return;
}//Ndbcntr::ph2ALab()
+inline
+Uint64
+setTimeout(Uint64 time, Uint32 timeoutValue){
+ if(timeoutValue == 0)
+ return ~0;
+ return time + timeoutValue;
+}
+
/*******************************/
/* READ_NODESCONF */
/*******************************/
void Ndbcntr::execREAD_NODESCONF(Signal* signal)
{
jamEntry();
- ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
+ const ReadNodesConf * readNodes = (ReadNodesConf *)&signal->theData[0];
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if(NodeBitmask::get(readNodes->allNodes, nodePtr.i)){
- jam();
- nodePtr.p->nodeDefined = ZTRUE;
- } else {
- jam();
- nodePtr.p->nodeDefined = ZFALSE;
- }//if
- }//for
+ cmasterNodeId = readNodes->masterNodeId;
+ cdynamicNodeId = readNodes->ndynamicId;
+
+ /**
+ * All defined nodes...
+ */
+ c_allDefinedNodes.assign(NdbNodeBitmask::Size, readNodes->allNodes);
+ c_clusterNodes.assign(NdbNodeBitmask::Size, readNodes->clusterNodes);
- CfgBlockRecPtr cfgBlockPtr;
+ Uint32 to_1 = 30000;
+ Uint32 to_2 = 0;
+ Uint32 to_3 = 0;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+
+ ndbrequire(p != 0);
+ ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTIAL_TIMEOUT, &to_1);
+ ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTITION_TIMEOUT, &to_2);
+ ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT, &to_3);
+
+ c_start.m_startPartialTimeout = setTimeout(c_start.m_startTime, to_1);
+ c_start.m_startPartitionedTimeout = setTimeout(c_start.m_startTime, to_2);
+ c_start.m_startFailureTimeout = setTimeout(c_start.m_startTime, to_3);
+
+ UpgradeStartup::sendCmAppChg(* this, signal, 0); // ADD
+
+ sendCntrStartReq(signal);
- cfgBlockPtr.i = 0;
- ptrAss(cfgBlockPtr, cfgBlockRec);
- signal->theData[0] = cownBlockref;
- signal->theData[1] = cfgBlockPtr.i;
- sendSignal(ccmvmiBlockref, GSN_CMVMI_CFGREQ, signal, 2, JBB);
return;
}
-/*******************************/
-/* CMVMI_CFGCONF */
-/*******************************/
-void Ndbcntr::execCMVMI_CFGCONF(Signal* signal)
-{
- CfgBlockRecPtr cfgBlockPtr;
+void
+Ndbcntr::execCM_ADD_REP(Signal* signal){
+ jamEntry();
+ c_clusterNodes.set(signal->theData[0]);
+}
+
+void
+Ndbcntr::sendCntrStartReq(Signal * signal){
jamEntry();
- CmvmiCfgConf * const cfgConf = (CmvmiCfgConf *)&signal->theData[0];
+ CntrStartReq * req = (CntrStartReq*)signal->getDataPtrSend();
+ req->startType = ctypeOfStart;
+ req->lastGci = c_start.m_lastGci;
+ req->nodeId = getOwnNodeId();
+ sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_START_REQ,
+ signal, CntrStartReq::SignalLength, JBB);
+}
- cfgBlockPtr.i = cfgConf->startPhase;
- ptrCheckGuard(cfgBlockPtr, ZSIZE_CFG_BLOCK_REC, cfgBlockRec);
- for(unsigned int i = 0; i<CmvmiCfgConf::NO_OF_WORDS; i++)
- cfgBlockPtr.p->cfgData[i] = cfgConf->theData[i];
+void
+Ndbcntr::execCNTR_START_REF(Signal * signal){
+ jamEntry();
+ const CntrStartRef * ref = (CntrStartRef*)signal->getDataPtr();
- if (cfgBlockPtr.i < 4) {
+ switch(ref->errorCode){
+ case CntrStartRef::NotMaster:
jam();
- cfgBlockPtr.i = cfgBlockPtr.i + 1;
- signal->theData[0] = cownBlockref;
- signal->theData[1] = cfgBlockPtr.i;
- sendSignal(ccmvmiBlockref, GSN_CMVMI_CFGREQ, signal, 2, JBB);
+ cmasterNodeId = ref->masterNodeId;
+ sendCntrStartReq(signal);
return;
- }
+ }
+ ndbrequire(false);
+}
+
+void
+Ndbcntr::StartRecord::reset(){
+ m_starting.clear();
+ m_waiting.clear();
+ m_withLog.clear();
+ m_withoutLog.clear();
+ m_lastGci = m_lastGciNodeId = 0;
+ m_startPartialTimeout = ~0;
+ m_startPartitionedTimeout = ~0;
+ m_startFailureTimeout = ~0;
- jam();
+ m_logNodesCount = 0;
+}
+
+void
+Ndbcntr::execCNTR_START_CONF(Signal * signal){
+ jamEntry();
+ const CntrStartConf * conf = (CntrStartConf*)signal->getDataPtr();
+
+ cnoStartNodes = conf->noStartNodes;
+ ctypeOfStart = (NodeState::StartType)conf->startType;
+ c_start.m_lastGci = conf->startGci;
+ cmasterNodeId = conf->masterNodeId;
+ NdbNodeBitmask tmp;
+ tmp.assign(NdbNodeBitmask::Size, conf->startedNodes);
+ c_startedNodes.bitOR(tmp);
+ c_start.m_starting.assign(NdbNodeBitmask::Size, conf->startingNodes);
+ ph2GLab(signal);
+
+ UpgradeStartup::sendCmAppChg(* this, signal, 2); //START
+}
+
+/**
+ * Tried with parallell nr, but it crashed in DIH
+ * so I turned it off, as I don't want to debug DIH now...
+ * Jonas 19/11-03
+ *
+ * After trying for 2 hours, I gave up.
+ * DIH is not designed to support it, and
+ * it requires quite of lot of changes to
+ * make it work
+ * Jonas 5/12-03
+ */
+#define PARALLELL_NR 0
+
+#if PARALLELL_NR
+const bool parallellNR = true;
+#else
+const bool parallellNR = false;
+#endif
- cfgBlockPtr.i = 0;
- ptrAss(cfgBlockPtr, cfgBlockRec);
+void
+Ndbcntr::execCNTR_START_REP(Signal* signal){
+ jamEntry();
+ Uint32 nodeId = signal->theData[0];
+ c_startedNodes.set(nodeId);
+ c_start.m_starting.clear(nodeId);
- cdelayStart = cfgBlockPtr.p->cfgData[0];
+ if(!c_start.m_starting.isclear()){
+ jam();
+ return;
+ }
- signal->theData[0] = cownBlockref;
- signal->theData[1] = strlen(ZNAME_OF_APPL) | (ZNAME_OF_APPL[0] << 8);
- signal->theData[2] = ZNAME_OF_APPL[1] | (ZNAME_OF_APPL[2] << 8);
- signal->theData[9] = ZAPPL_SUBTYPE;
- signal->theData[10] = 0; //NDB_VERSION;
- sendSignal(cqmgrBlockref, GSN_APPL_REGREQ, signal, 11, JBB);
- return; /* WAIT FOR APPL_REGCONF */
-}//Ndbcntr::execCMVMI_CFGCONF()
+ if(cmasterNodeId != getOwnNodeId()){
+ c_start.reset();
+ return;
+ }
-/*******************************/
-/* APPL_REGCONF */
-/*******************************/
-void Ndbcntr::execAPPL_REGCONF(Signal* signal)
-{
- jamEntry();
- cqmgrConnectionP = signal->theData[0];
- cnoNdbNodes = signal->theData[1];
- if(ctypeOfStart == NodeState::ST_INITIAL_START){
- cmasterCandidateId = signal->theData[2];
- } else {
- cmasterCandidateId = ZNIL;
+ if(c_start.m_waiting.isclear()){
+ c_start.reset();
+ return;
}
- nodePtr.i = getOwnNodeId();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
+ startWaitingNodes(signal);
+}
+
+void
+Ndbcntr::execCNTR_START_REQ(Signal * signal){
+ jamEntry();
+ const CntrStartReq * req = (CntrStartReq*)signal->getDataPtr();
- /*----------------------------------------------------------------------*/
- /* CALCULATE HOW MANY NODES THAT WE NEED TO PERFORM A START. MAKE A */
- /* DECISION ABOUT WAITING FOR MORE NODES OR TO CONTINUE AT ONCE */
- /*----------------------------------------------------------------------*/
- nodePtr.p->state = ZADD;
- nodePtr.p->ndbVersion = 0; //NDB_VERSION;
- nodePtr.p->subType = ZAPPL_SUBTYPE;
- nodePtr.p->dynamicId = signal->theData[3];
- // Save dynamic nodeid in global variable
- cdynamicNodeId = nodePtr.p->dynamicId;
- cnoRegNodes = cnoRegNodes + 1;
- switch((NodeState::StartType)ctypeOfStart){
- case NodeState::ST_INITIAL_START:
+ const Uint32 nodeId = req->nodeId;
+ const Uint32 lastGci = req->lastGci;
+ const NodeState::StartType st = (NodeState::StartType)req->startType;
+
+ if(cmasterNodeId == 0){
jam();
- cnoNeedNodes = cnoNdbNodes;
- break;
- case NodeState::ST_SYSTEM_RESTART:
- if (cnoNdbNodes == 2) {
- jam();
- /*--------------------------------------*/
- /* NEED > 50% OF ALL NODES. */
- /* WE WILL SEND CONTINUEB WHEN THE WE */
- /* RECEIVE THE FIRST APPL_CHANGEREP. */
- /*--------------------------------------*/
- cnoNeedNodes = 1; /* IF ONLY 2 NODES IN CLUSTER, 1 WILL DO*/
- } else {
- jam();
- cnoNeedNodes = (cnoNdbNodes >> 1) + 1;
- }//if
- break;
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- break;
- default:
- ndbrequire(false);
- }//if
+ // Has not completed READNODES yet
+ sendSignalWithDelay(reference(), GSN_CNTR_START_REQ, signal, 100,
+ signal->getLength());
+ return;
+ }
- /*--------------------------------------------------------------*/
- /* WE CAN COME HERE ALSO IN A NODE RESTART IF THE */
- /* REGISTRATION OF A RUNNING NODE HAPPENS TO ARRIVE BEFORE*/
- /* THE APPL_REGCONF SIGNAL. */
- /* IN THAT CASE CNO_NEED_NODES = ZNIL IF NOT NODE_STATE */
- /* SIGNAL HAS RETURNED THE PROPER VALUE. IN BOTH CASES WE */
- /* DO NOT NEED TO ASSIGN IT HERE. */
- /*--------------------------------------------------------------*/
- ph2CLab(signal);
- return;
-}//Ndbcntr::execAPPL_REGCONF()
-
-/*--------------------------------------------------------------*/
-/* CHECK THAT WE GOT ALL NODES REGISTRATED AS WE NEED FOR THIS */
-/* KIND OF START. WE ALWAYS END UP HERE AFTER HANDLING OF */
-/* APPL_CHANGEREP AND NODE_STATESCONF */
-/*--------------------------------------------------------------*/
-void Ndbcntr::ph2CLab(Signal* signal)
-{
- NodeRecPtr ownNodePtr;
- ownNodePtr.i = getOwnNodeId();
- ptrCheckGuard(ownNodePtr, MAX_NDB_NODES, nodeRec);
- if (ownNodePtr.p->state != ZADD) {
+ if(cmasterNodeId != getOwnNodeId()){
jam();
+ sendCntrStartRef(signal, nodeId, CntrStartRef::NotMaster);
return;
- }//if
- switch (ctypeOfStart) {
- case NodeState::ST_INITIAL_START:
+ }
+
+ const NodeState & nodeState = getNodeState();
+ switch(nodeState.startLevel){
+ case NodeState::SL_NOTHING:
+ case NodeState::SL_CMVMI:
jam();
- if (cnoRegNodes == cnoNeedNodes) {
- jam();
- ph2ELab(signal);
-/*******************************/
-/* ALL NODES ADDED */
-/*******************************/
- return;
- }//if
+ ndbrequire(false);
+ case NodeState::SL_STARTING:
+ case NodeState::SL_STARTED:
+ break;
+
+ case NodeState::SL_STOPPING_1:
+ case NodeState::SL_STOPPING_2:
+ case NodeState::SL_STOPPING_3:
+ case NodeState::SL_STOPPING_4:
+ jam();
+ sendCntrStartRef(signal, nodeId, CntrStartRef::StopInProgress);
+ return;
+ }
+
+ /**
+ * Am I starting (or started)
+ */
+ const bool starting = (nodeState.startLevel != NodeState::SL_STARTED);
+
+ c_start.m_waiting.set(nodeId);
+ switch(st){
+ case NodeState::ST_INITIAL_START:
+ c_start.m_withoutLog.set(nodeId);
break;
case NodeState::ST_SYSTEM_RESTART:
- ndbrequire(cnoRunNodes == 0);
- if (cnoRegNodes == cnoNdbNodes) {
+ c_start.m_withLog.set(nodeId);
+ if(starting && lastGci > c_start.m_lastGci){
jam();
- /*******************************/
- /* ALL NODES ADDED */
- /*******************************/
- ph2ELab(signal);
+ CntrStartRef * ref = (CntrStartRef*)signal->getDataPtrSend();
+ ref->errorCode = CntrStartRef::NotMaster;
+ ref->masterNodeId = nodeId;
+ NodeReceiverGroup rg (NDBCNTR, c_start.m_waiting);
+ sendSignal(rg, GSN_CNTR_START_REF, signal,
+ CntrStartRef::SignalLength, JBB);
return;
- }//if
- if (cwaitContinuebFlag == ZFALSE) {
- if (cnoRegNodes == cnoNeedNodes) {
- jam();
- /****************************************/
- /* ENOUGH NODES ADDED, WAIT CDELAY_START*/
- /****************************************/
- cwaitContinuebFlag = ZTRUE;
- /*******************************/
- /* A DELAY SIGNAL TO MYSELF */
- /*******************************/
- signal->theData[0] = ZCONTINUEB_1;
- sendSignalWithDelay(cownBlockref, GSN_CONTINUEB,
- signal, cdelayStart * 1000, 1);
- return;
- }//if
- }//if
+ }
+ if(starting){
+ Uint32 i = c_start.m_logNodesCount++;
+ c_start.m_logNodes[i].m_nodeId = nodeId;
+ c_start.m_logNodes[i].m_lastGci = req->lastGci;
+ }
break;
case NodeState::ST_NODE_RESTART:
case NodeState::ST_INITIAL_NODE_RESTART:
- jam();
- if (cnoNeedNodes <= cnoRunNodes) {
- /*----------------------------------------------*/
- /* GOT ALL RUNNING NODES */
- /* " =< " :NODES MAY HAVE FINISHED A NODERESTART*/
- /* WHILE WE WERE WAITING FOR NODE_STATESCONF */
- /*----------------------------------------------*/
- if (cnoRegNodes != (cnoRunNodes + 1)) {
- jam();
- systemErrorLab(signal);
- return;
- }//if
- getStartNodes(signal);
- cwaitContinuebFlag = ZFALSE;
- cstartProgressFlag = ZTRUE;
- /*--------------------------------------------------------------*/
- /* IF SOMEONE ELSE IS PERFORMING NODERESTART THEN WE GOT A REF */
- /* AND WE HAVE TO MAKE A NEW NODE_STATESREQ */
- /*--------------------------------------------------------------*/
- sendCntrMasterreq(signal);
- }//if
- break;
- default:
- jam();
- systemErrorLab(signal);
- return;
- break;
- }//switch
- /*--------------------------------------------------------------*/
- /* WAIT FOR THE CONTINUEB SIGNAL */
- /* AND / OR MORE NODES TO REGISTER */
- /*--------------------------------------------------------------*/
- return;
-}//Ndbcntr::ph2CLab()
+ case NodeState::ST_ILLEGAL_TYPE:
+ ndbrequire(false);
+ }
-/*******************************/
-/* CONTINUEB */
-/*******************************/
-/*--------------------------------------------------------------*/
-/* WE COME HERE ONLY IN SYSTEM RESTARTS AND INITIAL START. FOR */
-/* INITIAL START WE HAVE ALREADY CALCULATED THE MASTER. FOR */
-/* SYSTEM RESTART WE NEED TO PERFORM A VOTING SCHEME TO AGREE */
-/* ON A COMMON MASTER. WE GET OUR VOTE FROM DIH AND THE RESTART */
-/* INFORMATION IN DIH. */
-/*--------------------------------------------------------------*/
-void Ndbcntr::ph2ELab(Signal* signal)
-{
- cwaitContinuebFlag = ZFALSE;
-/*--------------------------------------*/
-/* JMP TO THIS WHEN ENOUGH NO OF */
-/* NODES ADDED */
-/*--------------------------------------*/
-/*--------------------------------------*/
-/* IGNORE CONTINUEB SIGNAL */
-/* CONTINUEB SIGNALS WILL EXIT AT */
-/* SIGNAL RECEPTION */
-/*--------------------------------------*/
- if (cnoRegNodes >= cnoNeedNodes) {
+ const bool startInProgress = !c_start.m_starting.isclear();
+
+ if((starting && startInProgress) || (startInProgress && !parallellNR)){
jam();
- getStartNodes(signal);
- if (ctypeOfStart == NodeState::ST_INITIAL_START) {
- if (cmasterCandidateId != getOwnNodeId()) {
- jam();
-/*--------------------------------------*/
-/* THIS NODE IS NOT THE MASTER */
-/* DON'T SEND ANY MORE CNTR_MASTERREQ */
-/* VOTE FOR MASTER */
-/*--------------------------------------*/
- cstartProgressFlag = ZTRUE;
- sendCntrMasterreq(signal);
- resetStartVariables(signal);
- } else {
- jam();
- masterreq020Lab(signal);
- }//if
- } else if (ctypeOfStart == NodeState::ST_SYSTEM_RESTART) {
- jam();
-/*--------------------------------------------------------------*/
-/* WE START THE SELECTION OF MASTER PROCESS. IF WE HAVE NOT */
-/* COMPLETED THIS BEFORE THE TIME OUT WE WILL TRY A NEW RESTART.*/
-/*--------------------------------------------------------------*/
- cwaitContinuebFlag = ZTRUE;
- cstartProgressFlag = ZVOTING;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->state == ZADD) {
- jam();
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = cmasterDihId;
- signal->theData[2] = clastGci;
- sendSignal(nodePtr.p->cntrBlockref, GSN_VOTE_MASTERORD,
- signal, 3, JBB);
- }//if
- }//for
- } else {
- jam();
- systemErrorLab(signal);
- }//if
+ // We're already starting together with a bunch of nodes
+ // Let this node wait...
+ return;
+ }
+
+ if(starting){
+ trySystemRestart(signal);
} else {
- jam();
-/*--------------------------------------------------------------*/
-/* TOO FEW NODES TO START */
-/* WE HAVE WAITED FOR THE GIVEN TIME OUT AND NOT ENOUGH NODES */
-/* HAS REGISTERED. WE WILL CRASH AND RENEW THE ATTEMPT TO START */
-/* THE SYSTEM. */
-/*--------------------------------------------------------------*/
- systemErrorLab(signal);
- }//if
+ startWaitingNodes(signal);
+ }
+
return;
-}//Ndbcntr::ph2ELab()
+}
-/*******************************/
-/* MASTER NODE CONFIRMS REQ */
-/* CNTR_MASTERCONF */
-/*******************************/
-void Ndbcntr::execCNTR_MASTERCONF(Signal* signal)
-{
+void
+Ndbcntr::startWaitingNodes(Signal * signal){
+
+#if ! PARALLELL_NR
+ const Uint32 nodeId = c_start.m_waiting.find(0);
+ const Uint32 Tref = calcNdbCntrBlockRef(nodeId);
+ ndbrequire(nodeId != c_start.m_waiting.NotFound);
+
+ NodeState::StartType nrType = NodeState::ST_NODE_RESTART;
+ if(c_start.m_withoutLog.get(nodeId)){
+ nrType = NodeState::ST_INITIAL_NODE_RESTART;
+ }
+
+ /**
+ * Let node perform restart
+ */
+ CntrStartConf * conf = (CntrStartConf*)signal->getDataPtrSend();
+ conf->noStartNodes = 1;
+ conf->startType = nrType;
+ conf->startGci = ~0; // Not used
+ conf->masterNodeId = getOwnNodeId();
+ BitmaskImpl::clear(NdbNodeBitmask::Size, conf->startingNodes);
+ BitmaskImpl::set(NdbNodeBitmask::Size, conf->startingNodes, nodeId);
+ c_startedNodes.copyto(NdbNodeBitmask::Size, conf->startedNodes);
+ sendSignal(Tref, GSN_CNTR_START_CONF, signal,
+ CntrStartConf::SignalLength, JBB);
+
+ c_start.m_waiting.clear(nodeId);
+ c_start.m_withLog.clear(nodeId);
+ c_start.m_withoutLog.clear(nodeId);
+ c_start.m_starting.set(nodeId);
+#else
+ // Parallell nr
+
+ c_start.m_starting = c_start.m_waiting;
+ c_start.m_waiting.clear();
+
+ CntrStartConf * conf = (CntrStartConf*)signal->getDataPtrSend();
+ conf->noStartNodes = 1;
+ conf->startGci = ~0; // Not used
+ conf->masterNodeId = getOwnNodeId();
+ c_start.m_starting.copyto(NdbNodeBitmask::Size, conf->startingNodes);
+ c_startedNodes.copyto(NdbNodeBitmask::Size, conf->startedNodes);
+
+ char buf[100];
+ if(!c_start.m_withLog.isclear()){
+ ndbout_c("Starting nodes w/ log: %s", c_start.m_withLog.getText(buf));
+
+ NodeReceiverGroup rg(NDBCNTR, c_start.m_withLog);
+ conf->startType = NodeState::ST_NODE_RESTART;
+
+ sendSignal(rg, GSN_CNTR_START_CONF, signal,
+ CntrStartConf::SignalLength, JBB);
+ }
+
+ if(!c_start.m_withoutLog.isclear()){
+ ndbout_c("Starting nodes wo/ log: %s", c_start.m_withoutLog.getText(buf));
+ NodeReceiverGroup rg(NDBCNTR, c_start.m_withoutLog);
+ conf->startType = NodeState::ST_INITIAL_NODE_RESTART;
+
+ sendSignal(rg, GSN_CNTR_START_CONF, signal,
+ CntrStartConf::SignalLength, JBB);
+ }
+
+ c_start.m_waiting.clear();
+ c_start.m_withLog.clear();
+ c_start.m_withoutLog.clear();
+#endif
+}
+
+void
+Ndbcntr::sendCntrStartRef(Signal * signal,
+ Uint32 nodeId, CntrStartRef::ErrorCode code){
+ CntrStartRef * ref = (CntrStartRef*)signal->getDataPtrSend();
+ ref->errorCode = code;
+ ref->masterNodeId = cmasterNodeId;
+ sendSignal(calcNdbCntrBlockRef(nodeId), GSN_CNTR_START_REF, signal,
+ CntrStartRef::SignalLength, JBB);
+}
+
+CheckNodeGroups::Output
+Ndbcntr::checkNodeGroups(Signal* signal, const NdbNodeBitmask & mask){
+ CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
+ sd->blockRef = reference();
+ sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
+ sd->mask = mask;
+ EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
+ CheckNodeGroups::SignalLength);
jamEntry();
+ return (CheckNodeGroups::Output)sd->output;
+}
- CntrMasterConf * const cntrMasterConf =
- (CntrMasterConf *)&signal->theData[0];
+bool
+Ndbcntr::trySystemRestart(Signal* signal){
+ /**
+ * System restart something
+ */
+ const bool allNodes = c_start.m_waiting.equal(c_allDefinedNodes);
+ const bool allClusterNodes = c_start.m_waiting.equal(c_clusterNodes);
+ const Uint64 now = NdbTick_CurrentMillisecond();
- cnoStartNodes = cntrMasterConf->noStartNodes;
- int index = 0;
- unsigned i;
- for (i = 1; i < MAX_NDB_NODES; i++) {
+ if(!allClusterNodes){
jam();
- if (NodeBitmask::get(cntrMasterConf->theNodes, i)) {
- jam();
- cstartNodes[index] = i;
- index++;
- }//if
- }//for
- if (cnoStartNodes != index) {
+ return false;
+ }
+
+ if(!allNodes && c_start.m_startPartialTimeout > now){
jam();
- systemErrorLab(signal);
- }//if
- ph2FLab(signal);
- return;
-}//Ndbcntr::execCNTR_MASTERCONF()
+ return false;
+ }
-void Ndbcntr::ph2FLab(Signal* signal)
-{
-/*--------------------------------------------------------------*/
-//The nodes have been selected and we now know which nodes are
-// included in the system restart. We can reset wait for CONTINUEB
-// flag to ensure system is not restarted when CONTINUEB after the
-// delay.
-/*--------------------------------------------------------------*/
- cmasterNodeId = cmasterCandidateId;
- cwaitContinuebFlag = ZFALSE;
- ph2GLab(signal);
- return;
-}//Ndbcntr::ph2FLab()
+ NodeState::StartType srType = NodeState::ST_SYSTEM_RESTART;
+ if(c_start.m_waiting.equal(c_start.m_withoutLog)){
+ if(!allNodes){
+ jam();
+ return false;
+ }
+ srType = NodeState::ST_INITIAL_START;
+ c_start.m_starting = c_start.m_withoutLog; // Used for starting...
+ c_start.m_withoutLog.clear();
+ } else {
+
+ CheckNodeGroups::Output wLog = checkNodeGroups(signal, c_start.m_withLog);
+
+ switch (wLog) {
+ case CheckNodeGroups::Win:
+ jam();
+ break;
+ case CheckNodeGroups::Lose:
+ jam();
+ // If we lose with all nodes, then we're in trouble
+ ndbrequire(!allNodes);
+ return false;
+ break;
+ case CheckNodeGroups::Partitioning:
+ jam();
+ bool allowPartition = (c_start.m_startPartitionedTimeout != (Uint64)~0);
+
+ if(allNodes){
+ jam();
+ if(allowPartition){
+ jam();
+ break;
+ }
+ ndbrequire(false); // All nodes -> partitioning, which is not allowed
+ }
+
+ if(c_start.m_startPartitionedTimeout > now){
+ jam();
+ return false;
+ }
+ break;
+ }
+
+ // For now only with the "logged"-ones.
+ // Let the others do node restart afterwards...
+ c_start.m_starting = c_start.m_withLog;
+ c_start.m_withLog.clear();
+ }
+
+ /**
+ * Okidoki, we try to start
+ */
+ CntrStartConf * conf = (CntrStartConf*)signal->getDataPtr();
+ conf->noStartNodes = c_start.m_starting.count();
+ conf->startType = srType;
+ conf->startGci = c_start.m_lastGci;
+ conf->masterNodeId = c_start.m_lastGciNodeId;
+ c_start.m_starting.copyto(NdbNodeBitmask::Size, conf->startingNodes);
+ c_startedNodes.copyto(NdbNodeBitmask::Size, conf->startedNodes);
+
+ ndbrequire(c_start.m_lastGciNodeId == getOwnNodeId());
+
+ NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
+ sendSignal(rg, GSN_CNTR_START_CONF, signal, CntrStartConf::SignalLength,JBB);
+
+ c_start.m_waiting.bitANDC(c_start.m_starting);
+
+ return true;
+}
-/*--------------------------------------*/
-/* RECEIVED CNTR_MASTERCONF */
-/*--------------------------------------*/
-/*******************************/
-/* NDB_STTORRY */
-/*******************************/
-/*---------------------------------------------------------------------------*/
-// NOW WE CAN START NDB START PHASE 1. IN THIS PHASE ALL BLOCKS
-// (EXCEPT DIH THAT INITIALISED WHEN
-// RECEIVING DIH_RESTARTREQ) WILL INITIALISE THEIR DATA, COMMON VARIABLES,
-// LINKED LISTS AND RECORD VARIABLES.
-/*---------------------------------------------------------------------------*/
void Ndbcntr::ph2GLab(Signal* signal)
{
if (cndbBlocksCount < ZNO_NDB_BLOCKS) {
@@ -879,11 +868,6 @@ void Ndbcntr::ph2GLab(Signal* signal)
/*******************************/
void Ndbcntr::startPhase3Lab(Signal* signal)
{
- cinternalStartphase = cstartPhase - 1;
-/*--------------------------------------*/
-/* CASE: CSTART_PHASE = ZSTART_PHASE_3 */
-/*--------------------------------------*/
- cndbBlocksCount = 0;
ph3ALab(signal);
return;
}//Ndbcntr::startPhase3Lab()
@@ -893,29 +877,12 @@ void Ndbcntr::startPhase3Lab(Signal* signal)
/*******************************/
void Ndbcntr::ph3ALab(Signal* signal)
{
- Uint16 tnoStartNodes;
-
if (cndbBlocksCount < ZNO_NDB_BLOCKS) {
jam();
sendNdbSttor(signal);
return;
}//if
-/*******************************/
-/*< APPL_STARTREG <*/
-/*******************************/
- if (ctypeOfStart == NodeState::ST_NODE_RESTART) {
- jam();
- tnoStartNodes = 1;
- } else if (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART) {
- jam();
- tnoStartNodes = 1;
- } else {
- jam();
- tnoStartNodes = cnoStartNodes;
- }//if
- signal->theData[0] = cqmgrConnectionP;
- signal->theData[1] = tnoStartNodes;
- sendSignal(cqmgrBlockref, GSN_APPL_STARTREG, signal, 2, JBB);
+
sendSttorry(signal);
return;
}//Ndbcntr::ph3ALab()
@@ -933,49 +900,12 @@ void Ndbcntr::ph3ALab(Signal* signal)
/*******************************/
void Ndbcntr::startPhase4Lab(Signal* signal)
{
- cinternalStartphase = cstartPhase - 1;
-/*--------------------------------------*/
-/* CASE: CSTART_PHASE = ZSTART_PHASE_4 */
-/*--------------------------------------*/
- cndbBlocksCount = 0;
- cnoWaitrep = 0;
- if (capplStartconfFlag != ZTRUE) {
- jam();
-/*------------------------------------------------------*/
-/* HAVE WE ALREADY RECEIVED APPL_STARTCONF */
-/*------------------------------------------------------*/
- return;
- }//if
ph4ALab(signal);
- return;
}//Ndbcntr::startPhase4Lab()
-/*******************************/
-/* APPL_STARTCONF */
-/*******************************/
-void Ndbcntr::execAPPL_STARTCONF(Signal* signal)
-{
- jamEntry();
- if (cstartPhase == ZSTART_PHASE_4) {
- jam();
- ph4ALab(signal);
- return;
- } else {
- jam();
- capplStartconfFlag = ZTRUE;
-//------------------------------------------------
-/* FLAG WILL BE CHECKED WHEN WE RECEIVED STTOR */
-/* SIGNAL MAY BE RECEIVED IN STARTPHASE 3 */
-//------------------------------------------------
- return;
- }//if
-}//Ndbcntr::execAPPL_STARTCONF()
void Ndbcntr::ph4ALab(Signal* signal)
{
- nodePtr.i = getOwnNodeId();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- nodePtr.p->state = ZSTART;
ph4BLab(signal);
return;
}//Ndbcntr::ph4ALab()
@@ -1014,6 +944,7 @@ void Ndbcntr::waitpoint41Lab(Signal* signal)
cnoWaitrep++;
if (cnoWaitrep == cnoStartNodes) {
jam();
+ cnoWaitrep = 0;
/*---------------------------------------------------------------------------*/
// NDB_STARTREQ STARTS UP ALL SET UP OF DISTRIBUTION INFORMATION IN DIH AND
// DICT. AFTER SETTING UP THIS
@@ -1025,9 +956,9 @@ void Ndbcntr::waitpoint41Lab(Signal* signal)
// 3) EXECUTING THE FRAGMENT REDO LOG FROM ONE OR SEVERAL NODES TO
// RESTORE THE RESTART CONFIGURATION OF DATA IN NDB CLUSTER.
/*---------------------------------------------------------------------------*/
- signal->theData[0] = cownBlockref;
+ signal->theData[0] = reference();
signal->theData[1] = ctypeOfStart;
- sendSignal(cdihBlockref, GSN_NDB_STARTREQ, signal, 2, JBB);
+ sendSignal(DBDIH_REF, GSN_NDB_STARTREQ, signal, 2, JBB);
}//if
} else {
jam();
@@ -1037,11 +968,10 @@ void Ndbcntr::waitpoint41Lab(Signal* signal)
/* SLAVES WONT DO ANYTHING UNTIL THEY */
/* RECEIVE A WAIT REPORT FROM THE MASTER*/
/*--------------------------------------*/
- nodePtr.i = cmasterNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
signal->theData[0] = getOwnNodeId();
signal->theData[1] = ZWAITPOINT_4_1;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB);
+ sendSignal(calcNdbCntrBlockRef(cmasterNodeId),
+ GSN_CNTR_WAITREP, signal, 2, JBB);
}//if
return;
}//Ndbcntr::waitpoint41Lab()
@@ -1052,23 +982,11 @@ void Ndbcntr::waitpoint41Lab(Signal* signal)
void Ndbcntr::execNDB_STARTCONF(Signal* signal)
{
jamEntry();
- UintR guard0;
- UintR Ttemp1;
- guard0 = cnoStartNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- for (Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) {
- jam();
- if (cstartNodes[Ttemp1] != getOwnNodeId()) {
- jam();
- nodePtr.i = cstartNodes[Ttemp1];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_4_2;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB);
- }//if
- }//for
- sendSttorry(signal);
+ NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
+ signal->theData[0] = getOwnNodeId();
+ signal->theData[1] = ZWAITPOINT_4_2;
+ sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB);
return;
}//Ndbcntr::execNDB_STARTCONF()
@@ -1084,9 +1002,6 @@ void Ndbcntr::execNDB_STARTCONF(Signal* signal)
/*******************************/
void Ndbcntr::startPhase5Lab(Signal* signal)
{
- cinternalStartphase = cstartPhase - 1;
- cndbBlocksCount = 0;
- cnoWaitrep = 0;
ph5ALab(signal);
return;
}//Ndbcntr::startPhase5Lab()
@@ -1147,16 +1062,17 @@ void Ndbcntr::ph5ALab(Signal* signal)
// SEND NDB START PHASE 5 IN NODE RESTARTS TO COPY DATA TO THE NEWLY
// STARTED NODE.
/*----------------------------------------------------------------------*/
- req->senderRef = cownBlockref;
+ req->senderRef = reference();
req->nodeId = getOwnNodeId();
req->internalStartPhase = cinternalStartphase;
req->typeOfStart = ctypeOfStart;
req->masterNodeId = cmasterNodeId;
+ //#define TRACE_STTOR
#ifdef TRACE_STTOR
ndbout_c("sending NDB_STTOR(%d) to DIH", cinternalStartphase);
#endif
- sendSignal(cdihBlockref, GSN_NDB_STTOR, signal,
+ sendSignal(DBDIH_REF, GSN_NDB_STTOR, signal,
NdbSttor::SignalLength, JBB);
return;
case NodeState::ST_INITIAL_START:
@@ -1170,11 +1086,10 @@ void Ndbcntr::ph5ALab(Signal* signal)
/* RECEIVE A WAIT REPORT FROM THE MASTER*/
/* WHEN THE MASTER HAS FINISHED HIS WORK*/
/*--------------------------------------*/
- nodePtr.i = cmasterNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
signal->theData[0] = getOwnNodeId();
signal->theData[1] = ZWAITPOINT_5_2;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB);
+ sendSignal(calcNdbCntrBlockRef(cmasterNodeId),
+ GSN_CNTR_WAITREP, signal, 2, JBB);
return;
default:
ndbrequire(false);
@@ -1198,8 +1113,10 @@ void Ndbcntr::waitpoint52Lab(Signal* signal)
/*--------------------------------------*/
if (cnoWaitrep == cnoStartNodes) {
jam();
+ cnoWaitrep = 0;
+
NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend();
- req->senderRef = cownBlockref;
+ req->senderRef = reference();
req->nodeId = getOwnNodeId();
req->internalStartPhase = cinternalStartphase;
req->typeOfStart = ctypeOfStart;
@@ -1207,7 +1124,7 @@ void Ndbcntr::waitpoint52Lab(Signal* signal)
#ifdef TRACE_STTOR
ndbout_c("sending NDB_STTOR(%d) to DIH", cinternalStartphase);
#endif
- sendSignal(cdihBlockref, GSN_NDB_STTOR, signal,
+ sendSignal(DBDIH_REF, GSN_NDB_STTOR, signal,
NdbSttor::SignalLength, JBB);
}//if
return;
@@ -1218,28 +1135,19 @@ void Ndbcntr::waitpoint52Lab(Signal* signal)
/*******************************/
void Ndbcntr::ph6ALab(Signal* signal)
{
- UintR guard0;
- UintR Ttemp1;
-
if ((ctypeOfStart == NodeState::ST_NODE_RESTART) ||
(ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) {
jam();
waitpoint51Lab(signal);
return;
}//if
- guard0 = cnoStartNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- for (Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) {
- jam();
- if (cstartNodes[Ttemp1] != getOwnNodeId()) {
- jam();
- nodePtr.i = cstartNodes[Ttemp1];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_5_1;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB);
- }//if
- }//for
+
+ NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
+ rg.m_nodes.clear(getOwnNodeId());
+ signal->theData[0] = getOwnNodeId();
+ signal->theData[1] = ZWAITPOINT_5_1;
+ sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB);
+
waitpoint51Lab(signal);
return;
}//Ndbcntr::ph6ALab()
@@ -1283,28 +1191,18 @@ void Ndbcntr::waitpoint61Lab(Signal* signal)
cnoWaitrep6++;
if (cnoWaitrep6 == cnoStartNodes) {
jam();
- Uint32 guard0 = cnoStartNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- for (Uint32 Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) {
- jam();
- if (cstartNodes[Ttemp1] != getOwnNodeId()) {
- jam();
- nodePtr.i = cstartNodes[Ttemp1];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_6_2;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB);
- }
- }
+ NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
+ rg.m_nodes.clear(getOwnNodeId());
+ signal->theData[0] = getOwnNodeId();
+ signal->theData[1] = ZWAITPOINT_6_2;
+ sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB);
sendSttorry(signal);
}
} else {
jam();
- nodePtr.i = cmasterNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
signal->theData[0] = getOwnNodeId();
signal->theData[1] = ZWAITPOINT_6_1;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB);
+ sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB);
}
}
@@ -1339,28 +1237,18 @@ void Ndbcntr::waitpoint71Lab(Signal* signal)
cnoWaitrep7++;
if (cnoWaitrep7 == cnoStartNodes) {
jam();
- Uint32 guard0 = cnoStartNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- for (Uint32 Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) {
- jam();
- if (cstartNodes[Ttemp1] != getOwnNodeId()) {
- jam();
- nodePtr.i = cstartNodes[Ttemp1];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_7_2;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB);
- }
- }
+ NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
+ rg.m_nodes.clear(getOwnNodeId());
+ signal->theData[0] = getOwnNodeId();
+ signal->theData[1] = ZWAITPOINT_7_2;
+ sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB);
sendSttorry(signal);
}
} else {
jam();
- nodePtr.i = cmasterNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
signal->theData[0] = getOwnNodeId();
signal->theData[1] = ZWAITPOINT_7_1;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_WAITREP, signal, 2, JBB);
+ sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB);
}
}
@@ -1378,315 +1266,11 @@ void Ndbcntr::ph8ALab(Signal* signal)
// NODES WHICH PERFORM A NODE RESTART NEEDS TO GET THE DYNAMIC ID'S
// OF THE OTHER NODES HERE.
/*---------------------------------------------------------------------------*/
- signal->theData[0] = cqmgrConnectionP;
- sendSignal(cqmgrBlockref, GSN_APPL_RUN, signal, 1, JBB);
- nodePtr.i = getOwnNodeId();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- nodePtr.p->state = ZRUN;
- cnoRunNodes = cnoRunNodes + 1;
sendSttorry(signal);
- cstartProgressFlag = ZFALSE;
- ctypeOfStart = (NodeState::StartType)ZSYSTEM_RUN;
resetStartVariables(signal);
return;
}//Ndbcntr::ph8BLab()
-/*
-4.7 HANDLE GLOBAL EVENTS, NOT BOUNDED TO INITIALSTART OR SYSTEM RESTART */
-/*#######################################################################*/
-/*******************************/
-/* APPL_CHANGEREP */
-/*******************************/
-void Ndbcntr::execAPPL_CHANGEREP(Signal* signal)
-{
- jamEntry();
- Uint16 TapplEvent = signal->theData[0];
- Uint16 TapplVersion = signal->theData[1];
- Uint16 TapplNodeId = signal->theData[2];
- Uint16 TapplSubType = signal->theData[3];
-
- nodePtr.i = TapplNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- nodePtr.p->subType = TapplSubType;
- nodePtr.p->ndbVersion = TapplVersion;
- nodePtr.p->dynamicId = signal->theData[4];
-
- switch (TapplEvent) {
- case ZADD:
-/*----------------------------*/
-/* ADD A NEW NDB NODE TO FILE */
-/*----------------------------*/
- if (nodePtr.p->state == ZREMOVE) {
- jam();
- if (cnoRegNodes == cnoNdbNodes) {
- jam();
-/*----------------------------------------------*/
-/* DON'T ACCEPT MORE NODES THAN SYSFILE.CFG SPEC*/
-/*----------------------------------------------*/
- systemErrorLab(signal);
- return;
- }//if
- nodePtr.p->state = ZADD;
- cnoRegNodes = cnoRegNodes + 1;
- } else {
- jam();
- systemErrorLab(signal);
- return;
- }//if
- if (cstartProgressFlag == ZFALSE) {
-/*----------------------------------------------*/
-/* FLAG = TRUE WHEN CNTR_MASTERREQ IS SENT */
-/*----------------------------------------------*/
- switch (ctypeOfStart) {
- case NodeState::ST_INITIAL_START:
- case NodeState::ST_SYSTEM_RESTART:
- jam();
- ph2CLab(signal);
-/*----------------------------------------------*/
-/* CHECK IF READY TO MAKE A CNTR_MASTERREQ */
-/*----------------------------------------------*/
- break;
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- jam();
-/*------------------------------------------------------------------------*/
-/* THIS SHOULD NEVER OCCUR SINCE WE HAVE ALREADY BEEN ALLOWED TO */
-/* START OUR NODE. THE NEXT NODE CANNOT START UNTIL WE ARE FINISHED */
-/*------------------------------------------------------------------------*/
- systemErrorLab(signal);
- break;
- case ZSYSTEM_RUN:
- jam();
- /*empty*/;
- break;
- default:
- jam();
-/*------------------------------------------------------------------------*/
-/* NO PARTICULAR ACTION IS NEEDED. THE NODE WILL PERFORM A NODE */
-/* RESTART BUT NO ACTION IS NEEDED AT THIS STAGE IN THE RESTART. */
-/*------------------------------------------------------------------------*/
- systemErrorLab(signal);
- break;
- }//switch
- } else {
- jam();
-/*--------------------------------------------------------------------------*/
-// WHEN A RESTART IS IN PROGRESS THERE IS A POSSIBILITY THAT A NODE
-// REGISTER AND
-// THINKS THAT HE WOULD BE THE MASTER (LOWER NODE ID) BUT THE OTHER NODE IS
-// ALREADY RUNNING THE RESTART. THIS WILL BE DETECTED WHEN HE ATTEMPTS A
-// CNTR_MASTERREQ AND RECEIVES A REFUSE SIGNAL IN RETURN. THIS WILL CAUSE HIM
-// TO CRASH. IF HE ATTEMPTS TO JOIN AS A NON-MASTER HE WILL WAIT FOR THE MASTER.
-// IN THIS CASE IT IS BETTER TO SHOT HIM DOWN. FOR SAFETY REASONS WE WILL ALWAYS
-// SHOT HIM DOWN.
-/*--------------------------------------------------------------------------*/
- const BlockReference tblockref = calcNdbCntrBlockRef(nodePtr.i);
-
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::StartInProgressError;
- sysErr->errorRef = reference();
- sendSignal(tblockref, GSN_SYSTEM_ERROR, signal, SystemError::SignalLength, JBA);
- }//if
- break;
- case ZSTART:
- jam();
- if (nodePtr.p->state != ZADD) {
- jam();
- systemErrorLab(signal);
- return;
- }//if
- nodePtr.p->state = ZSTART;
- break;
- case ZRUN:
- if (nodePtr.p->state == ZREMOVE) {
- jam();
- cnoRegNodes = cnoRegNodes + 1;
- } else {
- jam();
- if (nodePtr.p->state != ZSTART) {
- jam();
-/*----------------------------------------------*/
-/* STATE ZADD OR ZRUN -> ZRUN NOT ALLOWED */
-/*----------------------------------------------*/
- systemErrorLab(signal);
- return;
- }//if
- }//if
- cnoRunNodes = cnoRunNodes + 1;
- nodePtr.p->state = ZRUN;
- switch (ctypeOfStart) {
- case NodeState::ST_INITIAL_START:
- jam();
- detectNoderestart(signal);
- if (ctypeOfStart == NodeState::ST_NODE_RESTART) {
- jam();
-/*--------------------------------------------------------------------------*/
-/* WE DISCOVERED THAT WE ARE TRYING TO PERFORM A INITIAL START WHEN THERE */
-/* ARE ALREADY RUNNING NODES. THIS MEANS THAT THE NODE HAS CLEANED THE */
-/* FILE SYSTEM AND CONTAINS NO DATA. THIS IS AN INITIAL NODE RESTART WHICH */
-/* IS NECESSARY TO START A NODE THAT HAS BEEN TAKEN OVER. */
-/*--------------------------------------------------------------------------*/
- ctypeOfStart = NodeState::ST_INITIAL_NODE_RESTART;
- }//if
- break;
- case NodeState::ST_SYSTEM_RESTART:
- jam();
- detectNoderestart(signal);
-/*----------------------------------------------*/
-/* SHOULD THIS NODE PERFORM A NODE RESTART? */
-/* THEN CHANGE CTYPE_OF_START TO NodeState::ST_NODE_RESTART */
-/* AND SEND NODE_STATESREQ. */
-/* WAIT FOR NODE_STATESCONF. */
-/*----------------------------------------------*/
- break;
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- jam();
-/*----------------------------------------------*/
-/* IF WE ARE WAITING FOR NODE_STATESCONF, THIS */
-/* JUMP WILL EXIT BECAUSE CNO_NEED_NODES = ZNIL */
-/* UNTIL WE RECEIVE NODE_STATESCONF */
-/*----------------------------------------------*/
- ph2CLab(signal);
- break;
- case ZSYSTEM_RUN:
- jam();
- break;
- default:
- jam();
- systemErrorLab(signal);
- break;
- }//switch
- break;
- default:
- jam();
- systemErrorLab(signal);
- break;
- }//switch
- return;
-}//Ndbcntr::execAPPL_CHANGEREP()
-
-/*--------------------------------------------------------------------------*/
-// A NODE HAS ADDED HAS VOTE ON WHICH MASTER IS TO BE CHOOSEN IN A SYSTEM
-// RESTART. WHEN ALL VOTES HAVE
-// BEEN ADDED THEN WE ARE PREPARED TO CHOOSE MASTER AND CONTINUE WITH THE
-// RESTART PROCESSING.
-/*--------------------------------------------------------------------------*/
-
-/*******************************/
-/* VOT_MASTERORD */
-/*******************************/
-void Ndbcntr::execVOTE_MASTERORD(Signal* signal)
-{
- jamEntry();
- nodePtr.i = signal->theData[0];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- UintR TmasterCandidateId = signal->theData[1];
- UintR TlastGci = signal->theData[2];
- if (ctypeOfStart != NodeState::ST_SYSTEM_RESTART) {
- jam();
- progError(__LINE__,
- ERR_SR_RESTARTCONFLICT,
- "One ore more nodes probably requested an initial SR");
- return;
- }//if
- cmasterVoters = cmasterVoters + 1;
- if (cmasterVoters == 1) {
- jam();
- cmasterCurrentId = TmasterCandidateId;
- cmasterLastGci = TlastGci;
- } else {
- if (cmasterLastGci < TlastGci) {
- jam();
- cmasterCurrentId = TmasterCandidateId;
- cmasterLastGci = TlastGci;
- } else if (cmasterLastGci == TlastGci) {
- jam();
- if (cmasterCurrentId != TmasterCandidateId) {
- jam();
- systemErrorLab(signal);
- return;
- }//if
- }//if
- }//if
- if (cstartProgressFlag == ZVOTING) {
-/*--------------------------------------------------------------------------*/
-// UNLESS START PROGRESS FLAG IS SET TO VOTING WE HAVE NOT YET REACHED A
-// STATE WHERE WE ARE READY TO
-// PROCEED WITH THE SYSTEM RESTART. OUR OWN NOTE HAVE AT LEAST NOT BEEN
-// CAST INTO THE BALLOT YET.
-/*--------------------------------------------------------------------------*/
- if (cmasterVoters == cnoRegNodes) {
- cmasterCandidateId = cmasterCurrentId;
- if (cmasterCandidateId == getOwnNodeId()) {
- jam();
- masterreq020Lab(signal);
- return;
- } else {
- jam();
- cstartProgressFlag = ZTRUE;
- sendCntrMasterreq(signal);
- resetStartVariables(signal);
- }//if
- }//if
- }//if
- return;
-}//Ndbcntr::execVOTE_MASTERORD()
-
-/*******************************/
-/* CNTR_MASTERREQ */
-/*******************************/
-void Ndbcntr::execCNTR_MASTERREQ(Signal* signal)
-{
- Uint16 ttypeOfStart;
-
- jamEntry();
-
- CntrMasterReq * const cntrMasterReq =
- (CntrMasterReq *)&signal->theData[0];
-
-//-----------------------------------------------
-// cntrMasterReq->userBlockRef NOT USED
-//-----------------------------------------------
- Uint16 TuserNodeId = cntrMasterReq->userNodeId;
- ttypeOfStart = cntrMasterReq->typeOfStart;
- Uint16 TnoRestartNodes = cntrMasterReq->noRestartNodes;
- int index = 0;
- unsigned i;
- for (i = 1; i < MAX_NDB_NODES; i++) {
- jam();
- if (NodeBitmask::get(cntrMasterReq->theNodes, i)) {
- jam();
- cstartNodes[index] = i;
- index++;
- }//if
- }//for
- if (TnoRestartNodes != index) {
- jam();
- systemErrorLab(signal);
- }//if
- switch (ttypeOfStart) {
- case NodeState::ST_INITIAL_START:
- case NodeState::ST_SYSTEM_RESTART:
- jam();
-//--------------------------------
-/* ELECTION OF MASTER AT */
-/* INITIAL OR SYSTEM RESTART */
-//--------------------------------
- masterreq010Lab(signal, TnoRestartNodes, TuserNodeId);
- break;
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- jam();
- masterreq030Lab(signal, TnoRestartNodes, TuserNodeId);
- break;
- default:
- jam();
- systemErrorLab(signal);
- break;
- }//switch
-}//Ndbcntr::execCNTR_MASTERREQ()
-
/*******************************/
/* CNTR_WAITREP */
/*******************************/
@@ -1736,243 +1320,102 @@ void Ndbcntr::execCNTR_WAITREP(Signal* signal)
}//switch
}//Ndbcntr::execCNTR_WAITREP()
-/*
-4.7.4 MASTERREQ_010 ( CASE: INITIALSTART OR SYSTEMRESTART ) */
-/*--------------------------------------------------------------------------*/
-// ELECTION OF MASTER AND ELECTION OF PARTICIPANTS IN START. SENDER OF
-// CNTR_MASTERREQ THINKS THAT THIS NODE
-// SHOULD BE THE MASTER. WE CAN'T MAKE A DECISION ABOUT WHO THE MASTER
-// SHOULD BE UNTIL TIMELIMIT HAS EXPIRED AND
-// THAT AT LEAST CNO_NEED_NODES ARE ZADD IN NODE_PTR_REC. IF THIS NODE IS
-// MASTER THEN MAKE SURE THAT ALL NODES IN
-// THE CLUSTER COMES TO AN AGREEMENT ABOUT A SUBSET OF NODES THAT SATISFIES
-// THE NUMBER CNO_NEED_NODES. THERE IS
-// A POSSIBILITY THAT THE RECEIVER OF CNTR_MASTERREQ DOESN'T HAS CHOOSEN
-// A MASTER, THEN THE RECEIVER CAN'T
-// EITHER CONFIRM OR REFUSE JUST STORE THE VOTES OF THE CLUSTERMEMBERS.
-// IF THIS NODE BECOME AWARE OF THAT ANOTHER NODE IS MASTER THEN CHECK IF
-// ANYONE HAS VOTED (SENT CNTR_MASTERREQ) */
-// AND THEN SEND THEM CNTR_MASTERREF BACK.
-/*--------------------------------------------------------------------------*/
-void Ndbcntr::masterreq010Lab(Signal* signal,
- Uint16 TnoRestartNodes,
- Uint16 TuserNodeId)
-{
- UintR guard0;
- UintR Ttemp1;
-
- nodePtr.i = TuserNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- if (cstartProgressFlag == ZTRUE) {
- jam();
-/*--------------------------------------*/
-/* RESTART ALREADY IN PROGRESS */
-/*--------------------------------------*/
- if (ctypeOfStart == NodeState::ST_INITIAL_START) {
- jam();
- systemErrorLab(signal);
- return;
- }//if
- signal->theData[0] = cownBlockref;
- signal->theData[1] = getOwnNodeId();
- signal->theData[2] = ZSTART_IN_PROGRESS_ERROR;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERREF, signal, 3, JBB);
- return;
- }//if
- cnoVoters = cnoVoters + 1;
- nodePtr.p->voter = ZTRUE;
- guard0 = TnoRestartNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- for (Ttemp1 = 0; Ttemp1 <= guard0; Ttemp1++) {
- jam();
- nodePtr.i = cstartNodes[Ttemp1];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- nodePtr.p->votes = nodePtr.p->votes + 1;
- }//for
- masterreq020Lab(signal);
- return;
-}//Ndbcntr::masterreq010Lab()
-
-/*----------------------------------------------------------------------*/
-/* WHEN WE JUST WANT TO CHECK OUR VOTES IT IS POSSIBLE TO JUMP TO THIS */
-/* LABEL. IF WE HAVEN'T RECEIVED ANY VOTES SINCE OUR LASTCHECK WE WILL */
-/* JUST PERFORM AN EXIT */
-/*----------------------------------------------------------------------*/
-void Ndbcntr::masterreq020Lab(Signal* signal)
-{
- if (cmasterCandidateId == ZNIL) {
- jam();
-/*--------------------------------------*/
-/* MASTER UNKNOWN */
-/*--------------------------------------*/
- return;
- } else if (cmasterCandidateId == getOwnNodeId()) {
- jam();
-/*--------------------------------------*/
-/* SATISFIED WHEN WE HAVE AS MANY VOTERS*/
-/* AS RESTARTNODES - 1, DIFFERENT NODES?*/
-/* <- CNO_START_NODES, ALL NODES AGREED */
-/* ON THESE CNO_START_NODES */
-/*--------------------------------------*/
- if ((cnoStartNodes - 1) == cnoVoters) {
- chooseRestartNodes(signal);
- if (cnoStartNodes >= cnoNeedNodes) {
- jam();
- cstartProgressFlag = ZTRUE;
-/*--------------------------------------*/
-/* DON'T SEND ANY MORE CNTR_MASTERREQ */
-/*--------------------------------------*/
- replyMasterconfToAll(signal);
-/*--------------------------------------*/
-/* SEND CONF TO ALL PASSED REQ */
-/* DON'T SEND ANYTHING TO REJECTED NODES*/
-/* BLOCK THEM UNTIL SYSTEM IS RUNNING */
-/* CONTINUE RESTART */
-/*--------------------------------------*/
- ph2FLab(signal);
- } else {
- jam();
- systemErrorLab(signal);
- }//if
- }//if
- } else {
- jam();
-/*----------------------------------------------------------------------*/
-/* WE RECEIVED A REQUEST TO A MASTER WHILE NOT BEING MASTER. THIS */
-/* MUST BE AN ERROR INDICATION. WE CRASH. */
-/*----------------------------------------------------------------------*/
- systemErrorLab(signal);
- }//if
- return; /* WAIT FOR MORE CNTR_MASTERREQ */
-}//Ndbcntr::masterreq020Lab()
-
-void Ndbcntr::masterreq030Lab(Signal* signal,
- Uint16 TnoRestartNodes,
- Uint16 TuserNodeId)
-{
- UintR TretCode;
- if (cmasterNodeId == getOwnNodeId()) {
- jam();
- TretCode = checkNodelist(signal, TnoRestartNodes);
- nodePtr.i = TuserNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- if (TretCode == 1) {
- jam();
-/*******************************************************<*/
-/* CSTART_NODES IS OVERWRITTEN IN RECEIVING BLOCK, */
-/* SO WE MUST SEND CNTR_MASTERCONF TO THE SAME */
-/* CSTART_NODES AS WE RECEIVED IN CNTR_MASTERREQ */
-/*******************************************************<*/
-
- CntrMasterConf * const cntrMasterConf =
- (CntrMasterConf *)&signal->theData[0];
- NodeBitmask::clear(cntrMasterConf->theNodes);
- for (int i = 0; i < TnoRestartNodes; i++){
- jam();
- UintR Tnode = cstartNodes[i];
- arrGuard(Tnode, MAX_NDB_NODES);
- NodeBitmask::set(cntrMasterConf->theNodes, Tnode);
- }//for
- cntrMasterConf->noStartNodes = TnoRestartNodes;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERCONF,
- signal, CntrMasterConf::SignalLength, JBB);
- } else {
- jam();
- signal->theData[0] = cownBlockref;
- signal->theData[1] = getOwnNodeId();
- signal->theData[2] = ZTOO_FEW_NODES;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERREF, signal, 3, JBB);
- }//if
- } else {
- jam();
- nodePtr.i = TuserNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- signal->theData[0] = cownBlockref;
- signal->theData[1] = getOwnNodeId();
- signal->theData[2] = ZNOT_MASTER;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERREF, signal, 3, JBB);
- }//if
- return;
-}//Ndbcntr::masterreq030Lab()
-
/*******************************/
/* NODE_FAILREP */
/*******************************/
void Ndbcntr::execNODE_FAILREP(Signal* signal)
{
- UintR TfailureNr;
- UintR TnoOfNodes;
- UintR TreadNodes[MAX_NDB_NODES];
-
jamEntry();
+ const NodeFailRep * nodeFail = (NodeFailRep *)&signal->theData[0];
+ NdbNodeBitmask allFailed;
+ allFailed.assign(NdbNodeBitmask::Size, nodeFail->theNodes);
+
+ NdbNodeBitmask failedStarted = c_startedNodes;
+ NdbNodeBitmask failedStarting = c_start.m_starting;
+ NdbNodeBitmask failedWaiting = c_start.m_waiting;
+
+ failedStarted.bitAND(allFailed);
+ failedStarting.bitAND(allFailed);
+ failedWaiting.bitAND(allFailed);
+
+ const bool tMasterFailed = allFailed.get(cmasterNodeId);
+ const bool tStarted = !failedStarted.isclear();
+ const bool tStarting = !failedStarting.isclear();
+ const bool tWaiting = !failedWaiting.isclear();
+
+ if(tMasterFailed){
+ jam();
+ /**
+ * If master has failed choose qmgr president as master
+ */
+ cmasterNodeId = nodeFail->masterNodeId;
+ }
+
+ /**
+ * Clear node bitmasks from failed nodes
+ */
+ c_start.m_starting.bitANDC(allFailed);
+ c_start.m_waiting.bitANDC(allFailed);
+ c_start.m_withLog.bitANDC(allFailed);
+ c_start.m_withoutLog.bitANDC(allFailed);
+ c_clusterNodes.bitANDC(allFailed);
+ c_startedNodes.bitANDC(allFailed);
+
const NodeState & st = getNodeState();
if(st.startLevel == st.SL_STARTING){
- if(!st.getNodeRestartInProgress()){
+ jam();
+
+ const Uint32 phase = st.starting.startPhase;
+
+ const bool tStartConf = (phase > 2) || (phase == 2 && cndbBlocksCount > 0);
+
+ if(tMasterFailed){
progError(__LINE__,
ERR_SR_OTHERNODEFAILED,
- "Unhandled node failure during system restart");
+ "Unhandled node failure during restart");
+ }
+
+ if(tStartConf && tStarting){
+ // One of other starting nodes has crashed...
+ progError(__LINE__,
+ ERR_SR_OTHERNODEFAILED,
+ "Unhandled node failure of starting node during restart");
}
- }
-
- {
- NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
- TfailureNr = nodeFail->failNo;
- TnoOfNodes = nodeFail->noOfNodes;
- unsigned index = 0;
- unsigned i;
- for (i = 0; i < MAX_NDB_NODES; i++) {
- jam();
- if (NodeBitmask::get(nodeFail->theNodes, i)) {
- jam();
- TreadNodes[index] = i;
- index++;
- ndbrequire(getOwnNodeId() != i);
- }//if
+ if(tStartConf && tStarted){
+ // One of other started nodes has crashed...
+ progError(__LINE__,
+ ERR_SR_OTHERNODEFAILED,
+ "Unhandled node failure of started node during restart");
+ }
+
+ Uint32 nodeId = 0;
+ while(!allFailed.isclear()){
+ nodeId = allFailed.find(nodeId + 1);
+ allFailed.clear(nodeId);
+ signal->theData[0] = nodeId;
+ sendSignal(QMGR_REF, GSN_NDB_FAILCONF, signal, 1, JBB);
}//for
- ndbrequire(TnoOfNodes == index);
+
+ return;
}
- for (Uint32 i = 0; i < TnoOfNodes; i++) {
- jam();
- nodePtr.i = TreadNodes[i];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- signal->theData[0] = EventReport::NODE_FAILREP;
- signal->theData[1] = nodePtr.i;
- signal->theData[2] = nodePtr.p->state;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
- if (nodePtr.p->state != ZREMOVE) {
- jam();
- deleteNode(signal);
- }//if
- }//for
+ ndbrequire(!allFailed.get(getOwnNodeId()));
-/*******************************/
-/*< NODE_FAILREP <*/
-/*******************************/
- NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
-
- nodeFail->failNo = TfailureNr;
- nodeFail->masterNodeId = cmasterNodeId;
+ NodeFailRep * rep = (NodeFailRep *)&signal->theData[0];
+ rep->masterNodeId = cmasterNodeId;
- nodeFail->noOfNodes = TnoOfNodes;
- NodeBitmask::clear(nodeFail->theNodes);
- for (unsigned i = 0; i < TnoOfNodes; i++) {
- jam();
- NodeBitmask::set(nodeFail->theNodes, TreadNodes[i]);
- }//for
-
- sendSignal(ctcBlockref, GSN_NODE_FAILREP, signal,
+ sendSignal(DBTC_REF, GSN_NODE_FAILREP, signal,
NodeFailRep::SignalLength, JBB);
- sendSignal(clqhBlockref, GSN_NODE_FAILREP, signal,
+ sendSignal(DBLQH_REF, GSN_NODE_FAILREP, signal,
NodeFailRep::SignalLength, JBB);
- sendSignal(cdihBlockref, GSN_NODE_FAILREP, signal,
+ sendSignal(DBDIH_REF, GSN_NODE_FAILREP, signal,
NodeFailRep::SignalLength, JBB);
- sendSignal(cdictBlockref, GSN_NODE_FAILREP, signal,
+ sendSignal(DBDICT_REF, GSN_NODE_FAILREP, signal,
NodeFailRep::SignalLength, JBB);
sendSignal(BACKUP_REF, GSN_NODE_FAILREP, signal,
@@ -1983,80 +1426,25 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal)
sendSignal(GREP_REF, GSN_NODE_FAILREP, signal,
NodeFailRep::SignalLength, JBB);
- return;
-}//Ndbcntr::execNODE_FAILREP()
-/*******************************/
-/* NODE_STATESCONF */
-/*******************************/
-void Ndbcntr::execNODE_STATESCONF(Signal* signal)
-{
- jamEntry();
- cmasterCandidateId = signal->theData[0];
- cnoNeedNodes = signal->theData[1];
-/*----------------------------------------------------------------------*/
-// Now that we have knowledge of how many nodes are needed we will call
-// ph2CLab to ensure that node restart continues if we already received
-// all APPL_CHANGEREP signals.
-/*----------------------------------------------------------------------*/
- ph2CLab(signal);
- return;
-}//Ndbcntr::execNODE_STATESCONF()
-
-/*******************************/
-/* NODE_STATESREF */
-/*******************************/
-void Ndbcntr::execNODE_STATESREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal);
- return;
-}//Ndbcntr::execNODE_STATESREF()
+ Uint32 nodeId = 0;
+ while(!allFailed.isclear()){
+ nodeId = allFailed.find(nodeId + 1);
+ allFailed.clear(nodeId);
+ signal->theData[0] = EventReport::NODE_FAILREP;
+ signal->theData[1] = nodeId;
+ signal->theData[2] = 0;
+ sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
+ }//for
-/*******************************/
-/* NODE_STATESREQ */
-/*******************************/
-void Ndbcntr::execNODE_STATESREQ(Signal* signal)
-{
- UintR TnoNeedNodes = 0;
- NodeRecPtr TNodePtr;
- jamEntry();
- BlockReference TuserBlockref = signal->theData[0];
-/*----------------------------------------------------------------------*/
-// IF WE ARE RUNNING, WE WILL ANSWER THIS SIGNAL WITH THE AMOUNT OF NODES
-// THAT ARE IN THE RUN STATE OR START STATE.
-/*----------------------------------------------------------------------*/
- TNodePtr.i = getOwnNodeId();
- ptrCheckGuard(TNodePtr, MAX_NDB_NODES, nodeRec);
- if (TNodePtr.p->state == ZRUN) {
- jam();
- for (TNodePtr.i = 1; TNodePtr.i < MAX_NDB_NODES; TNodePtr.i++) {
- jam();
- ptrAss(TNodePtr, nodeRec);
- if ((TNodePtr.p->state == ZRUN) ||
- (TNodePtr.p->state == ZSTART)) {
- jam();
- TnoNeedNodes++;
- }//if
- }//for
- signal->theData[0] = cmasterNodeId;
- signal->theData[1] = TnoNeedNodes;
- sendSignal(TuserBlockref, GSN_NODE_STATESCONF, signal, 2, JBB);
- } else {
- jam();
- signal->theData[0] = ZERROR_NOT_RUNNING;
- sendSignal(TuserBlockref, GSN_NODE_STATESREF, signal, 1, JBB);
- }//if
return;
-}//Ndbcntr::execNODE_STATESREQ()
+}//Ndbcntr::execNODE_FAILREP()
/*******************************/
/* READ_NODESREQ */
/*******************************/
void Ndbcntr::execREAD_NODESREQ(Signal* signal)
{
- UintR TnoNodes = 0;
- NodeRecPtr TNodePtr;
jamEntry();
/*----------------------------------------------------------------------*/
@@ -2067,59 +1455,36 @@ void Ndbcntr::execREAD_NODESREQ(Signal* signal)
BlockReference TuserBlockref = signal->theData[0];
ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
- if (cstartPhase > ZSTART_PHASE_2) {
- ndbrequire(cstartProgressFlag == ZTRUE);
-
- NodeBitmask::clear(readNodes->allNodes);
- NodeBitmask::clear(readNodes->inactiveNodes);
-
- /**
- * Add started nodes
- */
- for (int i = 0; i < cnoStartNodes; i++){
- jam();
- TNodePtr.i = cstartNodes[i];
- ptrCheckGuard(TNodePtr, MAX_NDB_NODES, nodeRec);
-
- NodeBitmask::set(readNodes->allNodes, TNodePtr.i);
- readNodes->setVersionId(TNodePtr.i, TNodePtr.p->ndbVersion,
- readNodes->theVersionIds);
- TnoNodes++;
- }//for
-
- /**
- * Sometimes add myself
- */
- if ((ctypeOfStart == NodeState::ST_NODE_RESTART) ||
- (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
-
- NodeBitmask::set(readNodes->allNodes, getOwnNodeId());
- readNodes->setVersionId(getOwnNodeId(), NDB_VERSION,
- readNodes->theVersionIds);
- TnoNodes++;
- }//if
- /**
- * Check all nodes which are defined but not already added
- */
- for (TNodePtr.i = 1; TNodePtr.i < MAX_NDB_NODES; TNodePtr.i++) {
- jam();
- ptrAss(TNodePtr, nodeRec);
- if ((TNodePtr.p->nodeDefined == ZTRUE) &&
- (NodeBitmask::get(readNodes->allNodes, TNodePtr.i) == false)){
- jam();
+ /**
+ * Prepare inactiveNodes bitmask.
+ * The concept as such is by the way pretty useless.
+ * It makes parallell starts more or less impossible...
+ */
+ NdbNodeBitmask tmp1;
+ tmp1.bitOR(c_startedNodes);
+ if(!getNodeState().getNodeRestartInProgress()){
+ tmp1.bitOR(c_start.m_starting);
+ } else {
+ tmp1.set(getOwnNodeId());
+ }
- NodeBitmask::set(readNodes->allNodes, TNodePtr.i);
- NodeBitmask::set(readNodes->inactiveNodes, TNodePtr.i);
- readNodes->setVersionId(TNodePtr.i, NDB_VERSION,
- readNodes->theVersionIds);
-
- TnoNodes++;
- }//if
- }//for
-
- readNodes->noOfNodes = TnoNodes;
- readNodes->masterNodeId = cmasterNodeId;
+ NdbNodeBitmask tmp2;
+ tmp2.bitOR(c_allDefinedNodes);
+ tmp2.bitANDC(tmp1);
+ /**
+ * Fill in return signal
+ */
+ tmp2.copyto(NdbNodeBitmask::Size, readNodes->inactiveNodes);
+ c_allDefinedNodes.copyto(NdbNodeBitmask::Size, readNodes->allNodes);
+ c_clusterNodes.copyto(NdbNodeBitmask::Size, readNodes->clusterNodes);
+ c_startedNodes.copyto(NdbNodeBitmask::Size, readNodes->startedNodes);
+ c_start.m_starting.copyto(NdbNodeBitmask::Size, readNodes->startingNodes);
+
+ readNodes->noOfNodes = c_allDefinedNodes.count();
+ readNodes->masterNodeId = cmasterNodeId;
+ readNodes->ndynamicId = cdynamicNodeId;
+ if (cstartPhase > ZSTART_PHASE_2) {
+ jam();
sendSignal(TuserBlockref, GSN_READ_NODESCONF, signal,
ReadNodesConf::SignalLength, JBB);
@@ -2237,8 +1602,8 @@ void Ndbcntr::startInsertTransactions(Signal* signal)
ckey = 1;
ctransidPhase = ZTRUE;
- signal->theData[1] = cownBlockref;
- sendSignal(ctcBlockref, GSN_TCSEIZEREQ, signal, 2, JBB);
+ signal->theData[1] = reference();
+ sendSignal(DBTC_REF, GSN_TCSEIZEREQ, signal, 2, JBB);
return;
}//Ndbcntr::startInsertTransactions()
@@ -2312,7 +1677,7 @@ void Ndbcntr::crSystab7Lab(Signal* signal)
AttributeHeader::init(&tAIDataPtr[2], 1, 2);
tAIDataPtr[3] = (tkey << 16);
tAIDataPtr[4] = 1;
- sendSignal(ctcBlockref, GSN_TCKEYREQ, signal,
+ sendSignal(DBTC_REF, GSN_TCKEYREQ, signal,
TcKeyReq::StaticLength + 6, JBB);
}//for
ckey = ckey + RowsPerCommit;
@@ -2335,7 +1700,7 @@ void Ndbcntr::execTCKEYCONF(Signal* signal)
Uint32 transId2 = keyConf->transId2;
signal->theData[0] = transId1;
signal->theData[1] = transId2;
- sendSignal(ctcBlockref, GSN_TC_COMMIT_ACK, signal, 2, JBB);
+ sendSignal(DBTC_REF, GSN_TC_COMMIT_ACK, signal, 2, JBB);
}//if
cresponses = cresponses + TcKeyConf::getNoOfOperations(confInfo);
@@ -2363,8 +1728,8 @@ void Ndbcntr::crSystab8Lab(Signal* signal)
return;
}//if
signal->theData[0] = ctcConnectionP;
- signal->theData[1] = cownBlockref;
- sendSignal(ctcBlockref, GSN_TCRELEASEREQ, signal, 2, JBB);
+ signal->theData[1] = reference();
+ sendSignal(DBTC_REF, GSN_TCRELEASEREQ, signal, 2, JBB);
return;
}//Ndbcntr::crSystab8Lab()
@@ -2380,8 +1745,8 @@ void Ndbcntr::execTCRELEASECONF(Signal* signal)
void Ndbcntr::crSystab9Lab(Signal* signal)
{
- signal->theData[1] = cownBlockref;
- sendSignalWithDelay(cdihBlockref, GSN_GETGCIREQ, signal, 100, 2);
+ signal->theData[1] = reference();
+ sendSignalWithDelay(DBDIH_REF, GSN_GETGCIREQ, signal, 100, 2);
return;
}//Ndbcntr::crSystab9Lab()
@@ -2435,309 +1800,28 @@ void Ndbcntr::execTCSEIZEREF(Signal* signal)
return;
}//Ndbcntr::execTCSEIZEREF()
-/*
-4.10 SUBROUTINES */
-/*##########################################################################*/
-/*
-4.10.1 CHECK_NODELIST */
-/*---------------------------------------------------------------------------*/
-/*CHECK THAT ALL THE NEW NODE HAS DETECTED ALL RUNNING NODES */
-/*INPUT: CSTART_NODES */
-/* TNO_RESTART_NODES */
-/* TUSER_NODE_ID */
-/*RET: CNODE_RESTART */
-/*---------------------------------------------------------------------------*/
-UintR Ndbcntr::checkNodelist(Signal* signal, Uint16 TnoRestartNodes)
-{
- UintR guard1;
- UintR Ttemp1;
-
- if (cnoRunNodes == TnoRestartNodes) {
- jam();
- guard1 = TnoRestartNodes - 1;
- arrGuard(guard1, MAX_NDB_NODES);
- for (Ttemp1 = 0; Ttemp1 <= guard1; Ttemp1++) {
- jam();
- nodePtr.i = cstartNodes[Ttemp1];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- if (nodePtr.p->state != ZRUN) {
- jam();
- return 0;
- }//if
- }//for
- return 1;
- }//if
- return 0;
-}//Ndbcntr::checkNodelist()
-
-/*---------------------------------------------------------------------------*/
-// SELECT NODES THAT ARE IN THE STATE TO PERFORM A INITIALSTART OR
-// SYSTEMRESTART.
-// THIS SUBROUTINE CAN ONLY BE INVOKED BY THE MASTER NODE.
-// TO BE CHOOSEN A NODE NEED AS MANY VOTES AS THERE ARE VOTERS, AND OF
-// COURSE THE NODE HAS TO BE KNOWN BY THE
-// MASTER
-// INPUT: NODE_REC
-// CNO_NEED_NODES
-// RETURN:CNO_START_NODES
-// CSTART_NODES
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::chooseRestartNodes(Signal* signal)
-{
- cnoStartNodes = 0;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->votes == cnoVoters) {
- jam();
- if (nodePtr.p->state == ZADD) {
- jam();
- arrGuard(cnoStartNodes, MAX_NDB_NODES);
- cstartNodes[cnoStartNodes] = nodePtr.i;
- cnoStartNodes++;
- }//if
- } else {
- jam();
- if (nodePtr.p->votes > 0) {
- jam();
- systemErrorLab(signal);
- return;
- }//if
- }//if
- }//for
-}//Ndbcntr::chooseRestartNodes()
-
-/*
-4.10.6 DELETE_NODE */
-/*---------------------------------------------------------------------------*/
-// INPUT: NODE_PTR
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::deleteNode(Signal* signal)
-{
- UintR tminDynamicId;
-
- if (nodePtr.p->state == ZRUN) {
- jam();
- cnoRunNodes = cnoRunNodes - 1;
- }//if
- nodePtr.p->state = ZREMOVE;
- nodePtr.p->votes = 0;
- nodePtr.p->voter = ZFALSE;
- cnoRegNodes--;
- if (nodePtr.i == cmasterNodeId) {
- jam();
- cmasterNodeId = ZNIL;
-/*---------------------------------------------------------------------------*/
-// IF MASTER HAVE CRASHED WE NEED TO SELECT A NEW MASTER.
-/*---------------------------------------------------------------------------*/
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->state == ZRUN) {
- if (cmasterNodeId == ZNIL) {
- jam();
- cmasterNodeId = nodePtr.i;
- tminDynamicId = nodePtr.p->dynamicId;
- } else {
- jam();
- if (nodePtr.p->dynamicId < tminDynamicId) {
- jam();
- cmasterNodeId = nodePtr.i;
- tminDynamicId = nodePtr.p->dynamicId;
- }//if
- }//if
- }//if
- }//for
- }//if
-}//Ndbcntr::deleteNode()
-
-/*---------------------------------------------------------------------------*/
-// A NEW NODE TRIES TO DETECT A NODE RESTART. NodeState::ST_NODE_RESTART IS A POSSIBLE
-// STATE ONLY WHEN THE SYSTEM IS RUNNING.
-// IF THE SYSTEM IS RUNNING THEN
-// CTYPE_OF_START = NodeState::ST_SYSTEM_RESTART UNTIL THE FIRST NODE HAS REGISTERED.
-// IF SYSTEM IS */
-// RUNNING THE FIRST NODE TO REGISTER WILL BE ZRUN AND CTYPE_OF_START
-// WILL BE CHANGED */
-// TO NodeState::ST_NODE_RESTART AT PH_2C. WHEN A NodeState::ST_NODE_RESTART IS DETECTED THE NEW NODE
-// HAS TO SEND */
-// A CNTR_MASTERREQ TO THE MASTER
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::detectNoderestart(Signal* signal)
-{
- NodeRecPtr ownNodePtr;
- ownNodePtr.i = getOwnNodeId();
- ptrCheckGuard(ownNodePtr, MAX_NDB_NODES, nodeRec);
- if (ownNodePtr.p->state != ZADD) {
- if (ownNodePtr.p->state != ZREMOVE) {
- jam();
- return;
- }//if
- }//if
- ctypeOfStart = NodeState::ST_NODE_RESTART;
-/*----------------------------------------------*/
-/* THIS NODE WILL PERFORM A NODE RESTART */
-/* REQUEST OF ALL NODES STATES IN SYSTEM */
-// The purpose of this signal is to ensure that
-// the starting node knows when it has received
-// all APPL_CHANGEREP signals and thus can continue
-// to the next step of the node restart. Thus we
-// need to know the amount of nodes that are in the
-// RUN state and in the START state (more than one
-// node can be copying data simultaneously in the
-// cluster.
-/*----------------------------------------------*/
- signal->theData[0] = cownBlockref;
- sendSignal(nodePtr.p->cntrBlockref, GSN_NODE_STATESREQ, signal, 1, JBB);
- cnoNeedNodes = ZNIL;
-/*---------------------------------*/
-/* PREVENT TO SEND NODE_STATESREQ */
-/*---------------------------------------------------------------------------*/
-/* WE NEED TO WATCH THE NODE RESTART WITH A TIME OUT TO NOT WAIT FOR EVER. */
-/*---------------------------------------------------------------------------*/
- cwaitContinuebFlag = ZTRUE;
- signal->theData[0] = ZCONTINUEB_1;
- sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 3 * 1000, 1);
-}//Ndbcntr::detectNoderestart()
-
-/*---------------------------------------------------------------------------*/
-// SCAN NODE_REC FOR APPROPRIATE NODES FOR A START.
-// SYSTEMRESTART AND INITALSTART DEMANDS NODES OF STATE ZADD.
-// NODERESTART DEMANDS NODE OF THE STATE ZRUN.
-// INPUT: CTYPE_OF_START, NODE_REC
-// RETURN: CSTART_NODES(), CNO_START_NODES, CMASTER_CANDIDATE_ID
-// (SYSTEMRESTART AND INITALSTART)
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::getStartNodes(Signal* signal)
-{
- UintR Ttemp1;
- if ((ctypeOfStart == NodeState::ST_NODE_RESTART) ||
- (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
- Ttemp1 = ZRUN;
- } else {
- jam();
-/*---------------------------------*/
-/* SYSTEM RESTART AND INITIAL START*/
-/*---------------------------------*/
- Ttemp1 = ZADD;
- }//if
- cnoStartNodes = 0;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->state == Ttemp1) {
- jam();
- cstartNodes[cnoStartNodes] = nodePtr.i;/*OVERWRITTEN AT CNTR_MASTERCONF*/
- cnoStartNodes++;
- }//if
- }//for
-}//Ndbcntr::getStartNodes()
/*---------------------------------------------------------------------------*/
/*INITIALIZE VARIABLES AND RECORDS */
/*---------------------------------------------------------------------------*/
void Ndbcntr::initData(Signal* signal)
{
- cmasterNodeId = ZNIL;
- cmasterCandidateId = ZNIL;
- cmasterVoters = 0;
- cstartProgressFlag = ZFALSE;
- capplStartconfFlag = ZFALSE;
- cnoVoters = 0;
+ c_start.reset();
+ cmasterNodeId = 0;
cnoStartNodes = 0;
- for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- ptrAss(nodePtr, nodeRec);
- nodePtr.p->cntrBlockref = calcNdbCntrBlockRef(nodePtr.i);
- nodePtr.p->state = ZREMOVE;
- nodePtr.p->dynamicId = 0;
- nodePtr.p->votes = 0; /* USED BY MASTER */
- nodePtr.p->voter = ZFALSE; /* USED BY MASTER */
- nodePtr.p->masterReq = ZFALSE; /* USED BY MASTER */
- }//for
+ cnoWaitrep = 0;
}//Ndbcntr::initData()
-/*---------------------------------------------------------------------------*/
-// THE MASTER NODE HAS CHOOSEN THE NODES WHO WERE QUALIFIED TO
-// PARTICIPATE IN A INITIALSTART OR SYSTEMRESTART.
-// THIS SUBROTINE SENDS A CNTR_MASTERCONF TO THESE NODES
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::replyMasterconfToAll(Signal* signal)
-{
- if (cnoStartNodes > 1) {
- /**
- * Construct a MasterConf signal
- */
-
- CntrMasterConf * const cntrMasterConf =
- (CntrMasterConf *)&signal->theData[0];
- NodeBitmask::clear(cntrMasterConf->theNodes);
-
- cntrMasterConf->noStartNodes = cnoStartNodes;
-
- for(int i = 0; i<cnoStartNodes; i++)
- NodeBitmask::set(cntrMasterConf->theNodes, cstartNodes[i]);
-
- /**
- * Then distribute it to everyone but myself
- */
- for(int i = 0; i<cnoStartNodes; i++){
- const NodeId nodeId = cstartNodes[i];
- if(nodeId != getOwnNodeId()){
- sendSignal(numberToRef(number(), nodeId),
- GSN_CNTR_MASTERCONF,
- signal, CntrMasterConf::SignalLength, JBB);
- }
- }
- }
-}//Ndbcntr::replyMasterconfToAll()
/*---------------------------------------------------------------------------*/
/*RESET VARIABLES USED DURING THE START */
/*---------------------------------------------------------------------------*/
void Ndbcntr::resetStartVariables(Signal* signal)
{
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- ptrAss(nodePtr, nodeRec);
- nodePtr.p->votes = 0;
- nodePtr.p->voter = ZFALSE;
- nodePtr.p->masterReq = ZFALSE;
- }//for
- cnoVoters = 0;
cnoStartNodes = 0;
cnoWaitrep6 = cnoWaitrep7 = 0;
}//Ndbcntr::resetStartVariables()
-/*---------------------------------------------------------------------------*/
-// SENDER OF THIS SIGNAL HAS CHOOSEN A MASTER NODE AND SENDS A REQUEST
-// TO THE MASTER_CANDIDATE AS AN VOTE FOR
-// THE MASTER. THE SIGNAL ALSO INCLUDES VOTES FOR NODES WHICH SENDER
-// THINKS SHOULD PARTICIPATE IN THE START.
-// INPUT: CNO_START_NODES
-// CSTART_NODES
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::sendCntrMasterreq(Signal* signal)
-{
- nodePtr.i = cmasterCandidateId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
-/*--------------------------------------------------------------*/
-/* O:INITIALSTART, 1:SYSTEMRESTART (ELECTION OF MASTER) */
-/* 2:NODE RESTART (SENDER NODE NOT INCLUDED IN CSTART_NODES) */
-/*--------------------------------------------------------------*/
- CntrMasterReq * const cntrMasterReq = (CntrMasterReq*)&signal->theData[0];
- NodeBitmask::clear(cntrMasterReq->theNodes);
- for (int i = 0; i < cnoStartNodes; i++){
- jam();
- UintR Tnode = cstartNodes[i];
- arrGuard(Tnode, MAX_NDB_NODES);
- NodeBitmask::set(cntrMasterReq->theNodes, Tnode);
- }//for
- cntrMasterReq->userBlockRef = cownBlockref;
- cntrMasterReq->userNodeId = getOwnNodeId();
- cntrMasterReq->typeOfStart = ctypeOfStart;
- cntrMasterReq->noRestartNodes = cnoStartNodes;
- sendSignal(nodePtr.p->cntrBlockref, GSN_CNTR_MASTERREQ,
- signal, CntrMasterReq::SignalLength, JBB);
-}//Ndbcntr::sendCntrMasterreq()
/*---------------------------------------------------------------------------*/
// SEND THE SIGNAL
@@ -2745,25 +1829,24 @@ void Ndbcntr::sendCntrMasterreq(Signal* signal)
/*---------------------------------------------------------------------------*/
void Ndbcntr::sendNdbSttor(Signal* signal)
{
- CfgBlockRecPtr cfgBlockPtr;
NdbBlocksRecPtr ndbBlocksPtr;
ndbBlocksPtr.i = cndbBlocksCount;
ptrCheckGuard(ndbBlocksPtr, ZSIZE_NDB_BLOCKS_REC, ndbBlocksRec);
- cfgBlockPtr.i = cinternalStartphase;
- ptrCheckGuard(cfgBlockPtr, ZSIZE_CFG_BLOCK_REC, cfgBlockRec);
+
NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend();
- req->senderRef = cownBlockref;
+ req->senderRef = reference();
req->nodeId = getOwnNodeId();
req->internalStartPhase = cinternalStartphase;
req->typeOfStart = ctypeOfStart;
req->masterNodeId = cmasterNodeId;
for (int i = 0; i < 16; i++) {
- req->config[i] = cfgBlockPtr.p->cfgData[i];
+ // Garbage
+ req->config[i] = 0x88776655;
+ //cfgBlockPtr.p->cfgData[i];
}
- //#define TRACE_STTOR
//#define MAX_STARTPHASE 2
#ifdef TRACE_STTOR
ndbout_c("sending NDB_STTOR(%d) to %s",
@@ -2779,9 +1862,6 @@ void Ndbcntr::sendNdbSttor(Signal* signal)
/*---------------------------------------------------------------------------*/
void Ndbcntr::sendSttorry(Signal* signal)
{
- signal->theData[0] = csignalKey;
- signal->theData[1] = 3;
- signal->theData[2] = 2;
signal->theData[3] = ZSTART_PHASE_1;
signal->theData[4] = ZSTART_PHASE_2;
signal->theData[5] = ZSTART_PHASE_3;
@@ -2801,9 +1881,8 @@ Ndbcntr::execDUMP_STATE_ORD(Signal* signal)
DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
if(signal->theData[0] == 13){
infoEvent("Cntr: cstartPhase = %d, cinternalStartphase = %d, block = %d",
- cstartPhase, cinternalStartphase, cndbBlocksCount);
- infoEvent("Cntr: cmasterNodeId = %d, cmasterCandidateId = %d",
- cmasterNodeId, cmasterCandidateId);
+ cstartPhase, cinternalStartphase, cndbBlocksCount);
+ infoEvent("Cntr: cmasterNodeId = %d", cmasterNodeId);
}
if (dumpState->args[0] == DumpStateOrd::NdbcntrTestStopOnError){
@@ -2823,6 +1902,7 @@ Ndbcntr::execDUMP_STATE_ORD(Signal* signal)
}//Ndbcntr::execDUMP_STATE_ORD()
void Ndbcntr::execSET_VAR_REQ(Signal* signal) {
+#if 0
SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0];
ConfigParamId var = setVarReq->variable();
@@ -2835,6 +1915,7 @@ void Ndbcntr::execSET_VAR_REQ(Signal* signal) {
default:
sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB);
}// switch
+#endif
}//Ndbcntr::execSET_VAR_REQ()
void Ndbcntr::updateNodeState(Signal* signal, const NodeState& newState) const{
@@ -2947,7 +2028,7 @@ Ndbcntr::execSTOP_REQ(Signal* signal){
}
updateNodeState(signal, newState);
signal->theData[0] = ZSHUTDOWN;
- sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 1);
+ sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1);
}
void
@@ -2991,14 +2072,9 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){
/**
* Check if I can survive me stopping
*/
- NodeBitmask ndbMask; ndbMask.clear();
- NodeRecPtr aPtr;
- for(aPtr.i = 1; aPtr.i < MAX_NDB_NODES; aPtr.i++){
- ptrAss(aPtr, cntr.nodeRec);
- if(aPtr.i != cntr.getOwnNodeId() && aPtr.p->state == ZRUN){
- ndbMask.set(aPtr.i);
- }
- }
+ NodeBitmask ndbMask;
+ ndbMask.assign(cntr.c_startedNodes);
+ ndbMask.clear(cntr.getOwnNodeId());
CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
sd->blockRef = cntr.reference();
@@ -3194,7 +2270,7 @@ void Ndbcntr::execSTOP_ME_CONF(Signal* signal){
c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond();
signal->theData[0] = ZSHUTDOWN;
- sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 1);
+ sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1);
}
void
@@ -3255,6 +2331,11 @@ void Ndbcntr::execSTTORRY(Signal* signal){
c_missra.execSTTORRY(signal);
}
+void Ndbcntr::execREAD_CONFIG_CONF(Signal* signal){
+ jamEntry();
+ c_missra.execREAD_CONFIG_CONF(signal);
+}
+
void Ndbcntr::execSTART_ORD(Signal* signal){
jamEntry();
ndbrequire(NO_OF_BLOCKS == ALL_BLOCKS_SZ);
@@ -3299,7 +2380,38 @@ void Ndbcntr::Missra::execSTART_ORD(Signal* signal){
signal->theData[0] = EventReport::NDBStartStarted;
signal->theData[1] = NDB_VERSION;
cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
+
+ currentBlockIndex = 0;
+ sendNextREAD_CONFIG_REQ(signal);
+}
+
+void Ndbcntr::Missra::sendNextREAD_CONFIG_REQ(Signal* signal){
+
+ if(currentBlockIndex < ALL_BLOCKS_SZ){
+ jam();
+
+ ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtrSend();
+ req->senderData = 0;
+ req->senderRef = cntr.reference();
+ req->noOfParameters = 0;
+
+ const BlockReference ref = ALL_BLOCKS[currentBlockIndex].Ref;
+
+#if 0
+ ndbout_c("sending READ_CONFIG_REQ to %s(ref=%x index=%d)",
+ getBlockName( refToBlock(ref)),
+ ref,
+ currentBlockIndex);
+#endif
+
+ cntr.sendSignal(ref, GSN_READ_CONFIG_REQ, signal,
+ ReadConfigReq::SignalLength, JBB);
+ return;
+ }
+ /**
+ * Finished...
+ */
currentStartPhase = 0;
for(Uint32 i = 0; i<NO_OF_BLOCKS; i++){
if(ALL_BLOCKS[i].NextSP < currentStartPhase)
@@ -3307,10 +2419,19 @@ void Ndbcntr::Missra::execSTART_ORD(Signal* signal){
}
currentBlockIndex = 0;
-
sendNextSTTOR(signal);
}
+void Ndbcntr::Missra::execREAD_CONFIG_CONF(Signal* signal){
+ const ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtr();
+
+ const Uint32 ref = conf->senderRef;
+ ndbrequire(refToBlock(ALL_BLOCKS[currentBlockIndex].Ref) == refToBlock(ref));
+
+ currentBlockIndex++;
+ sendNextREAD_CONFIG_REQ(signal);
+}
+
void Ndbcntr::Missra::execSTTORRY(Signal* signal){
const BlockReference ref = signal->senderBlockRef();
ndbrequire(refToBlock(ref) == refToBlock(ALL_BLOCKS[currentBlockIndex].Ref));
@@ -3365,8 +2486,8 @@ void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){
currentBlockIndex);
#endif
- cntr.sendSignal(ref, GSN_STTOR,
- signal, 8, JBB);
+ cntr.sendSignal(ref, GSN_STTOR, signal, 8, JBB);
+
return;
}
}
@@ -3391,4 +2512,145 @@ void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){
NodeState newState(NodeState::SL_STARTED);
cntr.updateNodeState(signal, newState);
+
+ /**
+ * Backward
+ */
+ UpgradeStartup::sendCmAppChg(cntr, signal, 3); //RUN
+
+ NdbNodeBitmask nodes = cntr.c_clusterNodes;
+ Uint32 node = 0;
+ while((node = nodes.find(node+1)) != NdbNodeBitmask::NotFound){
+ if(cntr.getNodeInfo(node).m_version < MAKE_VERSION(3,5,0)){
+ nodes.clear(node);
+ }
+ }
+
+ NodeReceiverGroup rg(NDBCNTR, nodes);
+ signal->theData[0] = cntr.getOwnNodeId();
+ cntr.sendSignal(rg, GSN_CNTR_START_REP, signal, 1, JBB);
+}
+
+/**
+ * Backward compatible code
+ */
+void
+UpgradeStartup::sendCmAppChg(Ndbcntr& cntr, Signal* signal, Uint32 startLevel){
+
+ if(cntr.getNodeInfo(cntr.cmasterNodeId).m_version >= MAKE_VERSION(3,5,0)){
+ jam();
+ return;
+ }
+
+ /**
+ * Old NDB running
+ */
+
+ signal->theData[0] = startLevel;
+ signal->theData[1] = cntr.getOwnNodeId();
+ signal->theData[2] = 3 | ('N' << 8);
+ signal->theData[3] = 'D' | ('B' << 8);
+ signal->theData[4] = 0;
+ signal->theData[5] = 0;
+ signal->theData[6] = 0;
+ signal->theData[7] = 0;
+ signal->theData[8] = 0;
+ signal->theData[9] = 0;
+ signal->theData[10] = 0;
+ signal->theData[11] = 0;
+
+ NdbNodeBitmask nodes = cntr.c_clusterNodes;
+ nodes.clear(cntr.getOwnNodeId());
+ Uint32 node = 0;
+ while((node = nodes.find(node+1)) != NdbNodeBitmask::NotFound){
+ if(cntr.getNodeInfo(node).m_version < MAKE_VERSION(3,5,0)){
+ cntr.sendSignal(cntr.calcQmgrBlockRef(node),
+ GSN_CM_APPCHG, signal, 12, JBB);
+ } else {
+ cntr.c_startedNodes.set(node); // Fake started
+ }
+ }
+}
+
+void
+UpgradeStartup::execCM_APPCHG(SimulatedBlock & block, Signal* signal){
+ Uint32 state = signal->theData[0];
+ Uint32 nodeId = signal->theData[1];
+ if(block.number() == QMGR){
+ Ndbcntr& cntr = * (Ndbcntr*)globalData.getBlock(CNTR);
+ switch(state){
+ case 0: // ZADD
+ break;
+ case 2: // ZSTART
+ break;
+ case 3: // ZRUN{
+ cntr.c_startedNodes.set(nodeId);
+
+ Uint32 recv = cntr.c_startedNodes.count();
+ Uint32 cnt = cntr.c_clusterNodes.count();
+ if(recv + 1 == cnt){ //+1 == own node
+ /**
+ * Check master
+ */
+ sendCntrMasterReq(cntr, signal, 0);
+ }
+ return;
+ }
+ }
+ block.progError(0,0);
+}
+
+void
+UpgradeStartup::sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n){
+ Uint32 node = cntr.c_startedNodes.find(n);
+ if(node != NdbNodeBitmask::NotFound &&
+ (node == cntr.getOwnNodeId() ||
+ cntr.getNodeInfo(node).m_version >= MAKE_VERSION(3,5,0))){
+ node = cntr.c_startedNodes.find(node+1);
+ }
+
+ if(node == NdbNodeBitmask::NotFound){
+ cntr.progError(0,0);
+ }
+
+ CntrMasterReq * const cntrMasterReq = (CntrMasterReq*)&signal->theData[0];
+ cntr.c_clusterNodes.copyto(NdbNodeBitmask::Size, cntrMasterReq->theNodes);
+ NdbNodeBitmask::clear(cntrMasterReq->theNodes, cntr.getOwnNodeId());
+ cntrMasterReq->userBlockRef = 0;
+ cntrMasterReq->userNodeId = cntr.getOwnNodeId();
+ cntrMasterReq->typeOfStart = NodeState::ST_INITIAL_NODE_RESTART;
+ cntrMasterReq->noRestartNodes = cntr.c_clusterNodes.count() - 1;
+ cntr.sendSignal(cntr.calcNdbCntrBlockRef(node), GSN_CNTR_MASTERREQ,
+ signal, CntrMasterReq::SignalLength, JBB);
+}
+
+void
+UpgradeStartup::execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal){
+ Uint32 gsn = signal->header.theVerId_signalNumber;
+ Uint32 node = refToNode(signal->getSendersBlockRef());
+ if(block.number() == CNTR){
+ Ndbcntr& cntr = (Ndbcntr&)block;
+ switch(gsn){
+ case GSN_CNTR_MASTERREF:
+ sendCntrMasterReq(cntr, signal, node + 1);
+ return;
+ break;
+ case GSN_CNTR_MASTERCONF:{
+ CntrStartConf* conf = (CntrStartConf*)signal->getDataPtrSend();
+ conf->startGci = 0;
+ conf->masterNodeId = node;
+ conf->noStartNodes = 1;
+ conf->startType = NodeState::ST_INITIAL_NODE_RESTART;
+ NodeBitmask mask;
+ mask.clear();
+ mask.copyto(NdbNodeBitmask::Size, conf->startedNodes);
+ mask.clear();
+ mask.set(cntr.getOwnNodeId());
+ mask.copyto(NdbNodeBitmask::Size, conf->startingNodes);
+ cntr.execCNTR_START_CONF(signal);
+ return;
+ }
+ }
+ }
+ block.progError(0,0);
}
diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index f73c1ec5ee7..7ba7d0d25c6 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -17,7 +17,8 @@
/**
* O_DIRECT
*/
-#ifdef NDB_LINUX
+#if 0
+//#ifdef NDB_LINUX
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
@@ -34,12 +35,14 @@
#include <NdbThread.h>
#include <signaldata/FsOpenReq.hpp>
-#ifdef NDB_LINUX
+#if 0
+#ifdef HAVE_PREAD
// This is for pread and pwrite
#ifndef __USE_UNIX98
#define __USE_UNIX98
#endif
#endif
+#endif
#if defined NDB_WIN32 || defined NDB_OSE || defined NDB_SOFTOSE
#else
@@ -343,12 +346,11 @@ void AsyncFile::openReq(Request* request)
}
#if 0
-#if NDB_LINUX
+ //#if NDB_LINUX
if(Global_useO_DIRECT){
new_flags |= O_DIRECT;
}
#endif
-#endif
switch(flags & 0x3){
case FsOpenReq::OM_READONLY:
diff --git a/ndb/src/kernel/blocks/ndbfs/Makefile.am b/ndb/src/kernel/blocks/ndbfs/Makefile.am
new file mode 100644
index 00000000000..c2b663c5042
--- /dev/null
+++ b/ndb/src/kernel/blocks/ndbfs/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LIBRARIES = libndbfs.a
+
+libndbfs_a_SOURCES = \
+ AsyncFile.cpp \
+ Ndbfs.cpp VoidFs.cpp \
+ Filename.cpp \
+ CircularIndex.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/ndbfs/Makefile b/ndb/src/kernel/blocks/ndbfs/Makefile_old
index 58e1458bf16..58e1458bf16 100644
--- a/ndb/src/kernel/blocks/ndbfs/Makefile
+++ b/ndb/src/kernel/blocks/ndbfs/Makefile_old
diff --git a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
index 36322ffad1e..c763d3b4786 100644
--- a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
@@ -60,10 +60,11 @@ Ndbfs::Ndbfs(const Configuration & conf) :
theFileSystemPath = conf.fileSystemPath();
theRequestPool = new Pool<Request>;
- const Properties * p = conf.getOwnProperties();
+ const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
ndbrequire(p != 0);
- ndbrequire(p->get("MaxNoOfOpenFiles", &m_maxFiles));
+ m_maxOpenedFiles = 40;
+ //ndb_mgm_get_int_parameter(p, CFG_DB_MAX_OPEN_FILES, &m_maxFiles);
// Create idle AsyncFiles
Uint32 noIdleFiles = 16;
diff --git a/ndb/src/kernel/blocks/qmgr/Makefile.am b/ndb/src/kernel/blocks/qmgr/Makefile.am
new file mode 100644
index 00000000000..52cadb3bd3d
--- /dev/null
+++ b/ndb/src/kernel/blocks/qmgr/Makefile.am
@@ -0,0 +1,11 @@
+noinst_LIBRARIES = libqmgr.a
+
+libqmgr_a_SOURCES = \
+ QmgrInit.cpp \
+ QmgrMain.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/qmgr/Makefile b/ndb/src/kernel/blocks/qmgr/Makefile_old
index cd15643ea60..cd15643ea60 100644
--- a/ndb/src/kernel/blocks/qmgr/Makefile
+++ b/ndb/src/kernel/blocks/qmgr/Makefile_old
diff --git a/ndb/src/kernel/blocks/qmgr/Qmgr.hpp b/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
index 7d2abd34ebe..0ff7cea6d9f 100644
--- a/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
+++ b/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
@@ -22,6 +22,8 @@
#include <NdbTick.h>
#include <SimulatedBlock.hpp>
#include <NodeBitmask.hpp>
+#include <SignalCounter.hpp>
+
#include <signaldata/EventReport.hpp>
#include <signaldata/ArbitSignalData.hpp>
#include <signaldata/CmRegSignalData.hpp>
@@ -33,24 +35,10 @@
#ifdef QMGR_C
#define NO_REG_APP 1
-/* Boolean flags --------------------------------*/
-#define ZNULL 0xfffe
/* Delay values, ms -----------------------------*/
#define ZDELAY_REGREQ 1000
-/* Phase of QMGR node ------------------------*/
-#define ZINIT 1 /* All nodes start in phase INIT */
-#define ZWAITING 2 /* Node is connecting to cluster */
-#define ZRUNNING 3 /* Node is running in the cluster */
-#define ZBLOCKED 4 /* Node is blocked from the cluster */
-#define ZWAIT_PRESIDENT 5
-#define ZDEAD 6
-#define ZAPI_ACTIVE 7 /* API IS RUNNING IN NODE */
-#define ZFAIL_CLOSING 8 /* API/NDB IS DISCONNECTING */
-#define ZPREPARE_FAIL 9 /* PREPARATION FOR FAILURE */
-#define ZAPI_INACTIVE 10 /* Inactive API */
-
/* Type of refuse in CM_NODEINFOREF -------------*/
#define ZNOT_RUNNING 0
@@ -100,18 +88,40 @@ public:
WAITING_FOR_FAILCONF2 = 2,
WAITING_FOR_NDB_FAILCONF = 3
};
+
+ enum Phase {
+ ZINIT = 1, /* All nodes start in phase INIT */
+ ZSTARTING = 2, /* Node is connecting to cluster */
+ ZRUNNING = 3, /* Node is running in the cluster */
+ ZPREPARE_FAIL = 4, /* PREPARATION FOR FAILURE */
+ ZFAIL_CLOSING = 5, /* API/NDB IS DISCONNECTING */
+ ZAPI_ACTIVE = 6, /* API IS RUNNING IN NODE */
+ ZAPI_INACTIVE = 7 /* Inactive API */
+ };
+
+ struct StartRecord {
+ void reset(){ m_startKey++; m_startNode = 0;}
+ Uint32 m_startKey;
+ Uint32 m_startNode;
+ Uint64 m_startTimeout;
+
+ Uint32 m_gsn;
+ SignalCounter m_nodes;
+ } c_start;
+
+ NdbNodeBitmask c_definedNodes; // DB nodes in config
+ NdbNodeBitmask c_clusterNodes; // DB nodes in cluster
+ NodeBitmask c_connectedNodes; // All kinds of connected nodes
+ Uint32 c_maxDynamicId;
// Records
struct NodeRec {
UintR ndynamicId;
- UintR phase;
+ Phase phase;
UintR alarmCount;
- bool m_connected;
QmgrState sendPrepFailReqStatus;
QmgrState sendCommitFailReqStatus;
- QmgrState sendCmAddPrepStatus;
- QmgrState sendCmAddCommitStatus;
QmgrState sendPresToStatus;
FailState failState;
BlockReference rcv[2]; // remember which failconf we have received
@@ -122,18 +132,6 @@ public:
typedef Ptr<NodeRec> NodeRecPtr;
- struct RegApp {
- NdbNodeBitmask m_runNodes;
- char name[15 + 1];
- UintR noofapps;
- UintR noofpending;
- BlockReference blockref;
- Uint16 version;
- Uint16 activity;
- };
-
- typedef Ptr<RegApp> RegAppPtr;
-
enum ArbitState {
ARBIT_NULL = 0,
ARBIT_INIT = 1, // create new ticket
@@ -191,7 +189,6 @@ private:
void execCM_HEARTBEAT(Signal* signal);
void execCM_ADD(Signal* signal);
void execCM_ACKADD(Signal* signal);
- void execCM_APPCHG(Signal* signal);
void execCM_REGREQ(Signal* signal);
void execCM_REGCONF(Signal* signal);
void execCM_REGREF(Signal* signal);
@@ -214,10 +211,6 @@ private:
void execCONNECT_REP(Signal* signal);
void execNDB_FAILCONF(Signal* signal);
void execSTTOR(Signal* signal);
- void execAPPL_REGREQ(Signal* signal);
- void execAPPL_STARTREG(Signal* signal);
- void execAPPL_RUN(Signal* signal);
- void execCM_INIT(Signal* signal);
void execCM_INFOCONF(Signal* signal);
void execCLOSE_COMCONF(Signal* signal);
void execAPI_REGREQ(Signal* signal);
@@ -242,53 +235,31 @@ private:
// Statement blocks
void node_failed(Signal* signal, Uint16 aFailedNode);
void checkStartInterface(Signal* signal);
- void applchangerep(Signal* signal,
- UintR aRegApp,
- Uint16 aNode,
- UintR aType,
- UintR aVersion);
- void cmappAdd(Signal* signal,
- UintR aRegApp,
- Uint16 aNode,
- UintR aType,
- UintR aVersion);
- void cmappStart(Signal* signal,
- UintR aRegApp,
- Uint16 aNode,
- UintR aType,
- UintR aVersion);
void failReport(Signal* signal,
Uint16 aFailedNode,
UintR aSendFailRep,
FailRep::FailCause failCause);
void findNeighbours(Signal* signal);
Uint16 translateDynamicIdToNodeId(Signal* signal, UintR TdynamicId);
- UintR getDynamicId(Signal* signal);
+
void initData(Signal* signal);
- void prepareAdd(Signal* signal, Uint16 addNode);
- void sendappchg(Signal* signal, UintR aRegApp, Uint16 aNode);
void sendCloseComReq(Signal* signal, BlockReference TBRef, Uint16 TfailNo);
void sendPrepFailReq(Signal* signal, Uint16 aNode);
void sendApiFailReq(Signal* signal, Uint16 aFailedNode);
void sendApiRegRef(Signal*, Uint32 ref, ApiRegRef::ErrorCode);
// Generated statement blocks
+ void startphase1(Signal* signal);
void electionWon();
void cmInfoconf010Lab(Signal* signal);
void apiHbHandlingLab(Signal* signal);
void timerHandlingLab(Signal* signal);
void hbReceivedLab(Signal* signal);
- void cmAdd010Lab(Signal* signal);
- void cmAckadd010Lab(Signal* signal);
- void cmAppchg010Lab(Signal* signal);
void sendCmRegrefLab(Signal* signal, BlockReference ref,
CmRegRef::ErrorCode);
void systemErrorBecauseOtherNodeFailed(Signal* signal, NodeId);
void systemErrorLab(Signal* signal,
const char* message = NULL);
- void cmRegref010Lab(Signal* signal);
- void cmNodeinforeq010Lab(Signal* signal);
- void cmNodeinfoconf010Lab(Signal* signal);
void prepFailReqLab(Signal* signal);
void prepFailConfLab(Signal* signal);
void prepFailRefLab(Signal* signal);
@@ -300,13 +271,10 @@ private:
void presToConfLab(Signal* signal);
void sendSttorryLab(Signal* signal);
void sttor020Lab(Signal* signal);
- void applRegreq010Lab(Signal* signal);
- void applStartreg010Lab(Signal* signal);
- void applRun010Lab(Signal* signal);
- void cmInit010Lab(Signal* signal);
void closeComConfLab(Signal* signal);
void apiRegReqLab(Signal* signal);
- void regreqTimelimitLab(Signal* signal, UintR callTime);
+ void regreqTimeLimitLab(Signal* signal);
+ void regreqTimeMasterLimitLab(Signal* signal);
void cmRegreq010Lab(Signal* signal);
void cmRegconf010Lab(Signal* signal);
void sttor010Lab(Signal* signal);
@@ -347,6 +315,12 @@ private:
bool checkAPIVersion(NodeId, Uint32 nodeVersion, Uint32 ownVersion) const;
bool checkNDBVersion(NodeId, Uint32 nodeVersion, Uint32 ownVersion) const;
+ void cmAddPrepare(Signal* signal, NodeRecPtr nodePtr, const NodeRec* self);
+ void sendCmAckAdd(Signal *, Uint32 nodeId, CmAdd::RequestType);
+ void joinedCluster(Signal* signal, NodeRecPtr nodePtr);
+ void sendCmRegReq(Signal * signal, Uint32 nodeId);
+ void sendCmNodeInfoReq(Signal* signal, Uint32 nodeId, const NodeRec * self);
+
private:
void sendPrepFailReqRef(Signal* signal,
Uint32 dstBlockRef,
@@ -364,7 +338,6 @@ private:
/**** Common stored variables ****/
NodeRec *nodeRec;
- RegApp * regApp;
ArbitRec arbitRec;
/* Block references ------------------------------*/
@@ -377,27 +350,17 @@ private:
/* Counters --------------------------------------*/
Uint16 cnoOfNodes; /* Static node counter */
- Uint16 cclustersize; /* Currently not used */
/* Status flags ----------------------------------*/
- Uint16 cstartseq; /* Marks what startseq we are in according to
- STTOR */
+ Uint32 c_restartPartialTimeout;
- Uint16 cpresidentBusy; /* Only used by the president, ZTRUE / ZFALSE */
- Uint16 cacceptRegreq; /* Used by president, ZTRUE / ZFALSE */
- Uint16 cwaitContinuebPhase1;
- Uint16 cwaitContinuebPhase2;
Uint16 creadyDistCom;
-
- UintR cstartNo;
Uint16 c_regReqReqSent;
Uint16 c_regReqReqRecv;
Uint64 c_stopElectionTime;
Uint16 cpresidentCandidate;
Uint16 cdelayRegreq;
Uint16 cpresidentAlive;
- Uint16 csignalkey;
- Uint16 cstartNode;
Uint16 cnoFailedNodes;
Uint16 cnoPrepFailedNodes;
Uint16 cnoCommitFailedNodes;
@@ -410,7 +373,6 @@ private:
UintR cfailureNr;
QmgrState ctoStatus;
- UintR ccm_infoconfCounter;
UintR cLqhTimeSignalCount;
bool cHbSent;
NDB_TICKS clatestTransactionCheck;
@@ -421,68 +383,10 @@ private:
class Timer hb_api_timer;
- UintR cnodemask[NdbNodeBitmask::Size];
Uint16 cfailedNodes[MAX_NDB_NODES];
Uint16 cprepFailedNodes[MAX_NDB_NODES];
Uint16 ccommitFailedNodes[MAX_NDB_NODES];
- /***************************************************************************/
- /* RECORD NODE_REC: The NodeList contains information about all other nodes
- * in the cluster.
- * Member variables:
- * NTYPE [ ZACTIVE,
- * ZPASSIVE, Marks the level of activity the
- * node will show in the cluster.
- * ZLISTENER ]
- * PHASE [ ZINIT, = Initial face, before node is added
- * to cluster
- * ZWAITING, = Node is added to the cluster and
- * ready to run
- * ZRUNNING, = Node is up and running.
- * ZBLOCKED = Node is not in the cluster
- * ZAPI_ACTIVE = Node has an active application
- * ZFAIL_CLOSING = Node is disconnecting
- * ZDEAD ] = Node has been declared as dead
- * ALARM_COUNT No of times an alarm has been sent before it is
- * acknowledged
- ***************************************************************************/
- /*************************************************************************
- * RECORD REG_APP: The REG_APP record is used to store information about
- * each registered application running on the current node.
- * Member variables:
- * BLOCKREF Reference of application block to receive cluster
- * signals
- * PTR Not used today but may be used by appl. in future
- * NAME Unique name of application, max 15 char. long
- * SUBTYPE Provided as a mechanism for applications to have
- * more than one type running in the same application
- * ring. i.e. NDB & NDB-API
- * VERSION Version no. of application. Two different versions
- * will be handled as different applications.
- * TYPE [ ZACTIVE,
- * ZPASSIVE,
- * ZLISTENER ] Type of member in the cluster
- * ACTIVITY [ ZADD, Application has been registered on
- * node.
- * ZSTART, Application is ready to start
- * running distributed.
- * ZRUN, Application is running actively.
- * ZDELETE ] Application is beeing removed from
- * the node.
- * HBDELAY Delay time for periodic intervalls.
- * STATUS Heartbeat status, indicates if app is responding
- * to HBREQ.
- * RUNNODES() If value is ZTRUE -> app. is also running on the
- * indexed node.
- * NOOFAPPS No. of applications left to register themselves as
- * ready to start, STATUS = ZSTART before we can send
- * APPL_STARTCONF.
- * NOOFPENDING No. of apps that have registered themselfs as ready
- * to start before this app has. We need this since
- * we set NOOFAPPS when we receive the local
- * APPL_START. NOOFPENDING is subtracted from NOOFAPPS
- * when NOOFAPPS is set.
- **************************************************************************/
-
};
+
#endif
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp b/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
index ffc1448548d..b0f1088779c 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
@@ -18,7 +18,6 @@
#define QMGR_C
#include "Qmgr.hpp"
-#include <Configuration.hpp>
#define DEBUG(x) { ndbout << "Qmgr::" << x << endl; }
@@ -29,10 +28,13 @@ void Qmgr::initData()
// Records with constant sizes
nodeRec = new NodeRec[MAX_NODES];
- regApp = new RegApp[NO_REG_APP];
- cclustersize = 0;
cnoCommitFailedNodes = 0;
+ c_maxDynamicId = 0;
+ c_clusterNodes.clear();
+
+ Uint32 hbDBAPI = 500;
+ setHbApiDelay(hbDBAPI);
}//Qmgr::initData()
void Qmgr::initRecords()
@@ -52,7 +54,6 @@ Qmgr::Qmgr(const class Configuration & conf)
addRecSignal(GSN_CM_HEARTBEAT, &Qmgr::execCM_HEARTBEAT);
addRecSignal(GSN_CM_ADD, &Qmgr::execCM_ADD);
addRecSignal(GSN_CM_ACKADD, &Qmgr::execCM_ACKADD);
- addRecSignal(GSN_CM_APPCHG, &Qmgr::execCM_APPCHG);
addRecSignal(GSN_CM_REGREQ, &Qmgr::execCM_REGREQ);
addRecSignal(GSN_CM_REGCONF, &Qmgr::execCM_REGCONF);
addRecSignal(GSN_CM_REGREF, &Qmgr::execCM_REGREF);
@@ -67,16 +68,11 @@ Qmgr::Qmgr(const class Configuration & conf)
addRecSignal(GSN_FAIL_REP, &Qmgr::execFAIL_REP);
addRecSignal(GSN_PRES_TOREQ, &Qmgr::execPRES_TOREQ);
addRecSignal(GSN_PRES_TOCONF, &Qmgr::execPRES_TOCONF);
- addRecSignal(GSN_CM_INFOCONF, &Qmgr::execCM_INFOCONF);
// Received signals
addRecSignal(GSN_CONNECT_REP, &Qmgr::execCONNECT_REP);
addRecSignal(GSN_NDB_FAILCONF, &Qmgr::execNDB_FAILCONF);
addRecSignal(GSN_STTOR, &Qmgr::execSTTOR);
- addRecSignal(GSN_APPL_REGREQ, &Qmgr::execAPPL_REGREQ);
- addRecSignal(GSN_APPL_STARTREG, &Qmgr::execAPPL_STARTREG);
- addRecSignal(GSN_APPL_RUN, &Qmgr::execAPPL_RUN);
- addRecSignal(GSN_CM_INIT, &Qmgr::execCM_INIT);
addRecSignal(GSN_CLOSE_COMCONF, &Qmgr::execCLOSE_COMCONF);
addRecSignal(GSN_API_REGREQ, &Qmgr::execAPI_REGREQ);
addRecSignal(GSN_API_VERSION_REQ, &Qmgr::execAPI_VERSION_REQ);
@@ -86,7 +82,6 @@ Qmgr::Qmgr(const class Configuration & conf)
addRecSignal(GSN_SET_VAR_REQ, &Qmgr::execSET_VAR_REQ);
// Arbitration signals
- addRecSignal(GSN_ARBIT_CFG, &Qmgr::execARBIT_CFG);
addRecSignal(GSN_ARBIT_PREPREQ, &Qmgr::execARBIT_PREPREQ);
addRecSignal(GSN_ARBIT_PREPCONF, &Qmgr::execARBIT_PREPCONF);
addRecSignal(GSN_ARBIT_PREPREF, &Qmgr::execARBIT_PREPREF);
@@ -97,18 +92,11 @@ Qmgr::Qmgr(const class Configuration & conf)
addRecSignal(GSN_ARBIT_STOPREP, &Qmgr::execARBIT_STOPREP);
initData();
-
- const ClusterConfiguration::ClusterData & clusterConf =
- theConfiguration.clusterConfigurationData() ;
- setHbDelay(clusterConf.ispValues[0][2]); //cmInit->heartbeatDbDb);
- setHbApiDelay(clusterConf.ispValues[0][3]); //;cmInit->heartbeatDbApi);
- setArbitTimeout(clusterConf.ispValues[0][5]); //cmInit->arbitTimeout);
}//Qmgr::Qmgr()
Qmgr::~Qmgr()
{
delete []nodeRec;
- delete []regApp;
}//Qmgr::~Qmgr()
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
index 0f82f8def6f..f2d2edb615d 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
@@ -20,7 +20,6 @@
#include <pc.hpp>
#include <NdbTick.h>
#include <signaldata/EventReport.hpp>
-#include <signaldata/SetVarReq.hpp>
#include <signaldata/StartOrd.hpp>
#include <signaldata/CmInit.hpp>
#include <signaldata/CloseComReqConf.hpp>
@@ -42,6 +41,20 @@
#include <NdbOut.hpp>
#endif
+//#define DEBUG_QMGR_START
+#ifdef DEBUG_QMGR_START
+#include <DebuggerNames.hpp>
+#define DEBUG(x) ndbout << "QMGR " << __LINE__ << ": " << x << endl
+#define DEBUG_START(gsn, node, msg) DEBUG(getSignalName(gsn) << " to: " << node << " - " << msg)
+#define DEBUG_START2(gsn, rg, msg) { char nodes[255]; DEBUG(getSignalName(gsn) << " to: " << rg.m_nodes.getText(nodes) << " - " << msg); }
+#define DEBUG_START3(signal, msg) DEBUG(getSignalName(signal->header.theVerId_signalNumber) << " from " << refToNode(signal->getSendersBlockRef()) << " - " << msg);
+#else
+#define DEBUG(x)
+#define DEBUG_START(gsn, node, msg)
+#define DEBUG_START2(gsn, rg, msg)
+#define DEBUG_START3(signal, msg)
+#endif
+
// Signal entries and statement blocks
/* 4 P R O G R A M */
/*******************************/
@@ -72,32 +85,27 @@ void Qmgr::execCM_NODEINFOREF(Signal* signal)
/*******************************/
void Qmgr::execCONTINUEB(Signal* signal)
{
- UintR tdata0;
- UintR tcontinuebType;
-
jamEntry();
- tcontinuebType = signal->theData[0];
- tdata0 = signal->theData[1];
+ const Uint32 tcontinuebType = signal->theData[0];
+ const Uint32 tdata0 = signal->theData[1];
+ const Uint32 tdata1 = signal->theData[2];
switch (tcontinuebType) {
case ZREGREQ_TIMELIMIT:
jam();
- if (cstartNo == tdata0) {
+ if (c_start.m_startKey != tdata0 || c_start.m_startNode != tdata1) {
jam();
- regreqTimelimitLab(signal, signal->theData[2]);
return;
- }
+ }//if
+ regreqTimeLimitLab(signal);
break;
case ZREGREQ_MASTER_TIMELIMIT:
jam();
- if (cstartNo != tdata0) {
+ if (c_start.m_startKey != tdata0 || c_start.m_startNode != tdata1) {
jam();
return;
}//if
- if (cpresidentBusy != ZTRUE) {
- jam();
- return;
- }//if
- failReportLab(signal, cstartNode, FailRep::ZSTART_IN_REGREQ);
+ //regreqMasterTimeLimitLab(signal);
+ failReportLab(signal, c_start.m_startNode, FailRep::ZSTART_IN_REGREQ);
return;
break;
case ZTIMER_HANDLING:
@@ -173,15 +181,23 @@ void Qmgr::execPRES_TOREQ(Signal* signal)
void Qmgr::execSTTOR(Signal* signal)
{
jamEntry();
- cstartseq = signal->theData[1];
- csignalkey = signal->theData[6];
- if (cstartseq == 1) {
- jam();
+
+ switch(signal->theData[1]){
+ case 1:
initData(signal);
+ startphase1(signal);
+ return;
+ case 7:
+ cactivateApiCheck = 1;
+ /**
+ * Start arbitration thread. This could be done as soon as
+ * we have all nodes (or a winning majority).
+ */
+ if (cpresident == getOwnNodeId())
+ handleArbitStart(signal);
+ break;
}
- setNodeInfo(getOwnNodeId()).m_version = NDB_VERSION;
-
sendSttorryLab(signal);
return;
}//Qmgr::execSTTOR()
@@ -191,85 +207,32 @@ void Qmgr::sendSttorryLab(Signal* signal)
/****************************<*/
/*< STTORRY <*/
/****************************<*/
- signal->theData[0] = csignalkey;
- signal->theData[1] = 3;
- signal->theData[2] = 2;
- signal->theData[3] = 2;
+ signal->theData[3] = 7;
signal->theData[4] = 255;
sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
return;
}//Qmgr::sendSttorryLab()
-/*
-4.2.2 CM_INIT */
-/**--------------------------------------------------------------------------
- * This signal is sent by the CLUSTERCTRL block.
- * It initiates the QMGR and provides needed info about the
- * cluster configuration (read from file).
- *
- * The signal starts all QMGR functions.
- * It is possible to register applications before this but the QMGR will
- * not be active before the registration face is complete.
- *
- * The CM_INIT will result in a one CM_NODEINFOREQ for each ndb node.
- * We will also send a CONTINUEB to ourselves as a timelimit.
- * If anyone sends a REF, CONF or a ( REQ with a lower NODENO than us ) during
- * this time, we are not the president .
- *--------------------------------------------------------------------------*/
-/*******************************/
-/* CM_INIT */
-/*******************************/
-void Qmgr::execCM_INIT(Signal* signal)
+void Qmgr::startphase1(Signal* signal)
{
jamEntry();
- CmInit * const cmInit = (CmInit *)&signal->theData[0];
-
- for(unsigned int i = 0; i<NdbNodeBitmask::Size; i++)
- cnodemask[i] = cmInit->allNdbNodes[i];
-
- cnoOfNodes = 0;
- setHbDelay(cmInit->heartbeatDbDb);
- setHbApiDelay(cmInit->heartbeatDbApi);
- setArbitTimeout(cmInit->arbitTimeout);
- arbitRec.state = ARBIT_NULL; // start state for all nodes
- arbitRec.apiMask[0].clear(); // prepare for ARBIT_CFG
NodeRecPtr nodePtr;
- for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (NdbNodeBitmask::get(cnodemask, nodePtr.i)) {
- jam();
-
- nodePtr.p->blockRef = calcQmgrBlockRef(nodePtr.i);
- nodePtr.p->phase = ZINIT; /* Not added to cluster */
- cnoOfNodes = cnoOfNodes + 1; /* Should never be changed after this loop. */
- ndbrequire(getNodeInfo(nodePtr.i).m_type == NodeInfo::DB);
- } else {
- jam();
- nodePtr.p->phase = ZBLOCKED;
- }//if
- }//for
- for (nodePtr.i = MAX_NDB_NODES; nodePtr.i < MAX_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- nodePtr.p->phase = ZBLOCKED;
- }//for
-
nodePtr.i = getOwnNodeId();
ptrAss(nodePtr, nodeRec);
- nodePtr.p->phase = ZINIT;
- nodePtr.p->m_connected = true;
+ nodePtr.p->phase = ZSTARTING;
+ nodePtr.p->blockRef = reference();
+ c_connectedNodes.set(nodePtr.i);
- /****************************<*/
- /*< CM_INFOREQ <*/
- /****************************<*/
- signal->theData[0] = reference();
- signal->theData[1] = getOwnNodeId();
- sendSignal(CMVMI_REF, GSN_CM_INFOREQ, signal, 2, JBB);
+ signal->theData[0] = 0; // no answer
+ signal->theData[1] = 0; // no id
+ signal->theData[2] = NodeInfo::DB;
+ sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 3, JBB);
+
+ execCM_INFOCONF(signal);
return;
-}//Qmgr::execCM_INIT()
+}
void Qmgr::setHbDelay(UintR aHbDelay)
{
@@ -293,11 +256,46 @@ void Qmgr::setArbitTimeout(UintR aArbitTimeout)
void Qmgr::execCONNECT_REP(Signal* signal)
{
- NodeRecPtr connectNodePtr;
- connectNodePtr.i = signal->theData[0];
- ptrCheckGuard(connectNodePtr, MAX_NODES, nodeRec);
- connectNodePtr.p->m_connected = true;
+ const Uint32 nodeId = signal->theData[0];
+ c_connectedNodes.set(nodeId);
+ NodeRecPtr nodePtr;
+ nodePtr.i = getOwnNodeId();
+ ptrCheckGuard(nodePtr, MAX_NODES, nodeRec);
+ switch(nodePtr.p->phase){
+ case ZSTARTING:
+ jam();
+ break;
+ case ZRUNNING:
+ case ZPREPARE_FAIL:
+ case ZFAIL_CLOSING:
+ jam();
+ return;
+ case ZINIT:
+ ndbrequire(false);
+ case ZAPI_ACTIVE:
+ case ZAPI_INACTIVE:
+ return;
+ }
+
+ if(!c_start.m_nodes.isWaitingFor(nodeId)){
+ jam();
+ return;
+ }
+
+ switch(c_start.m_gsn){
+ case GSN_CM_REGREQ:
+ jam();
+ sendCmRegReq(signal, nodeId);
+ return;
+ case GSN_CM_NODEINFOREQ:{
+ jam();
+ sendCmNodeInfoReq(signal, nodeId, nodePtr.p);
+ return;
+ }
+ default:
+ return;
+ }
return;
}//Qmgr::execCONNECT_REP()
@@ -310,25 +308,22 @@ void Qmgr::execCM_INFOCONF(Signal* signal)
cpresidentCandidate = getOwnNodeId();
cpresidentAlive = ZFALSE;
c_stopElectionTime = NdbTick_CurrentMillisecond();
- c_stopElectionTime += 30000; // 30s
+ c_stopElectionTime += c_restartPartialTimeout;
cmInfoconf010Lab(signal);
-#if 0
- /*****************************************************/
- /* Allow the CLUSTER CONTROL to send STTORRY */
- /* CM_RUN */
- /* so we can receive APPL_REGREQ from applications. */
- /*****************************************************/
- signal->theData[0] = 0;
- sendSignal(CMVMI_REF, GSN_CM_RUN, signal, 1, JBB);
-#endif
return;
}//Qmgr::execCM_INFOCONF()
void Qmgr::cmInfoconf010Lab(Signal* signal)
{
+ c_start.m_startKey = 0;
+ c_start.m_startNode = getOwnNodeId();
+ c_start.m_nodes.clearWaitingFor();
+ c_start.m_gsn = GSN_CM_REGREQ;
+
NodeRecPtr nodePtr;
c_regReqReqSent = c_regReqReqRecv = 0;
+ cnoOfNodes = 0;
for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
jam();
ptrAss(nodePtr, nodeRec);
@@ -336,19 +331,15 @@ void Qmgr::cmInfoconf010Lab(Signal* signal)
if(getNodeInfo(nodePtr.i).getType() != NodeInfo::DB)
continue;
- if(!nodePtr.p->m_connected)
+ c_start.m_nodes.setWaitingFor(nodePtr.i);
+ cnoOfNodes++;
+
+ if(!c_connectedNodes.get(nodePtr.i))
continue;
- c_regReqReqSent++;
- CmRegReq * const cmRegReq = (CmRegReq *)&signal->theData[0];
- cmRegReq->blockRef = reference();
- cmRegReq->nodeId = getOwnNodeId();
- cmRegReq->version = NDB_VERSION;
- sendSignal(nodePtr.p->blockRef, GSN_CM_REGREQ, signal,
- CmRegReq::SignalLength, JBB);
+ sendCmRegReq(signal, nodePtr.i);
}
- cstartNo = cstartNo + 1;
-
+
//----------------------------------------
/* Wait for a while. When it returns */
/* we will check if we got any CM_REGREF*/
@@ -356,14 +347,26 @@ void Qmgr::cmInfoconf010Lab(Signal* signal)
/* own). */
//----------------------------------------
signal->theData[0] = ZREGREQ_TIMELIMIT;
- signal->theData[1] = cstartNo;
- signal->theData[2] = 0;
- sendSignalWithDelay(QMGR_REF, GSN_CONTINUEB, signal, 3 * cdelayRegreq, 3);
- cwaitContinuebPhase1 = ZTRUE;
+ signal->theData[1] = c_start.m_startKey;
+ signal->theData[2] = c_start.m_startNode;
+ sendSignalWithDelay(QMGR_REF, GSN_CONTINUEB, signal, 3000, 3);
+
creadyDistCom = ZTRUE;
return;
}//Qmgr::cmInfoconf010Lab()
+void
+Qmgr::sendCmRegReq(Signal * signal, Uint32 nodeId){
+ c_regReqReqSent++;
+ CmRegReq * const cmRegReq = (CmRegReq *)&signal->theData[0];
+ cmRegReq->blockRef = reference();
+ cmRegReq->nodeId = getOwnNodeId();
+ cmRegReq->version = NDB_VERSION;
+ const Uint32 ref = calcQmgrBlockRef(nodeId);
+ sendSignal(ref, GSN_CM_REGREQ, signal, CmRegReq::SignalLength, JBB);
+ DEBUG_START(GSN_CM_REGREQ, nodeId, "");
+}
+
/*
4.4.11 CM_REGREQ */
/**--------------------------------------------------------------------------
@@ -403,6 +406,8 @@ void Qmgr::cmInfoconf010Lab(Signal* signal)
/*******************************/
void Qmgr::execCM_REGREQ(Signal* signal)
{
+ DEBUG_START3(signal, "");
+
NodeRecPtr addNodePtr;
jamEntry();
@@ -451,27 +456,15 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return;
}//if
- if (cpresidentBusy == ZTRUE) {
+ if (c_start.m_startNode != 0){
jam();
/**
- * President busy by adding another node
+ * President busy by adding another node
*/
sendCmRegrefLab(signal, Tblockref, CmRegRef::ZBUSY_PRESIDENT);
return;
}//if
- if (cacceptRegreq == ZFALSE &&
- getNodeState().startLevel != NodeState::SL_STARTING) {
- jam();
- /**
- * These checks are really confusing!
- * The variables that is being checked are probably not
- * set in the correct places.
- */
- sendCmRegrefLab(signal, Tblockref, CmRegRef::ZBUSY);
- return;
- }//if
-
if (ctoStatus == Q_ACTIVE) {
jam();
/**
@@ -481,7 +474,7 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return;
}//if
- if (addNodePtr.p->phase == ZBLOCKED) {
+ if (getNodeInfo(addNodePtr.i).m_type != NodeInfo::DB) {
jam();
/**
* The new node is not in config file
@@ -489,9 +482,11 @@ void Qmgr::execCM_REGREQ(Signal* signal)
sendCmRegrefLab(signal, Tblockref, CmRegRef::ZNOT_IN_CFG);
return;
}
-
- if (addNodePtr.p->phase != ZINIT) {
+
+ Phase phase = addNodePtr.p->phase;
+ if (phase != ZINIT){
jam();
+ DEBUG("phase = " << phase);
sendCmRegrefLab(signal, Tblockref, CmRegRef::ZNOT_DEAD);
return;
}//if
@@ -506,45 +501,56 @@ void Qmgr::execCM_REGREQ(Signal* signal)
* THE SIGNAL ARRIVES. IF IT HAS CHANGED THEN WE SIMPLY IGNORE
* THE TIMED SIGNAL.
*/
- cpresidentBusy = ZTRUE;
/**
- * Indicates that we are busy with node start/restart and do
- * not accept another start until this node is up and running
- * (cpresidentBusy is released a little too early to use for this
- * purpose).
+ * Update start record
*/
- cacceptRegreq = ZFALSE;
- cstartNo = cstartNo + 1;
- cstartNode = addNodePtr.i;
- signal->theData[0] = ZREGREQ_MASTER_TIMELIMIT;
- signal->theData[1] = cstartNo;
- sendSignalWithDelay(QMGR_REF, GSN_CONTINUEB, signal, 30000, 2);
- UintR TdynId = getDynamicId(signal); /* <- CDYNAMIC_ID */
- prepareAdd(signal, addNodePtr.i);
- setNodeInfo(addNodePtr.i).m_version = startingVersion;
-
+ c_start.m_startKey++;
+ c_start.m_startNode = addNodePtr.i;
+
/**
- * Send "prepare for adding a new node" to all
- * running nodes in cluster + the new node.
- * Give permission to the new node to join the
- * cluster
+ * Assign dynamic id
*/
- /*******************************/
- /*< CM_REGCONF <*/
- /*******************************/
+ UintR TdynId = ++c_maxDynamicId;
+ setNodeInfo(addNodePtr.i).m_version = startingVersion;
+ addNodePtr.p->ndynamicId = TdynId;
+ /**
+ * Reply with CM_REGCONF
+ */
CmRegConf * const cmRegConf = (CmRegConf *)&signal->theData[0];
-
cmRegConf->presidentBlockRef = reference();
cmRegConf->presidentNodeId = getOwnNodeId();
cmRegConf->presidentVersion = getNodeInfo(getOwnNodeId()).m_version;
cmRegConf->dynamicId = TdynId;
- for(unsigned int i = 0; i<NdbNodeBitmask::Size; i++)
- cmRegConf->allNdbNodes[i] = cnodemask[i];
-
+ c_clusterNodes.copyto(NdbNodeBitmask::Size, cmRegConf->allNdbNodes);
sendSignal(Tblockref, GSN_CM_REGCONF, signal,
- CmRegConf::SignalLength, JBB);
+ CmRegConf::SignalLength, JBA);
+ DEBUG_START(GSN_CM_REGCONF, refToNode(Tblockref), "");
+
+ /**
+ * Send CmAdd to all nodes (including starting)
+ */
+ c_start.m_nodes = c_clusterNodes;
+ c_start.m_nodes.setWaitingFor(addNodePtr.i);
+ c_start.m_gsn = GSN_CM_ADD;
+
+ NodeReceiverGroup rg(QMGR, c_start.m_nodes);
+ CmAdd * const cmAdd = (CmAdd*)signal->getDataPtrSend();
+ cmAdd->requestType = CmAdd::Prepare;
+ cmAdd->startingNodeId = addNodePtr.i;
+ cmAdd->startingVersion = startingVersion;
+ sendSignal(rg, GSN_CM_ADD, signal, CmAdd::SignalLength, JBA);
+ DEBUG_START2(GSN_CM_ADD, rg, "Prepare");
+
+ /**
+ * Set timer
+ */
+ return;
+ signal->theData[0] = ZREGREQ_MASTER_TIMELIMIT;
+ signal->theData[1] = c_start.m_startKey;
+ sendSignalWithDelay(QMGR_REF, GSN_CONTINUEB, signal, 30000, 2);
+
return;
}//Qmgr::execCM_REGREQ()
@@ -555,9 +561,10 @@ void Qmgr::sendCmRegrefLab(Signal* signal, BlockReference TBRef,
ref->blockRef = reference();
ref->nodeId = getOwnNodeId();
ref->errorCode = Terror;
- ref->presidentCandidate = cpresidentCandidate;
+ ref->presidentCandidate = (cpresident == ZNIL ? cpresidentCandidate : cpresident);
sendSignal(TBRef, GSN_CM_REGREF, signal,
CmRegRef::SignalLength, JBB);
+ DEBUG_START(GSN_CM_REGREF, refToNode(TBRef), "");
return;
}//Qmgr::sendCmRegrefLab()
@@ -575,14 +582,13 @@ void Qmgr::sendCmRegrefLab(Signal* signal, BlockReference TBRef,
/*******************************/
void Qmgr::execCM_REGCONF(Signal* signal)
{
+ DEBUG_START3(signal, "");
+
NodeRecPtr myNodePtr;
NodeRecPtr nodePtr;
- NodeRecPtr presidentNodePtr;
jamEntry();
- CmRegConf * const cmRegConf = (CmRegConf *)&signal->theData[0];
- cwaitContinuebPhase1 = ZFALSE;
- cwaitContinuebPhase2 = ZTRUE;
+ const CmRegConf * const cmRegConf = (CmRegConf *)&signal->theData[0];
if (!ndbCompatible_ndb_ndb(NDB_VERSION, cmRegConf->presidentVersion)) {
jam();
@@ -592,46 +598,12 @@ void Qmgr::execCM_REGCONF(Signal* signal)
return;
}
- /**
- * Check if all necessary connections has been established
- */
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- if (NodeBitmask::get(cmRegConf->allNdbNodes, nodePtr.i) == true){
- jam();
- ptrAss(nodePtr, nodeRec);
- if (!nodePtr.p->m_connected) {
- jam();
-
- /**
- * Missing connection
- */
-#ifdef VM_TRACE
- ndbout_c("Resending CM_REGCONF, node %d is not connected", nodePtr.i);
- ndbout << " presidentBlockRef="<<cmRegConf->presidentBlockRef<<endl
- << " presidentNodeId="<<cmRegConf->presidentNodeId<<endl
- << " presidentVersion="<<cmRegConf->presidentVersion<<endl
- << " dynamicId="<<cmRegConf->dynamicId<<endl;
-#endif
- for(unsigned int i = 0; i<NdbNodeBitmask::Size; i++) {
- jam();
-#ifdef VM_TRACE
- ndbout << " " << i << ": "
- << hex << cmRegConf->allNdbNodes[i]<<endl;
-#endif
- }
- sendSignalWithDelay(reference(), GSN_CM_REGCONF, signal, 100,
- signal->getLength());
- return;
- }
- }
- }
-
+
cpdistref = cmRegConf->presidentBlockRef;
cpresident = cmRegConf->presidentNodeId;
UintR TdynamicId = cmRegConf->dynamicId;
- for(unsigned int i = 0; i<NdbNodeBitmask::Size; i++)
- cnodemask[i] = cmRegConf->allNdbNodes[i];
+ c_maxDynamicId = TdynamicId;
+ c_clusterNodes.assign(NdbNodeBitmask::Size, cmRegConf->allNdbNodes);
/*--------------------------------------------------------------*/
// Send this as an EVENT REPORT to inform about hearing about
@@ -646,67 +618,40 @@ void Qmgr::execCM_REGCONF(Signal* signal)
myNodePtr.i = getOwnNodeId();
ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
myNodePtr.p->ndynamicId = TdynamicId;
- presidentNodePtr.i = cpresident;
- ptrCheckGuard(presidentNodePtr, MAX_NDB_NODES, nodeRec);
- cpdistref = presidentNodePtr.p->blockRef;
-
- CmNodeInfoReq * const req = (CmNodeInfoReq*)signal->getDataPtrSend();
- req->nodeId = getOwnNodeId();
- req->dynamicId = myNodePtr.p->ndynamicId;
- req->version = getNodeInfo(getOwnNodeId()).m_version;
for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
jam();
- if (NdbNodeBitmask::get(cnodemask, nodePtr.i) == true){
+ if (c_clusterNodes.get(nodePtr.i)){
jam();
ptrAss(nodePtr, nodeRec);
- switch(nodePtr.p->phase){
- case ZINIT: /* All nodes start in phase INIT */
- jam();
- break;
- case ZWAITING: /* Node is connecting to cluster */
- jam();
- break;
- case ZRUNNING: /* Node is running in the cluster */
- jam();
- break;
- case ZBLOCKED: /* Node is blocked from the cluster */
- jam();
- break;
- case ZWAIT_PRESIDENT:
- jam();
- break;
- case ZDEAD:
- jam();
- break;
- case ZAPI_ACTIVE: /* API IS RUNNING IN NODE */
- jam();
- break;
- case ZFAIL_CLOSING: /* API/NDB IS DISCONNECTING */
- jam();
- break;
- case ZPREPARE_FAIL: /* PREPARATION FOR FAILURE */
- jam();
- break;
- case ZAPI_INACTIVE: /* Inactive API */
- jam();
- break;
- default:
+
+ ndbrequire(nodePtr.p->phase == ZINIT);
+ nodePtr.p->phase = ZRUNNING;
+
+ if(c_connectedNodes.get(nodePtr.i)){
jam();
- ndbout << "phase="<<nodePtr.p->phase<<endl;
- break;
+ sendCmNodeInfoReq(signal, nodePtr.i, myNodePtr.p);
}
- ndbrequire(nodePtr.p->phase == ZINIT);
- ndbrequire(nodePtr.i != getOwnNodeId());
- nodePtr.p->phase = ZWAITING;
-
- sendSignal(nodePtr.p->blockRef, GSN_CM_NODEINFOREQ,
- signal, CmNodeInfoReq::SignalLength, JBB);
}
}
+
+ c_start.m_gsn = GSN_CM_NODEINFOREQ;
+ c_start.m_nodes = c_clusterNodes;
+
return;
}//Qmgr::execCM_REGCONF()
+void
+Qmgr::sendCmNodeInfoReq(Signal* signal, Uint32 nodeId, const NodeRec * self){
+ CmNodeInfoReq * const req = (CmNodeInfoReq*)signal->getDataPtrSend();
+ req->nodeId = getOwnNodeId();
+ req->dynamicId = self->ndynamicId;
+ req->version = getNodeInfo(getOwnNodeId()).m_version;
+ const Uint32 ref = calcQmgrBlockRef(nodeId);
+ sendSignal(ref,GSN_CM_NODEINFOREQ, signal, CmNodeInfoReq::SignalLength, JBB);
+ DEBUG_START(GSN_CM_NODEINFOREQ, nodeId, "");
+}
+
/*
4.4.11 CM_REGREF */
/**--------------------------------------------------------------------------
@@ -735,9 +680,11 @@ void Qmgr::execCM_REGREF(Signal* signal)
UintR TrefuseReason = signal->theData[2];
Uint32 candidate = signal->theData[3];
+ DEBUG_START3(signal, TrefuseReason);
+
if(candidate != cpresidentCandidate){
jam();
- c_regReqReqRecv = c_regReqReqSent + 1;
+ c_regReqReqRecv = ~0;
}
switch (TrefuseReason) {
@@ -758,25 +705,16 @@ void Qmgr::execCM_REGREF(Signal* signal)
break;
case CmRegRef::ZNOT_DEAD:
jam();
- if(TaddNodeno == getOwnNodeId() && cpresident == getOwnNodeId()){
- jam();
- cwaitContinuebPhase1 = ZFALSE;
- cwaitContinuebPhase2 = ZFALSE;
- return;
- }
progError(__LINE__, ERR_NODE_NOT_DEAD);
break;
case CmRegRef::ZELECTION:
jam();
- if (cwaitContinuebPhase1 == ZFALSE) {
- jam();
- signal->theData[3] = 1;
- } else if (cpresidentCandidate > TaddNodeno) {
+ if (cpresidentCandidate > TaddNodeno) {
jam();
-//----------------------------------------
-/* We may already have a candidate */
-/* choose the lowest nodeno */
-//----------------------------------------
+ //----------------------------------------
+ /* We may already have a candidate */
+ /* choose the lowest nodeno */
+ //----------------------------------------
signal->theData[3] = 2;
cpresidentCandidate = TaddNodeno;
} else {
@@ -808,16 +746,19 @@ void Qmgr::execCM_REGREF(Signal* signal)
if(cpresidentAlive == ZTRUE){
jam();
+ DEBUG("");
return;
}
if(c_regReqReqSent != c_regReqReqRecv){
jam();
+ DEBUG( c_regReqReqSent << " != " << c_regReqReqRecv);
return;
}
if(cpresidentCandidate != getOwnNodeId()){
jam();
+ DEBUG("");
return;
}
@@ -829,10 +770,8 @@ void Qmgr::execCM_REGREF(Signal* signal)
jam();
electionWon();
-#if 1
- signal->theData[0] = 0;
- sendSignal(CMVMI_REF, GSN_CM_RUN, signal, 1, JBB);
-#endif
+ sendSttorryLab(signal);
+
/**
* Start timer handling
*/
@@ -851,14 +790,18 @@ Qmgr::electionWon(){
ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
myNodePtr.p->phase = ZRUNNING;
+
cpdistref = reference();
- cclustersize = 1;
cneighbourl = ZNIL;
cneighbourh = ZNIL;
myNodePtr.p->ndynamicId = 1;
-
+ c_maxDynamicId = 1;
+ c_clusterNodes.clear();
+ c_clusterNodes.set(getOwnNodeId());
+
cpresidentAlive = ZTRUE;
c_stopElectionTime = ~0;
+ c_start.reset();
}
/*
@@ -870,38 +813,11 @@ Qmgr::electionWon(){
/* CONTINUEB > SENDER: Own block, Own node */
/****************************>-------+INPUT : TCONTINUEB_TYPE */
/*--------------------------------------------------------------*/
-void Qmgr::regreqTimelimitLab(Signal* signal, UintR callTime)
+void Qmgr::regreqTimeLimitLab(Signal* signal)
{
- if (cwaitContinuebPhase1 == ZFALSE) {
- if (cwaitContinuebPhase2 == ZFALSE) {
- jam();
- return;
- } else {
- jam();
- if (callTime < 10) {
- /*-------------------------------------------------------------*/
- // We experienced a time-out of inclusion. Give it another few
- // seconds before crashing.
- /*-------------------------------------------------------------*/
- signal->theData[0] = ZREGREQ_TIMELIMIT;
- signal->theData[1] = cstartNo;
- signal->theData[2] = callTime + 1;
- sendSignalWithDelay(QMGR_REF, GSN_CONTINUEB, signal, 3000, 3);
- return;
- }//if
- /*-------------------------------------------------------------*/
- /* WE HAVE COME HERE BECAUSE THE INCLUSION SUFFERED FROM */
- /* TIME OUT. WE CRASH AND RESTART. */
- /*-------------------------------------------------------------*/
- systemErrorLab(signal);
- return;
- }//if
- } else {
- jam();
- cwaitContinuebPhase1 = ZFALSE;
- }//if
-
- cmInfoconf010Lab(signal);
+ if(cpresident == ZNIL){
+ cmInfoconf010Lab(signal);
+ }
}//Qmgr::regreqTimelimitLab()
/**---------------------------------------------------------------------------
@@ -917,32 +833,37 @@ void Qmgr::regreqTimelimitLab(Signal* signal, UintR callTime)
/*******************************/
void Qmgr::execCM_NODEINFOCONF(Signal* signal)
{
- NodeRecPtr replyNodePtr;
- NodeRecPtr nodePtr;
+ DEBUG_START3(signal, "");
+
jamEntry();
CmNodeInfoConf * const conf = (CmNodeInfoConf*)signal->getDataPtr();
- replyNodePtr.i = conf->nodeId;
- ptrCheckGuard(replyNodePtr, MAX_NDB_NODES, nodeRec);
- replyNodePtr.p->ndynamicId = conf->dynamicId;
- setNodeInfo(replyNodePtr.i).m_version = conf->version;
- replyNodePtr.p->phase = ZRUNNING;
-
+ const Uint32 nodeId = conf->nodeId;
+ const Uint32 dynamicId = conf->dynamicId;
+ const Uint32 version = conf->version;
+
+ NodeRecPtr nodePtr;
+ nodePtr.i = getOwnNodeId();
+ ptrAss(nodePtr, nodeRec);
+ ndbrequire(nodePtr.p->phase == ZSTARTING);
+ ndbrequire(c_start.m_gsn == GSN_CM_NODEINFOREQ);
+ c_start.m_nodes.clearWaitingFor(nodeId);
+
/**
- * A node in the cluster has replied nodeinfo about himself.
- * He is already running in the cluster.
+ * Update node info
*/
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
+ NodeRecPtr replyNodePtr;
+ replyNodePtr.i = nodeId;
+ ptrCheckGuard(replyNodePtr, MAX_NDB_NODES, nodeRec);
+ replyNodePtr.p->ndynamicId = dynamicId;
+ replyNodePtr.p->blockRef = signal->getSendersBlockRef();
+ setNodeInfo(replyNodePtr.i).m_version = version;
+
+ if(!c_start.m_nodes.done()){
jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZWAITING) {
- if (nodePtr.i != getOwnNodeId()) {
- jam();
- return;
- }//if
- }//if
- }//for
+ return;
+ }
/**********************************************<*/
/* Send an ack. back to the president. */
@@ -953,11 +874,7 @@ void Qmgr::execCM_NODEINFOCONF(Signal* signal)
/* for CM_ADD (commit) from president to become */
/* a running node in the cluster. */
/**********************************************<*/
- CmAckAdd * const cmAckAdd = (CmAckAdd*)signal->getDataPtrSend();
- cmAckAdd->requestType = CmAdd::Prepare;
- cmAckAdd->senderNodeId = getOwnNodeId();
- cmAckAdd->startingNodeId = getOwnNodeId();
- sendSignal(cpdistref, GSN_CM_ACKADD, signal, CmAckAdd::SignalLength, JBA);
+ sendCmAckAdd(signal, getOwnNodeId(), CmAdd::Prepare);
return;
}//Qmgr::execCM_NODEINFOCONF()
@@ -970,59 +887,99 @@ void Qmgr::execCM_NODEINFOCONF(Signal* signal)
/*******************************/
void Qmgr::execCM_NODEINFOREQ(Signal* signal)
{
- NodeRecPtr addNodePtr;
- NodeRecPtr myNodePtr;
jamEntry();
+ const Uint32 Tblockref = signal->getSendersBlockRef();
+
+ NodeRecPtr nodePtr;
+ nodePtr.i = getOwnNodeId();
+ ptrAss(nodePtr, nodeRec);
+ if(nodePtr.p->phase != ZRUNNING){
+ jam();
+ signal->theData[0] = reference();
+ signal->theData[1] = getOwnNodeId();
+ signal->theData[2] = ZNOT_RUNNING;
+ sendSignal(Tblockref, GSN_CM_NODEINFOREF, signal, 3, JBB);
+ return;
+ }
+
+ NodeRecPtr addNodePtr;
CmNodeInfoReq * const req = (CmNodeInfoReq*)signal->getDataPtr();
addNodePtr.i = req->nodeId;
ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
addNodePtr.p->ndynamicId = req->dynamicId;
+ addNodePtr.p->blockRef = signal->getSendersBlockRef();
setNodeInfo(addNodePtr.i).m_version = req->version;
-
- const BlockReference Tblockref = signal->getSendersBlockRef();
+ c_maxDynamicId = req->dynamicId;
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
- if (myNodePtr.p->phase == ZRUNNING) {
- if (addNodePtr.p->phase == ZWAITING) {
- jam();
- /* President have prepared us */
- /****************************<*/
- /*< CM_NODEINFOCONF <*/
- /****************************<*/
- CmNodeInfoConf * const conf = (CmNodeInfoConf*)signal->getDataPtrSend();
- conf->nodeId = getOwnNodeId();
- conf->dynamicId = myNodePtr.p->ndynamicId;
- conf->version = getNodeInfo(getOwnNodeId()).m_version;
- sendSignal(Tblockref, GSN_CM_NODEINFOCONF, signal,
- CmNodeInfoConf::SignalLength, JBB);
- /****************************************/
- /* Send an ack. back to the president */
- /* CM_ACKADD */
- /****************************************/
- CmAckAdd * const cmAckAdd = (CmAckAdd*)signal->getDataPtrSend();
- cmAckAdd->requestType = CmAdd::Prepare;
- cmAckAdd->senderNodeId = getOwnNodeId();
- cmAckAdd->startingNodeId = addNodePtr.i;
- sendSignal(cpdistref, GSN_CM_ACKADD, signal, CmAckAdd::SignalLength, JBA);
- } else {
- jam();
- addNodePtr.p->phase = ZWAIT_PRESIDENT;
- }//if
- } else {
- jam();
- /****************************<*/
- /*< CM_NODEINFOREF <*/
- /****************************<*/
- signal->theData[0] = myNodePtr.p->blockRef;
- signal->theData[1] = myNodePtr.i;
- signal->theData[2] = ZNOT_RUNNING;
- sendSignal(Tblockref, GSN_CM_NODEINFOREF, signal, 3, JBB);
- }//if
- return;
+ cmAddPrepare(signal, addNodePtr, nodePtr.p);
}//Qmgr::execCM_NODEINFOREQ()
+void
+Qmgr::cmAddPrepare(Signal* signal, NodeRecPtr nodePtr, const NodeRec * self){
+ jam();
+
+ switch(nodePtr.p->phase){
+ case ZINIT:
+ jam();
+ nodePtr.p->phase = ZSTARTING;
+ return;
+ case ZFAIL_CLOSING:
+ jam();
+#ifdef VM_TRACE
+ ndbout_c("Enabling communication to CM_ADD node state=%d",
+ nodePtr.p->phase);
+#endif
+ nodePtr.p->phase = ZSTARTING;
+ nodePtr.p->failState = NORMAL;
+ signal->theData[0] = 0;
+ signal->theData[1] = nodePtr.i;
+ sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 2, JBA);
+ return;
+ case ZSTARTING:
+ break;
+ case ZRUNNING:
+ case ZPREPARE_FAIL:
+ case ZAPI_ACTIVE:
+ case ZAPI_INACTIVE:
+ ndbrequire(false);
+ }
+
+ sendCmAckAdd(signal, nodePtr.i, CmAdd::Prepare);
+
+ /* President have prepared us */
+ CmNodeInfoConf * conf = (CmNodeInfoConf*)signal->getDataPtrSend();
+ conf->nodeId = getOwnNodeId();
+ conf->dynamicId = self->ndynamicId;
+ conf->version = getNodeInfo(getOwnNodeId()).m_version;
+ sendSignal(nodePtr.p->blockRef, GSN_CM_NODEINFOCONF, signal,
+ CmNodeInfoConf::SignalLength, JBB);
+ DEBUG_START(GSN_CM_NODEINFOCONF, refToNode(nodePtr.p->blockRef), "");
+}
+
+void
+Qmgr::sendCmAckAdd(Signal * signal, Uint32 nodeId, CmAdd::RequestType type){
+
+ CmAckAdd * cmAckAdd = (CmAckAdd*)signal->getDataPtrSend();
+ cmAckAdd->requestType = type;
+ cmAckAdd->startingNodeId = nodeId;
+ cmAckAdd->senderNodeId = getOwnNodeId();
+ sendSignal(cpdistref, GSN_CM_ACKADD, signal, CmAckAdd::SignalLength, JBA);
+ DEBUG_START(GSN_CM_ACKADD, cpresident, "");
+
+ switch(type){
+ case CmAdd::Prepare:
+ return;
+ case CmAdd::AddCommit:
+ case CmAdd::CommitNew:
+ break;
+ }
+
+ signal->theData[0] = nodeId;
+ EXECUTE_DIRECT(NDBCNTR, GSN_CM_ADD_REP, signal, 1);
+ jamEntry();
+}
+
/*
4.4.11 CM_ADD */
/**--------------------------------------------------------------------------
@@ -1040,156 +997,130 @@ void Qmgr::execCM_NODEINFOREQ(Signal* signal)
void Qmgr::execCM_ADD(Signal* signal)
{
NodeRecPtr addNodePtr;
- NodeRecPtr nodePtr;
- NodeRecPtr myNodePtr;
jamEntry();
+ NodeRecPtr nodePtr;
+ nodePtr.i = getOwnNodeId();
+ ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
+
CmAdd * const cmAdd = (CmAdd*)signal->getDataPtr();
const CmAdd::RequestType type = (CmAdd::RequestType)cmAdd->requestType;
addNodePtr.i = cmAdd->startingNodeId;
//const Uint32 startingVersion = cmAdd->startingVersion;
ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
- if(addNodePtr.p->phase == ZFAIL_CLOSING){
+ DEBUG_START3(signal, type);
+
+ if(nodePtr.p->phase == ZSTARTING){
jam();
-#ifdef VM_TRACE
- ndbout_c("Enabling communication to CM_ADD node state=%d",
- addNodePtr.p->phase);
-#endif
- addNodePtr.p->failState = NORMAL;
- signal->theData[0] = 0;
- signal->theData[1] = addNodePtr.i;
- sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 2, JBA);
+ /**
+ * We are joining...
+ */
+ ndbrequire(addNodePtr.i == nodePtr.i);
+ switch(type){
+ case CmAdd::Prepare:
+ ndbrequire(c_start.m_gsn == GSN_CM_NODEINFOREQ);
+ /**
+ * Wait for CM_NODEINFO_CONF
+ */
+ return;
+ case CmAdd::CommitNew:
+ /**
+ * Tata. we're in the cluster
+ */
+ joinedCluster(signal, addNodePtr);
+ return;
+ case CmAdd::AddCommit:
+ ndbrequire(false);
+ }
}
-
+
switch (type) {
case CmAdd::Prepare:
- jam();
- if (addNodePtr.i != getOwnNodeId()) {
- jam();
- if (addNodePtr.p->phase == ZWAIT_PRESIDENT) {
- jam();
- /****************************<*/
- /*< CM_NODEINFOCONF <*/
- /****************************<*/
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
-
- CmNodeInfoConf * const conf = (CmNodeInfoConf*)signal->getDataPtrSend();
- conf->nodeId = getOwnNodeId();
- conf->dynamicId = myNodePtr.p->ndynamicId;
- conf->version = getNodeInfo(getOwnNodeId()).m_version;
- sendSignal(addNodePtr.p->blockRef, GSN_CM_NODEINFOCONF, signal,
- CmNodeInfoConf::SignalLength, JBB);
- /****************************<*/
- /* Send an ack. back to the president */
- /*< CM_ACKADD <*/
- /****************************<*/
- CmAckAdd * const cmAckAdd = (CmAckAdd*)signal->getDataPtrSend();
- cmAckAdd->requestType = CmAdd::Prepare;
- cmAckAdd->senderNodeId = getOwnNodeId();
- cmAckAdd->startingNodeId = addNodePtr.i;
- sendSignal(cpdistref, GSN_CM_ACKADD, signal, CmAckAdd::SignalLength, JBA);
- }//if
- // -----------------------------------------
- /* Wait for the new node's CM_NODEINFOREQ.*/
- // -----------------------------------------
- addNodePtr.p->phase = ZWAITING;
- }//if
+ cmAddPrepare(signal, addNodePtr, nodePtr.p);
break;
case CmAdd::AddCommit:{
jam();
+ ndbrequire(addNodePtr.p->phase == ZSTARTING);
addNodePtr.p->phase = ZRUNNING;
addNodePtr.p->alarmCount = 0;
+ c_clusterNodes.set(addNodePtr.i);
findNeighbours(signal);
- /**-----------------------------------------------------------------------
+
+ /**
* SEND A HEARTBEAT IMMEDIATELY TO DECREASE THE RISK THAT WE MISS EARLY
* HEARTBEATS.
- *-----------------------------------------------------------------------*/
+ */
sendHeartbeat(signal);
- /*-----------------------------------------------------------------------*/
- /* ENABLE COMMUNICATION WITH ALL BLOCKS WITH THE NEWLY ADDED NODE. */
- /*-----------------------------------------------------------------------*/
+
+ /**
+ * ENABLE COMMUNICATION WITH ALL BLOCKS WITH THE NEWLY ADDED NODE
+ */
signal->theData[0] = addNodePtr.i;
sendSignal(CMVMI_REF, GSN_ENABLE_COMORD, signal, 1, JBA);
- /****************************<*/
- /*< CM_ACKADD <*/
- /****************************<*/
- CmAckAdd * const cmAckAdd = (CmAckAdd*)signal->getDataPtrSend();
- cmAckAdd->requestType = CmAdd::AddCommit;
- cmAckAdd->senderNodeId = getOwnNodeId();
- cmAckAdd->startingNodeId = addNodePtr.i;
- sendSignal(cpdistref, GSN_CM_ACKADD, signal, CmAckAdd::SignalLength, JBA);
+
+ sendCmAckAdd(signal, addNodePtr.i, CmAdd::AddCommit);
+ if(getOwnNodeId() != cpresident){
+ jam();
+ c_start.reset();
+ }
break;
}
- case CmAdd::CommitNew:{
+ case CmAdd::CommitNew:
jam();
- /*-----------------------------------------------------------------------*/
- /* WE HAVE BEEN INCLUDED IN THE CLUSTER WE CAN START BEING PART OF THE
- * HEARTBEAT PROTOCOL AND WE WILL ALSO ENABLE COMMUNICATION WITH ALL
- * NODES IN THE CLUSTER.
- *-----------------------------------------------------------------------*/
- addNodePtr.p->phase = ZRUNNING;
- addNodePtr.p->alarmCount = 0;
- findNeighbours(signal);
- /**-----------------------------------------------------------------------
- * SEND A HEARTBEAT IMMEDIATELY TO DECREASE THE RISK THAT WE MISS EARLY
- * HEARTBEATS.
- *-----------------------------------------------------------------------*/
- sendHeartbeat(signal);
- cwaitContinuebPhase2 = ZFALSE;
- /**-----------------------------------------------------------------------
- * ENABLE COMMUNICATION WITH ALL BLOCKS IN THE CURRENT CLUSTER AND SET
- * THE NODES IN THE CLUSTER TO BE RUNNING.
- *-----------------------------------------------------------------------*/
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if ((nodePtr.p->phase == ZRUNNING) &&
- (nodePtr.i != getOwnNodeId())) {
- /*-------------------------------------------------------------------*/
- // Enable full communication to all other nodes. Not really necessary
- // to open communication to ourself.
- /*-------------------------------------------------------------------*/
- jam();
- signal->theData[0] = nodePtr.i;
- sendSignal(CMVMI_REF, GSN_ENABLE_COMORD, signal, 1, JBA);
- }//if
- }//for
-
- /****************************<*/
- /*< CM_ACKADD <*/
- /****************************<*/
- CmAckAdd * const cmAckAdd = (CmAckAdd*)signal->getDataPtrSend();
- cmAckAdd->requestType = CmAdd::CommitNew;
- cmAckAdd->senderNodeId = getOwnNodeId();
- cmAckAdd->startingNodeId = addNodePtr.i;
- sendSignal(cpdistref, GSN_CM_ACKADD, signal, CmAckAdd::SignalLength, JBA);
-
-#if 1
- /**********************************************<*/
- /* Allow the CLUSTER CONTROL to send STTORRY */
- /* so we can receive CM_REG from applications. */
- /**********************************************<*/
- signal->theData[0] = 0;
- sendSignal(CMVMI_REF, GSN_CM_RUN, signal, 1, JBB);
-#endif
-
- /**
- * Start timer handling
- */
- signal->theData[0] = ZTIMER_HANDLING;
- sendSignal(QMGR_REF, GSN_CONTINUEB, signal, 10, JBB);
+ ndbrequire(false);
}
- break;
- default:
- jam();
- /*empty*/;
- break;
- }//switch
- return;
+
}//Qmgr::execCM_ADD()
+void
+Qmgr::joinedCluster(Signal* signal, NodeRecPtr nodePtr){
+ /**
+ * WE HAVE BEEN INCLUDED IN THE CLUSTER WE CAN START BEING PART OF THE
+ * HEARTBEAT PROTOCOL AND WE WILL ALSO ENABLE COMMUNICATION WITH ALL
+ * NODES IN THE CLUSTER.
+ */
+ nodePtr.p->phase = ZRUNNING;
+ nodePtr.p->alarmCount = 0;
+ findNeighbours(signal);
+ c_clusterNodes.set(nodePtr.i);
+ c_start.reset();
+
+ /**
+ * SEND A HEARTBEAT IMMEDIATELY TO DECREASE THE RISK
+ * THAT WE MISS EARLY HEARTBEATS.
+ */
+ sendHeartbeat(signal);
+
+ /**
+ * ENABLE COMMUNICATION WITH ALL BLOCKS IN THE CURRENT CLUSTER AND SET
+ * THE NODES IN THE CLUSTER TO BE RUNNING.
+ */
+ for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
+ jam();
+ ptrAss(nodePtr, nodeRec);
+ if ((nodePtr.p->phase == ZRUNNING) && (nodePtr.i != getOwnNodeId())) {
+ /*-------------------------------------------------------------------*/
+ // Enable full communication to all other nodes. Not really necessary
+ // to open communication to ourself.
+ /*-------------------------------------------------------------------*/
+ jam();
+ signal->theData[0] = nodePtr.i;
+ sendSignal(CMVMI_REF, GSN_ENABLE_COMORD, signal, 1, JBA);
+ }//if
+ }//for
+
+ sendSttorryLab(signal);
+
+ /**
+ * Start timer handling
+ */
+ signal->theData[0] = ZTIMER_HANDLING;
+ sendSignal(QMGR_REF, GSN_CONTINUEB, signal, 10, JBB);
+
+ sendCmAckAdd(signal, getOwnNodeId(), CmAdd::CommitNew);
+}
+
/* 4.10.7 CM_ACKADD - PRESIDENT IS RECEIVER - */
/*---------------------------------------------------------------------------*/
/* Entry point for an ack add signal.
@@ -1198,7 +1129,6 @@ void Qmgr::execCM_ADD(Signal* signal)
void Qmgr::execCM_ACKADD(Signal* signal)
{
NodeRecPtr addNodePtr;
- NodeRecPtr nodePtr;
NodeRecPtr senderNodePtr;
jamEntry();
@@ -1206,109 +1136,86 @@ void Qmgr::execCM_ACKADD(Signal* signal)
const CmAdd::RequestType type = (CmAdd::RequestType)cmAckAdd->requestType;
addNodePtr.i = cmAckAdd->startingNodeId;
senderNodePtr.i = cmAckAdd->senderNodeId;
+
+ DEBUG_START3(signal, type);
+
if (cpresident != getOwnNodeId()) {
jam();
/*-----------------------------------------------------------------------*/
/* IF WE ARE NOT PRESIDENT THEN WE SHOULD NOT RECEIVE THIS MESSAGE. */
/*------------------------------------------------------------_----------*/
+ warningEvent("Received CM_ACKADD from %d president=%d",
+ senderNodePtr.i, cpresident);
return;
}//if
- if (cpresidentBusy != ZTRUE) {
- jam();
- /**----------------------------------------------------------------------
- * WE ARE PRESIDENT BUT WE ARE NOT BUSY ADDING ANY NODE. THUS WE MUST
- * HAVE STOPPED THIS ADDING OF THIS NODE.
- *----------------------------------------------------------------------*/
- return;
- }//if
- if (addNodePtr.i != cstartNode) {
+
+ if (addNodePtr.i != c_start.m_startNode) {
jam();
/*----------------------------------------------------------------------*/
/* THIS IS NOT THE STARTING NODE. WE ARE ACTIVE NOW WITH ANOTHER START. */
/*----------------------------------------------------------------------*/
+ warningEvent("Received CM_ACKADD from %d with startNode=%d != own %d",
+ senderNodePtr.i, addNodePtr.i, c_start.m_startNode);
return;
}//if
+
+ ndbrequire(c_start.m_gsn == GSN_CM_ADD);
+ c_start.m_nodes.clearWaitingFor(senderNodePtr.i);
+ if(!c_start.m_nodes.done()){
+ jam();
+ return;
+ }
+
switch (type) {
case CmAdd::Prepare:{
jam();
- ptrCheckGuard(senderNodePtr, MAX_NDB_NODES, nodeRec);
- senderNodePtr.p->sendCmAddPrepStatus = Q_NOT_ACTIVE;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- /* Check if all prepare are acknowledged*/
- if (nodePtr.p->sendCmAddPrepStatus == Q_ACTIVE) {
- jam();
- return; /* Wait for more acknowledge's */
- }//if
- }//for
+
/*----------------------------------------------------------------------*/
/* ALL RUNNING NODES HAVE PREPARED THE INCLUSION OF THIS NEW NODE. */
/*----------------------------------------------------------------------*/
+ c_start.m_gsn = GSN_CM_ADD;
+ c_start.m_nodes = c_clusterNodes;
+
CmAdd * const cmAdd = (CmAdd*)signal->getDataPtrSend();
cmAdd->requestType = CmAdd::AddCommit;
cmAdd->startingNodeId = addNodePtr.i;
cmAdd->startingVersion = getNodeInfo(addNodePtr.i).m_version;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- sendSignal(nodePtr.p->blockRef, GSN_CM_ADD, signal,
- CmAdd::SignalLength, JBA);
- nodePtr.p->sendCmAddCommitStatus = Q_ACTIVE;
- }//if
- }//for
+ NodeReceiverGroup rg(QMGR, c_clusterNodes);
+ sendSignal(rg, GSN_CM_ADD, signal, CmAdd::SignalLength, JBA);
+ DEBUG_START2(GSN_CM_ADD, rg, "AddCommit");
return;
- break;
}
case CmAdd::AddCommit:{
jam();
- ptrCheckGuard(senderNodePtr, MAX_NDB_NODES, nodeRec);
- senderNodePtr.p->sendCmAddCommitStatus = Q_NOT_ACTIVE;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- /* Check to see if we need to wait for */
- if (nodePtr.p->sendCmAddCommitStatus == Q_ACTIVE) {
- jam();
- /* any more ack. commit add. */
- return; /* Exit and continue waiting. */
- }//if
- }//for
+
/****************************************/
/* Send commit to the new node so he */
/* will change PHASE into ZRUNNING */
/****************************************/
+ c_start.m_gsn = GSN_CM_ADD;
+ c_start.m_nodes.clearWaitingFor();
+ c_start.m_nodes.setWaitingFor(addNodePtr.i);
+
CmAdd * const cmAdd = (CmAdd*)signal->getDataPtrSend();
cmAdd->requestType = CmAdd::CommitNew;
cmAdd->startingNodeId = addNodePtr.i;
cmAdd->startingVersion = getNodeInfo(addNodePtr.i).m_version;
- ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
- sendSignal(addNodePtr.p->blockRef, GSN_CM_ADD, signal,
+ sendSignal(calcQmgrBlockRef(addNodePtr.i), GSN_CM_ADD, signal,
CmAdd::SignalLength, JBA);
- break;
+ DEBUG_START(GSN_CM_ADD, addNodePtr.i, "CommitNew");
+ return;
}
case CmAdd::CommitNew:
jam();
- /*----------------------------------------------------------------------*/
- /* Increment the amount of nodes in the cluster in waiting mode. */
- /* President now ready for more CM_REGREQ */
- /*----------------------------------------------------------------------*/
- cclustersize = cclustersize + 1;
/**
* Tell arbitration about new node.
*/
handleArbitNdbAdd(signal, addNodePtr.i);
- cpresidentBusy = ZFALSE;
- break;
- default:
- jam();
- /*empty*/;
- break;
+ c_start.reset();
+ return;
}//switch
- return;
+ ndbrequire(false);
}//Qmgr::execCM_ACKADD()
/**-------------------------------------------------------------------------
@@ -1433,51 +1340,30 @@ void Qmgr::findNeighbours(Signal* signal)
/*---------------------------------------------------------------------------*/
void Qmgr::initData(Signal* signal)
{
- RegAppPtr localRegAppptr;
-
- for (localRegAppptr.i = 0;
- localRegAppptr.i < NO_REG_APP; localRegAppptr.i++) {
- ptrAss(localRegAppptr, regApp);
- localRegAppptr.p->version = 0;
- localRegAppptr.p->blockref = 0;
- memset(localRegAppptr.p->name, 0, sizeof(localRegAppptr.p->name));
- localRegAppptr.p->activity = ZREMOVE;
- localRegAppptr.p->noofapps = 0;
- localRegAppptr.p->noofpending = 0;
- localRegAppptr.p->m_runNodes.clear();
- }//for
-
NodeRecPtr nodePtr;
for (nodePtr.i = 1; nodePtr.i < MAX_NODES; nodePtr.i++) {
ptrAss(nodePtr, nodeRec);
nodePtr.p->ndynamicId = 0;
- /* Subr NEXT_DYNAMIC_ID will use this to find */
- /* a unique higher value than any of these */
-
- /* Not in config file */
- nodePtr.p->phase = ZBLOCKED;
+ if(getNodeInfo(nodePtr.i).m_type == NodeInfo::DB){
+ nodePtr.p->phase = ZINIT;
+ c_definedNodes.set(nodePtr.i);
+ } else {
+ nodePtr.p->phase = ZAPI_INACTIVE;
+ }
+
nodePtr.p->alarmCount = 0;
nodePtr.p->sendPrepFailReqStatus = Q_NOT_ACTIVE;
nodePtr.p->sendCommitFailReqStatus = Q_NOT_ACTIVE;
- nodePtr.p->sendCmAddPrepStatus = Q_NOT_ACTIVE;
- nodePtr.p->sendCmAddCommitStatus = Q_NOT_ACTIVE;
nodePtr.p->sendPresToStatus = Q_NOT_ACTIVE;
- nodePtr.p->m_connected = false;
nodePtr.p->failState = NORMAL;
nodePtr.p->rcv[0] = 0;
nodePtr.p->rcv[1] = 0;
}//for
- ccm_infoconfCounter = 0;
cfailureNr = 1;
ccommitFailureNr = 1;
cprepareFailureNr = 1;
cnoFailedNodes = 0;
cnoPrepFailedNodes = 0;
- cwaitContinuebPhase1 = ZFALSE;
- cwaitContinuebPhase2 = ZFALSE;
- cstartNo = 0;
- cpresidentBusy = ZFALSE;
- cacceptRegreq = ZTRUE;
creadyDistCom = ZFALSE;
cpresident = ZNIL;
cpresidentCandidate = ZNIL;
@@ -1496,55 +1382,58 @@ void Qmgr::initData(Signal* signal)
// catch-all for missing initializations
memset(&arbitRec, 0, sizeof(arbitRec));
-}//Qmgr::initData()
-/*
-4.10.7 PREPARE_ADD */
-/**--------------------------------------------------------------------------
- * President sends CM_ADD to prepare all running nodes to add a new node.
- * Even the president node will get a CM_ADD (prepare).
- * The new node will make REQs to all running nodes after it has received the
- * CM_REGCONF. The president will just coordinate the adding of new nodes.
- * The CM_ADD (prepare) is sent to the cluster before the CM_REGCONF signal
- * to the new node.
- *
- * At the same time we will store all running nodes in CNODEMASK,
- * which will be sent to the new node
- * Scan the NODE_REC for all running nodes and create a nodemask where
- * each bit represents a node.
- * --------------------------------------------------------------------------*/
-void Qmgr::prepareAdd(Signal* signal, Uint16 anAddedNode)
-{
- NodeRecPtr nodePtr;
- NdbNodeBitmask::clear(cnodemask);
+ /**
+ * Timeouts
+ */
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
- CmAdd * const cmAdd = (CmAdd*)signal->getDataPtrSend();
- cmAdd->requestType = CmAdd::Prepare;
- cmAdd->startingNodeId = anAddedNode;
- cmAdd->startingVersion = getNodeInfo(anAddedNode).m_version;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- /* We found a node to prepare. */
- NdbNodeBitmask::set(cnodemask, nodePtr.i);
- sendSignal(nodePtr.p->blockRef, GSN_CM_ADD, signal, CmAdd::SignalLength, JBA);
- nodePtr.p->sendCmAddPrepStatus = Q_ACTIVE;
- }//if
- }//for
+ Uint32 hbDBDB = 1500;
+ Uint32 hbDBAPI = 1500;
+ Uint32 arbitTimeout = 1000;
+ c_restartPartialTimeout = 30000;
+ ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &hbDBDB);
+ ndb_mgm_get_int_parameter(p, CFG_DB_API_HEARTBEAT_INTERVAL, &hbDBAPI);
+ ndb_mgm_get_int_parameter(p, CFG_DB_ARBIT_TIMEOUT, &arbitTimeout);
+ ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTIAL_TIMEOUT,
+ &c_restartPartialTimeout);
+ if(c_restartPartialTimeout == 0){
+ c_restartPartialTimeout = ~0;
+ }
+
+ setHbDelay(hbDBDB);
+ setHbApiDelay(hbDBAPI);
+ setArbitTimeout(arbitTimeout);
+
+ arbitRec.state = ARBIT_NULL; // start state for all nodes
+ arbitRec.apiMask[0].clear(); // prepare for ARBIT_CFG
+
+ ArbitSignalData* const sd = (ArbitSignalData*)&signal->theData[0];
+ for (unsigned rank = 1; rank <= 2; rank++) {
+ sd->sender = getOwnNodeId();
+ sd->code = rank;
+ sd->node = 0;
+ sd->ticket.clear();
+ sd->mask.clear();
+ ndb_mgm_configuration_iterator * iter =
+ theConfiguration.getClusterConfigIterator();
+ for (ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)) {
+ Uint32 tmp = 0;
+ if (ndb_mgm_get_int_parameter(iter, CFG_NODE_ARBIT_RANK, &tmp) == 0 &&
+ tmp == rank){
+ Uint32 nodeId = 0;
+ ndbrequire(!ndb_mgm_get_int_parameter(iter, CFG_NODE_ID, &nodeId));
+ sd->mask.set(nodeId);
+ }
+ }
+
+ execARBIT_CFG(signal);
+ }
+ setNodeInfo(getOwnNodeId()).m_version = NDB_VERSION;
+}//Qmgr::initData()
- NodeRecPtr addNodePtr;
- addNodePtr.i = anAddedNode;
- ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
- /*****************************<
- * We send to the node to be added a CM_ADD as well.
- * We want him to send an ack when he has
- * received all CM_NODEINFOCONF.
- */
- sendSignal(addNodePtr.p->blockRef, GSN_CM_ADD, signal, CmAdd::SignalLength, JBA);
- addNodePtr.p->sendCmAddPrepStatus = Q_ACTIVE;
-}//Qmgr::prepareAdd()
/**---------------------------------------------------------------------------
* HERE WE RECEIVE THE JOB TABLE SIGNAL EVERY 10 MILLISECONDS.
@@ -1695,22 +1584,23 @@ void Qmgr::apiHbHandlingLab(Signal* signal)
NodeRecPtr TnodePtr;
for (TnodePtr.i = 1; TnodePtr.i < MAX_NODES; TnodePtr.i++) {
+ const Uint32 nodeId = TnodePtr.i;
ptrAss(TnodePtr, nodeRec);
- const NodeInfo::NodeType type = getNodeInfo(TnodePtr.i).getType();
+ const NodeInfo::NodeType type = getNodeInfo(nodeId).getType();
if(type == NodeInfo::DB)
continue;
if(type == NodeInfo::INVALID)
continue;
- if (TnodePtr.p->m_connected && TnodePtr.p->phase != ZAPI_INACTIVE){
+ if (TnodePtr.p->phase == ZAPI_ACTIVE){
jam();
TnodePtr.p->alarmCount ++;
-
+
if(TnodePtr.p->alarmCount > 2){
signal->theData[0] = EventReport::MissedHeartbeat;
- signal->theData[1] = TnodePtr.i;
+ signal->theData[1] = nodeId;
signal->theData[2] = TnodePtr.p->alarmCount - 1;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
}
@@ -1725,10 +1615,10 @@ void Qmgr::apiHbHandlingLab(Signal* signal)
/* We call node_failed to release all connections for this api node */
/*------------------------------------------------------------------*/
signal->theData[0] = EventReport::DeadDueToHeartbeat;
- signal->theData[1] = TnodePtr.i;
+ signal->theData[1] = nodeId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
- node_failed(signal, TnodePtr.i);
+ node_failed(signal, nodeId);
}//if
}//if
}//for
@@ -1748,7 +1638,7 @@ void Qmgr::checkStartInterface(Signal* signal)
if (nodePtr.p->phase == ZFAIL_CLOSING) {
jam();
nodePtr.p->alarmCount = nodePtr.p->alarmCount + 1;
- if (nodePtr.p->m_connected) {
+ if (c_connectedNodes.get(nodePtr.i)){
jam();
/*-------------------------------------------------------------------*/
// We need to ensure that the connection is not restored until it has
@@ -1766,11 +1656,12 @@ void Qmgr::checkStartInterface(Signal* signal)
nodePtr.p->failState = NORMAL;
if (getNodeInfo(nodePtr.i).m_type != NodeInfo::DB){
jam();
- nodePtr.p->phase = ZBLOCKED;
+ nodePtr.p->phase = ZAPI_INACTIVE;
} else {
jam();
nodePtr.p->phase = ZINIT;
}//if
+
nodePtr.p->alarmCount = 0;
signal->theData[0] = 0;
signal->theData[1] = nodePtr.i;
@@ -1908,13 +1799,13 @@ void Qmgr::execNDB_FAILCONF(Signal* signal)
for (nodePtr.i = 1; nodePtr.i < MAX_NODES; nodePtr.i++) {
jam();
ptrAss(nodePtr, nodeRec);
- if ((nodePtr.p->phase == ZAPI_ACTIVE) && nodePtr.p->m_connected) {
+ if (nodePtr.p->phase == ZAPI_ACTIVE){
jam();
sendSignal(nodePtr.p->blockRef, GSN_NF_COMPLETEREP, signal,
NFCompleteRep::SignalLength, JBA);
}//if
}//for
- }//if
+ }
return;
}//Qmgr::execNDB_FAILCONF()
@@ -1923,14 +1814,28 @@ void Qmgr::execNDB_FAILCONF(Signal* signal)
/*******************************/
void Qmgr::execDISCONNECT_REP(Signal* signal)
{
+ jamEntry();
const DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
- NodeRecPtr failedNodePtr;
+ const Uint32 nodeId = rep->nodeId;
+ c_connectedNodes.clear(nodeId);
- jamEntry();
- failedNodePtr.i = rep->nodeId;
- ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
- failedNodePtr.p->m_connected = false;
- node_failed(signal, failedNodePtr.i);
+ NodeRecPtr nodePtr;
+ nodePtr.i = getOwnNodeId();
+ ptrCheckGuard(nodePtr, MAX_NODES, nodeRec);
+ switch(nodePtr.p->phase){
+ case ZRUNNING:
+ jam();
+ break;
+ case ZINIT:
+ case ZSTARTING:
+ case ZPREPARE_FAIL:
+ case ZFAIL_CLOSING:
+ case ZAPI_ACTIVE:
+ case ZAPI_INACTIVE:
+ ndbrequire(false);
+ }
+
+ node_failed(signal, nodeId);
}//DISCONNECT_REP
void Qmgr::node_failed(Signal* signal, Uint16 aFailedNode)
@@ -1957,6 +1862,9 @@ void Qmgr::node_failed(Signal* signal, Uint16 aFailedNode)
case ZFAIL_CLOSING:
jam();
return;
+ case ZSTARTING:
+ c_start.reset();
+ // Fall-through
default:
jam();
/*---------------------------------------------------------------------*/
@@ -1987,11 +1895,11 @@ void Qmgr::node_failed(Signal* signal, Uint16 aFailedNode)
jam();
if (failedNodePtr.p->phase != ZFAIL_CLOSING){
jam();
- //--------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
// The API was active and has now failed. We need to initiate API failure
// handling. If the API had already failed then we can ignore this
// discovery.
- //--------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
failedNodePtr.p->phase = ZFAIL_CLOSING;
sendApiFailReq(signal, aFailedNode);
@@ -2056,11 +1964,6 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
apiRegConf->qmgrRef = reference();
apiRegConf->apiHeartbeatFrequency = (chbApiDelay / 10);
apiRegConf->version = NDB_VERSION;
-
-
- // if(apiNodePtr.i == getNodeState.single. && NodeState::SL_MAINTENANCE)
- // apiRegConf->nodeState = NodeState::SL_STARTED;
- //else
apiRegConf->nodeState = getNodeState();
{
NodeRecPtr nodePtr;
@@ -2079,7 +1982,7 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
if ((getNodeState().startLevel == NodeState::SL_STARTED ||
getNodeState().getSingleUserMode())
- && apiNodePtr.p->phase == ZBLOCKED) {
+ && apiNodePtr.p->phase == ZAPI_INACTIVE) {
jam();
/**----------------------------------------------------------------------
* THE API NODE IS REGISTERING. WE WILL ACCEPT IT BY CHANGING STATE AND
@@ -2186,15 +2089,6 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode,
failReport(signal, failedNodePtr.i, (UintR)ZTRUE, aFailCause);
if (cpresident == getOwnNodeId()) {
jam();
- if (cpresidentBusy == ZTRUE) {
- jam();
-/**-------------------------------------------------------------------
-* ALL STARTING NODES ARE CRASHED WHEN AN ALIVE NODE FAILS DURING ITS
-* START-UP. AS PRESIDENT OF THE CLUSTER IT IS OUR DUTY TO INFORM OTHERS
-* ABOUT THIS.
-*---------------------------------------------------------------------*/
- failReport(signal, cstartNode, (UintR)ZTRUE, FailRep::ZOTHER_NODE_WHEN_WE_START);
- }//if
if (ctoStatus == Q_NOT_ACTIVE) {
jam();
/**--------------------------------------------------------------------
@@ -2525,9 +2419,7 @@ void Qmgr::execCOMMIT_FAILREQ(Signal* signal)
return;
}//if
UintR guard0;
- UintR Ti;
UintR Tj;
- RegAppPtr localRegAppptr;
/**
* Block commit until node failures has stabilized
@@ -2547,37 +2439,19 @@ void Qmgr::execCOMMIT_FAILREQ(Signal* signal)
* SIGNAL. WE CAN HEAR IT SEVERAL TIMES IF THE PRESIDENTS KEEP FAILING.
*-----------------------------------------------------------------------*/
ccommitFailureNr = TfailureNr;
- for (localRegAppptr.i = 0;
- localRegAppptr.i < NO_REG_APP; localRegAppptr.i++) {
+ NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
+
+ nodeFail->failNo = ccommitFailureNr;
+ nodeFail->noOfNodes = cnoCommitFailedNodes;
+ nodeFail->masterNodeId = cpresident;
+ NodeBitmask::clear(nodeFail->theNodes);
+ for(unsigned i = 0; i < cnoCommitFailedNodes; i++) {
jam();
- ptrAss(localRegAppptr, regApp);
- if (localRegAppptr.p->activity != ZREMOVE) {
- /*------------------------------------------------------------------*/
- // We need to remove the failed nodes from the set of running nodes
- // in the registered application.
- //------------------------------------------------------------------*/
- for (Ti = 0; Ti < cnoCommitFailedNodes; Ti++) {
- jam();
- arrGuard(ccommitFailedNodes[Ti], MAX_NDB_NODES);
- localRegAppptr.p->m_runNodes.clear(ccommitFailedNodes[Ti]);
- }//for
- /*------------------------------------------------------------------*/
- // Send a signal to the registered application to inform him of the
- // node failure(s).
- /*------------------------------------------------------------------*/
- NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
+ NodeBitmask::set(nodeFail->theNodes, ccommitFailedNodes[i]);
+ }//if
+ sendSignal(NDBCNTR_REF, GSN_NODE_FAILREP, signal,
+ NodeFailRep::SignalLength, JBB);
- nodeFail->failNo = ccommitFailureNr;
- nodeFail->noOfNodes = cnoCommitFailedNodes;
- NodeBitmask::clear(nodeFail->theNodes);
- for(unsigned i = 0; i < cnoCommitFailedNodes; i++) {
- jam();
- NodeBitmask::set(nodeFail->theNodes, ccommitFailedNodes[i]);
- }//if
- sendSignal(localRegAppptr.p->blockref, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
- }//if
- }//for
guard0 = cnoCommitFailedNodes - 1;
arrGuard(guard0, MAX_NDB_NODES);
/**--------------------------------------------------------------------
@@ -2591,6 +2465,7 @@ void Qmgr::execCOMMIT_FAILREQ(Signal* signal)
nodePtr.p->phase = ZFAIL_CLOSING;
nodePtr.p->failState = WAITING_FOR_NDB_FAILCONF;
nodePtr.p->alarmCount = 0;
+ c_clusterNodes.clear(nodePtr.i);
}//for
/*----------------------------------------------------------------------*/
/* WE INFORM THE API'S WE HAVE CONNECTED ABOUT THE FAILED NODES. */
@@ -2753,226 +2628,31 @@ void Qmgr::execPRES_TOCONF(Signal* signal)
/*--------------------------------------------------------------------------*/
void Qmgr::execREAD_NODESREQ(Signal* signal)
{
- NodeRecPtr nodePtr;
- UintR TnoOfNodes = 0;
+ jamEntry();
+
BlockReference TBref = signal->theData[0];
ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
- NodeBitmask::clear(readNodes->allNodes);
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (getNodeInfo(nodePtr.i).getType() == NodeInfo::DB){
- jam();
- TnoOfNodes++;
- NodeBitmask::set(readNodes->allNodes, nodePtr.i);
- }//if
- }//for
- readNodes->noOfNodes = TnoOfNodes;
- sendSignal(TBref, GSN_READ_NODESCONF, signal,
- ReadNodesConf::SignalLength, JBB);
-}//Qmgr::execREAD_NODESREQ()
-/*--------------------------------------------------------------------------
- * Signal from an application requesting to be monitored in the cluster.
- * APPL_REGREQ can be entered at any time during the life of the QMGR.
- * It can be entered any number of times.
- * If QMGR is ZRUNNING a CM_APPCHG will be sent to all active nodes.
- *---------------------------------------------------------------------------*/
-void Qmgr::execAPPL_REGREQ(Signal* signal)
-{
NodeRecPtr nodePtr;
- NodeRecPtr myNodePtr;
- RegAppPtr lRegApptr;
- char Tappname[16];
- jamEntry();
- BlockReference Tappref = signal->theData[0];
- Tappname[0] = signal->theData[1] >> 8;
- Tappname[1] = signal->theData[2];
- Tappname[2] = signal->theData[2] >> 8;
- Tappname[3] = signal->theData[3];
- Tappname[4] = signal->theData[3] >> 8;
- Tappname[5] = signal->theData[4];
- Tappname[6] = signal->theData[4] >> 8;
- Tappname[7] = signal->theData[5];
- Tappname[8] = signal->theData[5] >> 8;
- Tappname[9] = signal->theData[6];
- Tappname[10] = signal->theData[6] >> 8;
- Tappname[11] = signal->theData[7];
- Tappname[12] = signal->theData[7] >> 8;
- Tappname[13] = signal->theData[8];
- Tappname[14] = signal->theData[8] >> 8;
- Tappname[signal->theData[1] & 0xFF] = 0;
- UintR Tversion = signal->theData[10];
- Uint16 Tnodeno = refToNode(Tappref);
- if (Tnodeno == 0) {
- jam();
- /* Fix for all not distributed applications. */
- Tnodeno = getOwnNodeId();
- }//if
- if (getOwnNodeId() == Tnodeno) {
- jam();
- /* Local application */
- UintR Tfound = RNIL;
- for (lRegApptr.i = NO_REG_APP-1; (Uint16)~lRegApptr.i; lRegApptr.i--) {
- jam();
- ptrAss(lRegApptr, regApp);
- if (lRegApptr.p->activity == ZREMOVE) {
- Tfound = lRegApptr.i;
- break;
- }//if
- }//for
- if (Tfound != RNIL) {
- jam();
- /* If there was a slot available we */
- /* register the application */
- lRegApptr.i = Tfound;
- ptrCheckGuard(lRegApptr, NO_REG_APP, regApp);
- lRegApptr.p->blockref = Tappref;
- strcpy(lRegApptr.p->name, Tappname);
- lRegApptr.p->version = Tversion;
- lRegApptr.p->activity = ZADD;
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
- /****************************<*/
- /*< APPL_REGCONF <*/
- /****************************<*/
- signal->theData[0] = lRegApptr.i;
- signal->theData[1] = cnoOfNodes;
- signal->theData[2] = cpresident;
- signal->theData[3] = myNodePtr.p->ndynamicId;
- sendSignal(lRegApptr.p->blockref, GSN_APPL_REGCONF, signal, 4, JBB);
- if (myNodePtr.p->phase == ZRUNNING) {
- jam();
- /* Check to see if any further action */
- for (nodePtr.i = 1;
- nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- /* is needed at this time */
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- sendappchg(signal, lRegApptr.i, nodePtr.i);
- }//if
- }//for
- }//if
- } else {
- jam();
- /****************************<*/
- /*< APPL_REGREF <*/
- /****************************<*/
- signal->theData[0] = ZERRTOOMANY;
- sendSignal(Tappref, GSN_APPL_REGREF, signal, 1, JBB);
- }//if
- } else {
- jam();
- /* TOO MANY REGISTERED APPLICATIONS */
- systemErrorLab(signal);
- }//if
- return;
-}//Qmgr::execAPPL_REGREQ()
-
-/*
-4.4.11 APPL_STARTREG */
-/**--------------------------------------------------------------------------
- * Signal from an application indicating that it is ready to start running
- * distributed. If the application is running alone or if all other
- * applications of the same kind already have registered as STARTING then
- * APPL_STARTCONF will be sent to the application as soon as phase four of
- * STTOR is reached.
- *--------------------------------------------------------------------------*/
-/*******************************/
-/* APPL_STARTREG */
-/*******************************/
-void Qmgr::execAPPL_STARTREG(Signal* signal)
-{
- RegAppPtr lRegApptr;
- NodeRecPtr myNodePtr;
- UintR TnodeId;
- jamEntry();
- lRegApptr.i = signal->theData[0];
- ptrCheckGuard(lRegApptr, NO_REG_APP, regApp);
- UintR Tcounter = signal->theData[1];
+ nodePtr.i = getOwnNodeId();
+ ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- lRegApptr.p->activity = ZSTART;
- /* Application is ready to start. */
+ NdbNodeBitmask tmp = c_definedNodes;
+ tmp.bitANDC(c_clusterNodes);
- /* Calculate how many apps we wait for */
- lRegApptr.p->noofapps = (Tcounter - 1) - lRegApptr.p->noofpending;
- /* send info to all other running nodes in the */
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
- /* cluster indicating the status change of the */
- if (myNodePtr.p->phase == ZRUNNING) {
- /* application. */
- for (TnodeId = 1; TnodeId < MAX_NDB_NODES; TnodeId++) {
- jam();
- if (lRegApptr.p->m_runNodes.get(TnodeId)){
- jam();
- sendappchg(signal, lRegApptr.i, TnodeId);
- }//if
- }//for
- }//if
- /****************************<*/
- /*< APPL_STARTCONF <*/
- /****************************<*/
- if (lRegApptr.p->noofapps == 0) {
- jam();
- sendSignal(lRegApptr.p->blockref, GSN_APPL_STARTCONF, signal, 1, JBB);
- }//if
- return;
-}//Qmgr::execAPPL_STARTREG()
-
-/*
- 4.4.11 APPL_RUN */
-/*--------------------------------------------------------------------------*/
-/* Signal from an application announcing that it is running. */
-/*--------------------------------------------------------------------------*/
-/*******************************/
-/* APPL_RUN */
-/*******************************/
-void Qmgr::execAPPL_RUN(Signal* signal)
-{
- RegAppPtr lRegApptr;
- NodeRecPtr myNodePtr;
- UintR TnodeId;
- jamEntry();
- lRegApptr.i = signal->theData[0];
- ptrCheckGuard(lRegApptr, NO_REG_APP, regApp);
- lRegApptr.p->activity = ZRUN;
- /* Flag the application as running. */
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
- if (myNodePtr.p->phase == ZRUNNING) {
- /* If we are running send the appl. status */
- for (TnodeId = 1; TnodeId < MAX_NDB_NODES; TnodeId++) {
- jam();
- /* change to all other running nodes. */
- if (lRegApptr.p->m_runNodes.get(TnodeId)){
- jam();
- sendappchg(signal, lRegApptr.i, TnodeId);
- }//if
- }//for
- }//if
- /****************************<*/
- /*< CM_RUN <*/
- /****************************<*/
- /*---------------------------------------------------*/
- /* Inform the CLUSTER CONTROL of NDB started */
- /* so we can connect to API nodes. */
- /*---------------------------------------------------*/
- signal->theData[0] = 1;
- sendSignal(CMVMI_REF, GSN_CM_RUN, signal, 1, JBB);
- cactivateApiCheck = 1;
- /**
- * Start arbitration thread. This could be done as soon as
- * we have all nodes (or a winning majority).
- */
- if (cpresident == getOwnNodeId())
- handleArbitStart(signal);
- return;
-}//Qmgr::execAPPL_RUN()
+ readNodes->noOfNodes = c_definedNodes.count();
+ readNodes->masterNodeId = cpresident;
+ readNodes->ndynamicId = nodePtr.p->ndynamicId;
+ c_definedNodes.copyto(NdbNodeBitmask::Size, readNodes->definedNodes);
+ c_clusterNodes.copyto(NdbNodeBitmask::Size, readNodes->clusterNodes);
+ tmp.copyto(NdbNodeBitmask::Size, readNodes->inactiveNodes);
+ NdbNodeBitmask::clear(readNodes->startingNodes);
+ NdbNodeBitmask::clear(readNodes->startedNodes);
+ sendSignal(TBref, GSN_READ_NODESCONF, signal,
+ ReadNodesConf::SignalLength, JBB);
+}//Qmgr::execREAD_NODESREQ()
void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal,
NodeId failedNodeId) {
@@ -3003,234 +2683,6 @@ void Qmgr::systemErrorLab(Signal* signal, const char * message)
return;
}//Qmgr::systemErrorLab()
-/*
-4.4.11 CM_APPCHG */
-/*---------------------------------------------------------------------------*/
-/*Signal between two QMGRs used to announce any changes of state for an appl.*/
-/*---------------------------------------------------------------------------*/
-/*******************************/
-/* CM_APPCHG */
-/*******************************/
-void Qmgr::execCM_APPCHG(Signal* signal)
-{
- RegAppPtr lRegApptr;
- char Tappname[16];
- jamEntry();
- UintR Ttype = signal->theData[0];
- Uint16 Tnodeno = signal->theData[1];
- Tappname[0] = signal->theData[2] >> 8;
- Tappname[1] = signal->theData[3];
- Tappname[2] = signal->theData[3] >> 8;
- Tappname[3] = signal->theData[4];
- Tappname[4] = signal->theData[4] >> 8;
- Tappname[5] = signal->theData[5];
- Tappname[6] = signal->theData[5] >> 8;
- Tappname[7] = signal->theData[6];
- Tappname[8] = signal->theData[6] >> 8;
- Tappname[9] = signal->theData[7];
- Tappname[10] = signal->theData[7] >> 8;
- Tappname[11] = signal->theData[8];
- Tappname[12] = signal->theData[8] >> 8;
- Tappname[13] = signal->theData[9];
- Tappname[14] = signal->theData[9] >> 8;
- Tappname[signal->theData[2] & 0xFF] = 0;
- UintR Tversion = signal->theData[11];
- switch (Ttype) {
- case ZADD:
- jam();
- /* A new application has started on the sending node */
- for (lRegApptr.i = NO_REG_APP-1; (Uint16)~lRegApptr.i; lRegApptr.i--) {
- jam();
- /* We are hosting this application */
- ptrAss(lRegApptr, regApp);
- if (strcmp(lRegApptr.p->name, Tappname) == 0) {
- cmappAdd(signal, lRegApptr.i, Tnodeno, Ttype, Tversion);
- }//if
- }//for
- break;
-
- case ZSTART:
- jam();
- /* A registered application is ready to start on the sending node */
- for (lRegApptr.i = NO_REG_APP-1; (Uint16)~lRegApptr.i; lRegApptr.i--) {
- jam();
- ptrAss(lRegApptr, regApp);
- if (strcmp(lRegApptr.p->name, Tappname) == 0) {
- cmappStart(signal, lRegApptr.i, Tnodeno, Ttype, Tversion);
- }//if
- }//for
- break;
-
- case ZRUN:
- /* A registered application on the sending node has started to run */
- jam();
- for (lRegApptr.i = NO_REG_APP-1; (Uint16)~lRegApptr.i; lRegApptr.i--) {
- jam();
- ptrAss(lRegApptr, regApp);
- if (strcmp(lRegApptr.p->name, Tappname) == 0) {
- arrGuard(Tnodeno, MAX_NDB_NODES);
- lRegApptr.p->m_runNodes.set(Tnodeno);
- applchangerep(signal, lRegApptr.i, Tnodeno, Ttype, Tversion);
- }//if
- }//for
- cacceptRegreq = ZTRUE; /* We can now start accepting new CM_REGREQ */
- /* since the new node is running */
- break;
-
- case ZREMOVE:
- /* A registered application has been deleted on the sending node */
- jam();
- for (lRegApptr.i = NO_REG_APP-1; (Uint16)~lRegApptr.i; lRegApptr.i--) {
- jam();
- ptrAss(lRegApptr, regApp);
- if (strcmp(lRegApptr.p->name, Tappname) == 0) {
- applchangerep(signal, lRegApptr.i, Tnodeno, Ttype, Tversion);
- }//if
- }//for
- break;
-
- default:
- jam();
- /*empty*/;
- break;
- }//switch
- return;
-}//Qmgr::execCM_APPCHG()
-
-/**--------------------------------------------------------------------------
- * INPUT REG_APPPTR
- * TNODENO
- *--------------------------------------------------------------------------*/
-void Qmgr::applchangerep(Signal* signal,
- UintR aRegApp,
- Uint16 aNode,
- UintR aType,
- UintR aVersion)
-{
- RegAppPtr lRegApptr;
- NodeRecPtr localNodePtr;
- lRegApptr.i = aRegApp;
- ptrCheckGuard(lRegApptr, NO_REG_APP, regApp);
- if (lRegApptr.p->blockref != 0) {
- jam();
- localNodePtr.i = aNode;
- ptrCheckGuard(localNodePtr, MAX_NDB_NODES, nodeRec);
- /****************************************/
- /* Send a report of changes on another */
- /* node to the local application */
- /****************************************/
- signal->theData[0] = aType;
- signal->theData[1] = aVersion;
- signal->theData[2] = localNodePtr.i;
- signal->theData[4] = localNodePtr.p->ndynamicId;
- sendSignal(lRegApptr.p->blockref, GSN_APPL_CHANGEREP, signal, 5, JBB);
- }//if
-}//Qmgr::applchangerep()
-
-/*
- 4.10.7 CMAPP_ADD */
-/**--------------------------------------------------------------------------
- * We only map applications of the same version. We have the same application
- * and version locally.
- * INPUT REG_APPPTR
- * TNODENO Sending node
- * TVERSION Version of application
- * OUTPUT REG_APPPTR, TNODENO ( not changed)
- *---------------------------------------------------------------------------*/
-void Qmgr::cmappAdd(Signal* signal,
- UintR aRegApp,
- Uint16 aNode,
- UintR aType,
- UintR aVersion)
-{
- RegAppPtr lRegApptr;
- lRegApptr.i = aRegApp;
- ptrCheckGuard(lRegApptr, NO_REG_APP, regApp);
- if (lRegApptr.p->version == aVersion) {
- jam();
- arrGuard(aNode, MAX_NDB_NODES);
- if (lRegApptr.p->m_runNodes.get(aNode) == false){
- jam();
- /* Check if we already have added it. */
- /*-------------------------------------------------------*/
- /* Since we only add remote applications, if we also are */
- /* hosting them we need to send a reply indicating that */
- /* we also are hosting the application. */
- /*-------------------------------------------------------*/
- sendappchg(signal, lRegApptr.i, aNode);
- lRegApptr.p->m_runNodes.set(aNode);
- /*---------------------------------------*/
- /* Add the remote node to the the local */
- /* nodes memberlist. */
- /* Inform the local application of the */
- /* new application running remotely. */
- /*---------------------------------------*/
- applchangerep(signal, lRegApptr.i, aNode, aType, aVersion);
- }//if
- }//if
-}//Qmgr::cmappAdd()
-
-/*
-4.10.7 CMAPP_START */
-/**--------------------------------------------------------------------------
- * Inform the local application of the change in node state on the remote node
- * INPUT REG_APPPTR
- * OUTPUT -
- *---------------------------------------------------------------------------*/
-void Qmgr::cmappStart(Signal* signal,
- UintR aRegApp,
- Uint16 aNode,
- UintR aType,
- UintR aVersion)
-{
- RegAppPtr lRegApptr;
- lRegApptr.i = aRegApp;
- ptrCheckGuard(lRegApptr, NO_REG_APP, regApp);
- if (lRegApptr.p->version == aVersion) {
- applchangerep(signal, lRegApptr.i, aNode, aType, aVersion);
- if (lRegApptr.p->activity == ZSTART) {
- jam();
- //----------------------------------------
- /* If the local application is already */
- /* in START face then we do some checks.*/
- //----------------------------------------
- if (lRegApptr.p->noofapps > 0) {
- jam();
- //----------------------------------------
- /* Check if we need to decrement the no */
- /* of apps. */
- /* This indicates how many startsignals */
- /* from apps remaining before we can */
- /* send a APPL_STARTCONF. */
- //----------------------------------------
- lRegApptr.p->noofapps--;
- }//if
- if (lRegApptr.p->noofapps == 0) {
- jam();
- //----------------------------------------
- /* All applications have registered as */
- /* ready to start. */
- //----------------------------------------
- /****************************<*/
- /*< APPL_STARTCONF <*/
- /****************************<*/
- sendSignal(lRegApptr.p->blockref, GSN_APPL_STARTCONF, signal, 1, JBB);
- }//if
- } else {
- jam();
- /**--------------------------------------------------------------------
- * Add the ready node to the nodes pending counter.
- * This counter is used to see how many remote nodes that are waiting
- * for this node to enter the start face.
- * It is used when the appl. sends a APPL_STARTREG signal.
- *---------------------------------------------------------------------*/
- if (lRegApptr.p->activity == ZADD) {
- jam();
- lRegApptr.p->noofpending++;
- }//if
- }//if
- }//if
-}//Qmgr::cmappStart()
/**---------------------------------------------------------------------------
* A FAILURE HAVE BEEN DISCOVERED ON A NODE. WE NEED TO CLEAR A
@@ -3249,17 +2701,6 @@ void Qmgr::failReport(Signal* signal,
failedNodePtr.i = aFailedNode;
ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRec);
- if (((cpresidentBusy == ZTRUE) ||
- (cacceptRegreq == ZFALSE)) &&
- (cstartNode == aFailedNode)) {
- jam();
-/*----------------------------------------------------------------------*/
-// A node crashed keeping the president busy and that ensures that there
-// is no acceptance of regreq's which is not acceptable after its crash.
-/*----------------------------------------------------------------------*/
- cpresidentBusy = ZFALSE;
- cacceptRegreq = ZTRUE;
- }//if
if (failedNodePtr.p->phase == ZRUNNING) {
jam();
/* WE ALSO NEED TO ADD HERE SOME CODE THAT GETS OUR NEW NEIGHBOURS. */
@@ -3278,8 +2719,6 @@ void Qmgr::failReport(Signal* signal,
}//if
}//if
failedNodePtr.p->phase = ZPREPARE_FAIL;
- failedNodePtr.p->sendCmAddPrepStatus = Q_NOT_ACTIVE;
- failedNodePtr.p->sendCmAddCommitStatus = Q_NOT_ACTIVE;
failedNodePtr.p->sendPrepFailReqStatus = Q_NOT_ACTIVE;
failedNodePtr.p->sendCommitFailReqStatus = Q_NOT_ACTIVE;
failedNodePtr.p->sendPresToStatus = Q_NOT_ACTIVE;
@@ -3412,74 +2851,6 @@ Uint16 Qmgr::translateDynamicIdToNodeId(Signal* signal, UintR TdynamicId)
return TtdiNodeId;
}//Qmgr::translateDynamicIdToNodeId()
-
-/*
-4.10.7 GET_DYNAMIC_ID */
-/**--------------------------------------------------------------------------
- * FIND THE CLOSEST HIGHER DYNAMIC ID AMONG THE RUNNING NODES. ADD ONE TO
- * THAT VALUE AND WE HAVE CREATED A NEW, UNIQUE AND HIGHER DYNAMIC VALUE THAN
- * ANYONE ELSE IN THE CLUSTER.THIS WAY WE DON'T HAVE TO KEEP TRACK OF VARIABLE
- * THAT HOLDS THE LAST USED DYNAMIC ID, ESPECIALLY WE DON'T NEED TO INFORM
- * ANY VICE PRESIDENTS ABOUT THAT DYNAMIC VARIABLE.
- * INPUT -
- * RET CDYNAMIC_ID USED AS A TEMPORARY VARIABLE TO PASS THE VALUE TO THE
- * CALLER OF THIS SUBROUTINE
- *---------------------------------------------------------------------------*/
-UintR Qmgr::getDynamicId(Signal* signal)
-{
- NodeRecPtr nodePtr;
- UintR TdynamicId = 0;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- if (nodePtr.p->ndynamicId > TdynamicId) {
- jam();
- TdynamicId = nodePtr.p->ndynamicId;
- }//if
- }//if
- }//for
- TdynamicId++;
- return TdynamicId;
-}//Qmgr::getDynamicId()
-
-/*
-4.10.7 SENDAPPCHG */
-/*---------------------------------------------------------------------------*/
-/* We only send changes to external nodes. */
-/* INPUT: TNODENO */
-/* REG_APPPTR */
-/*---------------------------------------------------------------------------*/
-void Qmgr::sendappchg(Signal* signal, UintR aRegApp, Uint16 aNode)
-{
- NodeRecPtr localNodePtr;
- RegAppPtr lRegApptr;
- if (aNode != getOwnNodeId()) {
- jam();
- localNodePtr.i = aNode;
- ptrCheckGuard(localNodePtr, MAX_NDB_NODES, nodeRec);
- lRegApptr.i = aRegApp;
- ptrCheckGuard(lRegApptr, NO_REG_APP, regApp);
- /****************************************/
- /* Signal any application changes to */
- /* the receiving node */
- /****************************************/
- signal->theData[0] = lRegApptr.p->activity;
- signal->theData[1] = getOwnNodeId();
- signal->theData[2] = strlen(lRegApptr.p->name)|(lRegApptr.p->name[0] << 8);
- signal->theData[3] = lRegApptr.p->name[1] | (lRegApptr.p->name[2] << 8);
- signal->theData[4] = lRegApptr.p->name[3] | (lRegApptr.p->name[4] << 8);
- signal->theData[5] = lRegApptr.p->name[5] | (lRegApptr.p->name[6] << 8);
- signal->theData[6] = lRegApptr.p->name[7] | (lRegApptr.p->name[8] << 8);
- signal->theData[7] = lRegApptr.p->name[9] | (lRegApptr.p->name[10] << 8);
- signal->theData[8] = lRegApptr.p->name[11] | (lRegApptr.p->name[12] << 8);
- signal->theData[9] = lRegApptr.p->name[13] | (lRegApptr.p->name[14] << 8);
- signal->theData[10] = 0;
- signal->theData[11] = lRegApptr.p->version;
- sendSignal(localNodePtr.p->blockRef, GSN_CM_APPCHG, signal, 12, JBA);
- }//if
-}//Qmgr::sendappchg()
-
/**--------------------------------------------------------------------------
* WHEN RECEIVING PREPARE FAILURE REQUEST WE WILL IMMEDIATELY CLOSE
* COMMUNICATION WITH ALL THOSE NODES.
@@ -4450,14 +3821,10 @@ Qmgr::execDUMP_STATE_ORD(Signal* signal)
{
switch (signal->theData[0]) {
case 1:
- infoEvent("creadyDistCom = %d, cpresident = %d, cpresidentBusy = %d\n",
- creadyDistCom, cpresident, cpresidentBusy);
- infoEvent("cacceptRegreq = %d, ccm_infoconfCounter = %d\n",
- cacceptRegreq, ccm_infoconfCounter);
- infoEvent("cstartNo = %d, cstartNode = %d, cwaitC..phase1 = %d\n",
- cstartNo, cstartNode, cwaitContinuebPhase1);
- infoEvent("cwaitC..phase2 = %d, cpresidentAlive = %d, cpresidentCand = %d\n"
- ,cwaitContinuebPhase2, cpresidentAlive, cpresidentCandidate);
+ infoEvent("creadyDistCom = %d, cpresident = %d\n",
+ creadyDistCom, cpresident);
+ infoEvent("cpresidentAlive = %d, cpresidentCand = %d\n",
+ cpresidentAlive, cpresidentCandidate);
infoEvent("ctoStatus = %d\n", ctoStatus);
for(Uint32 i = 1; i<MAX_NDB_NODES; i++){
if(getNodeInfo(i).getType() == NodeInfo::DB){
@@ -4469,18 +3836,15 @@ Qmgr::execDUMP_STATE_ORD(Signal* signal)
case ZINIT:
sprintf(buf, "Node %d: ZINIT(%d)", i, nodePtr.p->phase);
break;
- case ZBLOCKED:
- sprintf(buf, "Node %d: ZBLOCKED(%d)", i, nodePtr.p->phase);
- break;
- case ZWAITING:
- sprintf(buf, "Node %d: ZWAITING(%d)", i, nodePtr.p->phase);
- break;
- case ZWAIT_PRESIDENT:
- sprintf(buf, "Node %d: ZWAIT_PRESIDENT(%d)", i, nodePtr.p->phase);
+ case ZSTARTING:
+ sprintf(buf, "Node %d: ZSTARTING(%d)", i, nodePtr.p->phase);
break;
case ZRUNNING:
sprintf(buf, "Node %d: ZRUNNING(%d)", i, nodePtr.p->phase);
break;
+ case ZPREPARE_FAIL:
+ sprintf(buf, "Node %d: ZPREPARE_FAIL(%d)", i, nodePtr.p->phase);
+ break;
case ZFAIL_CLOSING:
sprintf(buf, "Node %d: ZFAIL_CLOSING(%d)", i, nodePtr.p->phase);
break;
@@ -4490,9 +3854,6 @@ Qmgr::execDUMP_STATE_ORD(Signal* signal)
case ZAPI_ACTIVE:
sprintf(buf, "Node %d: ZAPI_ACTIVE(%d)", i, nodePtr.p->phase);
break;
- case ZPREPARE_FAIL:
- sprintf(buf, "Node %d: ZPREPARE_FAIL(%d)", i, nodePtr.p->phase);
- break;
default:
sprintf(buf, "Node %d: <UNKNOWN>(%d)", i, nodePtr.p->phase);
break;
@@ -4507,6 +3868,7 @@ Qmgr::execDUMP_STATE_ORD(Signal* signal)
void Qmgr::execSET_VAR_REQ(Signal* signal)
{
+#if 0
SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0];
ConfigParamId var = setVarReq->variable();
UintR val = setVarReq->value();
@@ -4530,4 +3892,5 @@ void Qmgr::execSET_VAR_REQ(Signal* signal)
default:
sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB);
}// switch
+#endif
}//execSET_VAR_REQ()
diff --git a/ndb/src/kernel/blocks/suma/Makefile.am b/ndb/src/kernel/blocks/suma/Makefile.am
new file mode 100644
index 00000000000..4dacb22af51
--- /dev/null
+++ b/ndb/src/kernel/blocks/suma/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libsuma.a
+
+libsuma_a_SOURCES = Suma.cpp SumaInit.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/suma/Makefile b/ndb/src/kernel/blocks/suma/Makefile_old
index 20014c94670..20014c94670 100644
--- a/ndb/src/kernel/blocks/suma/Makefile
+++ b/ndb/src/kernel/blocks/suma/Makefile_old
diff --git a/ndb/src/kernel/blocks/trix/Makefile.am b/ndb/src/kernel/blocks/trix/Makefile.am
new file mode 100644
index 00000000000..803da815cf0
--- /dev/null
+++ b/ndb/src/kernel/blocks/trix/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libtrix.a
+
+libtrix_a_SOURCES = Trix.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/blocks/trix/Makefile b/ndb/src/kernel/blocks/trix/Makefile_old
index 5ac0da11f33..5ac0da11f33 100644
--- a/ndb/src/kernel/blocks/trix/Makefile
+++ b/ndb/src/kernel/blocks/trix/Makefile_old
diff --git a/ndb/src/kernel/blocks/trix/Trix.hpp b/ndb/src/kernel/blocks/trix/Trix.hpp
index 05563559b77..f096e135094 100644
--- a/ndb/src/kernel/blocks/trix/Trix.hpp
+++ b/ndb/src/kernel/blocks/trix/Trix.hpp
@@ -39,6 +39,15 @@ public:
Trix(const class Configuration & conf);
virtual ~Trix();
+public:
+ // Subscription data, when communicating with SUMA
+
+ enum RequestType {
+ TABLE_REORG = 0,
+ INDEX_BUILD = 1
+ };
+ typedef DataBuffer<11> AttrOrderBuffer;
+
private:
// Private attributes
@@ -87,14 +96,6 @@ private:
Uint16 c_noNodesFailed;
Uint16 c_noActiveNodes;
- // Subscription data, when communicating with SUMA
- enum RequestType {
- TABLE_REORG = 0,
- INDEX_BUILD = 1
- };
-
- typedef DataBuffer<11> AttrOrderBuffer;
-
AttrOrderBuffer::DataBufferPool c_theAttrOrderBufferPool;
struct SubscriptionRecord {
diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp
index 56627cba46f..20a9dd8a993 100644
--- a/ndb/src/kernel/error/ErrorReporter.cpp
+++ b/ndb/src/kernel/error/ErrorReporter.cpp
@@ -40,8 +40,8 @@ const char* errorType[] = {
static int WriteMessage(ErrorCategory thrdType, int thrdMessageID,
const char* thrdProblemData,
const char* thrdObjRef,
- Uint32 thrdTheEmulatedJamIndex = 0,
- Uint8 thrdTheEmulatedJam[] = 0);
+ Uint32 thrdTheEmulatedJamIndex,
+ Uint8 thrdTheEmulatedJam[]);
static void dumpJam(FILE* jamStream,
Uint32 thrdTheEmulatedJamIndex,
@@ -157,21 +157,18 @@ ErrorReporter::handleAssert(const char* message, const char* file, int line)
{
char refMessage[100];
-#ifdef USE_EMULATED_JAM
+#ifdef NO_EMULATED_JAM
+ snprintf(refMessage, 100, "file: %s lineNo: %d",
+ file, line);
+#else
const Uint32 blockNumber = theEmulatedJamBlockNumber;
const char *blockName = getBlockName(blockNumber);
snprintf(refMessage, 100, "%s line: %d (block: %s)",
file, line, blockName);
-
+#endif
WriteMessage(assert, ERR_ERROR_PRGERR, message, refMessage,
theEmulatedJamIndex, theEmulatedJam);
-#else
- snprintf(refMessage, 100, "file: %s lineNo: %d",
- file, line);
-
- WriteMessage(assert, ERR_ERROR_PRGERR, message, refMessage);
-#endif
NdbShutdown(NST_ErrorHandler);
}
@@ -199,12 +196,8 @@ ErrorReporter::handleError(ErrorCategory type, int messageID,
// The value for type is not always set correctly in the calling function.
// So, to correct this, we set it set it to the value corresponding to
// the function that is called.
-#ifdef USE_EMULATED_JAM
WriteMessage(type, messageID, problemData,
objRef, theEmulatedJamIndex, theEmulatedJam);
-#else
- WriteMessage(type, messageID, problemData, objRef);
-#endif
if(messageID == ERR_ERROR_INSERT){
NdbShutdown(NST_ErrorInsert);
} else {
@@ -212,9 +205,6 @@ ErrorReporter::handleError(ErrorCategory type, int messageID,
}
}
-// This is the function to write the error-message,
-// when the USE_EMULATED_JAM-flag is set
-// during compilation.
int
WriteMessage(ErrorCategory thrdType, int thrdMessageID,
const char* thrdProblemData, const char* thrdObjRef,
@@ -302,9 +292,7 @@ WriteMessage(ErrorCategory thrdType, int thrdMessageID,
// ...and "dump the jam" there.
// ErrorReporter::dumpJam(jamStream);
if(thrdTheEmulatedJam != 0){
-#ifdef USE_EMULATED_JAM
dumpJam(jamStream, thrdTheEmulatedJamIndex, thrdTheEmulatedJam);
-#endif
}
/* Dont print the jobBuffers until a way to copy them,
@@ -325,7 +313,7 @@ void
dumpJam(FILE *jamStream,
Uint32 thrdTheEmulatedJamIndex,
Uint8 thrdTheEmulatedJam[]) {
-#ifdef USE_EMULATED_JAM
+#ifndef NO_EMULATED_JAM
// print header
const int maxaddr = 8;
fprintf(jamStream, "JAM CONTENTS up->down left->right ?=not block entry\n");
@@ -392,5 +380,5 @@ dumpJam(FILE *jamStream,
}
fprintf(jamStream, "\n");
fflush(jamStream);
-#endif // USE_EMULATED_JAM
+#endif // ifndef NO_EMULATED_JAM
}
diff --git a/ndb/src/kernel/error/ErrorReporter.hpp b/ndb/src/kernel/error/ErrorReporter.hpp
index 20340a9602f..b43b30f1873 100644
--- a/ndb/src/kernel/error/ErrorReporter.hpp
+++ b/ndb/src/kernel/error/ErrorReporter.hpp
@@ -37,21 +37,13 @@
ErrorReporter::handleThreadAssert(message, __FILE__, __LINE__); }
#ifdef NDEBUG
-
#define NDB_ASSERT(trueToContinue, message)
-#define THREAD_ASSERT(trueToContinue, message)
-
#else
-
#define NDB_ASSERT(trueToContinue, message) \
if ( !(trueToContinue) ) { \
ErrorReporter::handleAssert(message, __FILE__, __LINE__); }
-
-#define THREAD_ASSERT(trueToContinue, message) \
- if ( !(trueToContinue) ) { \
- ErrorReporter::handleThreadAssert(message, __FILE__, __LINE__); }
-
#endif
+
// Description:
// This macro is used to report programming errors.
// Parameters:
diff --git a/ndb/src/kernel/error/Makefile.am b/ndb/src/kernel/error/Makefile.am
new file mode 100644
index 00000000000..4514d2d105c
--- /dev/null
+++ b/ndb/src/kernel/error/Makefile.am
@@ -0,0 +1,11 @@
+noinst_LIBRARIES = liberror.a
+
+liberror_a_SOURCES = TimeModule.cpp \
+ ErrorReporter.cpp \
+ ErrorMessages.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/error/Makefile b/ndb/src/kernel/error/Makefile_old
index 0fe81f083ce..0fe81f083ce 100644
--- a/ndb/src/kernel/error/Makefile
+++ b/ndb/src/kernel/error/Makefile_old
diff --git a/ndb/src/kernel/ndb-main/Main.cpp b/ndb/src/kernel/ndb-main/Main.cpp
deleted file mode 100644
index 46eb41b0ec6..00000000000
--- a/ndb/src/kernel/ndb-main/Main.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <ndb_global.h>
-
-#include <ndb_version.h>
-#include "Configuration.hpp"
-#include <TransporterRegistry.hpp>
-
-#include "SimBlockList.hpp"
-#include "ThreadConfig.hpp"
-#include <SignalLoggerManager.hpp>
-#include <NdbOut.hpp>
-#include <NdbMain.h>
-#include <NdbDaemon.h>
-#include <NdbConfig.h>
-#include <WatchDog.hpp>
-
-#include <LogLevel.hpp>
-#include <EventLogger.hpp>
-#include <NodeState.hpp>
-
-#if defined NDB_SOLARIS
-#include <sys/processor.h> // For system informatio
-#endif
-
-#if !defined NDB_SOFTOSE && !defined NDB_OSE
-#include <signal.h> // For process signals
-#endif
-
-extern EventLogger g_eventLogger;
-
-void catchsigs(bool ignore); // for process signal handling
-extern "C" void handler(int signo); // for process signal handling
-
-// Shows system information
-void systemInfo(const Configuration & conf,
- const LogLevel & ll);
-
-const char programName[] = "NDB Kernel";
-
-extern int global_ndb_check;
-NDB_MAIN(ndb_kernel){
-
- global_ndb_check = 1;
-
- // Print to stdout/console
- g_eventLogger.createConsoleHandler();
- g_eventLogger.setCategory("NDB");
- g_eventLogger.enable(Logger::LL_INFO, Logger::LL_ALERT); // Log INFO to ALERT
-
- globalEmulatorData.create();
-
- // Parse command line options
- Configuration* theConfig = globalEmulatorData.theConfiguration;
- if(!theConfig->init(argc, argv)){
- return 0;
- }
-
- { // Do configuration
- theConfig->setupConfiguration();
- }
-
- // Get NDB_HOME path
- char homePath[255];
- NdbConfig_HomePath(homePath, 255);
-
- if (theConfig->getDaemonMode()) {
- // Become a daemon
- char lockfile[255], logfile[255];
- snprintf(lockfile, 255, "%snode%d.pid", homePath, globalData.ownId);
- snprintf(logfile, 255, "%snode%d.out", homePath, globalData.ownId);
- if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
- ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
- return 1;
- }
- }
-
- for(pid_t child = fork(); child != 0; child = fork()){
- /**
- * Parent
- */
- catchsigs(true);
- int status = 0;
- while(waitpid(child, &status, 0) != child);
- if(WIFEXITED(status) || !theConfig->stopOnError()){
- switch(WEXITSTATUS(status)){
- case NRT_Default:
- g_eventLogger.info("Angel shutting down");
- exit(0);
- break;
- case NRT_NoStart_Restart:
- theConfig->setInitialStart(false);
- globalData.theRestartFlag = initial_state;
- break;
- case NRT_NoStart_InitialStart:
- theConfig->setInitialStart(true);
- globalData.theRestartFlag = initial_state;
- break;
- case NRT_DoStart_InitialStart:
- theConfig->setInitialStart(true);
- globalData.theRestartFlag = perform_start;
- break;
- default:
- case NRT_DoStart_Restart:
- theConfig->setInitialStart(false);
- globalData.theRestartFlag = perform_start;
- break;
- }
- g_eventLogger.info("Ndb has terminated (pid %d) restarting", child);
- } else {
- /**
- * Error shutdown && stopOnError()
- */
- exit(0);
- }
- }
-
- g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid());
-
- systemInfo(* theConfig,
- theConfig->clusterConfigurationData().SizeAltData.logLevel);
-
- // Load blocks
- globalEmulatorData.theSimBlockList->load(* theConfig);
-
- // Set thread concurrency for Solaris' light weight processes
- int status;
- status = NdbThread_SetConcurrencyLevel(30);
- NDB_ASSERT(status == 0, "Can't set appropriate concurrency level.");
-
-#ifdef VM_TRACE
- // Create a signal logger
- char buf[255];
- strcpy(buf, homePath);
- FILE * signalLog = fopen(strncat(buf,"Signal.log", 255), "a");
- globalSignalLoggers.setOutputStream(signalLog);
-#endif
-
- catchsigs(false);
-
- /**
- * Do startup
- */
- switch(globalData.theRestartFlag){
- case initial_state:
- globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
- break;
- case perform_start:
- globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
- globalEmulatorData.theThreadConfig->doStart(NodeState::SL_STARTING);
- break;
- default:
- NDB_ASSERT(0, "Illegal state globalData.theRestartFlag");
- }
-
- globalTransporterRegistry.startSending();
- globalTransporterRegistry.startReceiving();
- globalEmulatorData.theWatchDog->doStart();
-
- globalEmulatorData.theThreadConfig->ipControlLoop();
-
- NdbShutdown(NST_Normal);
- return NRT_Default;
-}
-
-
-void
-systemInfo(const Configuration & config, const LogLevel & logLevel){
-#ifdef NDB_WIN32
- int processors = 0;
- int speed;
- SYSTEM_INFO sinfo;
- GetSystemInfo(&sinfo);
- processors = sinfo.dwNumberOfProcessors;
- HKEY hKey;
- if(ERROR_SUCCESS==RegOpenKeyEx
- (HKEY_LOCAL_MACHINE,
- TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
- 0, KEY_READ, &hKey)) {
- DWORD dwMHz;
- DWORD cbData = sizeof(dwMHz);
- if(ERROR_SUCCESS==RegQueryValueEx(hKey,
- "~MHz", 0, 0, (LPBYTE)&dwMHz, &cbData)) {
- speed = int(dwMHz);
- }
- RegCloseKey(hKey);
- }
-#elif defined NDB_SOLARIS
- // Search for at max 16 processors among the first 256 processor ids
- processor_info_t pinfo; memset(&pinfo, 0, sizeof(pinfo));
- int pid = 0;
- while(processors < 16 && pid < 256){
- if(!processor_info(pid++, &pinfo))
- processors++;
- }
- speed = pinfo.pi_clock;
-#endif
-
- if(logLevel.getLogLevel(LogLevel::llStartUp) > 0){
- g_eventLogger.info("NDB Cluster -- DB node %d", globalData.ownId);
- g_eventLogger.info("%s --", NDB_VERSION_STRING);
-#ifdef NDB_SOLARIS
- g_eventLogger.info("NDB is running on a machine with %d processor(s) at %d MHz",
- processor, speed);
-#endif
- }
- if(logLevel.getLogLevel(LogLevel::llStartUp) > 3){
- Uint32 t = config.timeBetweenWatchDogCheck();
- g_eventLogger.info("WatchDog timer is set to %d ms", t);
- }
-
-}
-
-void
-catchsigs(bool ignore){
-#if ! defined NDB_SOFTOSE && !defined NDB_OSE
-
-#if defined SIGRTMIN
- #define MAX_SIG_CATCH SIGRTMIN
-#elif defined NSIG
- #define MAX_SIG_CATCH NSIG
-#else
- #error "neither SIGRTMIN or NSIG is defined on this platform, please report bug at bugs.mysql.com"
-#endif
-
- // Makes the main process catch process signals, eg installs a
- // handler named "handler". "handler" will then be called is instead
- // of the defualt process signal handler)
- if(ignore){
- for(int i = 1; i < MAX_SIG_CATCH; i++){
- if(i != SIGCHLD)
- signal(i, SIG_IGN);
- }
- } else {
- for(int i = 1; i < MAX_SIG_CATCH; i++){
- signal(i, handler);
- }
- }
-#endif
-}
-
-extern "C"
-void
-handler(int sig){
- switch(sig){
- case SIGHUP: /* 1 - Hang up */
- case SIGINT: /* 2 - Interrupt */
- case SIGQUIT: /* 3 - Quit */
- case SIGTERM: /* 15 - Terminate */
-#ifdef SIGPWR
- case SIGPWR: /* 19 - Power fail */
-#endif
-#ifdef SIGPOLL
- case SIGPOLL: /* 22 */
-#endif
- case SIGSTOP: /* 23 */
- case SIGTSTP: /* 24 */
- case SIGTTIN: /* 26 */
- case SIGTTOU: /* 27 */
- globalData.theRestartFlag = perform_stop;
- break;
-#ifdef SIGWINCH
- case SIGWINCH:
-#endif
- case SIGPIPE:
- /**
- * Can happen in TCP Transporter
- *
- * Just ignore
- */
- break;
- default:
- // restart the system
- char errorData[40];
- snprintf(errorData, 40, "Signal %d received", sig);
- ERROR_SET(fatal, 0, errorData, __FILE__);
- break;
- }
-}
-
-
-
-
-
-
-
-
diff --git a/ndb/src/kernel/ndb-main/Makefile b/ndb/src/kernel/ndb-main/Makefile
deleted file mode 100644
index 29b7ea7e708..00000000000
--- a/ndb/src/kernel/ndb-main/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-BIN_TARGET := ndb
-BIN_TARGET_ARCHIVES := mgmapi \
- cmvmi dbacc dbdict dbdih dblqh dbtc \
- dbtup ndbfs ndbcntr qmgr trix backup dbutil suma grep dbtux \
- transporter \
- kernel \
- error \
- trace \
- signaldataprint \
- mgmsrvcommon \
- portlib \
- logger \
- general
-
-# Source files of non-templated classes (.cpp files)
-SOURCES = \
- Main.cpp \
- SimBlockList.cpp
-
-CCFLAGS_LOC = -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/cmvmi) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/dbacc) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/dbdict) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/dbdih) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/dblqh) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/dbtc) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/dbtup) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/ndbfs) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/missra) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/ndbcntr) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/qmgr) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/trix) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/backup) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/dbutil) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/suma) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/grep) \
- -I$(call fixpath,$(NDB_TOP)/src/kernel/blocks/dbtux)
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/ndb-main/SimBlockList.cpp b/ndb/src/kernel/ndb-main/SimBlockList.cpp
deleted file mode 100644
index 9e1d28a7fce..00000000000
--- a/ndb/src/kernel/ndb-main/SimBlockList.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "SimBlockList.hpp"
-#include <SimulatedBlock.hpp>
-#include <Cmvmi.hpp>
-#include <Ndbfs.hpp>
-#include <Dbacc.hpp>
-#include <Dbdict.hpp>
-#include <Dbdih.hpp>
-#include <Dblqh.hpp>
-#include <Dbtc.hpp>
-#include <Dbtup.hpp>
-#include <Ndbcntr.hpp>
-#include <Qmgr.hpp>
-#include <Trix.hpp>
-#include <Backup.hpp>
-#include <DbUtil.hpp>
-#include <Suma.hpp>
-#include <Grep.hpp>
-#include <Dbtux.hpp>
-
-enum SIMBLOCKLIST_DUMMY { A_VALUE = 0 };
-
-static
-void * operator new (size_t sz, SIMBLOCKLIST_DUMMY dummy){
- char * tmp = (char *)malloc(sz);
-
-#ifndef NDB_PURIFY
-#ifdef VM_TRACE
- const int initValue = 0xf3;
-#else
- const int initValue = 0x0;
-#endif
-
- const int p = (sz / 4096);
- const int r = (sz % 4096);
-
- for(int i = 0; i<p; i++)
- memset(tmp+(i*4096), initValue, 4096);
-
- if(r > 0)
- memset(tmp+p*4096, initValue, r);
-
-#endif
-
- return tmp;
-}
-
-void
-SimBlockList::load(const Configuration & conf){
- noOfBlocks = 16;
- theList = new SimulatedBlock * [noOfBlocks];
- for(int i = 0; i<noOfBlocks; i++)
- theList[i] = 0;
- Dbdict* dbdict = 0;
- Dbdih* dbdih = 0;
-
- theList[0] = new (A_VALUE) Dbacc(conf);
- theList[1] = new (A_VALUE) Cmvmi(conf);
- theList[2] = new (A_VALUE) Ndbfs(conf);
- theList[3] = dbdict = new (A_VALUE) Dbdict(conf);
- theList[4] = dbdih = new (A_VALUE) Dbdih(conf);
- theList[5] = new (A_VALUE) Dblqh(conf);
- theList[6] = new (A_VALUE) Dbtc(conf);
- theList[7] = new (A_VALUE) Dbtup(conf);
- theList[8] = new (A_VALUE) Ndbcntr(conf);
- theList[9] = new (A_VALUE) Qmgr(conf);
- theList[10] = new (A_VALUE) Trix(conf);
- theList[11] = new (A_VALUE) Backup(conf);
- theList[12] = new (A_VALUE) DbUtil(conf);
- theList[13] = new (A_VALUE) Suma(conf);
- theList[14] = new (A_VALUE) Grep(conf);
- theList[15] = new (A_VALUE) Dbtux(conf);
-
- // Metadata common part shared by block instances
- ptrMetaDataCommon = new MetaData::Common(*dbdict, *dbdih);
- for (int i = 0; i < noOfBlocks; i++)
- theList[i]->setMetaDataCommon(ptrMetaDataCommon);
-}
-
-void
-SimBlockList::unload(){
- if(theList != 0){
- for(int i = 0; i<noOfBlocks; i++){
- if(theList[i] != 0){
- theList[i]->~SimulatedBlock();
- free(theList[i]);
- theList[i] = 0;
- }
- }
- delete [] theList;
- delete ptrMetaDataCommon;
- theList = 0;
- noOfBlocks = 0;
- ptrMetaDataCommon = 0;
- }
-}
diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp
index 706d75509f2..c97ad951cf3 100644
--- a/ndb/src/kernel/vm/Configuration.cpp
+++ b/ndb/src/kernel/vm/Configuration.cpp
@@ -27,6 +27,15 @@
#include <getarg.h>
+#include <mgmapi_configuration.hpp>
+#include <mgmapi_config_parameters_debug.h>
+#include <kernel_config_parameters.h>
+
+#include <kernel_types.h>
+#include <ndb_limits.h>
+#include "pc.hpp"
+#include <LogLevel.hpp>
+
extern "C" {
void ndbSetOwnVersion();
}
@@ -122,10 +131,8 @@ Configuration::init(int argc, const char** argv){
return true;
}
-Configuration::Configuration():
- the_clusterConfigurationData()
+Configuration::Configuration()
{
- m_ownProperties = 0;
_programName = 0;
_connectString = 0;
_fsPath = 0;
@@ -134,8 +141,6 @@ Configuration::Configuration():
}
Configuration::~Configuration(){
- delete m_ownProperties;
-
if(_programName != NULL)
free(_programName);
@@ -143,12 +148,6 @@ Configuration::~Configuration(){
free(_fsPath);
}
-const
-ClusterConfiguration&
-Configuration::clusterConfiguration() const {
- return the_clusterConfigurationData;
-}
-
void
Configuration::setupConfiguration(){
/**
@@ -157,7 +156,7 @@ Configuration::setupConfiguration(){
ConfigRetriever cr;
cr.setConnectString(_connectString);
stopOnError(true);
- Properties * p = cr.getConfig("DB", NDB_VERSION);
+ ndb_mgm_configuration * p = cr.getConfig(NDB_VERSION, NODE_TYPE_DB);
if(p == 0){
const char * s = cr.getErrorString();
if(s == 0)
@@ -171,56 +170,46 @@ Configuration::setupConfiguration(){
"/invalid configuration", s);
}
+ Uint32 nodeId = globalData.ownId = cr.getOwnNodeId();
+
/**
* Configure transporters
*/
{
- IPCConfig * theIPC = new IPCConfig(p);
-
- if(theIPC->init() != 0){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched", "");
- }
-
- if(theIPC->configureTransporters(&globalTransporterRegistry) <= 0){
+ int res = IPCConfig::configureTransporters(nodeId,
+ * p,
+ globalTransporterRegistry);
+ if(res <= 0){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"No transporters configured");
}
-
- globalData.ownId = theIPC->ownId();
- delete theIPC;
}
/**
* Setup cluster configuration data
*/
- const Properties * db = 0;
- if (!p->get("Node", globalData.ownId, &db)) {
+ ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE);
+ if (iter.find(CFG_NODE_ID, globalData.ownId)){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched", "DB missing");
}
- const char * type;
- if(!(db->get("Type", &type) && strcmp(type, "DB") == 0)){
+
+ unsigned type;
+ if(!(iter.get(CFG_TYPE_OF_SECTION, &type) == 0 && type == NODE_TYPE_DB)){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"I'm wrong type of node");
}
- /**
- * Save properties object to use in getOwnProperties()
- */
- m_ownProperties = new Properties(* db);
-
- the_clusterConfigurationData.init(* p, * db);
-
- if(!db->get("MaxNoOfSavedMessages", &_maxErrorLogs)){
+ if(iter.get(CFG_DB_NO_SAVE_MSGS, &_maxErrorLogs)){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"MaxNoOfSavedMessages missing");
}
- if(!db->get("LockPagesInMainMemory", &_lockPagesInMainMemory)){
+ if(iter.get(CFG_DB_MEMLOCK, &_lockPagesInMainMemory)){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"LockPagesInMainMemory missing");
}
- if(!db->get("TimeBetweenWatchDogCheck", &_timeBetweenWatchDogCheck)){
+ if(iter.get(CFG_DB_WATCHDOG_INTERVAL, &_timeBetweenWatchDogCheck)){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"TimeBetweenWatchDogCheck missing");
}
@@ -230,16 +219,16 @@ Configuration::setupConfiguration(){
*/
{
const char* pFileSystemPath = NULL;
- if(!db->get("FileSystemPath", &pFileSystemPath)){
+ if(iter.get(CFG_DB_FILESYSTEM_PATH, &pFileSystemPath)){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"FileSystemPath missing");
}
-
+
if(pFileSystemPath == 0 || strlen(pFileSystemPath) == 0){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"Configuration does not contain valid filesystem path");
}
-
+
if(pFileSystemPath[strlen(pFileSystemPath) - 1] == '/')
_fsPath = strdup(pFileSystemPath);
else {
@@ -248,19 +237,17 @@ Configuration::setupConfiguration(){
strcat(_fsPath, "/");
}
}
-
- if(!db->get("StopOnError", &_stopOnError)){
+
+ if(iter.get(CFG_DB_STOP_ON_ERROR, &_stopOnError)){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"StopOnError missing");
}
-
- if(!db->get("RestartOnErrorInsert", &m_restartOnErrorInsert)){
+
+ if(iter.get(CFG_DB_STOP_ON_ERROR_INSERT, &m_restartOnErrorInsert)){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"RestartOnErrorInsert missing");
}
- delete p;
-
/**
* Create the watch dog thread
*/
@@ -269,7 +256,14 @@ Configuration::setupConfiguration(){
t = globalEmulatorData.theWatchDog ->setCheckInterval(t);
_timeBetweenWatchDogCheck = t;
}
+
+ ConfigValues* cf = ConfigValuesFactory::extractCurrentSection(iter.m_config);
+
+ m_clusterConfig = p;
+ m_clusterConfigIter = ndb_mgm_create_configuration_iterator
+ (p, CFG_SECTION_NODE);
+ calcSizeAlt(cf);
}
bool
@@ -282,12 +276,6 @@ Configuration::timeBetweenWatchDogCheck() const {
return _timeBetweenWatchDogCheck;
}
-const
-ClusterConfiguration::ClusterData&
-Configuration::clusterConfigurationData() const {
- return the_clusterConfigurationData.clusterData();
-}
-
void
Configuration::timeBetweenWatchDogCheck(int value) {
_timeBetweenWatchDogCheck = value;
@@ -313,11 +301,6 @@ Configuration::stopOnError(bool val){
_stopOnError = val;
}
-const Properties *
-Configuration::getOwnProperties() const {
- return m_ownProperties;
-}
-
int
Configuration::getRestartOnErrorInsert() const {
return m_restartOnErrorInsert;
@@ -335,6 +318,350 @@ Configuration::getConnectStringCopy() const {
return 0;
}
+const ndb_mgm_configuration_iterator *
+Configuration::getOwnConfigIterator() const {
+ return m_ownConfigIterator;
+}
+
+ndb_mgm_configuration_iterator *
+Configuration::getClusterConfigIterator() const {
+ return m_clusterConfigIter;
+}
+
+void
+Configuration::calcSizeAlt(ConfigValues * ownConfig){
+ const char * msg = "Invalid configuration fetched";
+ char buf[255];
+
+ unsigned int noOfTables = 0;
+ unsigned int noOfIndexes = 0;
+ unsigned int noOfReplicas = 0;
+ unsigned int noOfDBNodes = 0;
+ unsigned int noOfAPINodes = 0;
+ unsigned int noOfMGMNodes = 0;
+ unsigned int noOfNodes = 0;
+ unsigned int noOfAttributes = 0;
+ unsigned int noOfOperations = 0;
+ unsigned int noOfTransactions = 0;
+ unsigned int noOfIndexPages = 0;
+ unsigned int noOfDataPages = 0;
+ unsigned int noOfScanRecords = 0;
+ m_logLevel = new LogLevel();
+
+ /**
+ * {"NoOfConcurrentCheckpointsDuringRestart", &cd.ispValues[1][5] },
+ * {"NoOfConcurrentCheckpointsAfterRestart", &cd.ispValues[2][4] },
+ * {"NoOfConcurrentProcessesHandleTakeover", &cd.ispValues[1][7] },
+ * {"TimeToWaitAlive", &cd.ispValues[0][0] },
+ */
+ struct AttribStorage { int paramId; Uint32 * storage; };
+ AttribStorage tmp[] = {
+ { CFG_DB_NO_SCANS, &noOfScanRecords },
+ { CFG_DB_NO_TABLES, &noOfTables },
+ { CFG_DB_NO_INDEXES, &noOfIndexes },
+ { CFG_DB_NO_REPLICAS, &noOfReplicas },
+ { CFG_DB_NO_ATTRIBUTES, &noOfAttributes },
+ { CFG_DB_NO_OPS, &noOfOperations },
+ { CFG_DB_NO_TRANSACTIONS, &noOfTransactions }
+#if 0
+ { "NoOfDiskPagesToDiskDuringRestartTUP", &cd.ispValues[3][8] },
+ { "NoOfDiskPagesToDiskAfterRestartTUP", &cd.ispValues[3][9] },
+ { "NoOfDiskPagesToDiskDuringRestartACC", &cd.ispValues[3][10] },
+ { "NoOfDiskPagesToDiskAfterRestartACC", &cd.ispValues[3][11] },
+#endif
+ };
+
+ ndb_mgm_configuration_iterator db(*(ndb_mgm_configuration*)ownConfig, 0);
+
+ const int sz = sizeof(tmp)/sizeof(AttribStorage);
+ for(int i = 0; i<sz; i++){
+ if(ndb_mgm_get_int_parameter(&db, tmp[i].paramId, tmp[i].storage)){
+ snprintf(buf, sizeof(buf), "ConfigParam: %d not found", tmp[i].paramId);
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ }
+ }
+
+ Uint64 indexMem = 0, dataMem = 0;
+ ndb_mgm_get_int64_parameter(&db, CFG_DB_DATA_MEM, &dataMem);
+ ndb_mgm_get_int64_parameter(&db, CFG_DB_INDEX_MEM, &indexMem);
+ if(dataMem == 0){
+ snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_DATA_MEM);
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ }
+
+ if(indexMem == 0){
+ snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_INDEX_MEM);
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ }
+
+ noOfDataPages = (dataMem / 8192);
+ noOfIndexPages = (indexMem / 8192);
+
+ for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
+ Uint32 tmp;
+ if(!ndb_mgm_get_int_parameter(&db, LogLevel::MIN_LOGLEVEL_ID+j, &tmp)){
+ m_logLevel->setLogLevel((LogLevel::EventCategory)j, tmp);
+ }
+ }
+
+ // tmp
+ ndb_mgm_configuration_iterator * p = m_clusterConfigIter;
+
+ Uint32 nodeNo = noOfNodes = 0;
+ NodeBitmask nodes;
+ for(ndb_mgm_first(p); ndb_mgm_valid(p); ndb_mgm_next(p), nodeNo++){
+
+ Uint32 nodeId;
+ Uint32 nodeType;
+
+ if(ndb_mgm_get_int_parameter(p, CFG_NODE_ID, &nodeId)){
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, "Node data (Id) missing");
+ }
+
+ if(ndb_mgm_get_int_parameter(p, CFG_TYPE_OF_SECTION, &nodeType)){
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, "Node data (Type) missing");
+ }
+
+ if(nodeId > MAX_NODES || nodeId == 0){
+ snprintf(buf, sizeof(buf),
+ "Invalid node id: %d", nodeId);
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ }
+
+ if(nodes.get(nodeId)){
+ snprintf(buf, sizeof(buf), "Two node can not have the same node id: %d",
+ nodeId);
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ }
+ nodes.set(nodeId);
+
+ switch(nodeType){
+ case NODE_TYPE_DB:
+ noOfDBNodes++; // No of NDB processes
+
+ if(nodeId > MAX_NDB_NODES){
+ snprintf(buf, sizeof(buf), "Maximum node id for a ndb node is: %d",
+ MAX_NDB_NODES);
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ }
+ break;
+ case NODE_TYPE_API:
+ noOfAPINodes++; // No of API processes
+ break;
+ case NODE_TYPE_REP:
+ break;
+ case NODE_TYPE_MGM:
+ noOfMGMNodes++; // No of MGM processes
+ break;
+ case NODE_TYPE_EXT_REP:
+ break;
+ default:
+ snprintf(buf, sizeof(buf), "Unknown node type: %d", nodeType);
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ }
+ }
+ noOfNodes = nodeNo;
+
+ /**
+ * Do size calculations
+ */
+ ConfigValuesFactory cfg(ownConfig);
+
+ noOfTables++; // Remove impact of system table
+ noOfTables += noOfIndexes; // Indexes are tables too
+ noOfAttributes += 2; // ---"----
+ noOfTables *= 2; // Remove impact of Dict need 2 ids for each table
+
+ if (noOfDBNodes > 15) {
+ noOfDBNodes = 15;
+ }//if
+ Uint32 noOfLocalScanRecords = (noOfDBNodes * noOfScanRecords) + 1;
+ Uint32 noOfTCScanRecords = noOfScanRecords;
+
+ {
+ /**
+ * Acc Size Alt values
+ */
+ // Can keep 65536 pages (= 0.5 GByte)
+ cfg.put(CFG_ACC_DIR_RANGE,
+ 4 * NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas);
+
+ cfg.put(CFG_ACC_DIR_ARRAY,
+ (noOfIndexPages >> 8) +
+ 4 * NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas);
+
+ cfg.put(CFG_ACC_FRAGMENT,
+ 2 * NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas);
+
+ /*-----------------------------------------------------------------------*/
+ // The extra operation records added are used by the scan and node
+ // recovery process.
+ // Node recovery process will have its operations dedicated to ensure
+ // that they never have a problem with allocation of the operation record.
+ // The remainder are allowed for use by the scan processes.
+ /*-----------------------------------------------------------------------*/
+ cfg.put(CFG_ACC_OP_RECS,
+ noOfReplicas*((16 * noOfOperations) / 10 + 50) +
+ (noOfLocalScanRecords * MAX_PARALLEL_SCANS_PER_FRAG) +
+ NODE_RECOVERY_SCAN_OP_RECORDS);
+
+ cfg.put(CFG_ACC_OVERFLOW_RECS,
+ noOfIndexPages +
+ 2 * NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas);
+
+ cfg.put(CFG_ACC_PAGE8,
+ noOfIndexPages + 32);
+
+ cfg.put(CFG_ACC_ROOT_FRAG,
+ NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas);
+
+ cfg.put(CFG_ACC_TABLE, noOfTables);
+
+ cfg.put(CFG_ACC_SCAN, noOfLocalScanRecords);
+ }
+
+ {
+ /**
+ * Dict Size Alt values
+ */
+ cfg.put(CFG_DICT_ATTRIBUTE,
+ noOfAttributes);
+
+ cfg.put(CFG_DICT_CONNECT,
+ noOfOperations + 32);
+
+ cfg.put(CFG_DICT_FRAG_CONNECT,
+ NO_OF_FRAG_PER_NODE * noOfDBNodes * noOfReplicas);
+
+ cfg.put(CFG_DICT_TABLE,
+ noOfTables);
+
+ cfg.put(CFG_DICT_TC_CONNECT,
+ 2* noOfOperations);
+ }
+
+ {
+ /**
+ * Dih Size Alt values
+ */
+ cfg.put(CFG_DIH_API_CONNECT,
+ 2 * noOfTransactions);
+
+ cfg.put(CFG_DIH_CONNECT,
+ noOfOperations + 46);
+
+ cfg.put(CFG_DIH_FRAG_CONNECT,
+ NO_OF_FRAG_PER_NODE * noOfTables * noOfDBNodes);
+
+ int temp;
+ temp = noOfReplicas - 2;
+ if (temp < 0)
+ temp = 1;
+ else
+ temp++;
+ cfg.put(CFG_DIH_MORE_NODES,
+ temp * NO_OF_FRAG_PER_NODE *
+ noOfTables * noOfDBNodes);
+
+ cfg.put(CFG_DIH_REPLICAS,
+ NO_OF_FRAG_PER_NODE * noOfTables *
+ noOfDBNodes * noOfReplicas);
+
+ cfg.put(CFG_DIH_TABLE,
+ noOfTables);
+ }
+
+ {
+ /**
+ * Lqh Size Alt values
+ */
+ cfg.put(CFG_LQH_FRAG,
+ NO_OF_FRAG_PER_NODE * noOfTables * noOfReplicas);
+
+ cfg.put(CFG_LQH_CONNECT,
+ noOfReplicas*((11 * noOfOperations) / 10 + 50));
+
+ cfg.put(CFG_LQH_TABLE,
+ noOfTables);
+
+ cfg.put(CFG_LQH_TC_CONNECT,
+ noOfReplicas*((16 * noOfOperations) / 10 + 50));
+
+ cfg.put(CFG_LQH_REPLICAS,
+ noOfReplicas);
+
+ cfg.put(CFG_LQH_SCAN,
+ noOfLocalScanRecords);
+ }
+
+ {
+ /**
+ * Tc Size Alt values
+ */
+ cfg.put(CFG_TC_API_CONNECT,
+ 3 * noOfTransactions);
+
+ cfg.put(CFG_TC_TC_CONNECT,
+ noOfOperations + 16 + noOfTransactions);
+
+ cfg.put(CFG_TC_TABLE,
+ noOfTables);
+
+ cfg.put(CFG_TC_LOCAL_SCAN,
+ noOfLocalScanRecords);
+
+ cfg.put(CFG_TC_SCAN,
+ noOfTCScanRecords);
+ }
+
+ {
+ /**
+ * Tup Size Alt values
+ */
+ cfg.put(CFG_TUP_FRAG,
+ 2 * NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas);
+
+ cfg.put(CFG_TUP_OP_RECS,
+ noOfReplicas*((16 * noOfOperations) / 10 + 50));
+
+ cfg.put(CFG_TUP_PAGE,
+ noOfDataPages);
+
+ cfg.put(CFG_TUP_PAGE_RANGE,
+ 4 * NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas);
+
+ cfg.put(CFG_TUP_TABLE,
+ noOfTables);
+
+ cfg.put(CFG_TUP_TABLE_DESC,
+ 4 * NO_OF_FRAG_PER_NODE * noOfAttributes* noOfReplicas +
+ 12 * NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas );
+
+ cfg.put(CFG_TUP_STORED_PROC,
+ noOfLocalScanRecords);
+ }
+
+ {
+ /**
+ * Tux Size Alt values
+ */
+ cfg.put(CFG_TUX_INDEX,
+ noOfTables);
+
+ cfg.put(CFG_TUX_FRAGMENT,
+ 2 * NO_OF_FRAG_PER_NODE * noOfTables * noOfReplicas);
+
+ cfg.put(CFG_TUX_ATTRIBUTE,
+ noOfIndexes * 4);
+
+ cfg.put(CFG_TUX_SCAN_OP, noOfLocalScanRecords);
+ }
+
+ m_ownConfig = (ndb_mgm_configuration*)cfg.getConfigValues();
+ m_ownConfigIterator = ndb_mgm_create_configuration_iterator
+ (m_ownConfig, 0);
+}
+
void
Configuration::setInitialStart(bool val){
_initialStart = val;
diff --git a/ndb/src/kernel/vm/Configuration.hpp b/ndb/src/kernel/vm/Configuration.hpp
index 3f96bb454c5..1706ad05867 100644
--- a/ndb/src/kernel/vm/Configuration.hpp
+++ b/ndb/src/kernel/vm/Configuration.hpp
@@ -17,7 +17,8 @@
#ifndef Configuration_H
#define Configuration_H
-#include "ClusterConfiguration.hpp"
+#include <mgmapi.h>
+#include <ndb_types.h>
class Configuration {
public:
@@ -46,35 +47,36 @@ public:
void setRestartOnErrorInsert(int);
// Cluster configuration
- const ClusterConfiguration::ClusterData& clusterConfigurationData() const;
- const ClusterConfiguration& clusterConfiguration() const;
-
const char * programName() const;
const char * fileSystemPath() const;
char * getConnectStringCopy() const;
/**
- * Return Properties for own node
- */
- const Properties * getOwnProperties() const;
-
- /**
*
*/
bool getInitialStart() const;
void setInitialStart(bool val);
bool getDaemonMode() const;
-
+
+ const ndb_mgm_configuration_iterator * getOwnConfigIterator() const;
+
+ class LogLevel * m_logLevel;
private:
+ friend class Cmvmi;
+ friend class Qmgr;
+ ndb_mgm_configuration_iterator * getClusterConfigIterator() const;
+
Uint32 _stopOnError;
Uint32 m_restartOnErrorInsert;
Uint32 _maxErrorLogs;
Uint32 _lockPagesInMainMemory;
Uint32 _timeBetweenWatchDogCheck;
+ ndb_mgm_configuration * m_ownConfig;
+ ndb_mgm_configuration * m_clusterConfig;
- ClusterConfiguration the_clusterConfigurationData;
- const Properties * m_ownProperties;
+ ndb_mgm_configuration_iterator * m_clusterConfigIter;
+ ndb_mgm_configuration_iterator * m_ownConfigIterator;
/**
* arguments to NDB process
@@ -84,6 +86,8 @@ private:
bool _initialStart;
char * _connectString;
bool _daemonMode;
+
+ void calcSizeAlt(class ConfigValues * );
};
inline
diff --git a/ndb/src/kernel/vm/Emulator.cpp b/ndb/src/kernel/vm/Emulator.cpp
index 0d6d3f55acb..b615e41eb65 100644
--- a/ndb/src/kernel/vm/Emulator.cpp
+++ b/ndb/src/kernel/vm/Emulator.cpp
@@ -43,11 +43,11 @@ extern "C" {
* Declare the global variables
*/
-#ifdef USE_EMULATED_JAM
- Uint8 theEmulatedJam[EMULATED_JAM_SIZE * 4];
- Uint32 theEmulatedJamIndex = 0;
- Uint32 theEmulatedJamBlockNumber = 0;
-#endif // USE_EMULATED_JAM
+#ifndef NO_EMULATED_JAM
+Uint8 theEmulatedJam[EMULATED_JAM_SIZE * 4];
+Uint32 theEmulatedJamIndex = 0;
+Uint32 theEmulatedJamBlockNumber = 0;
+#endif
GlobalData globalData;
diff --git a/ndb/src/kernel/vm/Emulator.hpp b/ndb/src/kernel/vm/Emulator.hpp
index ba533eb873d..8c4504b9ba7 100644
--- a/ndb/src/kernel/vm/Emulator.hpp
+++ b/ndb/src/kernel/vm/Emulator.hpp
@@ -36,15 +36,18 @@ extern struct GlobalData globalData;
extern class SignalLoggerManager globalSignalLoggers;
#endif
-#ifdef USE_EMULATED_JAM
-#define EMULATED_JAM_SIZE 1024
-#define JAM_MASK ((EMULATED_JAM_SIZE * 4) - 1)
+#ifndef NO_EMULATED_JAM
+ #define EMULATED_JAM_SIZE 1024
+ #define JAM_MASK ((EMULATED_JAM_SIZE * 4) - 1)
-extern Uint8 theEmulatedJam[];
-extern Uint32 theEmulatedJamIndex;
-// last block entry, used in dumpJam() if jam contains no block entries
-extern Uint32 theEmulatedJamBlockNumber;
-#endif // USE_EMULATED_JAM
+ extern Uint8 theEmulatedJam[];
+ extern Uint32 theEmulatedJamIndex;
+ // last block entry, used in dumpJam() if jam contains no block entries
+ extern Uint32 theEmulatedJamBlockNumber;
+#else
+ const Uint8 theEmulatedJam[]=0;
+ const Uint32 theEmulatedJamIndex=0;
+#endif
struct EmulatorData {
class Configuration * theConfiguration;
diff --git a/ndb/src/kernel/vm/FastScheduler.cpp b/ndb/src/kernel/vm/FastScheduler.cpp
index e9ca4834562..eca456d26dd 100644
--- a/ndb/src/kernel/vm/FastScheduler.cpp
+++ b/ndb/src/kernel/vm/FastScheduler.cpp
@@ -316,14 +316,14 @@ APZJobBuffer::signal2buffer(Signal* signal,
void
APZJobBuffer::insert(const SignalHeader * const sh,
const Uint32 * const theData, const Uint32 secPtrI[3]){
- Uint32 tOccupancy = theOccupancy;
+ Uint32 tOccupancy = theOccupancy + 1;
Uint32 myWPtr = wPtr;
register BufferEntry& buf = buffer[myWPtr];
if (tOccupancy < bufSize) {
Uint32 cond = (++myWPtr == bufSize) - 1;
wPtr = myWPtr & cond;
- theOccupancy = tOccupancy + 1;
+ theOccupancy = tOccupancy;
buf.header = * sh;
const Uint32 len = buf.header.theLength;
@@ -342,8 +342,9 @@ APZJobBuffer::insert(const SignalHeader * const sh,
}//if
}
APZJobBuffer::APZJobBuffer()
- : rPtr(0), wPtr(0), theOccupancy(0), bufSize(0), buffer(NULL), memRef(NULL)
+ : bufSize(0), buffer(NULL), memRef(NULL)
{
+ clear();
}
APZJobBuffer::~APZJobBuffer()
@@ -354,9 +355,11 @@ APZJobBuffer::~APZJobBuffer()
void
APZJobBuffer::newBuffer(int size)
{
- buffer = new BufferEntry[size];
+ buffer = new BufferEntry[size + 1]; // +1 to support "overrrun"
if(buffer){
+#ifndef NDB_PURIFY
::memset(buffer, 0, (size * sizeof(BufferEntry)));
+#endif
bufSize = size;
} else
bufSize = 0;
@@ -474,10 +477,11 @@ FastScheduler::reportDoJobStatistics(Uint32 tMeanLoopCount) {
signal.theData[0] = EventReport::JobStatistic;
signal.theData[1] = tMeanLoopCount;
+ memset(&signal.header, 0, sizeof(SignalHeader));
signal.header.theLength = 2;
signal.header.theSendersSignalId = 0;
signal.header.theSendersBlockRef = numberToRef(0, 0);
-
+
execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
}
diff --git a/ndb/src/kernel/vm/FastScheduler.hpp b/ndb/src/kernel/vm/FastScheduler.hpp
index 586a7ea27ad..9749dab5d85 100644
--- a/ndb/src/kernel/vm/FastScheduler.hpp
+++ b/ndb/src/kernel/vm/FastScheduler.hpp
@@ -43,7 +43,7 @@ class BufferEntry
{
public:
SignalHeader header;
- Uint32 theDataRegister[28];
+ Uint32 theDataRegister[25];
};
class APZJobBuffer
@@ -68,7 +68,6 @@ public:
void retrieveDump(Signal *signal, Uint32 myRptr);
void clear();
- bool isEmpty() const;
Uint32 getOccupancy() const;
Uint32 getReadPtr() const;
@@ -313,13 +312,13 @@ void
APZJobBuffer::insert(Signal* signal,
BlockNumber bnr, GlobalSignalNumber gsn)
{
- Uint32 tOccupancy = theOccupancy;
+ Uint32 tOccupancy = theOccupancy + 1;
Uint32 myWPtr = wPtr;
if (tOccupancy < bufSize) {
register BufferEntry& buf = buffer[myWPtr];
Uint32 cond = (++myWPtr == bufSize) - 1;
wPtr = myWPtr & cond;
- theOccupancy = tOccupancy + 1;
+ theOccupancy = tOccupancy;
signal2buffer(signal, bnr, gsn, buf);
//---------------------------------------------------------
// Prefetch of buffer[wPtr] is done here. We prefetch for
@@ -343,11 +342,4 @@ APZJobBuffer::insert(Signal* signal, BlockNumber bnr,
signal2buffer(signal, bnr, gsn, buf);
}
-inline
-bool
-APZJobBuffer::isEmpty() const
-{
- return (theOccupancy == 0);
-}
-
#endif
diff --git a/ndb/src/kernel/vm/Makefile b/ndb/src/kernel/vm/Makefile
deleted file mode 100644
index 3f448b77b17..00000000000
--- a/ndb/src/kernel/vm/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := kernel
-
-SOURCES = \
- SimulatedBlock.cpp \
- FastScheduler.cpp \
- TimeQueue.cpp \
- VMSignal.cpp \
- ThreadConfig.cpp \
- TransporterCallback.cpp \
- Emulator.cpp \
- Configuration.cpp \
- ClusterConfiguration.cpp \
- WatchDog.cpp \
- SimplePropertiesSection.cpp \
- SectionReader.cpp \
- MetaData.cpp \
- Mutex.cpp SafeCounter.cpp
-
-DIRS := testCopy testDataBuffer testSimplePropertiesSection
-ifneq ($(USE_EDITLINE), N)
-DIRS += testLongSig
-endif
-
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/vm/Makefile.am b/ndb/src/kernel/vm/Makefile.am
new file mode 100644
index 00000000000..4e9dbe36c78
--- /dev/null
+++ b/ndb/src/kernel/vm/Makefile.am
@@ -0,0 +1,29 @@
+#SUBDIRS = testCopy testDataBuffer testSimplePropertiesSection
+#ifneq ($(USE_EDITLINE), N)
+#DIRS += testLongSig
+#endif
+
+noinst_LIBRARIES = libkernel.a
+
+libkernel_a_SOURCES = \
+ SimulatedBlock.cpp \
+ FastScheduler.cpp \
+ TimeQueue.cpp \
+ VMSignal.cpp \
+ ThreadConfig.cpp \
+ TransporterCallback.cpp \
+ Emulator.cpp \
+ Configuration.cpp \
+ WatchDog.cpp \
+ SimplePropertiesSection.cpp \
+ SectionReader.cpp \
+ MetaData.cpp \
+ Mutex.cpp SafeCounter.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_kernel.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/kernel/vm/Makefile_old b/ndb/src/kernel/vm/Makefile_old
new file mode 100644
index 00000000000..a162f3672ce
--- /dev/null
+++ b/ndb/src/kernel/vm/Makefile_old
@@ -0,0 +1,30 @@
+include .defs.mk
+
+TYPE := kernel
+
+ARCHIVE_TARGET := kernel
+
+SOURCES = \
+ SimulatedBlock.cpp \
+ FastScheduler.cpp \
+ TimeQueue.cpp \
+ VMSignal.cpp \
+ ThreadConfig.cpp \
+ TransporterCallback.cpp \
+ Emulator.cpp \
+ Configuration.cpp \
+ WatchDog.cpp \
+ SimplePropertiesSection.cpp \
+ SectionReader.cpp \
+ MetaData.cpp \
+ Mutex.cpp SafeCounter.cpp
+
+CFLAGS_Configuration.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
+
+DIRS := testCopy testDataBuffer testSimplePropertiesSection
+
+ifneq ($(USE_EDITLINE), N)
+DIRS += testLongSig
+endif
+
+include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/vm/SignalCounter.hpp b/ndb/src/kernel/vm/SignalCounter.hpp
index d572551ea92..ea770324aa6 100644
--- a/ndb/src/kernel/vm/SignalCounter.hpp
+++ b/ndb/src/kernel/vm/SignalCounter.hpp
@@ -21,6 +21,8 @@
#include <ErrorReporter.hpp>
class SignalCounter {
+ friend struct NodeReceiverGroup;
+
private:
Uint32 m_count;
NdbNodeBitmask m_nodes;
diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp
index e3f087d7d74..a6a8a6242cd 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.cpp
@@ -60,7 +60,8 @@ SimulatedBlock::SimulatedBlock(BlockNumber blockNumber,
c_fragmentIdCounter = 1;
c_fragSenderRunning = false;
- const Properties * p = conf.getOwnProperties();
+ Properties tmp;
+ const Properties * p = &tmp;
ndbrequire(p != 0);
Uint32 count = 10;
@@ -98,7 +99,9 @@ SimulatedBlock::SimulatedBlock(BlockNumber blockNumber,
for(GlobalSignalNumber i = 0; i<=MAX_GSN; i++)
theExecArray[i] = 0;
+
installSimulatedBlockFunctions();
+ UpgradeStartup::installEXEC(this);
CLEAR_ERROR_INSERT_VALUE;
}
@@ -127,6 +130,7 @@ SimulatedBlock::installSimulatedBlockFunctions(){
a[GSN_UTIL_LOCK_CONF] = &SimulatedBlock::execUTIL_LOCK_CONF;
a[GSN_UTIL_UNLOCK_REF] = &SimulatedBlock::execUTIL_UNLOCK_REF;
a[GSN_UTIL_UNLOCK_CONF] = &SimulatedBlock::execUTIL_UNLOCK_CONF;
+ a[GSN_READ_CONFIG_REQ] = &SimulatedBlock::execREAD_CONFIG_REQ;
}
void
@@ -182,7 +186,7 @@ SimulatedBlock::sendSignal(BlockReference ref,
Uint32 tSignalId = signal->header.theSignalId;
- if ((length == 0) || (length > 25) || (recBlock == 0)) {
+ if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
signal_error(gsn, length, recBlock, __FILE__, __LINE__);
return;
}//if
@@ -263,7 +267,7 @@ SimulatedBlock::sendSignal(NodeReceiverGroup rg,
signal->header.theSendersSignalId = tSignalId;
signal->header.theSendersBlockRef = reference();
- if ((length == 0) || (length > 25) || (recBlock == 0)) {
+ if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
signal_error(gsn, length, recBlock, __FILE__, __LINE__);
return;
}//if
@@ -371,7 +375,7 @@ SimulatedBlock::sendSignal(BlockReference ref,
Uint32 tSignalId = signal->header.theSignalId;
Uint32 tFragInfo = signal->header.m_fragmentInfo;
- if ((length == 0) || (length > 25) || (recBlock == 0)) {
+ if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
signal_error(gsn, length, recBlock, __FILE__, __LINE__);
return;
}//if
@@ -464,7 +468,7 @@ SimulatedBlock::sendSignal(NodeReceiverGroup rg,
signal->header.theSendersBlockRef = reference();
signal->header.m_noOfSections = noOfSections;
- if ((length == 0) || (length > 25) || (recBlock == 0)) {
+ if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
signal_error(gsn, length, recBlock, __FILE__, __LINE__);
return;
}//if
@@ -1338,7 +1342,7 @@ SimulatedBlock::sendFirstFragment(FragmentSendInfo & info,
*/
return true;
}
-
+
/**
* Setup info object
*/
@@ -1724,9 +1728,52 @@ void SimulatedBlock::execUTIL_UNLOCK_CONF(Signal* signal){
c_mutexMgr.execUTIL_UNLOCK_CONF(signal);
}
+void
+SimulatedBlock::execREAD_CONFIG_REQ(Signal* signal){
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
void
SimulatedBlock::ignoreMutexUnlockCallback(Signal* signal,
Uint32 ptrI, Uint32 retVal){
c_mutexMgr.release(ptrI);
}
+void
+UpgradeStartup::installEXEC(SimulatedBlock* block){
+ SimulatedBlock::ExecFunction * a = block->theExecArray;
+ switch(block->number()){
+ case QMGR:
+ a[UpgradeStartup::GSN_CM_APPCHG] = &SimulatedBlock::execUPGRADE;
+ break;
+ case CNTR:
+ a[UpgradeStartup::GSN_CNTR_MASTERREF] = &SimulatedBlock::execUPGRADE;
+ a[UpgradeStartup::GSN_CNTR_MASTERCONF] = &SimulatedBlock::execUPGRADE;
+ break;
+ }
+}
+
+void
+SimulatedBlock::execUPGRADE(Signal* signal){
+ Uint32 gsn = signal->header.theVerId_signalNumber;
+ switch(gsn){
+ case UpgradeStartup::GSN_CM_APPCHG:
+ UpgradeStartup::execCM_APPCHG(* this, signal);
+ break;
+ case UpgradeStartup::GSN_CNTR_MASTERREF:
+ UpgradeStartup::execCNTR_MASTER_REPLY(* this, signal);
+ break;
+ case UpgradeStartup::GSN_CNTR_MASTERCONF:
+ UpgradeStartup::execCNTR_MASTER_REPLY(* this, signal);
+ break;
+ }
+}
diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp
index 42b8a3034f5..491d432625e 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.hpp
@@ -45,6 +45,16 @@
#include "SafeCounter.hpp"
#include "MetaData.hpp"
+#include <mgmapi.h>
+#include <mgmapi_config_parameters.h>
+#include <mgmapi_config_parameters_debug.h>
+#include <kernel_config_parameters.h>
+#include <Configuration.hpp>
+
+#include <signaldata/ReadConfig.hpp>
+#include <signaldata/UpgradeStartup.hpp>
+
+
/**
* Something for filesystem access
*/
@@ -70,6 +80,7 @@ class SimulatedBlock {
friend class MutexManager;
friend class SafeCounter;
friend class SafeCounterManager;
+ friend struct UpgradeStartup;
public:
friend class BlockComponent;
virtual ~SimulatedBlock();
@@ -378,7 +389,7 @@ private:
void execSIGNAL_DROPPED_REP(Signal* signal);
void execCONTINUE_FRAGMENTED(Signal* signal);
-
+
Uint32 c_fragmentIdCounter;
ArrayPool<FragmentInfo> c_fragmentInfoPool;
DLHashTable<FragmentInfo> c_fragmentInfoHash;
@@ -404,7 +415,9 @@ private:
void execUTIL_UNLOCK_REF(Signal* signal);
void execUTIL_UNLOCK_CONF(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
protected:
+ void execUPGRADE(Signal* signal);
// Variable for storing inserted errors, see pc.H
ERROR_INSERT_VARIABLE;
diff --git a/ndb/src/kernel/vm/TransporterCallback.cpp b/ndb/src/kernel/vm/TransporterCallback.cpp
index 3798e4040c8..eb7d138895c 100644
--- a/ndb/src/kernel/vm/TransporterCallback.cpp
+++ b/ndb/src/kernel/vm/TransporterCallback.cpp
@@ -206,6 +206,7 @@ execute(void * callbackObj,
LinearSectionPtr ptr[3]){
const Uint32 secCount = header->m_noOfSections;
+ const Uint32 length = header->theLength;
#ifdef TRACE_DISTRIBUTED
ndbout_c("recv: %s(%d) from (%s, %d)",
@@ -225,6 +226,11 @@ execute(void * callbackObj,
case 1:
ok &= import(secPtr[0], ptr[0].p, ptr[0].sz);
}
+
+ /**
+ * Check that we haven't received a too long signal
+ */
+ ok &= (length + secCount <= 25);
Uint32 secPtrI[3];
if(ok){
@@ -234,6 +240,7 @@ execute(void * callbackObj,
secPtrI[0] = secPtr[0].i;
secPtrI[1] = secPtr[1].i;
secPtrI[2] = secPtr[2].i;
+
globalScheduler.execute(header, prio, theData, secPtrI);
return;
}
diff --git a/ndb/src/kernel/vm/VMSignal.hpp b/ndb/src/kernel/vm/VMSignal.hpp
index 45e731f2079..9111ee7949c 100644
--- a/ndb/src/kernel/vm/VMSignal.hpp
+++ b/ndb/src/kernel/vm/VMSignal.hpp
@@ -34,6 +34,7 @@ struct NodeReceiverGroup {
NodeReceiverGroup();
NodeReceiverGroup(Uint32 blockRef);
NodeReceiverGroup(Uint32 blockNo, const NodeBitmask &);
+ NodeReceiverGroup(Uint32 blockNo, const class SignalCounter &);
NodeReceiverGroup& operator=(BlockReference ref);
@@ -171,6 +172,14 @@ NodeReceiverGroup::NodeReceiverGroup(Uint32 blockNo, const NodeBitmask & nodes){
m_nodes = nodes;
}
+#include "SignalCounter.hpp"
+
+inline
+NodeReceiverGroup::NodeReceiverGroup(Uint32 blockNo, const SignalCounter & nodes){
+ m_block = blockNo;
+ m_nodes = nodes.m_nodes;
+}
+
inline
NodeReceiverGroup&
NodeReceiverGroup::operator=(BlockReference blockRef){
diff --git a/ndb/src/kernel/vm/pc.hpp b/ndb/src/kernel/vm/pc.hpp
index 873a986bc35..bc74adfc8f6 100644
--- a/ndb/src/kernel/vm/pc.hpp
+++ b/ndb/src/kernel/vm/pc.hpp
@@ -22,8 +22,14 @@
#include <NdbOut.hpp>
#include <ndb_limits.h>
-#ifdef USE_EMULATED_JAM
+#ifdef NO_EMULATED_JAM
+#define jam()
+#define jamLine(line)
+#define jamEntry()
+#define jamEntryLine(line)
+
+#else
#ifdef NDB_WIN32
#define jam() { \
@@ -72,11 +78,6 @@
#endif
-#else
-#define jam()
-#define jamLine(line)
-#define jamEntry()
-#define jamEntryLine(line)
#endif
#ifndef NDB_OPT
#define ptrCheck(ptr, limit, rec) if (ptr.i < (limit)) ptr.p = &rec[ptr.i]; else ptr.p = NULL
@@ -116,12 +117,6 @@
#define arrGuard(ind, size)
#endif
-// ------- EVENT STATES OF A NODE -----------------------------
-#define ZADD 0 /* New application added */
-#define ZREMOVE 1 /* An application has been removed */
-#define ZSTART 2 /* An application is ready to start */
-#define ZRUN 3 /* An application has started to run */
-
// -------- ERROR INSERT MACROS -------
#ifdef ERROR_INSERT
#define ERROR_INSERT_VARIABLE UintR cerrorInsert
@@ -190,7 +185,7 @@
*
* NOTE these may only be used within blocks
*/
-#if defined VM_TRACE || defined NDB_DEBUG
+#if defined VM_TRACE
#define ndbassert(check) \
if((check)){ \
} else { \
diff --git a/ndb/src/kernel/vm/testLongSig/testLongSig.cpp b/ndb/src/kernel/vm/testLongSig/testLongSig.cpp
index af4e2ca6e24..1d1fb8ebc82 100644
--- a/ndb/src/kernel/vm/testLongSig/testLongSig.cpp
+++ b/ndb/src/kernel/vm/testLongSig/testLongSig.cpp
@@ -39,6 +39,7 @@ print_help(){
ndbout << "11 - Sending of CONTINUEB fragmented signals w/ linear sections"
<< endl;
ndbout << "12 - As but using receiver group" << endl;
+ ndbout << "13 - Send 100 * 1000 25 len signals wo/ sections" << endl;
ndbout << "r - Recive signal from anyone" << endl;
ndbout << "a - Run tests 1 - 12 with variable sizes - 10 loops" << endl;
ndbout << "b - Run tests 1 - 12 with variable sizes - 100 loops" << endl;
@@ -103,7 +104,7 @@ main(void){
data[5] = 70;
data[6] = 123;
data[7] = 10;
- const Uint32 theDataLen = 8;
+ const Uint32 theDataLen = 18;
for(Uint32 i = 0; i<70; i++)
sec0[i] = i;
@@ -198,6 +199,38 @@ main(void){
delete ret1;
count--;
}
+ } else if (data[1] == 13) {
+ const Uint32 count = 3500;
+ const Uint32 loop = 1000;
+
+ signal1.set(ss, 0, CMVMI, GSN_TESTSIG, 25);
+ signal1.header.m_fragmentInfo = 0;
+ signal1.header.m_noOfSections = 0;
+ signal1.theData[1] = 14;
+ signal1.theData[3] = 0; // Print
+ signal1.theData[8] = count;
+ signal1.theData[9] = loop;
+ Uint32 nodeId = ss.getAliveNode();
+ ndbout_c("Sending 25 len signal to node %d", nodeId);
+ ss.sendSignal(nodeId, &signal1);
+
+ Uint32 total;
+ {
+ SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
+ ndbout_c("received from node %d",
+ refToNode(ret1->header.theSendersBlockRef));
+ total = ret1->theData[10] - 1;
+ delete ret1;
+ }
+
+ do {
+ ndbout << "Waiting for " << total << " signals... " << flush;
+ SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
+ ndbout_c("received from node %d",
+ refToNode(ret1->header.theSendersBlockRef));
+ delete ret1;
+ total --;
+ } while(total > 0);
} else {
print_help();
}
@@ -218,7 +251,6 @@ runTest(SignalSender & ss, Uint32 count, bool verbose){
sec2[i] = i * i;
}
- sig.set(ss, 0, CMVMI, GSN_TESTSIG, 8);
sig.theData[0] = ss.getOwnRef();
sig.theData[1] = 1; // TestType
sig.theData[2] = 128; // FragSize
@@ -236,6 +268,8 @@ runTest(SignalSender & ss, Uint32 count, bool verbose){
sig.ptr[1].sz = randRange(1, 256);
sig.ptr[2].sz = randRange(1, 256);
sig.header.m_noOfSections = secs;
+ const Uint32 len = 5 + (secs > 0 ? 1 : 0) * (25 - 5 - 7);
+ sig.set(ss, 0, CMVMI, GSN_TESTSIG, len);
ndbout << "Loop " << loop << " #secs = " << secs << " sizes = [ ";
unsigned min = 256;
unsigned max = 0;
@@ -248,7 +282,7 @@ runTest(SignalSender & ss, Uint32 count, bool verbose){
sum += sz;
sig.theData[5+i] = sz;
}
- ndbout_c("]");
+ ndbout_c("] len = %d", len);
for(int test = 1; test <= 12; test++){
sig.theData[1] = test;
Uint32 nodeId = ss.getAliveNode();
diff --git a/ndb/src/mgmapi/Makefile b/ndb/src/mgmapi/Makefile
deleted file mode 100644
index 9e7ba4f5ac7..00000000000
--- a/ndb/src/mgmapi/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-include .defs.mk
-
-TYPE := util
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := mgmapi
-
-A_LIB := Y
-SO_LIB := Y
-PIC_LIB := Y
-
-#DIRS := test
-
-LIB_TARGET := MGM_API
-LIB_TARGET_ARCHIVES := $(ARCHIVE_TARGET) general portlib
-
-# Source files of non-templated classes (.C files)
-SOURCES = mgmapi.cpp
-
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \
- -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
-
-CCFLAGS += -DNO_DEBUG_MESSAGES
-
-# -I$(NDB_TOP)/src/common/mgmcommon
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/mgmapi/Makefile.am b/ndb/src/mgmapi/Makefile.am
new file mode 100644
index 00000000000..e4fa1d449c6
--- /dev/null
+++ b/ndb/src/mgmapi/Makefile.am
@@ -0,0 +1,13 @@
+
+noinst_LTLIBRARIES = libmgmapi.la
+
+libmgmapi_la_SOURCES = mgmapi.cpp mgmapi_configuration.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/include/mgmapi -I$(top_srcdir)/ndb/src/common/mgmcommon
+DEFS_LOC = -DNO_DEBUG_MESSAGES
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_util.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/mgmapi/Makefile_old b/ndb/src/mgmapi/Makefile_old
new file mode 100644
index 00000000000..fa734f998e6
--- /dev/null
+++ b/ndb/src/mgmapi/Makefile_old
@@ -0,0 +1,27 @@
+include .defs.mk
+
+TYPE := util
+
+PIC_ARCHIVE := Y
+ARCHIVE_TARGET := mgmapi
+
+A_LIB := Y
+SO_LIB := Y
+PIC_LIB := Y
+
+#DIRS := test
+
+LIB_TARGET := MGM_API
+LIB_TARGET_ARCHIVES := $(ARCHIVE_TARGET) general portlib
+
+# Source files of non-templated classes (.C files)
+SOURCES = mgmapi.cpp mgmapi_configuration.cpp
+
+CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \
+ -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
+
+CCFLAGS += -DNO_DEBUG_MESSAGES
+
+# -I$(NDB_TOP)/src/common/mgmcommon
+
+include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index fcdfe943fb1..bb4b6be8221 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -19,6 +19,7 @@
#include <NdbTCP.h>
#include "mgmapi.h"
#include "mgmapi_debug.h"
+#include "mgmapi_configuration.hpp"
#include <socket_io.h>
#include <NdbOut.hpp>
@@ -26,6 +27,7 @@
#include <Parser.hpp>
#include <OutputStream.hpp>
#include <InputStream.hpp>
+#include <Base64.hpp>
#define MGM_CMD(name, fun, desc) \
@@ -93,15 +95,20 @@ struct ndb_mgm_handle {
#endif
};
-#define SET_ERROR(h, e, s) \
- { \
- char tmp[NDB_MGM_MAX_ERR_DESC_SIZE]; \
- snprintf(tmp, NDB_MGM_MAX_ERR_DESC_SIZE, " (mgmapi.cpp:%d)", __LINE__); \
- strncpy(h->last_error_desc, s, NDB_MGM_MAX_ERR_DESC_SIZE); \
- strncat(h->last_error_desc, tmp, NDB_MGM_MAX_ERR_DESC_SIZE); \
- h->last_error = e; \
- h->last_error_line = __LINE__; \
- }
+#define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
+
+static
+void
+setError(NdbMgmHandle h, int error, int error_line, const char * msg, ...){
+
+ h->last_error = error; \
+ h->last_error_line = error_line;
+
+ va_list ap;
+ va_start(ap, msg);
+ vsnprintf(h->last_error_desc, sizeof(h->last_error_desc), msg, ap);
+ va_end(ap);
+}
#define CHECK_HANDLE(handle, ret) \
if(handle == 0) { \
@@ -185,9 +192,12 @@ ndb_mgm_get_latest_error(const NdbMgmHandle h)
return h->last_error;
}
-/**
- * Get latest error line associated with a handle
- */
+extern "C"
+const char *
+ndb_mgm_get_latest_error_desc(const NdbMgmHandle h){
+ return h->last_error_desc;
+}
+
extern "C"
int
ndb_mgm_get_latest_error_line(const NdbMgmHandle h)
@@ -207,13 +217,6 @@ ndb_mgm_get_latest_error_msg(const NdbMgmHandle h)
return "Error"; // Unknown Error message
}
-extern "C"
-const char *
-ndb_mgm_get_latest_error_desc(const NdbMgmHandle h)
-{
- return h->last_error_desc;
-}
-
static
int
parse_connect_string(const char * connect_string,
@@ -372,7 +375,8 @@ ndb_mgm_connect(NdbMgmHandle handle, const char * mgmsrv)
// Convert ip address presentation format to numeric format
const int res1 = Ndb_getInAddr(&servaddr.sin_addr, handle->hostname);
if (res1 != 0) {
- SET_ERROR(handle, NDB_MGM_ILLEGAL_IP_ADDRESS, "");
+ DEBUG("Ndb_getInAddr(...) == -1");
+ setError(handle, EINVAL, __LINE__, "Invalid hostname/address");
return -1;
}
@@ -380,7 +384,8 @@ ndb_mgm_connect(NdbMgmHandle handle, const char * mgmsrv)
sizeof(servaddr));
if (res2 == -1) {
NDB_CLOSE_SOCKET(sockfd);
- SET_ERROR(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, "");
+ setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, "Unable to connect to %s",
+ mgmsrv);
return -1;
}
@@ -389,7 +394,7 @@ ndb_mgm_connect(NdbMgmHandle handle, const char * mgmsrv)
return 0;
}
-
+
/**
* Disconnect from a mgm server
*/
@@ -425,7 +430,7 @@ const int no_of_type_values = (sizeof(type_values) /
sizeof(ndb_mgm_type_atoi));
extern "C"
-enum ndb_mgm_node_type
+ndb_mgm_node_type
ndb_mgm_match_node_type(const char * type)
{
if(type == 0)
@@ -469,7 +474,7 @@ const int no_of_status_values = (sizeof(status_values) /
sizeof(ndb_mgm_status_atoi));
extern "C"
-enum ndb_mgm_node_status
+ndb_mgm_node_status
ndb_mgm_match_node_status(const char * status)
{
if(status == 0)
@@ -514,6 +519,8 @@ status_ackumulate(struct ndb_mgm_node_state * state,
state->node_group = atoi(value);
} else if(strcmp("version", field) == 0){
state->version = atoi(value);
+ } else if(strcmp("connect_count", field) == 0){
+ state->connect_count = atoi(value);
} else {
ndbout_c("Unknown field: %s", field);
}
@@ -1422,10 +1429,103 @@ ndb_mgm_abort_backup(NdbMgmHandle handle, unsigned int backupId,
return 0;
}
+extern "C"
+struct ndb_mgm_configuration *
+ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
+
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+ args.put("version", version);
+
+ const ParserRow<ParserDummy> reply[] = {
+ MGM_CMD("get config reply", NULL, ""),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_ARG("Content-Length", Int, Optional, "Content length in bytes"),
+ MGM_ARG("Content-Type", String, Optional, "Type (octet-stream)"),
+ MGM_ARG("Content-Transfer-Encoding", String, Optional, "Encoding(base64)"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop = ndb_mgm_call(handle, reply, "get config", &args);
+
+ if(prop == NULL) {
+ SET_ERROR(handle, EIO, "Unable to fetch config");
+ return 0;
+ }
+
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ ndbout_c("ERROR Message: %s\n", buf);
+ break;
+ }
+
+ buf = "<Unspecified>";
+ if(!prop->get("Content-Type", &buf) ||
+ strcmp(buf, "ndbconfig/octet-stream") != 0){
+ ndbout_c("Unhandled response type: %s", buf);
+ break;
+ }
+
+ buf = "<Unspecified>";
+ if(!prop->get("Content-Transfer-Encoding", &buf)
+ || strcmp(buf, "base64") != 0){
+ ndbout_c("Unhandled encoding: %s", buf);
+ break;
+ }
+
+ buf = "<Content-Length Unspecified>";
+ Uint32 len = 0;
+ if(!prop->get("Content-Length", &len)){
+ ndbout_c("Invalid response: %s\n", buf);
+ break;
+ }
+
+ len += 1; // Trailing \n
+
+ char* buf64 = new char[len];
+ int read = 0;
+ size_t start = 0;
+ do {
+ if((read = read_socket(handle->socket, handle->read_timeout,
+ &buf64[start], len-start)) == -1){
+ delete[] buf64;
+ buf64 = 0;
+ break;
+ }
+ start += read;
+ } while(start < len);
+ if(buf64 == 0)
+ break;
+
+ UtilBuffer tmp;
+ const int res = base64_decode(buf64, len-1, tmp);
+ delete[] buf64;
+ if(res != 0){
+ ndbout_c("Failed to decode buffer");
+ break;
+ }
+
+ ConfigValuesFactory cvf;
+ const int res2 = cvf.unpack(tmp);
+ if(!res2){
+ ndbout_c("Failed to unpack buffer");
+ break;
+ }
+
+ return (ndb_mgm_configuration*)cvf.m_cfg;
+ } while(0);
+
+ delete prop;
+ return 0;
+}
+
/*****************************************************************************
* Global Replication
- *****************************************************************************/
-
+ ******************************************************************************/
extern "C"
int
ndb_mgm_rep_command(NdbMgmHandle handle, unsigned int request,
diff --git a/ndb/src/mgmapi/mgmapi_configuration.cpp b/ndb/src/mgmapi/mgmapi_configuration.cpp
new file mode 100644
index 00000000000..ae7fe2c294c
--- /dev/null
+++ b/ndb/src/mgmapi/mgmapi_configuration.cpp
@@ -0,0 +1,157 @@
+#include <mgmapi.h>
+#include "mgmapi_configuration.hpp"
+#include <new>
+
+ndb_mgm_configuration_iterator::ndb_mgm_configuration_iterator
+(const ndb_mgm_configuration & conf, unsigned type_of_section)
+ : m_config(conf.m_config)
+{
+ m_sectionNo = ~0;
+ m_typeOfSection = type_of_section;
+ first();
+}
+
+ndb_mgm_configuration_iterator::~ndb_mgm_configuration_iterator(){
+ reset();
+}
+
+void
+ndb_mgm_configuration_iterator::reset(){
+ if(m_sectionNo != (Uint32)~0){
+ m_config.closeSection();
+ }
+}
+
+
+int
+ndb_mgm_configuration_iterator::enter(){
+ bool ok = m_config.openSection(m_typeOfSection, m_sectionNo);
+ if(ok){
+ return 0;
+ }
+
+ reset();
+ m_sectionNo = ~0;
+ return -1;
+}
+
+int
+ndb_mgm_configuration_iterator::first(){
+ reset();
+ m_sectionNo = 0;
+ return enter();
+}
+
+int
+ndb_mgm_configuration_iterator::next(){
+ reset();
+ m_sectionNo++;
+ return enter();
+}
+
+int
+ndb_mgm_configuration_iterator::valid() const {
+ return m_sectionNo != (Uint32)~0;
+}
+
+int
+ndb_mgm_configuration_iterator::find(int param, unsigned search){
+ unsigned val = search + 1;
+
+ while(get(param, &val) == 0 && val != search){
+ if(next() != 0)
+ break;
+ }
+
+ if(val == search)
+ return 0;
+
+ return -1;
+}
+
+int
+ndb_mgm_configuration_iterator::get(int param, unsigned * value) const {
+ return m_config.get(param, value) != true;
+
+}
+
+int
+ndb_mgm_configuration_iterator::get(int param,
+ unsigned long long * value) const{
+ return m_config.get(param, value) != true;
+}
+
+int
+ndb_mgm_configuration_iterator::get(int param, const char ** value) const {
+ return m_config.get(param, value) != true;
+}
+
+/**
+ * Published C interface
+ */
+extern "C"
+ndb_mgm_configuration_iterator*
+ndb_mgm_create_configuration_iterator(ndb_mgm_configuration * conf,
+ unsigned type_of_section){
+ ndb_mgm_configuration_iterator* iter = (ndb_mgm_configuration_iterator*)
+ malloc(sizeof(ndb_mgm_configuration_iterator));
+ if(iter == 0)
+ return 0;
+
+ return new(iter) ndb_mgm_configuration_iterator(* conf, type_of_section);
+}
+
+
+extern "C"
+void ndb_mgm_destroy_iterator(ndb_mgm_configuration_iterator* iter){
+ if(iter != 0){
+ iter->~ndb_mgm_configuration_iterator();
+ free(iter);
+ }
+}
+
+extern "C"
+int
+ndb_mgm_first(ndb_mgm_configuration_iterator* iter){
+ return iter->first();
+}
+
+extern "C"
+int
+ndb_mgm_next(ndb_mgm_configuration_iterator* iter){
+ return iter->next();
+}
+
+extern "C"
+int
+ndb_mgm_valid(const ndb_mgm_configuration_iterator* iter){
+ return iter->valid();
+}
+
+extern "C"
+int
+ndb_mgm_get_int_parameter(const ndb_mgm_configuration_iterator* iter,
+ int param, unsigned * value){
+ return iter->get(param, value);
+}
+
+extern "C"
+int
+ndb_mgm_get_int64_parameter(const ndb_mgm_configuration_iterator* iter,
+ int param, unsigned long long * value){
+ return iter->get(param, value);
+}
+
+extern "C"
+int
+ndb_mgm_get_string_parameter(const ndb_mgm_configuration_iterator* iter,
+ int param, const char ** value){
+ return iter->get(param, value);
+}
+
+extern "C"
+int
+ndb_mgm_find(ndb_mgm_configuration_iterator* iter,
+ int param, unsigned search){
+ return iter->find(param, search);
+}
diff --git a/ndb/src/mgmapi/mgmapi_configuration.hpp b/ndb/src/mgmapi/mgmapi_configuration.hpp
new file mode 100644
index 00000000000..c7feffd3a4e
--- /dev/null
+++ b/ndb/src/mgmapi/mgmapi_configuration.hpp
@@ -0,0 +1,32 @@
+#ifndef MGMAPI_CONFIGURATION_HPP
+#define MGMAPI_CONFIGURATION_HPP
+
+#include <ConfigValues.hpp>
+
+struct ndb_mgm_configuration {
+ ConfigValues m_config;
+};
+
+struct ndb_mgm_configuration_iterator {
+ Uint32 m_sectionNo;
+ Uint32 m_typeOfSection;
+ ConfigValues::ConstIterator m_config;
+
+ ndb_mgm_configuration_iterator(const ndb_mgm_configuration &, unsigned type);
+ ~ndb_mgm_configuration_iterator();
+
+ int first();
+ int next();
+ int valid() const;
+ int find(int param, unsigned value);
+
+ int get(int param, unsigned * value) const ;
+ int get(int param, unsigned long long * value) const ;
+ int get(int param, const char ** value) const ;
+
+ //
+ void reset();
+ int enter();
+};
+
+#endif
diff --git a/ndb/src/mgmapi/test/keso.c b/ndb/src/mgmapi/test/keso.c
index d5086b20b6a..d2675b2ca8a 100644
--- a/ndb/src/mgmapi/test/keso.c
+++ b/ndb/src/mgmapi/test/keso.c
@@ -29,6 +29,7 @@ static int testConnect(NdbMgmHandle h, struct ndb_mgm_reply* reply);
static int testDisconnect(NdbMgmHandle h, struct ndb_mgm_reply* reply);
static int testStatus(NdbMgmHandle h, struct ndb_mgm_reply* reply);
+static int testGetConfig(NdbMgmHandle h, struct ndb_mgm_reply* reply);
#ifdef VM_TRACE
static int testLogSignals(NdbMgmHandle h, struct ndb_mgm_reply* reply);
static int testStartSignalLog(NdbMgmHandle h, struct ndb_mgm_reply* reply);
@@ -152,6 +153,19 @@ int testDisconnect(NdbMgmHandle h, struct ndb_mgm_reply* reply) {
}
static
+int testGetConfig(NdbMgmHandle h, struct ndb_mgm_reply* reply) {
+ int i = 0;
+ struct ndb_mgm_configuration * config = ndb_mgm_get_configuration(h, 0);
+ if (config != NULL) {
+ free(config);
+ } else {
+ ndbout_c("Unable to get config");
+ return -1;
+ }
+ return 0;
+}
+
+static
int testStatus(NdbMgmHandle h, struct ndb_mgm_reply* reply) {
int i = 0;
struct ndb_mgm_cluster_state* cluster = ndb_mgm_get_status(h);
diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp
index fba5fda32dd..cf9d885847a 100644
--- a/ndb/src/mgmclient/CommandInterpreter.cpp
+++ b/ndb/src/mgmclient/CommandInterpreter.cpp
@@ -30,10 +30,6 @@
#include "MgmtErrorReporter.hpp"
#include "CpcClient.hpp"
-#ifdef NDB_SOLARIS // XXX fix me
-static char* strsep(char** x, const char* y) { return 0; }
-#endif
-
/*****************************************************************************
* HELP
@@ -1865,17 +1861,36 @@ CommandInterpreter::executeRep(char* parameters)
* CPC
*****************************************************************************/
+#if 0
+
+#if 0
+//#ifdef NDB_SOLARIS // XXX fix me
+static char* strsep(char** x, const char* y) { return 0; }
+#endif
+
+// Note this code has not been verified
+#if 0
+static char * my_strsep(char **stringp, const char *delim)
+{
+ char *tmp= *stringp;
+ if (tmp == 0)
+ return 0;
+ *stringp = strtok(tmp, delim);
+ return tmp;
+}
+#endif
+
void
CommandInterpreter::executeCpc(char *parameters)
{
char *host_str = NULL, *port_str = NULL, *end;
long port = 1234; /* XXX */
- while((host_str = strsep(&parameters, " \t:")) != NULL &&
+ while((host_str = my_strsep(&parameters, " \t:")) != NULL &&
host_str[0] == '\0');
if(parameters && parameters[0] != '\0') {
- while((port_str = strsep(&parameters, " \t:")) != NULL &&
+ while((port_str = my_strsep(&parameters, " \t:")) != NULL &&
port_str[0] == '\0');
errno = 0;
@@ -1944,6 +1959,7 @@ CommandInterpreter::executeCpc(char *parameters)
<< endl;
return;
}
+#endif
#if 0
static
diff --git a/ndb/src/mgmclient/CommandInterpreter.hpp b/ndb/src/mgmclient/CommandInterpreter.hpp
index 796a4e4838e..478e03d129a 100644
--- a/ndb/src/mgmclient/CommandInterpreter.hpp
+++ b/ndb/src/mgmclient/CommandInterpreter.hpp
@@ -17,7 +17,7 @@
#ifndef CommandInterpreter_H
#define CommandInterpreter_H
-#define HAVE_GLOBAL_REPLICATION
+//#define HAVE_GLOBAL_REPLICATION
//*****************************************************************************
// Author: Peter Lind
//*****************************************************************************
diff --git a/ndb/src/mgmclient/Makefile b/ndb/src/mgmclient/Makefile
deleted file mode 100644
index 9f9a6344ab9..00000000000
--- a/ndb/src/mgmclient/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi
-
-BIN_TARGET := mgmtclient
-BIN_TARGET_LIBS :=
-BIN_TARGET_ARCHIVES := trace logger general mgmapi mgmsrvcommon portlib repapi
-
-BIN_TARGET_ARCHIVES += editline
-
-DIRS = test_cpcd
-
-# Source files of non-templated classes (.cpp files)
-SOURCES = \
- main.cpp \
- CommandInterpreter.cpp \
- CpcClient.cpp
-
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \
- -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
-
-include $(NDB_TOP)/Epilogue.mk
-
-_bins_mkconfig : $(NDB_TOP)/bin/$(BIN_TARGET)
-
diff --git a/ndb/src/mgmclient/Makefile.am b/ndb/src/mgmclient/Makefile.am
new file mode 100644
index 00000000000..f3eaaaa68bd
--- /dev/null
+++ b/ndb/src/mgmclient/Makefile.am
@@ -0,0 +1,21 @@
+
+ndbtools_PROGRAMS = ndb_mgm
+
+ndb_mgm_SOURCES = \
+ main.cpp \
+ CommandInterpreter.cpp \
+ CpcClient.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
+
+INCLUDES += -I$(top_srcdir)/ndb/include/mgmapi -I$(top_srcdir)/ndb/src/common/mgmcommon
+
+LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la \
+ $(top_builddir)/ndb/src/common/editline/libeditline.a \
+ @TERMCAP_LIB@
+
+ndb_mgm_LDFLAGS = @ndb_bin_am_ldflags@
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/mgmclient/Makefile_old b/ndb/src/mgmclient/Makefile_old
new file mode 100644
index 00000000000..d1b2d60a52a
--- /dev/null
+++ b/ndb/src/mgmclient/Makefile_old
@@ -0,0 +1,25 @@
+include .defs.mk
+
+TYPE := ndbapi
+
+BIN_TARGET := mgmtclient
+BIN_TARGET_LIBS :=
+BIN_TARGET_ARCHIVES := trace logger mgmapi general mgmsrvcommon portlib repapi
+
+BIN_TARGET_ARCHIVES += editline
+
+DIRS = test_cpcd
+
+# Source files of non-templated classes (.cpp files)
+SOURCES = \
+ main.cpp \
+ CommandInterpreter.cpp \
+ CpcClient.cpp
+
+CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \
+ -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
+
+include $(NDB_TOP)/Epilogue.mk
+
+_bins_mkconfig : $(NDB_TOP)/bin/$(BIN_TARGET)
+
diff --git a/ndb/src/mgmsrv/CommandInterpreter.cpp b/ndb/src/mgmsrv/CommandInterpreter.cpp
index 8a7293b8434..004fc463b70 100644
--- a/ndb/src/mgmsrv/CommandInterpreter.cpp
+++ b/ndb/src/mgmsrv/CommandInterpreter.cpp
@@ -27,7 +27,6 @@
#include <signaldata/SetLogLevelOrd.hpp>
#include "ConfigInfo.hpp"
-extern "C"
#include <version.h>
@@ -453,14 +452,15 @@ void CommandInterpreter::executeShow(char* parameters) {
return;
} else if (strcmp(parameters, "PROPERTIES") == 0 ||
strcmp(parameters, "PROP") == 0) {
- _mgmtSrvr.getConfig()->print();
+ ndbout << "_mgmtSrvr.getConfig()->print();" << endl; /* XXX */
} else if (strcmp(parameters, "CONFIGURATION") == 0 ||
strcmp(parameters, "CONFIG") == 0){
+ ndbout << "_mgmtSrvr.getConfigFile()->print();" << endl; /* XXX */
_mgmtSrvr.getConfig()->printConfigFile();
} else if (strcmp(parameters, "PARAMETERS") == 0 ||
strcmp(parameters, "PARAMS") == 0 ||
strcmp(parameters, "PARAM") == 0) {
- _mgmtSrvr.getConfig()->getConfigInfo()->print();
+ ndbout << "_mgmtSrvr.getConfigInfo()->print();" << endl; /* XXX */
} else {
ndbout << "Invalid argument." << endl;
}
@@ -773,11 +773,11 @@ void CommandInterpreter::executeStatus(int processId,
}
ndb_mgm_node_status status;
- Uint32 startPhase, version, dynamicId, nodeGroup;
+ Uint32 startPhase, version, dynamicId, nodeGroup, connectCount;
bool system;
int result = _mgmtSrvr.status(processId,
&status, &version, &startPhase, &system,
- &dynamicId, &nodeGroup);
+ &dynamicId, &nodeGroup, &connectCount);
if(result != 0){
ndbout << _mgmtSrvr.getErrorText(result) << endl;
return;
diff --git a/ndb/src/mgmsrv/Makefile b/ndb/src/mgmsrv/Makefile
deleted file mode 100644
index b10bdb64d30..00000000000
--- a/ndb/src/mgmsrv/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi
-
-BIN_TARGET := mgmtsrvr
-BIN_TARGET_LIBS :=
-BIN_TARGET_ARCHIVES := mgmapi NDB_API mgmsrvcommon
-
-ifneq ($(USE_EDITLINE), N)
-BIN_TARGET_ARCHIVES += editline
-DIRS := mkconfig
-endif
-BIN_TARGET_ARCHIVES += general
-
-BIN_FLAGS += $(TERMCAP_LIB)
-
-# Source files of non-templated classes (.cpp files)
-SOURCES = \
- MgmtSrvr.cpp \
- MgmtSrvrGeneralSignalHandling.cpp \
- main.cpp \
- Services.cpp \
- convertStrToInt.cpp \
- NodeLogLevel.cpp \
- NodeLogLevelList.cpp \
- SignalQueue.cpp \
- MgmtSrvrConfig.cpp
-
-ifeq ($(findstring OSE, $(NDB_OS)),)
-SOURCES += CommandInterpreter.cpp
-endif
-
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/src/ndbapi) \
- -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \
- -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
-
-include $(NDB_TOP)/Epilogue.mk
-
-_bins_mkconfig : $(NDB_TOP)/bin/$(BIN_TARGET)
-
diff --git a/ndb/src/mgmsrv/Makefile.am b/ndb/src/mgmsrv/Makefile.am
new file mode 100644
index 00000000000..fc493fe10c7
--- /dev/null
+++ b/ndb/src/mgmsrv/Makefile.am
@@ -0,0 +1,30 @@
+
+ndbbin_PROGRAMS = ndb_mgmd
+
+ndb_mgmd_SOURCES = \
+ MgmtSrvr.cpp \
+ MgmtSrvrGeneralSignalHandling.cpp \
+ main.cpp \
+ Services.cpp \
+ convertStrToInt.cpp \
+ NodeLogLevel.cpp \
+ NodeLogLevelList.cpp \
+ SignalQueue.cpp \
+ MgmtSrvrConfig.cpp \
+ CommandInterpreter.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/ndbapi \
+ -I$(top_srcdir)/ndb/src/mgmapi \
+ -I$(top_srcdir)/ndb/src/common/mgmcommon
+
+LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la \
+ $(top_builddir)/ndb/src/common/editline/libeditline.a \
+ @TERMCAP_LIB@
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
+
+ndb_mgmd_LDFLAGS = @ndb_bin_am_ldflags@
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/mgmsrv/Makefile_old b/ndb/src/mgmsrv/Makefile_old
new file mode 100644
index 00000000000..c99875ae8b6
--- /dev/null
+++ b/ndb/src/mgmsrv/Makefile_old
@@ -0,0 +1,41 @@
+include .defs.mk
+
+TYPE := ndbapi mgmapiclient
+
+BIN_TARGET := mgmtsrvr
+BIN_TARGET_LIBS :=
+BIN_TARGET_ARCHIVES := NDB_API mgmsrvcommon mgmapi general
+
+ifneq ($(USE_EDITLINE), N)
+BIN_TARGET_ARCHIVES += editline
+DIRS := mkconfig
+endif
+BIN_TARGET_ARCHIVES += general
+
+BIN_FLAGS += $(TERMCAP_LIB)
+
+# Source files of non-templated classes (.cpp files)
+SOURCES = \
+ MgmtSrvr.cpp \
+ MgmtSrvrGeneralSignalHandling.cpp \
+ main.cpp \
+ Services.cpp \
+ convertStrToInt.cpp \
+ NodeLogLevel.cpp \
+ NodeLogLevelList.cpp \
+ SignalQueue.cpp \
+ MgmtSrvrConfig.cpp
+
+ifeq ($(findstring OSE, $(NDB_OS)),)
+SOURCES += CommandInterpreter.cpp
+endif
+
+CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/src/ndbapi) \
+ -I$(call fixpath,$(NDB_TOP)/src/mgmapi) \
+ -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \
+ -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
+
+include $(NDB_TOP)/Epilogue.mk
+
+_bins_mkconfig : $(NDB_TOP)/bin/$(BIN_TARGET)
+
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index 7c2d94c6b7f..713433cb8e9 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -21,7 +21,6 @@
#include "MgmtErrorReporter.hpp"
#include <NdbOut.hpp>
-#include <AttrType.hpp>
#include <NdbApiSignal.hpp>
#include <kernel_types.h>
#include <RefConvert.hpp>
@@ -29,7 +28,6 @@
#include <GlobalSignalNumbers.h>
#include <signaldata/TestOrd.hpp>
#include <signaldata/TamperOrd.hpp>
-#include <signaldata/SetVarReq.hpp>
#include <signaldata/StartOrd.hpp>
#include <signaldata/ApiVersion.hpp>
#include <signaldata/ResumeReq.hpp>
@@ -49,6 +47,10 @@
#include "NodeLogLevel.hpp"
#include <NdbConfig.h>
+#include <mgmapi.h>
+#include <mgmapi_configuration.hpp>
+#include <mgmapi_config_parameters.h>
+
//#define MGM_SRV_DEBUG
#ifdef MGM_SRV_DEBUG
#define DEBUG(x) do ndbout << x << endl; while(0)
@@ -225,19 +227,33 @@ void
MgmtSrvr::startEventLog()
{
g_EventLogger.setCategory("MgmSrvr");
- const Properties *mgmProps;
- _config->get("Node", _ownNodeId, &mgmProps);
+
+ ndb_mgm_configuration_iterator * iter = ndb_mgm_create_configuration_iterator
+ ((ndb_mgm_configuration*)_config->m_configValues, CFG_SECTION_NODE);
+ if(iter == 0)
+ return ;
+
+ if(ndb_mgm_find(iter, CFG_NODE_ID, _ownNodeId) != 0){
+ ndb_mgm_destroy_iterator(iter);
+ return ;
+ }
+
+ const char * tmp;
BaseString logdest;
char clusterLog[MAXPATHLEN];
-
NdbConfig_ClusterLogFileName(clusterLog, sizeof(clusterLog));
-
- mgmProps->get("LogDestination", logdest);
-
+
+
+ if(ndb_mgm_get_string_parameter(iter, CFG_LOG_DESTINATION, &tmp) == 0){
+ logdest.assign(tmp);
+ }
+ ndb_mgm_destroy_iterator(iter);
+
if(logdest.length()==0) {
- logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6", clusterLog);
+ logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6",
+ clusterLog);
}
-
+
if(!g_EventLogger.addHandler(logdest)) {
ndbout << "ERROR: cannot parse \"" << logdest << "\"" << endl;
exit(1);
@@ -375,8 +391,8 @@ MgmtSrvr::getNodeCount(enum ndb_mgm_node_type type) const
}
int
-MgmtSrvr::getStatPort() const
-{
+MgmtSrvr::getStatPort() const {
+#if 0
const Properties *mgmProps;
if(!getConfig()->get("Node", _ownNodeId, &mgmProps))
return -1;
@@ -386,12 +402,16 @@ MgmtSrvr::getStatPort() const
return -1;
return tmp;
+#else
+ return -1;
+#endif
}
/* Constructor */
MgmtSrvr::MgmtSrvr(NodeId nodeId,
const BaseString &configFilename,
- const BaseString &ndb_config_filename):
+ const BaseString &ndb_config_filename,
+ Config * config):
_blockNumber(1), // Hard coded block number since it makes it easy to send
// signals to other management servers.
_ownReference(0),
@@ -416,8 +436,8 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
m_nextConfigGenerationNumber = 0;
- _config = readConfig();
-
+ _config = (config == 0 ? readConfig() : config);
+
theMgmtWaitForResponseCondPtr = NdbCondition_Create();
m_configMutex = NdbMutex_Create();
@@ -428,31 +448,38 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
for(Uint32 i = 0; i<MAX_NODES; i++)
nodeTypes[i] = (enum ndb_mgm_node_type)-1;
- Properties::Iterator it(_config);
- const char * name;
- for(name = it.first(); name != NULL; name = it.next()){
- if(strncmp(name, "Node_", strlen("Node_")) == 0){
- const Properties * tmp;
+ ndb_mgm_configuration_iterator * iter = ndb_mgm_create_configuration_iterator
+ (config->m_configValues, CFG_SECTION_NODE);
+ for(ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)){
+ unsigned type, id;
+ if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0)
+ continue;
- _config->get(name, &tmp);
-
- Uint32 nodeId;
- BaseString type;
- MGM_REQUIRE(tmp->get("Id", &nodeId));
- MGM_REQUIRE(tmp->get("Type", type));
- MGM_REQUIRE(nodeId < MAX_NODES);
+ if(ndb_mgm_get_int_parameter(iter, CFG_NODE_ID, &id) != 0)
+ continue;
+
+ MGM_REQUIRE(id < MAX_NODES);
- if(type == "MGM")
- nodeTypes[nodeId] = NDB_MGM_NODE_TYPE_MGM;
- if(type == "API")
- nodeTypes[nodeId] = NDB_MGM_NODE_TYPE_API;
- if(type == "DB")
- nodeTypes[nodeId] = NDB_MGM_NODE_TYPE_NDB;
- if(type == "REP")
- nodeTypes[nodeId] = NDB_MGM_NODE_TYPE_API;
+ switch(type){
+ case NODE_TYPE_DB:
+ nodeTypes[id] = NDB_MGM_NODE_TYPE_NDB;
+ break;
+ case NODE_TYPE_API:
+ nodeTypes[id] = NDB_MGM_NODE_TYPE_API;
+ break;
+ case NODE_TYPE_MGM:
+ nodeTypes[id] = NDB_MGM_NODE_TYPE_MGM;
+ break;
+ case NODE_TYPE_REP:
+ nodeTypes[id] = NDB_MGM_NODE_TYPE_REP;
+ break;
+ case NODE_TYPE_EXT_REP:
+ default:
+ break;
}
}
-
+ ndb_mgm_destroy_iterator(iter);
+
m_statisticsListner = NULL;
_nodeLogLevelList = new NodeLogLevelList();
@@ -472,13 +499,6 @@ MgmtSrvr::check_start()
return false;
}
- _props = new Config(* _config);
- if (_props == 0) {
- DEBUG("MgmtSrvr.cpp: Object props is NULL.");
- return false;
- }
- MGM_REQUIRE(_props->put("LocalNodeId", _ownNodeId, true));
-
return true;
}
@@ -489,11 +509,10 @@ MgmtSrvr::start()
if (!check_start())
return false;
}
+ theFacade = TransporterFacade::start_instance
+ (_ownNodeId,
+ (ndb_mgm_configuration*)_config->m_configValues);
- theFacade = TransporterFacade::start_instance(_props, NULL);
- delete _props;
- _props = NULL;
-
if(theFacade == 0) {
DEBUG("MgmtSrvr.cpp: theFacade is NULL.");
return false;
@@ -506,14 +525,14 @@ MgmtSrvr::start()
_blockNumber = theFacade->open(this,
signalReceivedNotification,
nodeStatusNotification);
-
+
if(_blockNumber == -1){
DEBUG("MgmtSrvr.cpp: _blockNumber is -1.");
theFacade->stop_instance();
theFacade = 0;
return false;
}
-
+
_ownReference = numberToRef(_blockNumber, _ownNodeId);
startEventLog();
@@ -558,7 +577,11 @@ MgmtSrvr::~MgmtSrvr()
NdbMutex_Destroy(m_configMutex);
if(m_newConfig != NULL)
- delete m_newConfig;
+ free(m_newConfig);
+
+ if(_config != NULL)
+ delete _config;
+
delete _nodeLogLevelList;
delete _clusterLogLevelList;
@@ -813,9 +836,10 @@ MgmtSrvr::restart(bool nostart, bool initalStart, bool abort,
s = NDB_MGM_NODE_STATUS_NO_CONTACT;
while (s == NDB_MGM_NODE_STATUS_NO_CONTACT && waitTime > 0) {
Uint32 startPhase = 0, version = 0, dynamicId = 0, nodeGroup = 0;
+ Uint32 connectCount = 0;
bool system;
status(nodeId, &s, &version, &startPhase,
- &system, &dynamicId, &nodeGroup);
+ &system, &dynamicId, &nodeGroup, &connectCount);
NdbSleep_MilliSleep(100);
waitTime = (maxTime - NdbTick_CurrentMillisecond());
}
@@ -1298,7 +1322,8 @@ MgmtSrvr::status(int processId,
Uint32 * _phase,
bool * _system,
Uint32 * dynamic,
- Uint32 * nodegroup)
+ Uint32 * nodegroup,
+ Uint32 * connectCount)
{
if (getNodeType(processId) == NDB_MGM_NODE_TYPE_API) {
if(versionNode(processId, false,0,0) ==0)
@@ -1325,7 +1350,8 @@ MgmtSrvr::status(int processId,
* dynamic = node.m_state.dynamicId;
* nodegroup = node.m_state.nodeGroup;
-
+ * connectCount = node.m_info.m_connectCount;
+
switch(node.m_state.startLevel){
case NodeState::SL_CMVMI:
* _status = NDB_MGM_NODE_STATUS_NOT_STARTED;
@@ -1376,11 +1402,11 @@ MgmtSrvr::status(int processId,
* _phase = 0;
return 0;
}
-
+
return -1;
}
-
-
+
+
//****************************************************************************
//****************************************************************************
int
@@ -1950,7 +1976,7 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
BackupEvent event;
event.Event = BackupEvent::BackupStarted;
event.Started.BackupId = conf->backupId;
- event.Started.Nodes = conf->nodes;
+ event.Nodes = conf->nodes;
#ifdef VM_TRACE
ndbout_c("Backup master is %d", refToNode(signal->theSendersBlockRef));
#endif
@@ -2013,7 +2039,7 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
event.Completed.stopGCP = rep->stopGCP;
event.Completed.startGCP = rep->startGCP;
- event.Completed.Nodes = rep->nodes;
+ event.Nodes = rep->nodes;
backupCallback(event);
}
@@ -2170,8 +2196,9 @@ MgmtSrvr::getNextNodeId(NodeId * nodeId, enum ndb_mgm_node_type type) const
while(nodeTypes[tmp] != type && tmp < MAX_NODES)
tmp++;
- if(tmp == MAX_NODES)
+ if(tmp == MAX_NODES){
return false;
+ }
* nodeId = tmp;
return true;
@@ -2530,8 +2557,8 @@ MgmtSrvr::getStuff()
}
NodeId
-MgmtSrvr::getPrimaryNode() const
-{
+MgmtSrvr::getPrimaryNode() const {
+#if 0
Uint32 tmp;
const Properties *prop = NULL;
@@ -2542,4 +2569,7 @@ MgmtSrvr::getPrimaryNode() const
prop->get("PrimaryMGMNode", &tmp);
return tmp;
+#else
+ return 0;
+#endif
}
diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp
index ce8765d6c73..1d394a14857 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.hpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.hpp
@@ -27,6 +27,7 @@
#include <NodeBitmask.hpp>
#include <signaldata/ManagementServer.hpp>
#include "SignalQueue.hpp"
+#include <ndb_version.h>
#include "NodeLogLevelList.hpp"
@@ -151,7 +152,8 @@ public:
/* Constructor */
MgmtSrvr(NodeId nodeId, /* Local nodeid */
const BaseString &config_filename, /* Where to save config */
- const BaseString &ndb_config_filename); /* Ndb.cfg filename */
+ const BaseString &ndb_config_filename, /* Ndb.cfg filename */
+ Config * config);
/**
* Read (initial) config file, create TransporterFacade,
@@ -169,7 +171,8 @@ public:
Uint32 * phase,
bool * systemShutdown,
Uint32 * dynamicId,
- Uint32 * nodeGroup);
+ Uint32 * nodeGroup,
+ Uint32 * connectCount);
// All the functions below may return any of this error codes:
// NO_CONTACT_WITH_PROCESS, PROCESS_NOT_CONFIGURED, WRONG_PROCESS_TYPE,
@@ -307,10 +310,10 @@ public:
BackupAborted = 4
} Event;
+ NdbNodeBitmask Nodes;
union {
struct {
Uint32 BackupId;
- NdbNodeBitmask Nodes;
} Started ;
struct {
Uint32 ErrorCode;
@@ -321,7 +324,6 @@ public:
Uint32 NoOfRecords;
Uint32 NoOfLogBytes;
Uint32 NoOfLogRecords;
- NdbNodeBitmask Nodes;
Uint32 startGCP;
Uint32 stopGCP;
} Completed ;
@@ -522,7 +524,7 @@ private:
int _blockNumber;
NodeId _ownNodeId;
BlockReference _ownReference;
- NdbMutex *m_configMutex;
+ NdbMutex *m_configMutex;
const Config * _config;
Config * m_newConfig;
BaseString m_configFilename;
diff --git a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
index f4e53409b30..10316bd2851 100644
--- a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
@@ -275,31 +275,30 @@ MgmtSrvr::readConfig() {
Config *conf = NULL;
if(m_configFilename.length() != 0) {
/* Use config file */
- InitConfigFileParser parser(m_configFilename.c_str());
-
- if(!parser.readConfigFile()) {
+ InitConfigFileParser parser;
+ conf = parser.parseConfig(m_configFilename.c_str());
+
+ if(conf == NULL) {
/* Try to get configuration from other MGM server */
- ConfigRetriever cr;
- cr.setLocalConfigFileName(m_localNdbConfigFilename.c_str());
- conf = new Config(*cr.getConfig("MGM", NDB_VERSION));
- } else {
- conf = new Config(*parser.getConfig());
+ return fetchConfig();
}
-
- if(conf == NULL)
- return NULL;
}
return conf;
}
Config *
MgmtSrvr::fetchConfig() {
- Config *conf = NULL;
ConfigRetriever cr;
cr.setLocalConfigFileName(m_localNdbConfigFilename.c_str());
- conf = new Config(*cr.getConfig("MGM", NDB_VERSION));
+ struct ndb_mgm_configuration * tmp = cr.getConfig(NDB_VERSION,
+ NODE_TYPE_MGM);
+ if(tmp != 0){
+ Config * conf = new Config();
+ conf->m_configValues = tmp;
+ return conf;
+ }
- return conf;
+ return 0;
}
bool
diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp
index 24f41fe64bf..739eef90c52 100644
--- a/ndb/src/mgmsrv/Services.cpp
+++ b/ndb/src/mgmsrv/Services.cpp
@@ -26,6 +26,9 @@
#include <BaseString.hpp>
#include <Base64.hpp>
+#include <ConfigValues.hpp>
+#include <mgmapi_configuration.hpp>
+
#include "Services.hpp"
static const unsigned int MAX_READ_TIMEOUT = 1000 ;
@@ -275,12 +278,60 @@ MgmApiSession::getConfig_old(Parser_t::Context &ctx) {
}
#endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */
+inline void require(bool b){ if(!b) abort(); }
+
void
MgmApiSession::getConfig(Parser_t::Context &ctx,
const class Properties &args) {
getConfig_common(ctx, args);
}
+static Properties *
+backward(const char * base, const Properties* reply){
+ Properties * ret = new Properties();
+ Properties::Iterator it(reply);
+ for(const char * name = it.first(); name != 0; name=it.next()){
+ PropertiesType type;
+ reply->getTypeOf(name, &type);
+ switch(type){
+ case PropertiesType_Uint32:{
+ Uint32 val;
+ reply->get(name, &val);
+ ret->put(name, val);
+ }
+ break;
+ case PropertiesType_char:
+ {
+ const char * val;
+ reply->get(name, &val);
+ ret->put(name, val);
+ if(!strcmp(name, "Type") && !strcmp(val, "DB")){
+ ret->put("NoOfDiskBufferPages", (unsigned)0);
+ ret->put("NoOfDiskFiles", (unsigned)0);
+ ret->put("NoOfDiskClusters", (unsigned)0);
+ ret->put("NoOfFreeDiskClusters", (unsigned)0);
+ ret->put("NoOfDiskClustersPerDiskFile", (unsigned)0);
+ ret->put("NoOfConcurrentCheckpointsDuringRestart", (unsigned)1);
+ ret->put("NoOfConcurrentCheckpointsAfterRestart", (unsigned)1);
+ ret->put("NoOfConcurrentProcessesHandleTakeover", (unsigned)1);
+ }
+ }
+ break;
+ case PropertiesType_Properties:
+ {
+ const Properties * recurse;
+ reply->get(name, &recurse);
+ Properties * val = backward(name, recurse);
+ ret->put(name, val);
+ }
+ break;
+ case PropertiesType_Uint64:
+ break;
+ }
+ }
+ return ret;
+}
+
void
MgmApiSession::getConfig_common(Parser_t::Context &,
const class Properties &args,
@@ -290,92 +341,100 @@ MgmApiSession::getConfig_common(Parser_t::Context &,
args.get("version", &version);
args.get("node", &node);
-#if 0
- if(version != 0) {
- m_output->println("get config");
- m_output->println("result: Invalid version number");
- m_output->println("");
- return;
- }
-#endif
-
const Config *conf = m_mgmsrv.getConfig();
if(conf == NULL) {
- m_output->println("get config");
+ m_output->println("get config reply");
m_output->println("result: Could not fetch configuration");
m_output->println("");
return;
}
- bool compatible;
- switch (m_mgmsrv.getNodeType(node)) {
- case NDB_MGM_NODE_TYPE_NDB:
- compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version);
- break;
- case NDB_MGM_NODE_TYPE_API:
- case NDB_MGM_NODE_TYPE_MGM:
- compatible = ndbCompatible_mgmt_api(NDB_VERSION, version);
- break;
- default:
- m_output->println("get config");
- m_output->println("result: unrecognignized node type");
- m_output->println("");
- return;
- }
-
- if (!compatible){
- m_output->println("get config");
- m_output->println("result: incompatible version mgmt 0x%x and node 0x%x",
- NDB_VERSION, version);
- m_output->println("");
- return;
- }
-
- Properties *reply = new Properties(*conf);
- reply->put("Version", NDB_VERSION); // reply->put("Version", version);
- reply->put("LocalNodeId", node);
+ if(version > 0 && version < makeVersion(3, 5, 0) && compat){
+ Properties *reply = backward("", conf->m_oldConfig);
+ reply->put("Version", version);
+ reply->put("LocalNodeId", node);
-#ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT
- if(compat) {
+ backward("", reply);
+ //reply->print();
+
const Uint32 size = reply->getPackedSize();
Uint32 *buffer = new Uint32[size/4+1];
reply->pack(buffer);
delete reply;
-
+
const int uurows = (size + 44)/45;
char * uubuf = new char[uurows * 62+5];
-
+
const int uusz = uuencode_mem(uubuf, (char *)buffer, size);
delete[] buffer;
-
+
m_output->println("GET CONFIG %d %d %d %d %d",
- 0, NDB_VERSION, node, size, uusz);// 0, version, node, size, uusz);
-
+ 0, version, node, size, uusz);
+
m_output->println("begin 664 Ndb_cfg.bin");
-
+
/* XXX Need to write directly to the socket, because the uubuf is not
* NUL-terminated. This could/should probably be done in a nicer way.
*/
write_socket(m_socket, MAX_WRITE_TIMEOUT, uubuf, uusz);
delete[] uubuf;
-
+
m_output->println("end");
m_output->println("");
- } else {
-#endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */
-
- UtilBuffer buffer;
- BaseString str;
- reply->pack(buffer);
- delete reply;
- base64_encode(buffer, str);
+ return;
+ }
- m_output->println("config: %s", str.c_str());
- m_output->println("");
-#ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT
+ if(compat){
+ m_output->println("GET CONFIG %d %d %d %d %d",1, version, 0, 0, 0);
+ return;
}
-#endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */
+
+ if(node != 0){
+ bool compatible;
+ switch (m_mgmsrv.getNodeType(node)) {
+ case NDB_MGM_NODE_TYPE_NDB:
+ compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version);
+ break;
+ case NDB_MGM_NODE_TYPE_API:
+ case NDB_MGM_NODE_TYPE_MGM:
+ compatible = ndbCompatible_mgmt_api(NDB_VERSION, version);
+ break;
+ default:
+ m_output->println("get config");
+ m_output->println("result: unrecognignized node type");
+ m_output->println("");
+ return;
+ }
+
+ if (!compatible){
+ m_output->println("get config");
+ m_output->println("result: incompatible version mgmt 0x%x and node 0x%x",
+ NDB_VERSION, version);
+ m_output->println("");
+ return;
+ }
+ }
+
+ const ConfigValues * cfg = &conf->m_configValues->m_config;
+ const Uint32 size = cfg->getPackedSize();
+
+ UtilBuffer src;
+ cfg->pack(src);
+
+ BaseString str;
+ int res = base64_encode(src, str);
+
+ m_output->println("get config reply");
+ m_output->println("result: Ok");
+ m_output->println("Content-Length: %d", str.length());
+ m_output->println("Content-Type: ndbconfig/octet-stream");
+ m_output->println("Content-Transfer-Encoding: base64");
+ m_output->println("");
+ m_output->println(str.c_str());
+ m_output->println("");
+
+ return;
}
void
@@ -756,10 +815,14 @@ printNodeStatus(OutputStream *output,
NodeId nodeId = 0;
while(mgmsrv.getNextNodeId(&nodeId, type)) {
enum ndb_mgm_node_status status;
- Uint32 startPhase = 0, version = 0, dynamicId = 0, nodeGroup = 0;
+ Uint32 startPhase = 0,
+ version = 0,
+ dynamicId = 0,
+ nodeGroup = 0,
+ connectCount = 0;
bool system;
mgmsrv.status(nodeId, &status, &version, &startPhase,
- &system, &dynamicId, &nodeGroup);
+ &system, &dynamicId, &nodeGroup, &connectCount);
output->println("node.%d.type: %s",
nodeId,
ndb_mgm_get_node_type_string(type));
@@ -770,6 +833,7 @@ printNodeStatus(OutputStream *output,
output->println("node.%d.startphase: %d", nodeId, startPhase);
output->println("node.%d.dynamic_id: %d", nodeId, dynamicId);
output->println("node.%d.node_group: %d", nodeId, nodeGroup);
+ output->println("node.%d.connect_count: %d", nodeId, connectCount);
}
}
diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp
index 91b443f61a2..d9eb0001c44 100644
--- a/ndb/src/mgmsrv/main.cpp
+++ b/ndb/src/mgmsrv/main.cpp
@@ -34,6 +34,7 @@
#include <NdbHost.h>
#include <ndb_version.h>
#include <ConfigRetriever.hpp>
+#include <mgmapi_config_parameters.h>
#include <getarg.h>
#if defined NDB_OSE || defined NDB_SOFTOSE
@@ -191,7 +192,10 @@ NDB_MAIN(mgmsrv){
glob.mgmObject = new MgmtSrvr(glob.localNodeId,
BaseString(glob.config_filename),
- BaseString(glob.local_config_filename == 0 ? "" : glob.local_config_filename));
+ BaseString(glob.local_config_filename == 0 ? "" : glob.local_config_filename),
+ glob.cluster_config);
+
+ glob.cluster_config = 0;
if(!glob.mgmObject->check_start()){
ndbout_c("Unable to start management server.");
@@ -321,18 +325,21 @@ readGlobalConfig() {
return false;
/* Use config file */
- InitConfigFileParser parser(glob.config_filename);
-
- if(parser.readConfigFile()) {
- glob.cluster_config = new Config(*parser.getConfig());
- } else {
- /* Try to get configuration from other MGM server */
+ InitConfigFileParser parser;
+ glob.cluster_config = parser.parseConfig(glob.config_filename);
+ if(glob.cluster_config == 0){
+ /**
+ * Try to get configuration from other MGM server
+ * Note: Only new format
+ */
+ glob.cluster_config = new Config();
+
ConfigRetriever cr;
cr.setLocalConfigFileName(glob.local_config_filename);
- Properties* mgmconf = cr.getConfig("MGM", NDB_VERSION);
- if (mgmconf == NULL)
+ glob.cluster_config->m_configValues = cr.getConfig(NDB_VERSION,
+ NODE_TYPE_MGM);
+ if (glob.cluster_config->m_configValues == NULL)
return false;
- glob.cluster_config = new Config(*mgmconf);
}
return true;
}
@@ -350,15 +357,23 @@ static bool
setPortNo(){
const Properties *mgmProps;
- if(!glob.cluster_config->get("Node", glob.localNodeId, &mgmProps)){
+ ndb_mgm_configuration_iterator * iter =
+ ndb_mgm_create_configuration_iterator(glob.cluster_config->m_configValues,
+ CFG_SECTION_NODE);
+ if(iter == 0)
+ return false;
+
+ if(ndb_mgm_find(iter, CFG_NODE_ID, glob.localNodeId) != 0){
ndbout << "Could not retrieve configuration for Node "
<< glob.localNodeId << " in config file." << endl
<< "Have you set correct NodeId for this node?" << endl;
+ ndb_mgm_destroy_iterator(iter);
return false;
}
- BaseString type;
- if(!mgmProps->get("Type", type) || strcasecmp(type.c_str(), "MGM") != 0){
+ unsigned type;
+ if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0 ||
+ type != NODE_TYPE_MGM){
ndbout << "Local node id " << glob.localNodeId
<< " is not defined as management server" << endl
<< "Have you set correct NodeId for this node?" << endl;
@@ -369,7 +384,7 @@ setPortNo(){
* Set Port *
************/
Uint32 tmp = 0;
- if (!mgmProps->get("PortNumber", &tmp)){
+ if(ndb_mgm_get_int_parameter(iter, CFG_MGM_PORT, &tmp) != 0){
ndbout << "Could not find PortNumber in the configuration file." << endl;
return false;
}
@@ -378,15 +393,18 @@ setPortNo(){
/*****************
* Set Stat Port *
*****************/
+#if 0
if (!mgmProps->get("PortNumberStats", &tmp)){
ndbout << "Could not find PortNumberStats in the configuration file."
<< endl;
return false;
}
glob.port_stats = tmp;
+#endif
- BaseString host;
- if(!mgmProps->get("ExecuteOnComputer", host)){
+#if 0
+ const char * host;
+ if(ndb_mgm_get_string_parameter(iter, mgmProps->get("ExecuteOnComputer", host)){
ndbout << "Failed to find \"ExecuteOnComputer\" for my node" << endl;
ndbout << "Unable to verify own hostname" << endl;
return false;
@@ -422,8 +440,11 @@ setPortNo(){
return true;
}
- glob.use_specific_ip = false;
glob.interface_name = strdup(hostname);
-
+#endif
+
+ glob.interface_name = 0;
+ glob.use_specific_ip = false;
+
return true;
}
diff --git a/ndb/src/mgmsrv/mkconfig/Makefile b/ndb/src/mgmsrv/mkconfig/Makefile
index d35f68a5648..43574eefbd1 100644
--- a/ndb/src/mgmsrv/mkconfig/Makefile
+++ b/ndb/src/mgmsrv/mkconfig/Makefile
@@ -3,12 +3,11 @@ include .defs.mk
TYPE := ndbapi
BIN_TARGET := mkconfig
-BIN_TARGET_ARCHIVES := logger general trace mgmsrvcommon portlib
+BIN_TARGET_ARCHIVES := logger trace mgmsrvcommon portlib general
SOURCES := mkconfig.cpp
CCFLAGS_LOC += -I.. -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
-
-OBJECTS_LOC := ../convertStrToInt.o
+CFLAGS_mkconfig.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/mgmsrv/mkconfig/mkconfig.cpp b/ndb/src/mgmsrv/mkconfig/mkconfig.cpp
index 224c82aa8a1..3b2046d7b49 100644
--- a/ndb/src/mgmsrv/mkconfig/mkconfig.cpp
+++ b/ndb/src/mgmsrv/mkconfig/mkconfig.cpp
@@ -16,6 +16,7 @@
#include <ndb_global.h>
#include <ndb_version.h>
+#include <mgmapi_configuration.hpp>
#include <NdbMain.h>
#include <Properties.hpp>
@@ -36,25 +37,20 @@ NDB_COMMAND(mkconfig,
return 0;
}
- InitConfigFileParser parser(argv[1]);
- Config* cp;
+ InitConfigFileParser parser;
+ Config* _cp;
- if (!parser.readConfigFile())
+ if ((_cp = parser.parseConfig(argv[1])) == 0)
return false;
- cp = (Config *) parser.getConfig();
- if (cp == NULL)
- return false;
-
- cp->put("VersionId", (Uint32)NDB_VERSION);
-
+ ConfigValues* cp = &_cp->m_configValues->m_config;
Uint32 sz = cp->getPackedSize();
- Uint32 * buf = new Uint32[sz];
+ UtilBuffer buf;
if(!cp->pack(buf))
return -1;
-
+
FILE * f = fopen(argv[2], "w");
- if(fwrite(buf, 1, sz, f) != sz){
+ if(fwrite(buf.get_data(), 1, buf.length(), f) != sz){
fclose(f);
unlink(argv[2]);
return -1;
diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp
index 1b536b6d741..b26d550fe31 100644
--- a/ndb/src/ndbapi/ClusterMgr.cpp
+++ b/ndb/src/ndbapi/ClusterMgr.cpp
@@ -21,7 +21,6 @@
#include "TransporterFacade.hpp"
#include "ClusterMgr.hpp"
#include <IPCConfig.hpp>
-#include "AttrType.hpp"
#include "NdbApiSignal.hpp"
#include "API.hpp"
#include <NdbSleep.h>
@@ -33,6 +32,10 @@
#include <signaldata/NFCompleteRep.hpp>
#include <signaldata/ApiRegSignalData.hpp>
+#include <mgmapi.h>
+#include <mgmapi_configuration.hpp>
+#include <mgmapi_config_parameters.h>
+
// Just a C wrapper for threadMain
extern "C"
void*
@@ -70,32 +73,49 @@ ClusterMgr::~ClusterMgr(){
}
void
-ClusterMgr::init(const IPCConfig & config){
- NodeId tmp = 0;
- while(config.getNextRemoteNodeId(tmp)) {
+ClusterMgr::init(ndb_mgm_configuration_iterator & iter){
+ for(iter.first(); iter.valid(); iter.next()){
+ Uint32 tmp = 0;
+ if(iter.get(CFG_NODE_ID, &tmp))
+ continue;
+
theNodes[tmp].defined = true;
#if 0
ndbout << "--------------------------------------" << endl;
- config.print();
ndbout << "--------------------------------------" << endl;
ndbout_c("ClusterMgr: Node %d defined as %s", tmp, config.getNodeType(tmp));
#endif
- if(strcmp(config.getNodeType(tmp), "DB") == 0) {
+
+ unsigned type;
+ if(iter.get(CFG_TYPE_OF_SECTION, &type))
+ continue;
+
+ switch(type){
+ case NODE_TYPE_DB:
theNodes[tmp].m_info.m_type = NodeInfo::DB;
- } else if(strcmp(config.getNodeType(tmp), "API") == 0) {
+ break;
+ case NODE_TYPE_API:
theNodes[tmp].m_info.m_type = NodeInfo::API;
- } else if(strcmp(config.getNodeType(tmp), "MGM") == 0) {
+ break;
+ case NODE_TYPE_MGM:
theNodes[tmp].m_info.m_type = NodeInfo::MGM;
- } else if(strcmp(config.getNodeType(tmp), "REP") == 0) {
+ break;
+ case NODE_TYPE_REP:
theNodes[tmp].m_info.m_type = NodeInfo::REP;
- } else if(strcmp(config.getNodeType(tmp), "EXTERNAL REP") == 0) {
+ break;
+ case NODE_TYPE_EXT_REP:
theNodes[tmp].m_info.m_type = NodeInfo::REP;
- theNodes[tmp].hbFrequency = config.getREPHBFrequency(tmp);
- assert(100 <= theNodes[tmp].hbFrequency &&
- theNodes[tmp].hbFrequency < 60 * 60 * 1000);
- } else {
+ {
+ Uint32 hbFreq = 10000;
+ //ndb_mgm_get_int_parameter(iter, CFG_, &hbFreq);
+ theNodes[tmp].hbFrequency = hbFreq;
+ assert(100 <= hbFreq && hbFreq < 60 * 60 * 1000);
+ }
+ break;
+ default:
+ type = type;
#if 0
- ndbout_c("ClusterMgr: Unknown node type: %s", config.getNodeType(tmp));
+ ndbout_c("ClusterMgr: Unknown node type: %d", type);
#endif
}
}
@@ -163,45 +183,43 @@ ClusterMgr::threadMain( ){
const NodeId nodeId = i;
Node & theNode = theNodes[nodeId];
- if (theNode.defined == true) {
-#if 0
- ndbout_c("ClusterMgr: compatible %d", (int)nodeId);
-#endif
+ if (!theNode.defined)
+ continue;
- if (theNode.connected == false){
- theFacade.doConnect(nodeId);
- continue;
+ if (theNode.connected == false){
+ theFacade.doConnect(nodeId);
+ continue;
+ }
+
+ if (!theNode.compatible){
+ continue;
+ }
+
+ theNode.hbCounter += timeSlept;
+ if (theNode.hbCounter >= theNode.hbFrequency){
+ /**
+ * It is now time to send a new Heartbeat
+ */
+ theNode.hbSent++;
+ theNode.hbCounter = 0;
+ /**
+ * If the node is of type REP,
+ * then the receiver of the signal should be API_CLUSTERMGR
+ */
+ if (theNode.m_info.m_type == NodeInfo::REP) {
+ signal.theReceiversBlockNumber = API_CLUSTERMGR;
}
-
-#if 0
- ndbout_c("ClusterMgr: connected %d", (int)nodeId);
+#if 0
+ ndbout_c("ClusterMgr: Sending API_REGREQ to node %d", (int)nodeId);
#endif
-
- theNode.hbCounter += timeSlept;
- if (theNode.hbCounter >= theNode.hbFrequency){
- /**
- * It is now time to send a new Heartbeat
- */
- theNode.hbSent++;
- theNode.hbCounter = 0;
- /**
- * If the node is of type REP,
- * then the receiver of the signal should be API_CLUSTERMGR
- */
- if (theNode.m_info.m_type == NodeInfo::REP) {
- signal.theReceiversBlockNumber = API_CLUSTERMGR;
- }
-#if 0
- ndbout_c("ClusterMgr: Sending API_REGREQ to node %d", (int)nodeId);
-#endif
- theFacade.sendSignalUnCond(&signal, nodeId);
- }//if
-
- if (theNode.hbSent == 4 && theNode.hbFrequency > 0){
- reportNodeFailed(i);
- }//if
- }//if(defined)
- }//for
+ theFacade.sendSignalUnCond(&signal, nodeId);
+ }//if
+
+ if (theNode.hbSent == 4 && theNode.hbFrequency > 0){
+ reportNodeFailed(i);
+ }//if
+ }
+
/**
* End of secure area. Let other threads in
*/
@@ -282,6 +300,10 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
const ApiRegConf * const apiRegConf = (ApiRegConf *)&theData[0];
const NodeId nodeId = refToNode(apiRegConf->qmgrRef);
+#if 0
+ ndbout_c("ClusterMgr: Recd API_REGCONF from node %d", nodeId);
+#endif
+
assert(nodeId > 0 && nodeId < MAX_NODES);
Node & node = theNodes[nodeId];
diff --git a/ndb/src/ndbapi/ClusterMgr.hpp b/ndb/src/ndbapi/ClusterMgr.hpp
index 7b7b947742b..cc3cf66c8aa 100644
--- a/ndb/src/ndbapi/ClusterMgr.hpp
+++ b/ndb/src/ndbapi/ClusterMgr.hpp
@@ -40,7 +40,7 @@ class ClusterMgr {
public:
ClusterMgr(class TransporterFacade &);
~ClusterMgr();
- void init(const IPCConfig & config);
+ void init(struct ndb_mgm_configuration_iterator & config);
void reportConnected(NodeId nodeId);
void reportDisconnected(NodeId nodeId);
@@ -114,7 +114,7 @@ ClusterMgr::getNoOfConnectedNodes() const {
return noOfConnectedNodes;
}
-/******************************************************************************/
+/*****************************************************************************/
/**
* @class ArbitMgr
diff --git a/ndb/src/ndbapi/DictCache.hpp b/ndb/src/ndbapi/DictCache.hpp
index e59793bbc09..098acc9006a 100644
--- a/ndb/src/ndbapi/DictCache.hpp
+++ b/ndb/src/ndbapi/DictCache.hpp
@@ -56,13 +56,14 @@ public:
NdbTableImpl* put(const char * name, NdbTableImpl *);
void drop(NdbTableImpl *);
void release(NdbTableImpl *);
-private:
+public:
enum Status {
OK = 0,
DROPPED = 1,
RETREIVING = 2
};
+private:
struct TableVersion {
Uint32 m_version;
Uint32 m_refCount;
diff --git a/ndb/src/ndbapi/Makefile b/ndb/src/ndbapi/Makefile
deleted file mode 100644
index f4c82e5d6ba..00000000000
--- a/ndb/src/ndbapi/Makefile
+++ /dev/null
@@ -1,63 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi
-
-PIC_ARCHIVE := Y
-NONPIC_ARCHIVE := Y
-ARCHIVE_TARGET := ndbapi
-
-A_LIB := Y
-SO_LIB := Y
-PIC_LIB := Y
-LIB_TARGET := NDB_API
-
-LIB_TARGET_ARCHIVES := $(ARCHIVE_TARGET) \
- transporter \
- general \
- signaldataprint \
- mgmsrvcommon \
- portlib \
- logger \
- trace
-
-DIRS := signal-sender
-
-# Source files of non-templated classes (.cpp files)
-SOURCES = \
- TransporterFacade.cpp \
- ClusterMgr.cpp \
- Ndb.cpp \
- NdbPoolImpl.cpp NdbPool.cpp \
- Ndblist.cpp \
- Ndbif.cpp \
- Ndbinit.cpp \
- Ndberr.cpp \
- ndberror.c \
- NdbErrorOut.cpp \
- NdbConnection.cpp \
- NdbConnectionScan.cpp \
- NdbOperation.cpp \
- NdbOperationSearch.cpp \
- NdbOperationScan.cpp \
- NdbOperationInt.cpp \
- NdbOperationDefine.cpp \
- NdbOperationExec.cpp \
- NdbScanReceiver.cpp \
- NdbResultSet.cpp \
- NdbCursorOperation.cpp \
- NdbScanOperation.cpp NdbScanFilter.cpp \
- NdbIndexOperation.cpp \
- NdbEventOperation.cpp \
- NdbEventOperationImpl.cpp \
- NdbApiSignal.cpp \
- NdbRecAttr.cpp \
- NdbSchemaCon.cpp \
- NdbSchemaOp.cpp \
- NdbUtil.cpp \
- NdbReceiver.cpp \
- NdbDictionary.cpp NdbDictionaryImpl.cpp DictCache.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
-###
-# Backward compatible
diff --git a/ndb/src/ndbapi/Makefile.am b/ndb/src/ndbapi/Makefile.am
new file mode 100644
index 00000000000..2ec58ab6e85
--- /dev/null
+++ b/ndb/src/ndbapi/Makefile.am
@@ -0,0 +1,50 @@
+#SUBDIRS = signal-sender
+
+noinst_LTLIBRARIES = libndbapi.la
+
+libndbapi_la_SOURCES = \
+ TransporterFacade.cpp \
+ ClusterMgr.cpp \
+ Ndb.cpp \
+ NdbPoolImpl.cpp \
+ NdbPool.cpp \
+ Ndblist.cpp \
+ Ndbif.cpp \
+ Ndbinit.cpp \
+ Ndberr.cpp \
+ ndberror.c \
+ NdbErrorOut.cpp \
+ NdbConnection.cpp \
+ NdbConnectionScan.cpp \
+ NdbOperation.cpp \
+ NdbOperationSearch.cpp \
+ NdbOperationScan.cpp \
+ NdbOperationInt.cpp \
+ NdbOperationDefine.cpp \
+ NdbOperationExec.cpp \
+ NdbResultSet.cpp \
+ NdbCursorOperation.cpp \
+ NdbScanReceiver.cpp NdbScanOperation.cpp \
+ NdbScanFilter.cpp \
+ NdbIndexOperation.cpp \
+ NdbEventOperation.cpp \
+ NdbEventOperationImpl.cpp \
+ NdbApiSignal.cpp \
+ NdbRecAttr.cpp \
+ NdbUtil.cpp \
+ NdbReceiver.cpp \
+ NdbDictionary.cpp \
+ NdbDictionaryImpl.cpp \
+ DictCache.cpp \
+ NdbBlob.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi
+
+# Ndbapi cannot handle -O3
+NDB_CXXFLAGS_RELEASE_LOC = -O2
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/src/ndbapi/Makefile_old b/ndb/src/ndbapi/Makefile_old
new file mode 100644
index 00000000000..c2bb0189a7f
--- /dev/null
+++ b/ndb/src/ndbapi/Makefile_old
@@ -0,0 +1,67 @@
+include .defs.mk
+
+TYPE := ndbapi
+
+PIC_ARCHIVE := Y
+NONPIC_ARCHIVE := Y
+ARCHIVE_TARGET := ndbapi
+
+A_LIB := Y
+SO_LIB := Y
+PIC_LIB := Y
+LIB_TARGET := NDB_API
+
+LIB_TARGET_ARCHIVES := $(ARCHIVE_TARGET) \
+ transporter \
+ general \
+ signaldataprint \
+ mgmapi mgmsrvcommon \
+ portlib \
+ logger \
+ trace
+
+DIRS := signal-sender
+
+CFLAGS_TransporterFacade.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
+CFLAGS_ClusterMgr.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
+
+# Source files of non-templated classes (.cpp files)
+SOURCES = \
+ TransporterFacade.cpp \
+ ClusterMgr.cpp \
+ Ndb.cpp \
+ NdbPoolImpl.cpp NdbPool.cpp \
+ Ndblist.cpp \
+ Ndbif.cpp \
+ Ndbinit.cpp \
+ Ndberr.cpp \
+ ndberror.c \
+ NdbErrorOut.cpp \
+ NdbConnection.cpp \
+ NdbConnectionScan.cpp \
+ NdbOperation.cpp \
+ NdbOperationSearch.cpp \
+ NdbOperationScan.cpp \
+ NdbOperationInt.cpp \
+ NdbOperationDefine.cpp \
+ NdbOperationExec.cpp \
+ NdbScanReceiver.cpp \
+ NdbResultSet.cpp \
+ NdbCursorOperation.cpp \
+ NdbScanOperation.cpp NdbScanFilter.cpp \
+ NdbIndexOperation.cpp \
+ NdbEventOperation.cpp \
+ NdbEventOperationImpl.cpp \
+ NdbApiSignal.cpp \
+ NdbRecAttr.cpp \
+ NdbSchemaCon.cpp \
+ NdbSchemaOp.cpp \
+ NdbUtil.cpp \
+ NdbReceiver.cpp \
+ NdbDictionary.cpp NdbDictionaryImpl.cpp DictCache.cpp \
+ NdbBlob.cpp
+
+include $(NDB_TOP)/Epilogue.mk
+
+###
+# Backward compatible
diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp
index 448a29ca485..fe7260c4693 100644
--- a/ndb/src/ndbapi/Ndb.cpp
+++ b/ndb/src/ndbapi/Ndb.cpp
@@ -26,8 +26,6 @@ Name: Ndb.cpp
#include "NdbApiSignal.hpp"
#include "NdbImpl.hpp"
-#include "NdbSchemaOp.hpp"
-#include "NdbSchemaCon.hpp"
#include <NdbOperation.hpp>
#include <NdbConnection.hpp>
#include <NdbEventOperation.hpp>
@@ -40,8 +38,6 @@ Name: Ndb.cpp
#include <NdbEnv.h>
#include <BaseString.hpp>
-static bool fullyQualifiedNames = true;
-
/****************************************************************************
void connect();
@@ -155,7 +151,7 @@ Ndb::NDB_connect(Uint32 tNode)
// Set connection pointer as NdbConnection object
//************************************************
tSignal->setData(theMyRef, 2); // Set my block reference
- tNdbCon->Status(Connecting); // Set status to connecting
+ tNdbCon->Status(NdbConnection::Connecting); // Set status to connecting
Uint32 nodeSequence;
{ // send and receive signal
tp->lock_mutex();
@@ -178,7 +174,7 @@ Ndb::NDB_connect(Uint32 tNode)
}//if
}
- if ((tReturnCode == 0) && (tNdbCon->Status() == Connected)) {
+ if ((tReturnCode == 0) && (tNdbCon->Status() == NdbConnection::Connected)) {
//************************************************
// Send and receive was successful
//************************************************
@@ -434,7 +430,7 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
theFirstTransId = tFirstTransId + 1;
}//if
#ifdef VM_TRACE
- if (tConnection->theListState != NotInList) {
+ if (tConnection->theListState != NdbConnection::NotInList) {
printState("startTransactionLocal %x", tConnection);
abort();
}
@@ -476,6 +472,19 @@ Ndb::closeTransaction(NdbConnection* aConnection)
//-----------------------------------------------------
// closeTransaction called on non-existing transaction
//-----------------------------------------------------
+
+ if(aConnection->theError.code == 4008){
+ /**
+ * When a SCAN timed-out, returning the NdbConnection leads
+ * to reuse. And TC crashes when the API tries to reuse it to
+ * something else...
+ */
+#ifdef VM_TRACE
+ printf("Scan timeout:ed NdbConnection-> not returning it-> memory leak\n");
+#endif
+ return;
+ }
+
#ifdef VM_TRACE
printf("Non-existing transaction into closeTransaction\n");
abort();
@@ -589,7 +598,7 @@ Ndb::NdbTamper(TamperType aAction, int aNode)
tSignal.setData (tAction, 1);
tSignal.setData(tNdbConn->ptr2int(),2);
tSignal.setData(theMyRef,3); // Set return block reference
- tNdbConn->Status(Connecting); // Set status to connecting
+ tNdbConn->Status(NdbConnection::Connecting); // Set status to connecting
TransporterFacade *tp = TransporterFacade::instance();
if (tAction == 3) {
tp->lock_mutex();
@@ -622,7 +631,7 @@ Ndb::NdbTamper(TamperType aAction, int aNode)
}//if
ret_code = sendRecSignal(tNode, WAIT_NDB_TAMPER, &tSignal, 0);
if (ret_code == 0) {
- if (tNdbConn->Status() != Connected) {
+ if (tNdbConn->Status() != NdbConnection::Connected) {
theRestartGCI = 0;
}//if
releaseNdbCon(tNdbConn);
@@ -637,6 +646,7 @@ Ndb::NdbTamper(TamperType aAction, int aNode)
return 0;
#endif
}
+#if 0
/****************************************************************************
NdbSchemaCon* startSchemaTransaction();
@@ -678,7 +688,7 @@ Ndb::closeSchemaTransaction(NdbSchemaCon* aSchemaCon)
theSchemaConToNdbList = NULL;
return;
}//Ndb::closeSchemaTransaction()
-
+#endif
/*****************************************************************************
void RestartGCI(int aRestartGCI);
@@ -826,7 +836,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
tOperation->interpretedUpdateTuple();
tOperation->equal("SYSKEY_0", aTableId );
{
-#ifdef NDB_SOLARIS
+#ifdef WORDS_BIGENDIAN
Uint64 cacheSize64 = opValue; // XXX interpreter bug on Uint32
tOperation->incValue("NEXTID", cacheSize64);
#else
@@ -992,7 +1002,7 @@ Ndb::StartTransactionNodeSelectionData::release(){
Uint32
convertEndian(Uint32 Data)
{
-#ifdef _BIG_ENDIAN
+#ifdef WORDS_BIGENDIAN
Uint32 t1, t2, t3, t4;
t4 = (Data >> 24) & 255;
t3 = (Data >> 16) & 255;
@@ -1014,18 +1024,14 @@ const char * Ndb::getCatalogName() const
void Ndb::setCatalogName(const char * a_catalog_name)
{
if (a_catalog_name) {
- strncpy(theDataBase, a_catalog_name, NDB_MAX_DATABASE_NAME_SIZE);
- // Prepare prefix for faster operations
- uint db_len = MIN(strlen(theDataBase), NDB_MAX_DATABASE_NAME_SIZE - 1);
- uint schema_len =
- MIN(strlen(theDataBaseSchema), NDB_MAX_SCHEMA_NAME_SIZE - 1);
- strncpy(prefixName, theDataBase, NDB_MAX_DATABASE_NAME_SIZE - 1);
- prefixName[db_len] = '/';
- strncpy(prefixName+db_len+1, theDataBaseSchema,
- NDB_MAX_SCHEMA_NAME_SIZE - 1);
- prefixName[db_len+schema_len+1] = '/';
- prefixName[db_len+schema_len+2] = '\0';
- prefixEnd = prefixName + db_len+schema_len + 2;
+ snprintf(theDataBase, sizeof(theDataBase), "%s",
+ a_catalog_name ? a_catalog_name : "");
+
+ int len = snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
+ theDataBase, table_name_separator,
+ theDataBaseSchema, table_name_separator);
+ prefixEnd = prefixName + (len < sizeof(prefixName) ? len :
+ sizeof(prefixName) - 1);
}
}
@@ -1037,18 +1043,14 @@ const char * Ndb::getSchemaName() const
void Ndb::setSchemaName(const char * a_schema_name)
{
if (a_schema_name) {
- strncpy(theDataBaseSchema, a_schema_name, NDB_MAX_SCHEMA_NAME_SIZE);
- // Prepare prefix for faster operations
- uint db_len = MIN(strlen(theDataBase), NDB_MAX_DATABASE_NAME_SIZE - 1);
- uint schema_len =
- MIN(strlen(theDataBaseSchema), NDB_MAX_SCHEMA_NAME_SIZE - 1);
- strncpy(prefixName, theDataBase, NDB_MAX_DATABASE_NAME_SIZE - 1);
- prefixName[db_len] = '/';
- strncpy(prefixName+db_len+1, theDataBaseSchema,
- NDB_MAX_SCHEMA_NAME_SIZE - 1);
- prefixName[db_len+schema_len+1] = '/';
- prefixName[db_len+schema_len+2] = '\0';
- prefixEnd = prefixName + db_len+schema_len + 2;
+ snprintf(theDataBaseSchema, sizeof(theDataBase), "%s",
+ a_schema_name ? a_schema_name : "");
+
+ int len = snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
+ theDataBase, table_name_separator,
+ theDataBaseSchema, table_name_separator);
+ prefixEnd = prefixName + (len < sizeof(prefixName) ? len :
+ sizeof(prefixName) - 1);
}
}
@@ -1086,43 +1088,36 @@ bool Ndb::usingFullyQualifiedNames()
}
const char *
-Ndb::externalizeTableName(const char * internalTableName)
+Ndb::externalizeTableName(const char * internalTableName, bool fullyQualifiedNames)
{
if (fullyQualifiedNames) {
register const char *ptr = internalTableName;
// Skip database name
- while (*ptr && *ptr++ != '/');
+ while (*ptr && *ptr++ != table_name_separator);
// Skip schema name
- while (*ptr && *ptr++ != '/');
-
+ while (*ptr && *ptr++ != table_name_separator);
return ptr;
}
else
return internalTableName;
}
-
const char *
-Ndb::internalizeTableName(const char * externalTableName)
+Ndb::externalizeTableName(const char * internalTableName)
{
- if (fullyQualifiedNames) {
- strncpy(prefixEnd, externalTableName, NDB_MAX_TAB_NAME_SIZE);
- return prefixName;
- }
- else
- return externalTableName;
+ return externalizeTableName(internalTableName, usingFullyQualifiedNames());
}
-
+
const char *
-Ndb::externalizeIndexName(const char * internalIndexName)
+Ndb::externalizeIndexName(const char * internalIndexName, bool fullyQualifiedNames)
{
if (fullyQualifiedNames) {
register const char *ptr = internalIndexName;
// Scan name from the end
while (*ptr++); ptr--; // strend
- while (ptr >= internalIndexName && *ptr != '/')
+ while (ptr >= internalIndexName && *ptr != table_name_separator)
ptr--;
return ptr + 1;
@@ -1130,6 +1125,23 @@ Ndb::externalizeIndexName(const char * internalIndexName)
else
return internalIndexName;
}
+
+const char *
+Ndb::externalizeIndexName(const char * internalIndexName)
+{
+ return externalizeIndexName(internalIndexName, usingFullyQualifiedNames());
+}
+
+const char *
+Ndb::internalizeTableName(const char * externalTableName)
+{
+ if (fullyQualifiedNames) {
+ strncpy(prefixEnd, externalTableName, NDB_MAX_TAB_NAME_SIZE);
+ return prefixName;
+ }
+ else
+ return externalTableName;
+}
const char *
Ndb::internalizeIndexName(const NdbTableImpl * table,
@@ -1140,7 +1152,7 @@ Ndb::internalizeIndexName(const NdbTableImpl * table,
sprintf(tableId, "%d", table->m_tableId);
Uint32 tabIdLen = strlen(tableId);
strncpy(prefixEnd, tableId, tabIdLen);
- prefixEnd[tabIdLen] = '/';
+ prefixEnd[tabIdLen] = table_name_separator;
strncpy(prefixEnd + tabIdLen + 1,
externalIndexName, NDB_MAX_TAB_NAME_SIZE);
return prefixName;
@@ -1156,8 +1168,8 @@ Ndb::getDatabaseFromInternalName(const char * internalName)
strcpy(databaseName, internalName);
register char *ptr = databaseName;
- /* Scan name for the first '/' */
- while (*ptr && *ptr != '/')
+ /* Scan name for the first table_name_separator */
+ while (*ptr && *ptr != table_name_separator)
ptr++;
*ptr = '\0';
BaseString ret = BaseString(databaseName);
@@ -1171,12 +1183,12 @@ Ndb::getSchemaFromInternalName(const char * internalName)
char * schemaName = new char[strlen(internalName)];
register const char *ptr1 = internalName;
- /* Scan name for the second '/' */
- while (*ptr1 && *ptr1 != '/')
+ /* Scan name for the second table_name_separator */
+ while (*ptr1 && *ptr1 != table_name_separator)
ptr1++;
strcpy(schemaName, ptr1 + 1);
register char *ptr = schemaName;
- while (*ptr && *ptr != '/')
+ while (*ptr && *ptr != table_name_separator)
ptr++;
*ptr = '\0';
BaseString ret = BaseString(schemaName);
diff --git a/ndb/src/ndbapi/NdbApiSignal.cpp b/ndb/src/ndbapi/NdbApiSignal.cpp
index a9cd5b1d53a..a44937cd398 100644
--- a/ndb/src/ndbapi/NdbApiSignal.cpp
+++ b/ndb/src/ndbapi/NdbApiSignal.cpp
@@ -29,7 +29,6 @@ Adjust: 971114 UABMNST First version.
******************************************************************************/
#include "API.hpp"
#include "NdbApiSignal.hpp"
-#include <AttrType.hpp>
/**
* The following include includes
diff --git a/ndb/src/ndbapi/NdbApiSignal.hpp b/ndb/src/ndbapi/NdbApiSignal.hpp
index 76cefe0e882..9d5bc0847be 100644
--- a/ndb/src/ndbapi/NdbApiSignal.hpp
+++ b/ndb/src/ndbapi/NdbApiSignal.hpp
@@ -31,7 +31,6 @@
#define NdbApiSignal_H
#include <kernel_types.h>
-#include "AttrType.hpp"
#include "TransporterFacade.hpp"
#include <TransporterDefinitions.hpp>
#include "Ndb.hpp"
diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp
new file mode 100644
index 00000000000..8e067f770e8
--- /dev/null
+++ b/ndb/src/ndbapi/NdbBlob.cpp
@@ -0,0 +1,1349 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Ndb.hpp"
+#include "NdbDictionaryImpl.hpp"
+#include "NdbConnection.hpp"
+#include "NdbOperation.hpp"
+#include "NdbIndexOperation.hpp"
+#include "NdbRecAttr.hpp"
+#include "NdbBlob.hpp"
+
+#ifdef NDB_BLOB_DEBUG
+#define DBG(x) \
+ do { \
+ static const char* p = getenv("NDB_BLOB_DEBUG"); \
+ if (p == 0 || *p == 0 || *p == '0') break; \
+ const char* cname = theColumn == NULL ? "BLOB" : theColumn->m_name.c_str(); \
+ ndbout << cname << " " << __LINE__ << " " << x << " " << *this << endl; \
+ } while (0)
+#define EXE() assert(theNdbCon->executeNoBlobs(NoCommit) == 0)
+#else
+#define DBG(x)
+#endif
+
+static char*
+ndb_blob_debug(const Uint32* data, unsigned size)
+{
+ static char buf[128 + 1]; // MT irrelevant
+ buf[0] = 0;
+ for (unsigned i = 0; i < size && i < 128 / 4; i++) {
+ sprintf(buf + strlen(buf), "%*s%08x", i != 0, "", data[i]);
+ }
+ return buf;
+}
+
+/*
+ * Reading index table directly (as a table) is faster but there are
+ * bugs or limitations. Keep the code but make possible to choose.
+ */
+static const bool g_ndb_blob_ok_to_read_index_table = false;
+
+// state (inline)
+
+inline void
+NdbBlob::setState(State newState)
+{
+ DBG("setState " << newState);
+ theState = newState;
+}
+
+// define blob table
+
+int
+NdbBlob::getBlobTableName(char* btname, Ndb* anNdb, const char* tableName, const char* columnName)
+{
+ NdbTableImpl* t = anNdb->theDictionary->m_impl.getTable(tableName);
+ if (t == NULL)
+ return -1;
+ NdbColumnImpl* c = t->getColumn(columnName);
+ if (c == NULL)
+ return -1;
+ getBlobTableName(btname, t, c);
+ return 0;
+}
+
+void
+NdbBlob::getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnImpl* c)
+{
+ assert(t != 0 && c != 0 && c->getBlobType());
+ memset(btname, 0, BlobTableNameSize);
+ sprintf(btname, "NDB$BLOB_%d_%d_%d", (int)t->m_tableId, (int)t->m_version, (int)c->m_attrId);
+}
+
+void
+NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnImpl* c)
+{
+ char btname[BlobTableNameSize];
+ getBlobTableName(btname, t, c);
+ bt.setName(btname);
+ bt.setLogging(t->getLogging());
+ bt.setFragmentType(t->getFragmentType());
+ { NdbDictionary::Column bc("DIST");
+ bc.setType(NdbDictionary::Column::Unsigned);
+ bc.setPrimaryKey(true);
+ bc.setDistributionKey(true);
+ bt.addColumn(bc);
+ }
+ { NdbDictionary::Column bc("PART");
+ bc.setType(NdbDictionary::Column::Unsigned);
+ bc.setPrimaryKey(true);
+ bt.addColumn(bc);
+ }
+ { NdbDictionary::Column bc("PK");
+ bc.setType(NdbDictionary::Column::Unsigned);
+ assert(t->m_sizeOfKeysInWords != 0);
+ bc.setLength(t->m_sizeOfKeysInWords);
+ bc.setPrimaryKey(true);
+ bt.addColumn(bc);
+ }
+ { NdbDictionary::Column bc("DATA");
+ switch (c->m_type) {
+ case NdbDictionary::Column::Blob:
+ bc.setType(NdbDictionary::Column::Binary);
+ break;
+ case NdbDictionary::Column::Clob:
+ bc.setType(NdbDictionary::Column::Char);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ bc.setLength(c->getPartSize());
+ bt.addColumn(bc);
+ }
+}
+
+// initialization
+
+NdbBlob::NdbBlob()
+{
+ init();
+}
+
+void
+NdbBlob::init()
+{
+ theState = Idle;
+ theBlobTableName[0] = 0;
+ theNdb = NULL;
+ theNdbCon = NULL;
+ theNdbOp = NULL;
+ theTable = NULL;
+ theAccessTable = NULL;
+ theColumn = NULL;
+ theFillChar = 0;
+ theInlineSize = 0;
+ thePartSize = 0;
+ theStripeSize = 0;
+ theGetFlag = false;
+ theGetBuf = NULL;
+ theSetFlag = false;
+ theSetBuf = NULL;
+ theGetSetBytes = 0;
+ theHead = NULL;
+ theInlineData = NULL;
+ theHeadInlineRecAttr = NULL;
+ theHeadInlineUpdateFlag = false;
+ theNewPartFlag = false;
+ theNullFlag = -1;
+ theLength = 0;
+ thePos = 0;
+ theNext = NULL;
+}
+
+void
+NdbBlob::release()
+{
+ setState(Idle);
+}
+
+// buffers
+
+NdbBlob::Buf::Buf() :
+ data(NULL),
+ size(0),
+ maxsize(0)
+{
+}
+
+NdbBlob::Buf::~Buf()
+{
+ delete [] data;
+}
+
+void
+NdbBlob::Buf::alloc(unsigned n)
+{
+ size = n;
+ if (maxsize < n) {
+ delete [] data;
+ // align to Uint64
+ if (n % 8 != 0)
+ n += 8 - n % 8;
+ data = new char [n];
+ maxsize = n;
+ }
+#ifdef VM_TRACE
+ memset(data, 'X', maxsize);
+#endif
+}
+
+// classify operations (inline)
+
+inline bool
+NdbBlob::isTableOp()
+{
+ return theTable == theAccessTable;
+}
+
+inline bool
+NdbBlob::isIndexOp()
+{
+ return theTable != theAccessTable;
+}
+
+inline bool
+NdbBlob::isKeyOp()
+{
+ return
+ theNdbOp->theOperationType == NdbOperation::InsertRequest ||
+ theNdbOp->theOperationType == NdbOperation::UpdateRequest ||
+ theNdbOp->theOperationType == NdbOperation::ReadRequest ||
+ theNdbOp->theOperationType == NdbOperation::ReadExclusive ||
+ theNdbOp->theOperationType == NdbOperation::DeleteRequest;
+}
+
+inline bool
+NdbBlob::isReadOp()
+{
+ return
+ theNdbOp->theOperationType == NdbOperation::ReadRequest ||
+ theNdbOp->theOperationType == NdbOperation::ReadExclusive;
+}
+
+inline bool
+NdbBlob::isInsertOp()
+{
+ return
+ theNdbOp->theOperationType == NdbOperation::InsertRequest;
+}
+
+inline bool
+NdbBlob::isUpdateOp()
+{
+ return
+ theNdbOp->theOperationType == NdbOperation::UpdateRequest;
+}
+
+inline bool
+NdbBlob::isDeleteOp()
+{
+ return
+ theNdbOp->theOperationType == NdbOperation::DeleteRequest;
+}
+
+inline bool
+NdbBlob::isScanOp()
+{
+ return
+ theNdbOp->theOperationType == NdbOperation::OpenScanRequest ||
+ theNdbOp->theOperationType == NdbOperation::OpenRangeScanRequest;
+}
+
+// computations (inline)
+
+inline Uint32
+NdbBlob::getPartNumber(Uint64 pos)
+{
+ assert(pos >= theInlineSize);
+ return (pos - theInlineSize) / thePartSize;
+}
+
+inline Uint32
+NdbBlob::getPartCount()
+{
+ if (theLength <= theInlineSize)
+ return 0;
+ return 1 + getPartNumber(theLength - 1);
+}
+
+inline Uint32
+NdbBlob::getDistKey(Uint32 part)
+{
+ assert(theStripeSize != 0);
+ return (part / theStripeSize) % theStripeSize;
+}
+
+// getters and setters
+
+int
+NdbBlob::getTableKeyValue(NdbOperation* anOp)
+{
+ Uint32* data = (Uint32*)theKeyBuf.data;
+ unsigned pos = 0;
+ DBG("getTableKeyValue");
+ for (unsigned i = 0; i < theTable->m_columns.size(); i++) {
+ NdbColumnImpl* c = theTable->m_columns[i];
+ assert(c != NULL);
+ if (c->m_pk) {
+ unsigned len = c->m_attrSize * c->m_arraySize;
+ if (anOp->getValue(c, (char*)&data[pos]) == NULL) {
+ setErrorCode(anOp);
+ return -1;
+ }
+ // odd bytes receive no data and must be zeroed
+ while (len % 4 != 0) {
+ char* p = (char*)&data[pos] + len++;
+ *p = 0;
+ }
+ pos += len / 4;
+ }
+ }
+ assert(pos == theKeyBuf.size / 4);
+ return 0;
+}
+
+int
+NdbBlob::setTableKeyValue(NdbOperation* anOp)
+{
+ const Uint32* data = (const Uint32*)theKeyBuf.data;
+ unsigned pos = 0;
+ const unsigned size = theTable->m_columns.size();
+ DBG("setTableKeyValue key=" << ndb_blob_debug(data, size));
+ for (unsigned i = 0; i < size; i++) {
+ NdbColumnImpl* c = theTable->m_columns[i];
+ assert(c != NULL);
+ if (c->m_pk) {
+ unsigned len = c->m_attrSize * c->m_arraySize;
+ if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
+ setErrorCode(anOp);
+ return -1;
+ }
+ pos += (len + 3) / 4;
+ }
+ }
+ assert(pos == theKeyBuf.size / 4);
+ return 0;
+}
+
+int
+NdbBlob::setAccessKeyValue(NdbOperation* anOp)
+{
+ const Uint32* data = (const Uint32*)theAccessKeyBuf.data;
+ unsigned pos = 0;
+ const unsigned size = theAccessTable->m_columns.size();
+ DBG("setAccessKeyValue key=" << ndb_blob_debug(data, size));
+ for (unsigned i = 0; i < size; i++) {
+ NdbColumnImpl* c = theAccessTable->m_columns[i];
+ assert(c != NULL);
+ if (c->m_pk) {
+ unsigned len = c->m_attrSize * c->m_arraySize;
+ if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
+ setErrorCode(anOp);
+ return -1;
+ }
+ pos += (len + 3) / 4;
+ }
+ }
+ assert(pos == theAccessKeyBuf.size / 4);
+ return 0;
+}
+
+int
+NdbBlob::setPartKeyValue(NdbOperation* anOp, Uint32 part)
+{
+ Uint32* data = (Uint32*)theKeyBuf.data;
+ unsigned size = theTable->m_sizeOfKeysInWords;
+ DBG("setPartKeyValue dist=" << getDistKey(part) << " part=" << part << " key=" << ndb_blob_debug(data, size));
+ if (anOp->equal((Uint32)0, getDistKey(part)) == -1 ||
+ anOp->equal((Uint32)1, part) == -1 ||
+ anOp->equal((Uint32)2, theKeyBuf.data) == -1) {
+ setErrorCode(anOp);
+ return -1;
+ }
+ return 0;
+}
+
+int
+NdbBlob::getHeadInlineValue(NdbOperation* anOp)
+{
+ DBG("getHeadInlineValue");
+ theHeadInlineRecAttr = anOp->getValue(theColumn, theHeadInlineBuf.data);
+ if (theHeadInlineRecAttr == NULL) {
+ setErrorCode(anOp);
+ return -1;
+ }
+ return 0;
+}
+
+void
+NdbBlob::getHeadFromRecAttr()
+{
+ assert(theHeadInlineRecAttr != NULL);
+ theNullFlag = theHeadInlineRecAttr->isNULL();
+ assert(theNullFlag != -1);
+ theLength = ! theNullFlag ? theHead->length : 0;
+ DBG("getHeadFromRecAttr out");
+}
+
+int
+NdbBlob::setHeadInlineValue(NdbOperation* anOp)
+{
+ DBG("setHeadInlineValue");
+ theHead->length = theLength;
+ if (theLength < theInlineSize)
+ memset(theInlineData + theLength, 0, theInlineSize - theLength);
+ assert(theNullFlag != -1);
+ const char* aValue = theNullFlag ? 0 : theHeadInlineBuf.data;
+ if (anOp->setValue(theColumn, aValue, theHeadInlineBuf.size) == -1) {
+ setErrorCode(anOp);
+ return -1;
+ }
+ theHeadInlineUpdateFlag = false;
+ return 0;
+}
+
+// getValue/setValue
+
+int
+NdbBlob::getValue(void* data, Uint32 bytes)
+{
+ DBG("getValue data=" << hex << data << " bytes=" << dec << bytes);
+ if (theGetFlag || theState != Prepared) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ if (! isReadOp() && ! isScanOp()) {
+ setErrorCode(ErrUsage);
+ return -1;
+ }
+ if (data == NULL && bytes != 0) {
+ setErrorCode(ErrUsage);
+ return -1;
+ }
+ theGetFlag = true;
+ theGetBuf = static_cast<char*>(data);
+ theGetSetBytes = bytes;
+ return 0;
+}
+
+int
+NdbBlob::setValue(const void* data, Uint32 bytes)
+{
+ DBG("setValue data=" << hex << data << " bytes=" << dec << bytes);
+ if (theSetFlag || theState != Prepared) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ if (! isInsertOp() && ! isUpdateOp()) {
+ setErrorCode(ErrUsage);
+ return -1;
+ }
+ if (data == NULL && bytes != 0) {
+ setErrorCode(ErrUsage);
+ return -1;
+ }
+ theSetFlag = true;
+ theSetBuf = static_cast<const char*>(data);
+ theGetSetBytes = bytes;
+ if (isInsertOp()) {
+ // write inline part now
+ if (theSetBuf != 0) {
+ unsigned n = theGetSetBytes;
+ if (n > theInlineSize)
+ n = theInlineSize;
+ if (writeDataPrivate(0, theSetBuf, n) == -1)
+ return -1;
+ } else {
+ theNullFlag = true;
+ theLength = 0;
+ }
+ if (setHeadInlineValue(theNdbOp) == -1)
+ return -1;
+ }
+ return 0;
+}
+
+// misc operations
+
+int
+NdbBlob::getNull(bool& isNull)
+{
+ if (theState == Prepared && theSetFlag) {
+ isNull = (theSetBuf == NULL);
+ return 0;
+ }
+ if (theNullFlag == -1) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ isNull = theNullFlag;
+ return 0;
+}
+
+int
+NdbBlob::setNull()
+{
+ DBG("setNull");
+ if (theNullFlag == -1) {
+ if (theState == Prepared) {
+ return setValue(0, 0);
+ }
+ setErrorCode(ErrState);
+ return -1;
+ }
+ if (theNullFlag)
+ return 0;
+ if (deleteParts(0, getPartCount()) == -1)
+ return -1;
+ theNullFlag = true;
+ theLength = 0;
+ theHeadInlineUpdateFlag = true;
+ return 0;
+}
+
+int
+NdbBlob::getLength(Uint64& len)
+{
+ if (theState == Prepared && theSetFlag) {
+ len = theGetSetBytes;
+ return 0;
+ }
+ if (theNullFlag == -1) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ len = theLength;
+ return 0;
+}
+
+int
+NdbBlob::truncate(Uint64 length)
+{
+ DBG("truncate kength=" << length);
+ if (theNullFlag == -1) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ if (theLength > length) {
+ if (length >= theInlineSize) {
+ Uint32 part1 = getPartNumber(length);
+ Uint32 part2 = getPartNumber(theLength - 1);
+ assert(part2 >= part1);
+ if (deleteParts(part1, part2 - part1) == -1)
+ return -1;
+ } else {
+ if (deleteParts(0, getPartCount()) == -1)
+ return -1;
+ }
+ theLength = length;
+ theHeadInlineUpdateFlag = true;
+ }
+ return 0;
+}
+
+int
+NdbBlob::getPos(Uint64& pos)
+{
+ if (theNullFlag == -1) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ pos = thePos;
+ return 0;
+}
+
+int
+NdbBlob::setPos(Uint64 pos)
+{
+ if (theNullFlag == -1) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ if (pos > theLength) {
+ setErrorCode(ErrSeek);
+ return -1;
+ }
+ thePos = pos;
+ return 0;
+}
+
+// read/write
+
+int
+NdbBlob::readData(void* data, Uint32& bytes)
+{
+ if (readData(thePos, data, bytes) == -1)
+ return -1;
+ thePos += bytes;
+ assert(thePos <= theLength);
+ return 0;
+}
+
+int
+NdbBlob::readData(Uint64 pos, void* data, Uint32& bytes)
+{
+ if (theState != Active) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ char* buf = static_cast<char*>(data);
+ return readDataPrivate(pos, buf, bytes);
+}
+
+int
+NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
+{
+ DBG("readData pos=" << pos << " bytes=" << bytes);
+ if (pos > theLength) {
+ setErrorCode(ErrSeek);
+ return -1;
+ }
+ if (bytes > theLength - pos)
+ bytes = theLength - pos;
+ Uint32 len = bytes;
+ if (len > 0) {
+ // inline part
+ if (pos < theInlineSize) {
+ Uint32 n = theInlineSize - pos;
+ if (n > len)
+ n = len;
+ memcpy(buf, theInlineData + pos, n);
+ pos += n;
+ buf += n;
+ len -= n;
+ }
+ }
+ if (len > 0) {
+ assert(pos >= theInlineSize);
+ Uint32 off = (pos - theInlineSize) % thePartSize;
+ // partial first block
+ if (off != 0) {
+ DBG("partial first block pos=" << pos << " len=" << len);
+ Uint32 part = (pos - theInlineSize) / thePartSize;
+ if (readParts(thePartBuf.data, part, 1) == -1)
+ return -1;
+ DBG("force execute");
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
+ setErrorCode(theNdbOp);
+ return -1;
+ }
+ Uint32 n = thePartSize - off;
+ if (n > len)
+ n = len;
+ memcpy(buf, thePartBuf.data + off, n);
+ pos += n;
+ buf += n;
+ len -= n;
+ }
+ }
+ if (len > 0) {
+ assert((pos - theInlineSize) % thePartSize == 0);
+ // complete blocks in the middle
+ if (len >= thePartSize) {
+ Uint32 part = (pos - theInlineSize) / thePartSize;
+ Uint32 count = len / thePartSize;
+ if (readParts(buf, part, count) == -1)
+ return -1;
+ Uint32 n = thePartSize * count;
+ pos += n;
+ buf += n;
+ len -= n;
+ }
+ }
+ if (len > 0) {
+ // partial last block
+ DBG("partial last block pos=" << pos << " len=" << len);
+ assert((pos - theInlineSize) % thePartSize == 0 && len < thePartSize);
+ Uint32 part = (pos - theInlineSize) / thePartSize;
+ if (readParts(thePartBuf.data, part, 1) == -1)
+ return -1;
+ DBG("force execute");
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
+ setErrorCode(theNdbOp);
+ return -1;
+ }
+ memcpy(buf, thePartBuf.data, len);
+ Uint32 n = len;
+ pos += n;
+ buf += n;
+ len -= n;
+ }
+ assert(len == 0);
+ return 0;
+}
+
+int
+NdbBlob::writeData(const void* data, Uint32 bytes)
+{
+ if (writeData(thePos, data, bytes) == -1)
+ return -1;
+ thePos += bytes;
+ assert(thePos <= theLength);
+ return 0;
+}
+
+int
+NdbBlob::writeData(Uint64 pos, const void* data, Uint32 bytes)
+{
+ if (theState != Active) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ const char* buf = static_cast<const char*>(data);
+ return writeDataPrivate(pos, buf, bytes);
+}
+
+int
+NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes)
+{
+ DBG("writeData pos=" << pos << " bytes=" << bytes);
+ if (pos > theLength) {
+ setErrorCode(ErrSeek);
+ return -1;
+ }
+ Uint32 len = bytes;
+ // any write makes blob not NULL
+ if (theNullFlag) {
+ theNullFlag = false;
+ theHeadInlineUpdateFlag = true;
+ }
+ if (len > 0) {
+ // inline part
+ if (pos < theInlineSize) {
+ Uint32 n = theInlineSize - pos;
+ if (n > len)
+ n = len;
+ memcpy(theInlineData + pos, buf, n);
+ theHeadInlineUpdateFlag = true;
+ pos += n;
+ buf += n;
+ len -= n;
+ }
+ }
+ if (len > 0) {
+ assert(pos >= theInlineSize);
+ Uint32 off = (pos - theInlineSize) % thePartSize;
+ // partial first block
+ if (off != 0) {
+ DBG("partial first block pos=" << pos << " len=" << len);
+ if (theNewPartFlag) {
+ // must flush insert to guarantee read
+ DBG("force execute");
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
+ setErrorCode(theNdbOp);
+ return -1;
+ }
+ theNewPartFlag = false;
+ }
+ Uint32 part = (pos - theInlineSize) / thePartSize;
+ if (readParts(thePartBuf.data, part, 1) == -1)
+ return -1;
+ DBG("force execute");
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
+ setErrorCode(theNdbOp);
+ return -1;
+ }
+ Uint32 n = thePartSize - off;
+ if (n > len) {
+ memset(thePartBuf.data + off + len, theFillChar, n - len);
+ n = len;
+ }
+ memcpy(thePartBuf.data + off, buf, n);
+ if (updateParts(thePartBuf.data, part, 1) == -1)
+ return -1;
+ pos += n;
+ buf += n;
+ len -= n;
+ }
+ }
+ if (len > 0) {
+ assert((pos - theInlineSize) % thePartSize == 0);
+ // complete blocks in the middle
+ if (len >= thePartSize) {
+ Uint32 part = (pos - theInlineSize) / thePartSize;
+ Uint32 count = len / thePartSize;
+ for (unsigned i = 0; i < count; i++) {
+ if (part + i < getPartCount()) {
+ if (updateParts(buf, part + i, 1) == -1)
+ return -1;
+ } else {
+ if (insertParts(buf, part + i, 1) == -1)
+ return -1;
+ }
+ Uint32 n = thePartSize;
+ pos += n;
+ buf += n;
+ len -= n;
+ }
+ }
+ }
+ if (len > 0) {
+ // partial last block
+ DBG("partial last block pos=" << pos << " len=" << len);
+ assert((pos - theInlineSize) % thePartSize == 0 && len < thePartSize);
+ Uint32 part = (pos - theInlineSize) / thePartSize;
+ if (theLength > pos + len) {
+ if (theNewPartFlag) {
+ // must flush insert to guarantee read
+ DBG("force execute");
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
+ setErrorCode(theNdbOp);
+ return -1;
+ }
+ theNewPartFlag = false;
+ }
+ if (readParts(thePartBuf.data, part, 1) == -1)
+ return -1;
+ DBG("force execute");
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
+ setErrorCode(theNdbOp);
+ return -1;
+ }
+ memcpy(thePartBuf.data, buf, len);
+ if (updateParts(thePartBuf.data, part, 1) == -1)
+ return -1;
+ } else {
+ memcpy(thePartBuf.data, buf, len);
+ memset(thePartBuf.data + len, theFillChar, thePartSize - len);
+ if (part < getPartCount()) {
+ if (updateParts(thePartBuf.data, part, 1) == -1)
+ return -1;
+ } else {
+ if (insertParts(thePartBuf.data, part, 1) == -1)
+ return -1;
+ }
+ }
+ Uint32 n = len;
+ pos += n;
+ buf += n;
+ len -= n;
+ }
+ assert(len == 0);
+ if (theLength < pos) {
+ theLength = pos;
+ theHeadInlineUpdateFlag = true;
+ }
+ DBG("writeData out");
+ return 0;
+}
+
+int
+NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
+{
+ DBG("readParts part=" << part << " count=" << count);
+ Uint32 n = 0;
+ while (n < count) {
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName);
+ if (tOp == NULL ||
+ tOp->readTuple() == -1 ||
+ setPartKeyValue(tOp, part + n) == -1 ||
+ tOp->getValue((Uint32)3, buf) == NULL) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ buf += thePartSize;
+ n++;
+ }
+ return 0;
+}
+
+int
+NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
+{
+ DBG("insertParts part=" << part << " count=" << count);
+ Uint32 n = 0;
+ while (n < count) {
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName);
+ if (tOp == NULL ||
+ tOp->insertTuple() == -1 ||
+ setPartKeyValue(tOp, part + n) == -1 ||
+ tOp->setValue((Uint32)3, buf) == -1) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ buf += thePartSize;
+ n++;
+ theNewPartFlag = true;
+ }
+ return 0;
+}
+
+int
+NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
+{
+ DBG("updateParts part=" << part << " count=" << count);
+ Uint32 n = 0;
+ while (n < count) {
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName);
+ if (tOp == NULL ||
+ tOp->updateTuple() == -1 ||
+ setPartKeyValue(tOp, part + n) == -1 ||
+ tOp->setValue((Uint32)3, buf) == -1) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ buf += thePartSize;
+ n++;
+ theNewPartFlag = true;
+ }
+ return 0;
+}
+
+int
+NdbBlob::deleteParts(Uint32 part, Uint32 count)
+{
+ DBG("deleteParts part=" << part << " count=" << count);
+ Uint32 n = 0;
+ while (n < count) {
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName);
+ if (tOp == NULL ||
+ tOp->deleteTuple() == -1 ||
+ setPartKeyValue(tOp, part + n) == -1) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ n++;
+ }
+ return 0;
+}
+
+// blob handle maintenance
+
+/*
+ * Prepare blob handle linked to an operation. Checks blob table.
+ * Allocates buffers. For key operation fetches key data from signal
+ * data. For read operation adds read of head+inline.
+ */
+int
+NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn)
+{
+ assert(theState == Idle);
+ // ndb api stuff
+ theNdb = anOp->theNdb;
+ theNdbCon = aCon; // for scan, this is the real transaction (m_transConnection)
+ theNdbOp = anOp;
+ theTable = anOp->m_currentTable;
+ theAccessTable = anOp->m_accessTable;
+ theColumn = aColumn;
+ DBG("atPrepare");
+ NdbDictionary::Column::Type partType = NdbDictionary::Column::Undefined;
+ switch (theColumn->getType()) {
+ case NdbDictionary::Column::Blob:
+ partType = NdbDictionary::Column::Binary;
+ theFillChar = 0x0;
+ break;
+ case NdbDictionary::Column::Clob:
+ partType = NdbDictionary::Column::Char;
+ theFillChar = 0x20;
+ break;
+ default:
+ setErrorCode(ErrUsage);
+ return -1;
+ }
+ // sizes
+ theInlineSize = theColumn->getInlineSize();
+ thePartSize = theColumn->getPartSize();
+ theStripeSize = theColumn->getStripeSize();
+ // blob table sanity check
+ assert((NDB_BLOB_HEAD_SIZE << 2) == sizeof(Head));
+ assert(theColumn->m_attrSize * theColumn->m_arraySize == sizeof(Head) + theInlineSize);
+ getBlobTableName(theBlobTableName, theTable, theColumn);
+ const NdbDictionary::Table* bt;
+ const NdbDictionary::Column* bc;
+ if (theInlineSize >= (1 << 16) ||
+ thePartSize == 0 ||
+ thePartSize >= (1 << 16) ||
+ theStripeSize == 0 ||
+ (bt = theNdb->theDictionary->getTable(theBlobTableName)) == NULL ||
+ (bc = bt->getColumn("DATA")) == NULL ||
+ bc->getType() != partType ||
+ bc->getLength() != (int)thePartSize) {
+ setErrorCode(ErrTable);
+ return -1;
+ }
+ // buffers
+ theKeyBuf.alloc(theTable->m_sizeOfKeysInWords << 2);
+ theAccessKeyBuf.alloc(theAccessTable->m_sizeOfKeysInWords << 2);
+ theHeadInlineBuf.alloc(sizeof(Head) + theInlineSize);
+ thePartBuf.alloc(thePartSize);
+ theHead = (Head*)theHeadInlineBuf.data;
+ theInlineData = theHeadInlineBuf.data + sizeof(Head);
+ // handle different operation types
+ bool supportedOp = false;
+ if (isKeyOp()) {
+ if (isTableOp()) {
+ // get table key
+ Uint32* data = (Uint32*)theKeyBuf.data;
+ unsigned size = theTable->m_sizeOfKeysInWords;
+ if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
+ setErrorCode(ErrUsage);
+ return -1;
+ }
+ }
+ if (isIndexOp()) {
+ // get index key
+ Uint32* data = (Uint32*)theAccessKeyBuf.data;
+ unsigned size = theAccessTable->m_sizeOfKeysInWords;
+ if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
+ setErrorCode(ErrUsage);
+ return -1;
+ }
+ }
+ if (isReadOp()) {
+ // add read of head+inline in this op
+ if (getHeadInlineValue(theNdbOp) == -1)
+ return -1;
+ }
+ if (isInsertOp()) {
+ // becomes NULL unless set before execute
+ theNullFlag = true;
+ theLength = 0;
+ }
+ supportedOp = true;
+ }
+ if (isScanOp()) {
+ // add read of head+inline in this op
+ if (getHeadInlineValue(theNdbOp) == -1)
+ return -1;
+ supportedOp = true;
+ }
+ if (! supportedOp) {
+ setErrorCode(ErrUsage);
+ return -1;
+ }
+ setState(Prepared);
+ DBG("atPrepare out");
+ return 0;
+}
+
+/*
+ * Before execute of prepared operation. May add new operations before
+ * this one. May ask that this operation and all before it (a "batch")
+ * is executed immediately in no-commit mode.
+ */
+int
+NdbBlob::preExecute(ExecType anExecType, bool& batch)
+{
+ DBG("preExecute");
+ if (theState == Invalid)
+ return -1;
+ assert(theState == Prepared);
+ // handle different operation types
+ assert(isKeyOp());
+ if (isReadOp()) {
+ if (theGetFlag && theGetSetBytes > theInlineSize) {
+ // need blob head before proceeding
+ batch = true;
+ }
+ }
+ if (isInsertOp()) {
+ if (theSetFlag && theGetSetBytes > theInlineSize) {
+ // add ops to write rest of a setValue
+ assert(theSetBuf != 0);
+ Uint64 pos = theInlineSize;
+ const char* buf = theSetBuf + theInlineSize;
+ Uint32 bytes = theGetSetBytes - theInlineSize;
+ if (writeDataPrivate(pos, buf, bytes) == -1)
+ return -1;
+ if (anExecType == Commit && theHeadInlineUpdateFlag) {
+ // add an operation to update head+inline
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theTable);
+ if (tOp == NULL ||
+ tOp->updateTuple() == -1 ||
+ setTableKeyValue(tOp) == -1 ||
+ setHeadInlineValue(tOp) == -1) {
+ setErrorCode(ErrAbort);
+ return -1;
+ }
+ }
+ }
+ }
+ if (isTableOp()) {
+ if (isUpdateOp() || isDeleteOp()) {
+ // add operation before this one to read head+inline
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theTable, theNdbOp);
+ if (tOp == NULL ||
+ tOp->readTuple() == -1 ||
+ setTableKeyValue(tOp) == -1 ||
+ getHeadInlineValue(tOp) == -1) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ // execute immediately
+ batch = true;
+ }
+ }
+ if (isIndexOp()) {
+ // add op before this one to read table key
+ NdbBlob* tFirstBlob = theNdbOp->theBlobList;
+ if (this == tFirstBlob) {
+ // first blob does it for all
+ if (g_ndb_blob_ok_to_read_index_table) {
+ Uint32 pkAttrId = theAccessTable->getNoOfColumns() - 1;
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theAccessTable, theNdbOp);
+ if (tOp == NULL ||
+ tOp->readTuple() == -1 ||
+ setAccessKeyValue(tOp) == -1 ||
+ tOp->getValue(pkAttrId, theKeyBuf.data) == NULL) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ } else {
+ NdbOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp);
+ if (tOp == NULL ||
+ tOp->readTuple() == -1 ||
+ setAccessKeyValue(tOp) == -1 ||
+ getTableKeyValue(tOp) == -1) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ }
+ }
+ if (isUpdateOp() || isDeleteOp()) {
+ // add op before this one to read head+inline via index
+ NdbIndexOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp);
+ if (tOp == NULL ||
+ tOp->readTuple() == -1 ||
+ setAccessKeyValue(tOp) == -1 ||
+ getHeadInlineValue(tOp) == -1) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ // execute immediately
+ batch = true;
+ }
+ }
+ DBG("preExecute out batch=" << batch);
+ return 0;
+}
+
+/*
+ * After execute, for any operation. If already Active, this routine
+ * has been done previously. Operations which requested a no-commit
+ * batch can add new operations after this one. They are added before
+ * any remaining prepared operations.
+ */
+int
+NdbBlob::postExecute(ExecType anExecType)
+{
+ DBG("postExecute type=" << anExecType);
+ if (theState == Invalid)
+ return -1;
+ if (theState == Active)
+ return 0;
+ assert(theState == Prepared);
+ assert(isKeyOp());
+ if (isIndexOp()) {
+ NdbBlob* tFirstBlob = theNdbOp->theBlobList;
+ if (this != tFirstBlob) {
+ // copy key from first blob
+ assert(theKeyBuf.size == tFirstBlob->theKeyBuf.size);
+ memcpy(theKeyBuf.data, tFirstBlob->theKeyBuf.data, tFirstBlob->theKeyBuf.size);
+ }
+ }
+ if (isReadOp()) {
+ getHeadFromRecAttr();
+ if (theGetFlag && theGetSetBytes > 0) {
+ // copy inline bytes to user buffer
+ assert(theGetBuf != NULL);
+ unsigned n = theGetSetBytes;
+ if (n > theInlineSize)
+ n = theInlineSize;
+ memcpy(theGetBuf, theInlineData, n);
+ }
+ if (theGetFlag && theGetSetBytes > theInlineSize) {
+ // add ops to read rest of a getValue
+ assert(anExecType == NoCommit);
+ assert(theGetBuf != 0);
+ Uint64 pos = theInlineSize;
+ char* buf = theGetBuf + theInlineSize;
+ Uint32 bytes = theGetSetBytes - theInlineSize;
+ if (readDataPrivate(pos, buf, bytes) == -1)
+ return -1;
+ }
+ }
+ if (isUpdateOp()) {
+ assert(anExecType == NoCommit);
+ getHeadFromRecAttr();
+ if (theSetFlag) {
+ // setValue overwrites everything
+ if (theSetBuf != 0) {
+ if (truncate(0) == -1)
+ return -1;
+ if (writeDataPrivate(0, theSetBuf, theGetSetBytes) == -1)
+ return -1;
+ } else {
+ if (setNull() == -1)
+ return -1;
+ }
+ }
+ }
+ if (isDeleteOp()) {
+ assert(anExecType == NoCommit);
+ getHeadFromRecAttr();
+ if (deleteParts(0, getPartCount()) == -1)
+ return -1;
+ }
+ theNewPartFlag = false;
+ setState(anExecType == NoCommit ? Active : Closed);
+ DBG("postExecute out");
+ return 0;
+}
+
+/*
+ * Before commit of completed operation. For write add operation to
+ * update head+inline.
+ */
+int
+NdbBlob::preCommit()
+{
+ DBG("preCommit");
+ if (theState == Invalid)
+ return -1;
+ assert(theState == Active);
+ assert(isKeyOp());
+ if (isInsertOp() || isUpdateOp()) {
+ if (theHeadInlineUpdateFlag) {
+ // add an operation to update head+inline
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theTable);
+ if (tOp == NULL ||
+ tOp->updateTuple() == -1 ||
+ setTableKeyValue(tOp) == -1 ||
+ setHeadInlineValue(tOp) == -1) {
+ setErrorCode(ErrAbort);
+ return -1;
+ }
+ }
+ }
+ DBG("preCommit out");
+ return 0;
+}
+
+/*
+ * After next scan result. Handle like read op above.
+ */
+int
+NdbBlob::atNextResult()
+{
+ DBG("atNextResult");
+ if (theState == Invalid)
+ return -1;
+ assert(isScanOp());
+ getHeadFromRecAttr();
+ // reset position
+ thePos = 0;
+ // get primary key
+ { Uint32* data = (Uint32*)theKeyBuf.data;
+ unsigned size = theTable->m_sizeOfKeysInWords;
+ if (theNdbOp->getKeyFromKEYINFO20(data, size) == -1) {
+ setErrorCode(ErrUsage);
+ return -1;
+ }
+ }
+ if (! theNullFlag) {
+ if (theGetFlag && theGetSetBytes > 0) {
+ // copy inline bytes to user buffer
+ assert(theGetBuf != NULL);
+ unsigned n = theGetSetBytes;
+ if (n > theLength)
+ n = theLength;
+ if (n > theInlineSize)
+ n = theInlineSize;
+ memcpy(theGetBuf, theInlineData, n);
+ }
+ if (theGetFlag && theGetSetBytes > theInlineSize && theLength > theInlineSize) {
+ // add ops to read rest of a getValue
+ assert(theGetBuf != 0);
+ Uint64 pos = theInlineSize;
+ char* buf = theGetBuf + theInlineSize;
+ Uint32 bytes = theGetSetBytes - theInlineSize;
+ if (readDataPrivate(pos, buf, bytes) == -1)
+ return -1;
+ // must also execute them
+ DBG("force execute");
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
+ setErrorCode((NdbOperation*)0);
+ return -1;
+ }
+ }
+ }
+ setState(Active);
+ DBG("atNextResult out");
+ return 0;
+}
+
+
+// misc
+
+const NdbDictionary::Column*
+NdbBlob::getColumn()
+{
+ return theColumn;
+}
+
+// errors
+
+void
+NdbBlob::setErrorCode(int anErrorCode, bool invalidFlag)
+{
+ DBG("setErrorCode code=" << anErrorCode);
+ theError.code = anErrorCode;
+ if (invalidFlag)
+ setState(Invalid);
+}
+
+void
+NdbBlob::setErrorCode(NdbOperation* anOp, bool invalidFlag)
+{
+ int code = 0;
+ if (anOp != NULL && (code = anOp->theError.code) != 0)
+ ;
+ else if ((code = theNdbCon->theError.code) != 0)
+ ;
+ else if ((code = theNdb->theError.code) != 0)
+ ;
+ else
+ code = ErrUnknown;
+ setErrorCode(code, invalidFlag);
+}
+
+void
+NdbBlob::setErrorCode(NdbConnection* aCon, bool invalidFlag)
+{
+ int code = 0;
+ if (theNdbCon != NULL && (code = theNdbCon->theError.code) != 0)
+ ;
+ else if ((code = theNdb->theError.code) != 0)
+ ;
+ else
+ code = ErrUnknown;
+ setErrorCode(code, invalidFlag);
+}
+
+#ifdef VM_TRACE
+NdbOut&
+operator<<(NdbOut& out, const NdbBlob& blob)
+{
+ ndbout << dec << "s=" << blob.theState;
+ ndbout << dec << " n=" << blob.theNullFlag;;
+ ndbout << dec << " l=" << blob.theLength;
+ ndbout << dec << " p=" << blob.thePos;
+ ndbout << dec << " u=" << blob.theHeadInlineUpdateFlag;
+ return out;
+}
+#endif
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp
index 4ec098c3c60..ad415b8acbf 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbConnection.cpp
@@ -35,6 +35,7 @@ Adjust: 971022 UABMNST First version.
#include "NdbApiSignal.hpp"
#include "TransporterFacade.hpp"
#include "API.hpp"
+#include "NdbBlob.hpp"
#include <ndb_limits.h>
#include <signaldata/TcKeyConf.hpp>
@@ -89,7 +90,8 @@ NdbConnection::NdbConnection( Ndb* aNdb ) :
theCurrentScanRec(NULL),
thePreviousScanRec(NULL),
theScanningOp(NULL),
- theBuddyConPtr(0xFFFFFFFF)
+ theBuddyConPtr(0xFFFFFFFF),
+ theBlobFlag(false)
{
theListState = NotInList;
theError.code = 0;
@@ -152,6 +154,8 @@ NdbConnection::init()
m_theLastCursorOperation = NULL;
m_firstExecutedCursorOp = 0;
theBuddyConPtr = 0xFFFFFFFF;
+ //
+ theBlobFlag = false;
}//NdbConnection::init()
/*****************************************************************************
@@ -251,6 +255,86 @@ NdbConnection::execute(ExecType aTypeOfExec,
AbortOption abortOption,
int forceSend)
{
+ if (! theBlobFlag)
+ return executeNoBlobs(aTypeOfExec, abortOption, forceSend);
+
+ // execute prepared ops in batches, as requested by blobs
+
+ ExecType tExecType;
+ NdbOperation* tPrepOp;
+
+ do {
+ tExecType = aTypeOfExec;
+ tPrepOp = theFirstOpInList;
+ while (tPrepOp != NULL) {
+ bool batch = false;
+ NdbBlob* tBlob = tPrepOp->theBlobList;
+ while (tBlob != NULL) {
+ if (tBlob->preExecute(tExecType, batch) == -1)
+ return -1;
+ tBlob = tBlob->theNext;
+ }
+ if (batch) {
+ // blob asked to execute all up to here now
+ tExecType = NoCommit;
+ break;
+ }
+ tPrepOp = tPrepOp->next();
+ }
+ // save rest of prepared ops if batch
+ NdbOperation* tRestOp;
+ NdbOperation* tLastOp;
+ if (tPrepOp != NULL) {
+ tRestOp = tPrepOp->next();
+ tPrepOp->next(NULL);
+ tLastOp = theLastOpInList;
+ theLastOpInList = tPrepOp;
+ }
+ if (tExecType == Commit) {
+ NdbOperation* tOp = theCompletedFirstOp;
+ while (tOp != NULL) {
+ NdbBlob* tBlob = tOp->theBlobList;
+ while (tBlob != NULL) {
+ if (tBlob->preCommit() == -1)
+ return -1;
+ tBlob = tBlob->theNext;
+ }
+ tOp = tOp->next();
+ }
+ }
+ if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
+ return -1;
+ {
+ NdbOperation* tOp = theCompletedFirstOp;
+ while (tOp != NULL) {
+ NdbBlob* tBlob = tOp->theBlobList;
+ while (tBlob != NULL) {
+ // may add new operations if batch
+ if (tBlob->postExecute(tExecType) == -1)
+ return -1;
+ tBlob = tBlob->theNext;
+ }
+ tOp = tOp->next();
+ }
+ }
+ // add saved prepared ops if batch
+ if (tPrepOp != NULL && tRestOp != NULL) {
+ if (theFirstOpInList == NULL)
+ theFirstOpInList = tRestOp;
+ else
+ theLastOpInList->next(tRestOp);
+ theLastOpInList = tLastOp;
+ }
+ } while (theFirstOpInList != NULL || tExecType != aTypeOfExec);
+
+ return 0;
+}
+
+int
+NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
+ AbortOption abortOption,
+ int forceSend)
+{
//------------------------------------------------------------------------
// We will start by preparing all operations in the transaction defined
// since last execute or since beginning. If this works ok we will continue
@@ -330,7 +414,6 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
* Reset error.code on execute
*/
theError.code = 0;
-
NdbCursorOperation* tcOp = m_theFirstCursorOperation;
if (tcOp != 0){
// Execute any cursor operations
@@ -885,7 +968,7 @@ Remark: Get an operation from NdbOperation object idlelist and
object, synchronous.
*****************************************************************************/
NdbOperation*
-NdbConnection::getNdbOperation(NdbTableImpl * tab)
+NdbConnection::getNdbOperation(NdbTableImpl * tab, NdbOperation* aNextOp)
{
NdbOperation* tOp;
@@ -897,14 +980,28 @@ NdbConnection::getNdbOperation(NdbTableImpl * tab)
tOp = theNdb->getOperation();
if (tOp == NULL)
goto getNdbOp_error1;
- if (theLastOpInList != NULL) {
- theLastOpInList->next(tOp);
- theLastOpInList = tOp;
+ if (aNextOp == NULL) {
+ if (theLastOpInList != NULL) {
+ theLastOpInList->next(tOp);
+ theLastOpInList = tOp;
+ } else {
+ theLastOpInList = tOp;
+ theFirstOpInList = tOp;
+ }//if
+ tOp->next(NULL);
} else {
- theLastOpInList = tOp;
- theFirstOpInList = tOp;
- }//if
- tOp->next(NULL);
+ // add before the given op
+ if (theFirstOpInList == aNextOp) {
+ theFirstOpInList = tOp;
+ } else {
+ NdbOperation* aLoopOp = theFirstOpInList;
+ while (aLoopOp != NULL && aLoopOp->next() != aNextOp)
+ aLoopOp = aLoopOp->next();
+ assert(aLoopOp != NULL);
+ aLoopOp->next(tOp);
+ }
+ tOp->next(aNextOp);
+ }
if (tOp->init(tab, this) != -1) {
return tOp;
} else {
@@ -1068,21 +1165,36 @@ Remark: Get an operation from NdbIndexOperation object idlelist and get
*****************************************************************************/
NdbIndexOperation*
NdbConnection::getNdbIndexOperation(NdbIndexImpl * anIndex,
- NdbTableImpl * aTable)
+ NdbTableImpl * aTable,
+ NdbOperation* aNextOp)
{
NdbIndexOperation* tOp;
tOp = theNdb->getIndexOperation();
if (tOp == NULL)
goto getNdbOp_error1;
- if (theLastOpInList != NULL) {
- theLastOpInList->next(tOp);
- theLastOpInList = tOp;
+ if (aNextOp == NULL) {
+ if (theLastOpInList != NULL) {
+ theLastOpInList->next(tOp);
+ theLastOpInList = tOp;
+ } else {
+ theLastOpInList = tOp;
+ theFirstOpInList = tOp;
+ }//if
+ tOp->next(NULL);
} else {
- theLastOpInList = tOp;
- theFirstOpInList = tOp;
- }//if
- tOp->next(NULL);
+ // add before the given op
+ if (theFirstOpInList == aNextOp) {
+ theFirstOpInList = tOp;
+ } else {
+ NdbOperation* aLoopOp = theFirstOpInList;
+ while (aLoopOp != NULL && aLoopOp->next() != aNextOp)
+ aLoopOp = aLoopOp->next();
+ assert(aLoopOp != NULL);
+ aLoopOp->next(tOp);
+ }
+ tOp->next(aNextOp);
+ }
if (tOp->indxInit(anIndex, aTable, this)!= -1) {
return tOp;
} else {
@@ -1706,7 +1818,7 @@ NdbConnection::getTransactionId()
return theTransactionId;
}//NdbConnection::getTransactionId()
-CommitStatusType
+NdbConnection::CommitStatusType
NdbConnection::commitStatus()
{
return theCommitStatus;
diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp
index b068ea6460f..413ad0745db 100644
--- a/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/ndb/src/ndbapi/NdbDictionary.cpp
@@ -103,6 +103,11 @@ NdbDictionary::Column::getLength() const{
return m_impl.m_length;
}
+int
+NdbDictionary::Column::getSize() const{
+ return m_impl.m_attrSize;
+}
+
void
NdbDictionary::Column::setNullable(bool val){
m_impl.m_nullable = val;
@@ -234,7 +239,7 @@ NdbDictionary::Table::~Table(){
}
NdbDictionary::Table&
-NdbDictionary::Table::operator=(const NdbDictionary::Table::Table& table)
+NdbDictionary::Table::operator=(const NdbDictionary::Table& table)
{
m_impl.assign(table.m_impl);
@@ -268,6 +273,9 @@ NdbDictionary::Table::addColumn(const Column & c){
if(c.getPrimaryKey()){
m_impl.m_noOfKeys++;
}
+ if (col->getBlobType()) {
+ m_impl.m_noOfBlobs++;
+ }
m_impl.buildColumnHash();
}
@@ -797,3 +805,74 @@ const struct NdbError &
NdbDictionary::Dictionary::getNdbError() const {
return m_impl.getNdbError();
}
+
+NdbOut& operator <<(NdbOut& ndbout, const NdbDictionary::Column::Type type)
+{
+ switch(type){
+ case NdbDictionary::Column::Bigunsigned:
+ ndbout << "Bigunsigned";
+ break;
+ case NdbDictionary::Column::Unsigned:
+ ndbout << "Unsigned";
+ break;
+ case NdbDictionary::Column::Smallunsigned:
+ ndbout << "Smallunsigned";
+ break;
+ case NdbDictionary::Column::Tinyunsigned:
+ ndbout << "Tinyunsigned";
+ break;
+ case NdbDictionary::Column::Bigint:
+ ndbout << "Bigint";
+ break;
+ case NdbDictionary::Column::Int:
+ ndbout << "Int";
+ break;
+ case NdbDictionary::Column::Smallint:
+ ndbout << "Smallint";
+ break;
+ case NdbDictionary::Column::Tinyint:
+ ndbout << "Tinyint";
+ break;
+ case NdbDictionary::Column::Char:
+ ndbout << "Char";
+ break;
+ case NdbDictionary::Column::Varchar:
+ ndbout << "Varchar";
+ break;
+ case NdbDictionary::Column::Float:
+ ndbout << "Float";
+ break;
+ case NdbDictionary::Column::Double:
+ ndbout << "Double";
+ break;
+ case NdbDictionary::Column::Mediumint:
+ ndbout << "Mediumint";
+ break;
+ case NdbDictionary::Column::Mediumunsigned:
+ ndbout << "Mediumunsigend";
+ break;
+ case NdbDictionary::Column::Binary:
+ ndbout << "Binary";
+ break;
+ case NdbDictionary::Column::Varbinary:
+ ndbout << "Varbinary";
+ break;
+ case NdbDictionary::Column::Decimal:
+ ndbout << "Decimal";
+ break;
+ case NdbDictionary::Column::Timespec:
+ ndbout << "Timespec";
+ break;
+ case NdbDictionary::Column::Blob:
+ ndbout << "Blob";
+ break;
+ case NdbDictionary::Column::Undefined:
+ ndbout << "Undefined";
+ break;
+ default:
+ ndbout << "Unknown type=" << (Uint32)type;
+ break;
+ }
+
+ return ndbout;
+}
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index 02e3ee23f9c..9589639a332 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -17,7 +17,6 @@
#include "NdbDictionaryImpl.hpp"
#include "API.hpp"
#include <NdbOut.hpp>
-#include <AttrType.hpp>
#include "NdbApiSignal.hpp"
#include "TransporterFacade.hpp"
#include <signaldata/GetTabInfo.hpp>
@@ -35,6 +34,7 @@
#include <AttributeList.hpp>
#include <NdbEventOperation.hpp>
#include "NdbEventOperationImpl.hpp"
+#include "NdbBlob.hpp"
#define DEBUG_PRINT 0
#define INCOMPATIBLE_VERSION -2
@@ -56,8 +56,8 @@ NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f)
init();
}
-NdbColumnImpl::NdbColumnImpl&
-NdbColumnImpl::operator=(const NdbColumnImpl::NdbColumnImpl& col)
+NdbColumnImpl&
+NdbColumnImpl::operator=(const NdbColumnImpl& col)
{
m_attrId = col.m_attrId;
m_name = col.m_name;
@@ -179,7 +179,14 @@ NdbColumnImpl::equal(const NdbColumnImpl& col) const
case NdbDictionary::Column::Double:
case NdbDictionary::Column::Datetime:
case NdbDictionary::Column::Timespec:
+ break;
case NdbDictionary::Column::Blob:
+ case NdbDictionary::Column::Clob:
+ if (m_precision != col.m_precision ||
+ m_scale != col.m_scale ||
+ m_length != col.m_length) {
+ return false;
+ }
break;
}
if (m_autoIncrement != col.m_autoIncrement){
@@ -224,6 +231,8 @@ NdbTableImpl::NdbTableImpl()
: NdbDictionary::Table(* this), m_facade(this)
{
m_noOfKeys = 0;
+ m_sizeOfKeysInWords = 0;
+ m_noOfBlobs = 0;
m_index = 0;
init();
}
@@ -258,6 +267,8 @@ NdbTableImpl::init(){
m_indexType = NdbDictionary::Index::Undefined;
m_noOfKeys = 0;
+ m_sizeOfKeysInWords = 0;
+ m_noOfBlobs = 0;
}
bool
@@ -337,6 +348,8 @@ NdbTableImpl::assign(const NdbTableImpl& org)
m_index = org.m_index;
m_noOfKeys = org.m_noOfKeys;
+ m_sizeOfKeysInWords = org.m_sizeOfKeysInWords;
+ m_noOfBlobs = org.m_noOfBlobs;
m_version = org.m_version;
m_status = org.m_status;
@@ -622,7 +635,7 @@ NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
const char * internalName =
m_ndb.internalizeIndexName(table, index->getName());
- return getTable(Ndb::externalizeTableName(internalName));
+ return getTable(m_ndb.externalizeTableName(internalName));
}
bool
@@ -863,7 +876,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
* get tab info
*/
NdbTableImpl *
-NdbDictInterface::getTable(int tableId)
+NdbDictInterface::getTable(int tableId, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
@@ -877,11 +890,11 @@ NdbDictInterface::getTable(int tableId)
tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
tSignal.theLength = GetTabInfoReq::SignalLength;
- return getTable(&tSignal, 0, 0);
+ return getTable(&tSignal, 0, 0, fullyQualifiedNames);
}
NdbTableImpl *
-NdbDictInterface::getTable(const char * name)
+NdbDictInterface::getTable(const char * name, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
@@ -905,13 +918,13 @@ NdbDictInterface::getTable(const char * name)
ptr[0].p = (Uint32*)name;
ptr[0].sz = strLen;
- return getTable(&tSignal, ptr, 1);
+ return getTable(&tSignal, ptr, 1, fullyQualifiedNames);
}
NdbTableImpl *
NdbDictInterface::getTable(class NdbApiSignal * signal,
LinearSectionPtr ptr[3],
- Uint32 noOfSections)
+ Uint32 noOfSections, bool fullyQualifiedNames)
{
//GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, signal->getDataPtrSend());
int r = dictSignal(signal,ptr,noOfSections,
@@ -925,7 +938,7 @@ NdbDictInterface::getTable(class NdbApiSignal * signal,
NdbTableImpl * rt = 0;
m_error.code = parseTableInfo(&rt,
(Uint32*)m_buffer.get_data(),
- m_buffer.length() / 4);
+ m_buffer.length() / 4, fullyQualifiedNames);
rt->buildColumnHash();
return rt;
}
@@ -1077,12 +1090,15 @@ columnTypeMapping[] = {
{ DictTabInfo::ExtVarbinary, NdbDictionary::Column::Varbinary },
{ DictTabInfo::ExtDatetime, NdbDictionary::Column::Datetime },
{ DictTabInfo::ExtTimespec, NdbDictionary::Column::Timespec },
+ { DictTabInfo::ExtBlob, NdbDictionary::Column::Blob },
+ { DictTabInfo::ExtClob, NdbDictionary::Column::Clob },
{ -1, -1 }
};
int
NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
- const Uint32 * data, Uint32 len)
+ const Uint32 * data, Uint32 len,
+ bool fullyQualifiedNames)
{
SimplePropertiesLinearReader it(data, len);
DictTabInfo::Table tableDesc; tableDesc.init();
@@ -1096,7 +1112,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
return 703;
}
const char * internalName = tableDesc.TableName;
- const char * externalName = Ndb::externalizeTableName(internalName);
+ const char * externalName = Ndb::externalizeTableName(internalName, fullyQualifiedNames);
NdbTableImpl * impl = new NdbTableImpl();
impl->m_tableId = tableDesc.TableId;
@@ -1125,12 +1141,13 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
if(impl->m_indexType == NdbDictionary::Index::Undefined){
} else {
const char * externalPrimary =
- Ndb::externalizeTableName(tableDesc.PrimaryTable);
+ Ndb::externalizeTableName(tableDesc.PrimaryTable, fullyQualifiedNames);
impl->m_primaryTable.assign(externalPrimary);
}
Uint32 keyInfoPos = 0;
Uint32 keyCount = 0;
+ Uint32 blobCount;
for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) {
DictTabInfo::Attribute attrDesc; attrDesc.init();
@@ -1187,6 +1204,8 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
} else {
col->m_keyInfoPos = 0;
}
+ if (col->getBlobType())
+ blobCount++;
NdbColumnImpl * null = 0;
impl->m_columns.fill(attrDesc.AttributeId, null);
@@ -1199,6 +1218,8 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
it.next();
}
impl->m_noOfKeys = keyCount;
+ impl->m_sizeOfKeysInWords = keyInfoPos;
+ impl->m_noOfBlobs = blobCount;
* ret = impl;
return 0;
}
@@ -1206,6 +1227,43 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
/*****************************************************************
* Create table and alter table
*/
+int
+NdbDictionaryImpl::createTable(NdbTableImpl &t)
+{
+ if (m_receiver.createTable(m_ndb, t) != 0)
+ return -1;
+ if (t.m_noOfBlobs == 0)
+ return 0;
+ // update table def from DICT
+ NdbTableImpl * tp = getTable(t.m_externalName.c_str());
+ if (tp == NULL) {
+ m_error.code = 709;
+ return -1;
+ }
+ if (createBlobTables(* tp) != 0) {
+ int save_code = m_error.code;
+ (void)dropTable(t);
+ m_error.code = save_code;
+ return -1;
+ }
+ return 0;
+}
+
+int
+NdbDictionaryImpl::createBlobTables(NdbTableImpl &t)
+{
+ for (unsigned i = 0; i < t.m_columns.size(); i++) {
+ NdbColumnImpl & c = *t.m_columns[i];
+ if (! c.getBlobType())
+ continue;
+ NdbTableImpl bt;
+ NdbBlob::getBlobTable(bt, &t, &c);
+ if (createTable(bt) != 0)
+ return -1;
+ }
+ return 0;
+}
+
int
NdbDictInterface::createTable(Ndb & ndb,
NdbTableImpl & impl)
@@ -1257,7 +1315,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
NdbTableImpl & impl,
bool alter)
{
- if((unsigned)impl.getNoOfPrimaryKeys() > MAXNROFTUPLEKEY){
+ if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){
m_error.code = 4317;
return -1;
}
@@ -1540,6 +1598,12 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
if (dropIndex(element.name, name) == -1)
return -1;
}
+
+ if (impl.m_noOfBlobs != 0) {
+ if (dropBlobTables(impl) != 0)
+ return -1;
+ }
+
int ret = m_receiver.dropTable(impl);
if(ret == 0){
const char * internalTableName = impl.m_internalName.c_str();
@@ -1555,6 +1619,23 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
}
int
+NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
+{
+ for (unsigned i = 0; i < t.m_columns.size(); i++) {
+ NdbColumnImpl & c = *t.m_columns[i];
+ if (! c.getBlobType())
+ continue;
+ char btname[NdbBlob::BlobTableNameSize];
+ NdbBlob::getBlobTableName(btname, &t, &c);
+ if (dropTable(btname) != 0) {
+ if (m_error.code != 709)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
NdbDictInterface::dropTable(const NdbTableImpl & impl)
{
NdbApiSignal tSignal(m_reference);
@@ -1867,7 +1948,7 @@ int
NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
{
const char * indexName = impl.getName();
- if (tableName || Ndb::usingFullyQualifiedNames()) {
+ if (tableName || m_ndb.usingFullyQualifiedNames()) {
NdbTableImpl * timpl = impl.m_table;
if (timpl == 0) {
@@ -2572,14 +2653,13 @@ NdbDictionaryImpl::listObjects(List& list, NdbDictionary::Object::Type type)
req.requestData = 0;
req.setTableType(getKernelConstant(type, objectTypeMapping, 0));
req.setListNames(true);
- return m_receiver.listObjects(list, req.requestData);
+ return m_receiver.listObjects(list, req.requestData, m_ndb.usingFullyQualifiedNames());
}
int
NdbDictionaryImpl::listIndexes(List& list, const char * tableName)
{
- ListTablesReq
- req;
+ ListTablesReq req;
NdbTableImpl* impl = getTable(tableName);
if (impl == 0)
return -1;
@@ -2587,12 +2667,12 @@ NdbDictionaryImpl::listIndexes(List& list, const char * tableName)
req.setTableId(impl->m_tableId);
req.setListNames(true);
req.setListIndexes(true);
- return m_receiver.listObjects(list, req.requestData);
+ return m_receiver.listObjects(list, req.requestData, m_ndb.usingFullyQualifiedNames());
}
int
NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
- Uint32 requestData)
+ Uint32 requestData, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
ListTablesReq* const req = CAST_PTR(ListTablesReq, tSignal.getDataPtrSend());
@@ -2657,7 +2737,7 @@ NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
memcpy(indexName, &data[pos], n << 2);
databaseName = Ndb::getDatabaseFromInternalName(indexName);
schemaName = Ndb::getSchemaFromInternalName(indexName);
- objectName = BaseString(Ndb::externalizeIndexName(indexName));
+ objectName = BaseString(Ndb::externalizeIndexName(indexName, fullyQualifiedNames));
delete [] indexName;
} else if ((element.type == NdbDictionary::Object::SystemTable) ||
(element.type == NdbDictionary::Object::UserTable)) {
@@ -2665,7 +2745,7 @@ NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
memcpy(tableName, &data[pos], n << 2);
databaseName = Ndb::getDatabaseFromInternalName(tableName);
schemaName = Ndb::getSchemaFromInternalName(tableName);
- objectName = BaseString(Ndb::externalizeTableName(tableName));
+ objectName = BaseString(Ndb::externalizeTableName(tableName, fullyQualifiedNames));
delete [] tableName;
}
else {
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index 3263a636a79..bf59838c198 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -81,6 +81,7 @@ public:
Uint32 m_keyInfoPos;
Uint32 m_extType; // used by restore (kernel type in versin v2x)
bool getInterpretableType() const ;
+ bool getBlobType() const;
/**
* Equality/assign
@@ -141,6 +142,8 @@ public:
* Aggregates
*/
Uint32 m_noOfKeys;
+ unsigned short m_sizeOfKeysInWords;
+ unsigned short m_noOfBlobs;
/**
* Equality/assign
@@ -283,17 +286,18 @@ public:
int stopSubscribeEvent(class Ndb & ndb, NdbEventImpl &);
int stopSubscribeEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
- int listObjects(NdbDictionary::Dictionary::List& list, Uint32 requestData);
+ int listObjects(NdbDictionary::Dictionary::List& list, Uint32 requestData, bool fullyQualifiedNames);
int listObjects(NdbApiSignal* signal);
- NdbTableImpl * getTable(int tableId);
- NdbTableImpl * getTable(const char * name);
+ NdbTableImpl * getTable(int tableId, bool fullyQualifiedNames);
+ NdbTableImpl * getTable(const char * name, bool fullyQualifiedNames);
NdbTableImpl * getTable(class NdbApiSignal * signal,
LinearSectionPtr ptr[3],
- Uint32 noOfSections);
+ Uint32 noOfSections, bool fullyQualifiedNames);
static int parseTableInfo(NdbTableImpl ** dst,
- const Uint32 * data, Uint32 len);
+ const Uint32 * data, Uint32 len,
+ bool fullyQualifiedNames);
NdbError & m_error;
private:
@@ -352,13 +356,12 @@ public:
bool setTransporter(class Ndb * ndb, class TransporterFacade * tf);
bool setTransporter(class TransporterFacade * tf);
- int createTable(NdbTableImpl &t)
- {
- return m_receiver.createTable(m_ndb, t);
- }
+ int createTable(NdbTableImpl &t);
+ int createBlobTables(NdbTableImpl &);
int alterTable(NdbTableImpl &t);
int dropTable(const char * name);
int dropTable(NdbTableImpl &);
+ int dropBlobTables(NdbTableImpl &);
int invalidateObject(NdbTableImpl &);
int removeCachedObject(NdbTableImpl &);
@@ -432,6 +435,13 @@ NdbColumnImpl::getInterpretableType() const {
}
inline
+bool
+NdbColumnImpl::getBlobType() const {
+ return (m_type == NdbDictionary::Column::Blob ||
+ m_type == NdbDictionary::Column::Clob);
+}
+
+inline
NdbTableImpl &
NdbTableImpl::getImpl(NdbDictionary::Table & t){
return t.m_impl;
@@ -601,7 +611,7 @@ NdbDictionaryImpl::getTableImpl(const char * internalTableName)
m_globalHash->unlock();
if (ret == 0){
- ret = m_receiver.getTable(internalTableName);
+ ret = m_receiver.getTable(internalTableName, m_ndb.usingFullyQualifiedNames());
m_globalHash->lock();
m_globalHash->put(internalTableName, ret);
@@ -624,7 +634,7 @@ NdbIndexImpl *
NdbDictionaryImpl::getIndex(const char * indexName,
const char * tableName)
{
- if (tableName || Ndb::usingFullyQualifiedNames()) {
+ if (tableName || m_ndb.usingFullyQualifiedNames()) {
const char * internalIndexName = 0;
if (tableName) {
NdbTableImpl * t = getTable(tableName);
diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/ndb/src/ndbapi/NdbEventOperationImpl.cpp
index acc726e28c5..b73a58d97c4 100644
--- a/ndb/src/ndbapi/NdbEventOperationImpl.cpp
+++ b/ndb/src/ndbapi/NdbEventOperationImpl.cpp
@@ -21,7 +21,6 @@
#include "NdbDictionaryImpl.hpp"
#include "API.hpp"
#include <NdbOut.hpp>
-#include <AttrType.hpp>
#include "NdbApiSignal.hpp"
#include "TransporterFacade.hpp"
#include <signaldata/CreateEvnt.hpp>
@@ -489,52 +488,7 @@ NdbEventOperationImpl::getEventType()
}
}
-void
-NdbEventOperationImpl::printRecAttr(NdbRecAttr *p)
-{
- int size = p->attrSize();
- int aSize = p->arraySize();
-
- switch(p->attrType()){
- case UnSigned:
- switch(size) {
- case 8: ndbout << p->u_64_value(); break;
- case 4: ndbout << p->u_32_value(); break;
- case 2: ndbout << p->u_short_value(); break;
- case 1: ndbout << (unsigned) p->u_char_value(); break;
- default: ndbout << "Unknown size" << endl;
- }
- break;
-
- case Signed:
- switch(size) {
- case 8: ndbout << p->int64_value(); break;
- case 4: ndbout << p->int32_value(); break;
- case 2: ndbout << p->short_value(); break;
- case 1: ndbout << (int) p->char_value(); break;
- default: ndbout << "Unknown size" << endl;
- }
- break;
-
- case String:
- {
- char* buf = new char[aSize+1];
- memcpy(buf, p->aRef(), aSize);
- buf[aSize] = 0;
- ndbout << buf;
- delete [] buf;
- }
- break;
-
- case Float:
- ndbout << p->float_value();
- break;
-
- default:
- ndbout << "Unknown";
- break;
- }
-}
+
void
NdbEventOperationImpl::print()
@@ -545,8 +499,7 @@ NdbEventOperationImpl::print()
NdbRecAttr *p = theFirstRecAttrs[i];
ndbout << " %u " << i;
while (p) {
- ndbout << " : " << p->attrId() << " = ";
- printRecAttr(p);
+ ndbout << " : " << p->attrId() << " = " << *p;
p = p->next();
}
ndbout << "\n";
diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.hpp b/ndb/src/ndbapi/NdbEventOperationImpl.hpp
index b7dee084a9f..f67c998e639 100644
--- a/ndb/src/ndbapi/NdbEventOperationImpl.hpp
+++ b/ndb/src/ndbapi/NdbEventOperationImpl.hpp
@@ -60,7 +60,6 @@ public:
void print();
void printAll();
- void printRecAttr(NdbRecAttr *);
Ndb *m_ndb;
NdbEventImpl *m_eventImpl;
diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp
index ee5491d72a8..631c09e2e6d 100644
--- a/ndb/src/ndbapi/NdbIndexOperation.cpp
+++ b/ndb/src/ndbapi/NdbIndexOperation.cpp
@@ -87,7 +87,7 @@ NdbIndexOperation::indxInit(NdbIndexImpl * anIndex,
m_accessTable = anIndex->m_table;
m_theIndexLen = 0;
m_theNoOfIndexDefined = 0;
- for (Uint32 i=0; i<MAXNROFTUPLEKEY; i++)
+ for (Uint32 i=0; i<NDB_MAX_ATTRIBUTES_IN_INDEX; i++)
for (int j=0; j<3; j++)
m_theIndexDefined[i][j] = false;
@@ -221,7 +221,7 @@ int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
goto equal_error2;
}//if
}//if
- } while (i < MAXNROFTUPLEKEY);
+ } while (i < NDB_MAX_ATTRIBUTES_IN_INDEX);
goto equal_error2;
} else {
goto equal_error1;
@@ -372,6 +372,17 @@ int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
} else if ((tOpType == ReadRequest) || (tOpType == DeleteRequest) ||
(tOpType == ReadExclusive)) {
theStatus = GetValue;
+ // create blob handles automatically
+ if (tOpType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) {
+ for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) {
+ NdbColumnImpl* c = m_currentTable->m_columns[i];
+ assert(c != 0);
+ if (c->getBlobType()) {
+ if (getBlobHandle(theNdbCon, c) == NULL)
+ return -1;
+ }
+ }
+ }
return 0;
} else if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) {
theStatus = SetValue;
@@ -695,7 +706,7 @@ NdbIndexOperation::receiveTCINDXREF( NdbApiSignal* aSignal)
theStatus = Finished;
- theNdbCon->theReturnStatus = ReturnFailure;
+ theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
//--------------------------------------------------------------------------//
// If the transaction this operation belongs to consists only of simple reads
// we set the error code on the transaction object.
diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp
index ccbfa767542..e6031a58c5f 100644
--- a/ndb/src/ndbapi/NdbOperation.cpp
+++ b/ndb/src/ndbapi/NdbOperation.cpp
@@ -31,7 +31,8 @@
#include "NdbApiSignal.hpp"
#include "NdbRecAttr.hpp"
#include "NdbUtil.hpp"
-
+#include "NdbBlob.hpp"
+#include "ndbapi_limits.h"
#include <signaldata/TcKeyReq.hpp>
#include "NdbDictionaryImpl.hpp"
@@ -103,7 +104,8 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
theFirstSCAN_TABINFO_Recv(NULL),
theLastSCAN_TABINFO_Recv(NULL),
theSCAN_TABCONF_Recv(NULL),
- theBoundATTRINFO(NULL)
+ theBoundATTRINFO(NULL),
+ theBlobList(NULL)
{
theReceiver.init(NdbReceiver::NDB_OPERATION, this);
theError.code = 0;
@@ -163,7 +165,7 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){
m_currentTable = m_accessTable = tab;
theNdbCon = myConnection;
- for (Uint32 i=0; i<MAXNROFTUPLEKEY; i++)
+ for (Uint32 i=0; i<NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; i++)
for (int j=0; j<3; j++)
theTupleKeyDefined[i][j] = false;
@@ -197,6 +199,7 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){
theTotalNrOfKeyWordInSignal = 8;
theMagicNumber = 0xABCDEF01;
theBoundATTRINFO = NULL;
+ theBlobList = NULL;
tSignal = theNdb->getSignal();
if (tSignal == NULL)
@@ -236,6 +239,8 @@ NdbOperation::release()
NdbCall* tSaveCall;
NdbSubroutine* tSubroutine;
NdbSubroutine* tSaveSubroutine;
+ NdbBlob* tBlob;
+ NdbBlob* tSaveBlob;
if (theTCREQ != NULL)
{
@@ -308,6 +313,14 @@ NdbOperation::release()
}
theBoundATTRINFO = NULL;
}
+ tBlob = theBlobList;
+ while (tBlob != NULL)
+ {
+ tSaveBlob = tBlob;
+ tBlob = tBlob->theNext;
+ theNdb->releaseNdbBlob(tSaveBlob);
+ }
+ theBlobList = NULL;
releaseScan();
}
@@ -356,6 +369,18 @@ NdbOperation::setValue( Uint32 anAttrId,
return setValue(m_currentTable->getColumn(anAttrId), aValuePassed, len);
}
+NdbBlob*
+NdbOperation::getBlobHandle(const char* anAttrName)
+{
+ return getBlobHandle(theNdbCon, m_currentTable->getColumn(anAttrName));
+}
+
+NdbBlob*
+NdbOperation::getBlobHandle(Uint32 anAttrId)
+{
+ return getBlobHandle(theNdbCon, m_currentTable->getColumn(anAttrId));
+}
+
int
NdbOperation::incValue(const char* anAttrName, Uint32 aValue)
{
@@ -428,4 +453,8 @@ NdbOperation::setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len
return setBound(m_accessTable->getColumn(anAttrId), type, aValue, len);
}
-
+const char*
+NdbOperation::getTableName() const
+{
+ return m_currentTable->m_externalName.c_str();
+}
diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp
index 18f8b79d12e..69a6602fe65 100644
--- a/ndb/src/ndbapi/NdbOperationDefine.cpp
+++ b/ndb/src/ndbapi/NdbOperationDefine.cpp
@@ -31,10 +31,10 @@
#include "NdbConnection.hpp"
#include "Ndb.hpp"
#include "NdbRecAttr.hpp"
-#include "AttrType.hpp"
#include "NdbUtil.hpp"
#include "NdbOut.hpp"
#include "NdbImpl.hpp"
+#include "NdbBlob.hpp"
#include <Interpreter.hpp>
@@ -529,9 +529,9 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
tAttrId = tAttrInfo->m_attrId;
const char *aValue = aValuePassed;
Uint32 ahValue;
- AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId, 0);
if (aValue == NULL) {
if (tAttrInfo->m_nullable) {
+ AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId, 0);
ah.setNULL();
insertATTRINFO(ahValue);
// Insert Attribute Id with the value
@@ -565,7 +565,8 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
}//if
const Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Including bits in last word
const Uint32 sizeInWords = sizeInBytes / 4; // Excluding bits in last word
- ah.setDataSize(totalSizeInWords);
+ AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId,
+ totalSizeInWords);
insertATTRINFO( ahValue );
/***********************************************************************
@@ -604,6 +605,33 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
return 0;
}//NdbOperation::setValue()
+NdbBlob*
+NdbOperation::getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* tAttrInfo)
+{
+ NdbBlob* tBlob = theBlobList;
+ NdbBlob* tLastBlob = NULL;
+ while (tBlob != NULL) {
+ if (tBlob->theColumn == tAttrInfo)
+ return tBlob;
+ tLastBlob = tBlob;
+ tBlob = tBlob->theNext;
+ }
+ tBlob = theNdb->getNdbBlob();
+ if (tBlob == NULL)
+ return NULL;
+ if (tBlob->atPrepare(aCon, this, tAttrInfo) == -1) {
+ theNdb->releaseNdbBlob(tBlob);
+ return NULL;
+ }
+ if (tLastBlob == NULL)
+ theBlobList = tBlob;
+ else
+ tLastBlob->theNext = tBlob;
+ tBlob->theNext = NULL;
+ theNdbCon->theBlobFlag = true;
+ return tBlob;
+}
+
/*
* Define bound on index column in range scan.
*/
diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp
index b2a6f99880c..d00c527550d 100644
--- a/ndb/src/ndbapi/NdbOperationExec.cpp
+++ b/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -757,7 +757,7 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal)
theStatus = Finished;
- theNdbCon->theReturnStatus = ReturnFailure;
+ theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
//-------------------------------------------------------------------------//
// If the transaction this operation belongs to consists only of simple reads
// we set the error code on the transaction object.
diff --git a/ndb/src/ndbapi/NdbOperationInt.cpp b/ndb/src/ndbapi/NdbOperationInt.cpp
index be23a1c274c..e61fc5b05d7 100644
--- a/ndb/src/ndbapi/NdbOperationInt.cpp
+++ b/ndb/src/ndbapi/NdbOperationInt.cpp
@@ -31,7 +31,6 @@ Adjust: 991029 UABRONM First version.
#include "NdbConnection.hpp"
#include "Ndb.hpp"
#include "NdbRecAttr.hpp"
-#include "AttrType.hpp"
#include "NdbUtil.hpp"
#include "Interpreter.hpp"
@@ -69,7 +68,7 @@ NdbOperation::incCheck(const NdbColumnImpl* tNdbColumnImpl)
}
return tNdbColumnImpl->m_attrId;
} else {
- if (theNdbCon->theCommitStatus == Started)
+ if (theNdbCon->theCommitStatus == NdbConnection::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -121,7 +120,7 @@ NdbOperation::write_attrCheck(const NdbColumnImpl* tNdbColumnImpl)
}
return tNdbColumnImpl->m_attrId;
} else {
- if (theNdbCon->theCommitStatus == Started)
+ if (theNdbCon->theCommitStatus == NdbConnection::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -169,7 +168,7 @@ NdbOperation::read_attrCheck(const NdbColumnImpl* tNdbColumnImpl)
}
return tNdbColumnImpl->m_attrId;
} else {
- if (theNdbCon->theCommitStatus == Started)
+ if (theNdbCon->theCommitStatus == NdbConnection::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -209,7 +208,7 @@ NdbOperation::initial_interpreterCheck()
}
return 0;
} else {
- if (theNdbCon->theCommitStatus == Started)
+ if (theNdbCon->theCommitStatus == NdbConnection::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -235,7 +234,7 @@ NdbOperation::labelCheck()
}
return 0;
} else {
- if (theNdbCon->theCommitStatus == Started)
+ if (theNdbCon->theCommitStatus == NdbConnection::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -255,7 +254,7 @@ NdbOperation::intermediate_interpreterCheck()
}
return 0;
} else {
- if (theNdbCon->theCommitStatus == Started)
+ if (theNdbCon->theCommitStatus == NdbConnection::Started)
setErrorCodeAbort(4200);
}
return -1;
diff --git a/ndb/src/ndbapi/NdbOperationScan.cpp b/ndb/src/ndbapi/NdbOperationScan.cpp
index df4f2421ec0..299e6f2adea 100644
--- a/ndb/src/ndbapi/NdbOperationScan.cpp
+++ b/ndb/src/ndbapi/NdbOperationScan.cpp
@@ -31,7 +31,7 @@ NdbOperation::openScanRead(Uint32 aParallelism)
{
aParallelism = checkParallelism(aParallelism);
- if ((theNdbCon->theCommitStatus != Started) &&
+ if ((theNdbCon->theCommitStatus != NdbConnection::Started) &&
(theStatus != Init) &&
(aParallelism == 0)) {
setErrorCode(4200);
@@ -48,7 +48,7 @@ NdbOperation::openScanExclusive(Uint32 aParallelism)
{
aParallelism = checkParallelism(aParallelism);
- if ((theNdbCon->theCommitStatus != Started) &&
+ if ((theNdbCon->theCommitStatus != NdbConnection::Started) &&
(theStatus != Init) &&
(aParallelism == 0)) {
setErrorCode(4200);
@@ -65,7 +65,7 @@ NdbOperation::openScanReadHoldLock(Uint32 aParallelism)
{
aParallelism = checkParallelism(aParallelism);
- if ((theNdbCon->theCommitStatus != Started) &&
+ if ((theNdbCon->theCommitStatus != NdbConnection::Started) &&
(theStatus != Init) &&
(aParallelism == 0)) {
setErrorCode(4200);
@@ -82,7 +82,7 @@ NdbOperation::openScanReadCommitted(Uint32 aParallelism)
{
aParallelism = checkParallelism(aParallelism);
- if ((theNdbCon->theCommitStatus != Started) &&
+ if ((theNdbCon->theCommitStatus != NdbConnection::Started) &&
(theStatus != Init) &&
(aParallelism == 0)) {
setErrorCode(4200);
@@ -569,8 +569,35 @@ NdbOperation::takeOverScanOp(OperationType opType, NdbConnection* updateTrans)
}
}
+ // create blob handles automatically
+ if (opType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) {
+ for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) {
+ NdbColumnImpl* c = m_currentTable->m_columns[i];
+ assert(c != 0);
+ if (c->getBlobType()) {
+ if (newOp->getBlobHandle(updateTrans, c) == NULL)
+ return NULL;
+ }
+ }
+ }
+
return newOp;
}
-
-
+int
+NdbOperation::getKeyFromKEYINFO20(Uint32* data, unsigned size)
+{
+ const NdbScanReceiver* tScanRec = theNdbCon->thePreviousScanRec;
+ NdbApiSignal* tSignal = tScanRec->theFirstKEYINFO20_Recv;
+ unsigned pos = 0;
+ unsigned n = 0;
+ while (pos < size) {
+ if (n == 20) {
+ tSignal = tSignal->next();
+ n = 0;
+ }
+ const unsigned h = KeyInfo20::HeaderLength;
+ data[pos++] = tSignal->getDataPtrSend()[h + n++];
+ }
+ return 0;
+}
diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp
index e1d5e823077..19cb133dbf7 100644
--- a/ndb/src/ndbapi/NdbOperationSearch.cpp
+++ b/ndb/src/ndbapi/NdbOperationSearch.cpp
@@ -35,7 +35,6 @@ Adjust: 971022 UABMNST First version.
#include <Ndb.hpp>
#include "NdbImpl.hpp"
#include <NdbOut.hpp>
-#include "AttrType.hpp"
#include <AttributeHeader.hpp>
#include <signaldata/TcKeyReq.hpp>
@@ -102,7 +101,7 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
goto equal_error2;
}//if
}//if
- } while (i < MAXNROFTUPLEKEY);
+ } while (i < NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY);
goto equal_error2;
} else {
goto equal_error1;
@@ -252,6 +251,17 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
} else if ((tOpType == ReadRequest) || (tOpType == DeleteRequest) ||
(tOpType == ReadExclusive)) {
theStatus = GetValue;
+ // create blob handles automatically
+ if (tOpType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) {
+ for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) {
+ NdbColumnImpl* c = m_currentTable->m_columns[i];
+ assert(c != 0);
+ if (c->getBlobType()) {
+ if (getBlobHandle(theNdbCon, c) == NULL)
+ return -1;
+ }
+ }
+ }
return 0;
} else if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) {
theStatus = SetValue;
@@ -498,3 +508,24 @@ LastWordLabel:
return 0;
}
+
+int
+NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
+{
+ assert(m_accessTable != 0 && m_accessTable->m_sizeOfKeysInWords != 0);
+ assert(m_accessTable->m_sizeOfKeysInWords == size);
+ unsigned pos = 0;
+ while (pos < 8 && pos < size) {
+ data[pos++] = theKEYINFOptr[pos];
+ }
+ NdbApiSignal* tSignal = theFirstKEYINFO;
+ unsigned n = 0;
+ while (pos < size) {
+ if (n == 20) {
+ tSignal = tSignal->next();
+ n = 0;
+ }
+ data[pos++] = tSignal->getDataPtrSend()[3 + n++];
+ }
+ return 0;
+}
diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp
index 0f7baeac4f5..0ed2ff4e796 100644
--- a/ndb/src/ndbapi/NdbRecAttr.cpp
+++ b/ndb/src/ndbapi/NdbRecAttr.cpp
@@ -27,17 +27,14 @@ Documentation:
Adjust: 971206 UABRONM First version
************************************************************************************************/
#include <ndb_global.h>
-#include "NdbRecAttr.hpp"
+#include <NdbOut.hpp>
+#include <NdbRecAttr.hpp>
#include "NdbDictionaryImpl.hpp"
+#include <NdbTCP.h>
-NdbRecAttr::NdbRecAttr() :
- theStorageX(NULL),
- theValue(NULL),
- theRef(NULL),
- theNext(NULL),
- theAttrId(0xFFFF),
- theNULLind(-1)
-{
+NdbRecAttr::NdbRecAttr()
+{
+ init();
}
NdbRecAttr::~NdbRecAttr()
@@ -46,6 +43,11 @@ NdbRecAttr::~NdbRecAttr()
}
int
+NdbRecAttr::setup(const class NdbDictionary::Column* col, char* aValue)
+{
+ return setup(&(col->m_impl), aValue);
+}
+int
NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
{
Uint32 tAttrSize = anAttrInfo->m_attrSize;
@@ -53,6 +55,7 @@ NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
Uint32 tAttrByteSize = tAttrSize * tArraySize;
m_column = anAttrInfo;
+
theAttrId = anAttrInfo->m_attrId;
theAttrSize = tAttrSize;
theArraySize = tArraySize;
@@ -124,3 +127,79 @@ NdbRecAttr::clone() const {
memcpy(ret->theRef, theRef, n);
return ret;
}
+
+NdbOut& operator<<(NdbOut& ndbout, const NdbRecAttr &r)
+{
+ if (r.isNULL())
+ {
+ ndbout << "[NULL]";
+ return ndbout;
+ }
+
+ if (r.arraySize() > 1)
+ ndbout << "[";
+
+ for (Uint32 j = 0; j < r.arraySize(); j++)
+ {
+ if (j > 0)
+ ndbout << " ";
+
+ switch(r.getType())
+ {
+ case NdbDictionary::Column::Bigunsigned:
+ ndbout << r.u_64_value();
+ break;
+ case NdbDictionary::Column::Unsigned:
+ ndbout << r.u_32_value();
+ break;
+ case NdbDictionary::Column::Smallunsigned:
+ ndbout << r.u_short_value();
+ break;
+ case NdbDictionary::Column::Tinyunsigned:
+ ndbout << (unsigned) r.u_char_value();
+ break;
+ case NdbDictionary::Column::Bigint:
+ ndbout << r.int64_value();
+ break;
+ case NdbDictionary::Column::Int:
+ ndbout << r.int32_value();
+ break;
+ case NdbDictionary::Column::Smallint:
+ ndbout << r.short_value();
+ break;
+ case NdbDictionary::Column::Tinyint:
+ ndbout << (int) r.char_value();
+ break;
+ case NdbDictionary::Column::Char:
+ ndbout.print("%.*s", r.arraySize(), r.aRef());
+ j = r.arraySize();
+ break;
+ case NdbDictionary::Column::Varchar:
+ {
+ short len = ntohs(r.u_short_value());
+ ndbout.print("%.*s", len, r.aRef()+2);
+ }
+ j = r.arraySize();
+ break;
+ case NdbDictionary::Column::Float:
+ ndbout << r.float_value();
+ break;
+ case NdbDictionary::Column::Double:
+ ndbout << r.double_value();
+ break;
+ default: /* no print functions for the rest, just print type */
+ ndbout << r.getType();
+ j = r.arraySize();
+ if (j > 1)
+ ndbout << " %u times" << j;
+ break;
+ }
+ }
+
+ if (r.arraySize() > 1)
+ {
+ ndbout << "]";
+ }
+
+ return ndbout;
+}
diff --git a/ndb/src/ndbapi/NdbResultSet.cpp b/ndb/src/ndbapi/NdbResultSet.cpp
index 8397d5eef91..65ed43f60d8 100644
--- a/ndb/src/ndbapi/NdbResultSet.cpp
+++ b/ndb/src/ndbapi/NdbResultSet.cpp
@@ -61,7 +61,8 @@ NdbResultSet::updateTuple(){
}
NdbScanOperation * op = (NdbScanOperation*)(m_operation);
- return op->takeOverScanOp(UpdateRequest, op->m_transConnection);
+ return op->takeOverScanOp(NdbOperation::UpdateRequest,
+ op->m_transConnection);
}
NdbOperation*
@@ -71,7 +72,8 @@ NdbResultSet::updateTuple(NdbConnection* takeOverTrans){
return 0;
}
- return m_operation->takeOverScanOp(UpdateRequest, takeOverTrans);
+ return m_operation->takeOverScanOp(NdbOperation::UpdateRequest,
+ takeOverTrans);
}
int
@@ -82,7 +84,8 @@ NdbResultSet::deleteTuple(){
}
NdbScanOperation * op = (NdbScanOperation*)(m_operation);
- void * res = op->takeOverScanOp(DeleteRequest, op->m_transConnection);
+ void * res = op->takeOverScanOp(NdbOperation::DeleteRequest,
+ op->m_transConnection);
if(res == 0)
return -1;
return 0;
@@ -95,7 +98,8 @@ NdbResultSet::deleteTuple(NdbConnection * takeOverTrans){
return 0;
}
- void * res = m_operation->takeOverScanOp(DeleteRequest, takeOverTrans);
+ void * res = m_operation->takeOverScanOp(NdbOperation::DeleteRequest,
+ takeOverTrans);
if(res == 0)
return -1;
return 0;
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index 4db0f30f56c..cc090ac0364 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -34,6 +34,7 @@
#include "NdbApiSignal.hpp"
#include <NdbOut.hpp>
#include "NdbDictionaryImpl.hpp"
+#include "NdbBlob.hpp"
NdbScanOperation::NdbScanOperation(Ndb* aNdb) :
NdbCursorOperation(aNdb),
@@ -86,8 +87,10 @@ NdbScanOperation::init(NdbTableImpl* tab, NdbConnection* myConnection)
m_transConnection = myConnection;
//NdbConnection* aScanConnection = theNdb->startTransaction(myConnection);
NdbConnection* aScanConnection = theNdb->hupp(myConnection);
- if (!aScanConnection)
+ if (!aScanConnection){
+ setErrorCodeAbort(theNdb->getNdbError().code);
return -1;
+ }
aScanConnection->theFirstOpInList = this;
aScanConnection->theLastOpInList = this;
NdbCursorOperation::cursInit();
@@ -106,11 +109,11 @@ NdbResultSet* NdbScanOperation::readTuples(Uint32 parallell,
break;
case NdbCursorOperation::LM_Exclusive:
parallell = (parallell == 0 ? 1 : parallell);
- res = openScan(parallell, true, /*irrelevant*/true, /*irrelevant*/false);
+ res = openScan(parallell, true, true, false);
break;
case NdbCursorOperation::LM_Dirty:
parallell = (parallell == 0 ? 240 : parallell);
- res = openScan(parallell, true, /*irrelevant*/true, /*irrelevant*/false);
+ res = openScan(parallell, false, false, true);
break;
default:
res = -1;
@@ -292,6 +295,18 @@ int NdbScanOperation::setValue(Uint32 anAttrId, double aValue)
return 0;
}
+NdbBlob*
+NdbScanOperation::getBlobHandle(const char* anAttrName)
+{
+ return NdbOperation::getBlobHandle(m_transConnection, m_currentTable->getColumn(anAttrName));
+}
+
+NdbBlob*
+NdbScanOperation::getBlobHandle(Uint32 anAttrId)
+{
+ return NdbOperation::getBlobHandle(m_transConnection, m_currentTable->getColumn(anAttrId));
+}
+
// Private methods
int NdbScanOperation::executeCursor(int ProcessorId)
@@ -342,6 +357,15 @@ int NdbScanOperation::nextResult(bool fetchAllowed)
const NdbError err = theNdbCon->getNdbError();
m_transConnection->setOperationErrorCode(err.code);
}
+ if (result == 0) {
+ // handle blobs
+ NdbBlob* tBlob = theBlobList;
+ while (tBlob != NULL) {
+ if (tBlob->atNextResult() == -1)
+ return -1;
+ tBlob = tBlob->theNext;
+ }
+ }
return result;
}
diff --git a/ndb/src/ndbapi/NdbSchemaCon.cpp b/ndb/src/ndbapi/NdbSchemaCon.cpp
deleted file mode 100644
index fbf30c70d12..00000000000
--- a/ndb/src/ndbapi/NdbSchemaCon.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*********************************************************************
-Name: NdbSchemaCon.C
-Include:
-Link:
-Author: UABMNST Mona Natterkvist UAB/B/SD
- EMIKRON Mikael Ronstrom
-Date: 020826
-Version: 2.0
-Description: Interface between application and NDB
-Documentation:
-Adjust: 980126 UABMNST First version.
- 020826 EMIKRON New version adapted to new DICT version
-************************************************************************************************/
-#include "NdbSchemaCon.hpp"
-#include "NdbSchemaOp.hpp"
-#include "NdbApiSignal.hpp"
-#include "TransporterFacade.hpp"
-#include <RefConvert.hpp>
-#include <signaldata/CreateIndx.hpp>
-#include <signaldata/DropIndx.hpp>
-#include <signaldata/CreateTable.hpp>
-#include <NdbOut.hpp>
-
-/*********************************************************************
-NdbSchemaCon(Ndb* aNdb);
-
-Parameters: aNdb: Pointers to the Ndb object
-Remark: Creates a schemacon object.
-************************************************************************************************/
-NdbSchemaCon::NdbSchemaCon( Ndb* aNdb ) :
- theNdb(aNdb),
- theFirstSchemaOpInList(NULL),
- theMagicNumber(0x75318642)
-{
- theError.code = 0;
-}//NdbSchemaCon::NdbSchemaCon()
-
-/*********************************************************************
-~NdbSchemaCon();
-
-Remark: Deletes the connection object.
-************************************************************************************************/
-NdbSchemaCon::~NdbSchemaCon()
-{
-}//NdbSchemaCon::~NdbSchemaCon()
-
-/*********************************************************************
-NdbSchemaOp* getNdbSchemaOp();
-
-Return Value Return a pointer to a NdbSchemaOp object if getNdbSchemaOp was sussesful.
- Return NULL: In all other case.
-Parameters: tableId : Id of the database table beeing deleted.
-************************************************************************************************/
-NdbSchemaOp*
-NdbSchemaCon::getNdbSchemaOp()
-{
- NdbSchemaOp* tSchemaOp;
- if (theFirstSchemaOpInList != NULL) {
- theError.code = 4401; // Only support one add table per transaction
- return NULL;
- }//if
- tSchemaOp = new NdbSchemaOp(theNdb);
- if ( tSchemaOp == NULL ) {
- theError.code = 4000; // Could not allocate schema operation
- return NULL;
- }//if
- theFirstSchemaOpInList = tSchemaOp;
- int retValue = tSchemaOp->init(this);
- if (retValue == -1) {
- release();
- theError.code = 4000; // Could not allocate buffer in schema operation
- return NULL;
- }//if
- return tSchemaOp;
-}//NdbSchemaCon::getNdbSchemaOp()
-
-/*********************************************************************
-int execute();
-
-Return Value: Return 0 : execute was successful.
- Return -1: In all other case.
-Parameters : aTypeOfExec: Type of execute.
-Remark: Initialise connection object for new transaction.
-************************************************************************************************/
-int
-NdbSchemaCon::execute()
-{
- if(theError.code != 0) {
- return -1;
- }//if
-
- NdbSchemaOp* tSchemaOp;
-
- tSchemaOp = theFirstSchemaOpInList;
- if (tSchemaOp == NULL) {
- theError.code = 4402;
- return -1;
- }//if
-
- if ((tSchemaOp->sendRec() == -1) || (theError.code != 0)) {
- // Error Code already set in other place
- return -1;
- }//if
-
- return 0;
-}//NdbSchemaCon::execute()
-
-/*********************************************************************
-void release();
-
-Remark: Release all schemaop.
-************************************************************************************************/
-void
-NdbSchemaCon::release()
-{
- NdbSchemaOp* tSchemaOp;
- tSchemaOp = theFirstSchemaOpInList;
- if (tSchemaOp != NULL) {
- tSchemaOp->release();
- delete tSchemaOp;
- }//if
- theFirstSchemaOpInList = NULL;
- return;
-}//NdbSchemaCon::release()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ndb/src/ndbapi/NdbSchemaOp.cpp b/ndb/src/ndbapi/NdbSchemaOp.cpp
deleted file mode 100644
index 9e495229661..00000000000
--- a/ndb/src/ndbapi/NdbSchemaOp.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-/*****************************************************************************
-Name: NdbSchemaOp.C
-Include:
-Link:
-Author: UABMNST Mona Natterkvist UAB/B/SD
- EMIKRON Mikael Ronstrom
-Date: 020826
-Version: 2.0
-Description: Interface between application and NDB
-Documentation: Handles createTable and createAttribute calls
-
-Adjust: 980125 UABMNST First version.
- 020826 EMIKRON New version for new DICT
-*****************************************************************************/
-#include <assert.h>
-#include "NdbSchemaOp.hpp"
-#include "NdbSchemaCon.hpp"
-#include "API.hpp"
-
-/*****************************************************************************
-NdbSchemaOp(Ndb* aNdb, Table* aTable);
-
-Return Value: None
-Parameters: aNdb: Pointers to the Ndb object.
- aTable: Pointers to the Table object
-Remark: Creat an object of NdbSchemaOp.
-*****************************************************************************/
-NdbSchemaOp::NdbSchemaOp(Ndb* aNdb) :
- theNdb(aNdb),
- theSchemaCon(NULL),
- m_currentTable(NULL)
-{
-}//NdbSchemaOp::NdbSchemaOp()
-
-/*****************************************************************************
-~NdbSchemaOp();
-
-Remark: Delete tables for connection pointers (id).
-*****************************************************************************/
-NdbSchemaOp::~NdbSchemaOp( )
-{
-}//~NdbSchemaOp::NdbSchemaOp()
-
-/*****************************************************************************
-int createTable( const char* tableName )
-*****************************************************************************/
-int
-NdbSchemaOp::createTable(const char* aTableName,
- Uint32 aTableSize,
- KeyType aTupleKey,
- int aNrOfPages,
- FragmentType aFragmentType,
- int aKValue,
- int aMinLoadFactor,
- int aMaxLoadFactor,
- int aMemoryType,
- bool aStoredTable)
-{
- if(m_currentTable != 0){
- return -1;
- }
-
- m_currentTable = new NdbDictionary::Table(aTableName);
- m_currentTable->setKValue(aKValue);
- m_currentTable->setMinLoadFactor(aMinLoadFactor);
- m_currentTable->setMaxLoadFactor(aMaxLoadFactor);
- m_currentTable->setLogging(aStoredTable);
- m_currentTable->setFragmentType(NdbDictionary::Object::FragAllMedium);
- return 0;
-}//NdbSchemaOp::createTable()
-
-/******************************************************************************
-int createAttribute( const char* anAttrName,
- KeyType aTupleyKey,
- int anAttrSize,
- int anArraySize,
- AttrType anAttrType,
- SafeType aSafeType,
- StorageMode aStorageMode,
- int aNullAttr,
- int aStorageAttr );
-
-******************************************************************************/
-int
-NdbSchemaOp::createAttribute( const char* anAttrName,
- KeyType aTupleKey,
- int anAttrSize,
- int anArraySize,
- AttrType anAttrType,
- StorageMode aStorageMode,
- bool nullable,
- StorageAttributeType aStorageAttr,
- int aDistributionKeyFlag,
- int aDistributionGroupFlag,
- int aDistributionGroupNoOfBits,
- bool aAutoIncrement,
- const char* aDefaultValue)
-{
- if (m_currentTable == 0){
- return -1;
- }//if
-
- NdbDictionary::Column col(anAttrName);
- switch(anAttrType){
- case Signed:
- if(anAttrSize == 64)
- col.setType(NdbDictionary::Column::Bigint);
- else
- col.setType(NdbDictionary::Column::Int);
- break;
- case UnSigned:
- if(anAttrSize == 64)
- col.setType(NdbDictionary::Column::Bigunsigned);
- else
- col.setType(NdbDictionary::Column::Unsigned);
- break;
- case Float:
- if(anAttrSize == 64)
- col.setType(NdbDictionary::Column::Double);
- else
- col.setType(NdbDictionary::Column::Float);
- break;
- case String:
- col.setType(NdbDictionary::Column::Char);
- break;
- case NoAttrTypeDef:
- abort();
- }
- col.setLength(anArraySize);
- col.setNullable(nullable);
- if(aTupleKey != NoKey)
- col.setPrimaryKey(true);
- else
- col.setPrimaryKey(false);
-
- col.setDistributionKey(aDistributionKeyFlag);
- col.setDistributionGroup(aDistributionGroupFlag,aDistributionGroupNoOfBits);
- col.setAutoIncrement(aAutoIncrement);
- col.setDefaultValue(aDefaultValue != 0 ? aDefaultValue : "");
-
- m_currentTable->addColumn(col);
- return 0;
-}
-
-/******************************************************************************
-void release();
-
-Remark: Release all objects connected to the schemaop object.
-******************************************************************************/
-void
-NdbSchemaOp::release(){
-}//NdbSchemaOp::release()
-
-/******************************************************************************
-int sendRec()
-
-Return Value: Return 0 : send was succesful.
- Return -1: In all other case.
-Parameters:
-Remark: Send and receive signals for schema transaction based on state
-******************************************************************************/
-int
-NdbSchemaOp::sendRec(){
- int retVal = 0;
- if(m_currentTable == 0){
- retVal = -1;
- } else {
- retVal = theNdb->getDictionary()->createTable(* m_currentTable);
- delete m_currentTable;
- theSchemaCon->theError.code = theNdb->getDictionary()->getNdbError().code;
- }
-
- return retVal;
-}//NdbSchemaOp::sendRec()
-
-/******************************************************************************
-int init();
-
-Return Value: Return 0 : init was successful.
- Return -1: In all other case.
-Remark: Initiates SchemaOp record after allocation.
-******************************************************************************/
-int
-NdbSchemaOp::init(NdbSchemaCon* aSchemaCon)
-{
- theSchemaCon = aSchemaCon;
- return 0;
-}//NdbSchemaOp::init()
diff --git a/ndb/src/ndbapi/NdbUtil.hpp b/ndb/src/ndbapi/NdbUtil.hpp
index 6a82af85987..80fc15ddd8c 100644
--- a/ndb/src/ndbapi/NdbUtil.hpp
+++ b/ndb/src/ndbapi/NdbUtil.hpp
@@ -30,7 +30,6 @@ Comment:
#define NdbUtil_H
#include <ndb_global.h>
-#include "AttrType.hpp"
class NdbApiSignal;
class NdbOperation;
diff --git a/ndb/src/ndbapi/Ndberr.cpp b/ndb/src/ndbapi/Ndberr.cpp
index faa2f00cfce..a8b968da03f 100644
--- a/ndb/src/ndbapi/Ndberr.cpp
+++ b/ndb/src/ndbapi/Ndberr.cpp
@@ -18,9 +18,9 @@
#include <NdbError.hpp>
#include "NdbImpl.hpp"
#include "NdbDictionaryImpl.hpp"
-#include <NdbSchemaCon.hpp>
#include <NdbOperation.hpp>
#include <NdbConnection.hpp>
+#include <NdbBlob.hpp>
static void
@@ -67,9 +67,9 @@ NdbOperation::getNdbError() const {
return theError;
}
-const
-NdbError &
-NdbSchemaCon::getNdbError() const {
+const
+NdbError &
+NdbBlob::getNdbError() const {
update(theError);
return theError;
}
diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp
index 696dfe68e40..a05eb4c54c3 100644
--- a/ndb/src/ndbapi/Ndbif.cpp
+++ b/ndb/src/ndbapi/Ndbif.cpp
@@ -16,10 +16,9 @@
#include "NdbApiSignal.hpp"
-#include "AttrType.hpp"
#include "NdbImpl.hpp"
-#include "NdbSchemaOp.hpp"
-#include "NdbSchemaCon.hpp"
+//#include "NdbSchemaOp.hpp"
+//#include "NdbSchemaCon.hpp"
#include "NdbOperation.hpp"
#include "NdbIndexOperation.hpp"
#include "NdbScanReceiver.hpp"
@@ -42,13 +41,12 @@
/******************************************************************************
- * int init( int aNrOfCon, int aNrOfOp );
+ * int init( int aMaxNoOfTransactions );
*
* Return Value: Return 0 : init was successful.
* Return -1: In all other case.
- * Parameters: aNrOfCon : Number of connections offered to the application.
- * aNrOfOp : Number of operations offered to the application.
- * Remark: Create pointers and idle list Synchronous.
+ * Parameters: aMaxNoOfTransactions : Max number of simultaneous transations
+ * Remark: Create pointers and idle list Synchronous.
****************************************************************************/
int
Ndb::init(int aMaxNoOfTransactions)
@@ -90,7 +88,7 @@ Ndb::init(int aMaxNoOfTransactions)
theMyRef = numberToRef(theNdbBlockNumber, theNode);
for (i = 1; i < MAX_NDB_NODES; i++){
- if (theFacade->getIsNodeDefined(i)){
+ if (theFacade->getIsDbNode(i)){
theDBnodes[theNoOfDBnodes] = i;
theNoOfDBnodes++;
}
@@ -254,8 +252,9 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
for (int i = tNoSentTransactions - 1; i >= 0; i--) {
NdbConnection* localCon = theSentTransactionsArray[i];
if (localCon->getConnectedNodeId() == aNodeId ) {
- const SendStatusType sendStatus = localCon->theSendStatus;
- if (sendStatus == sendTC_OP || sendStatus == sendTC_COMMIT) {
+ const NdbConnection::SendStatusType sendStatus = localCon->theSendStatus;
+ if (sendStatus == NdbConnection::sendTC_OP ||
+ sendStatus == NdbConnection::sendTC_COMMIT) {
/*
A transaction was interrupted in the prepare phase by a node
failure. Since the transaction was not found in the phase
@@ -263,13 +262,13 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
we report a normal node failure abort.
*/
localCon->setOperationErrorCodeAbort(4010);
- localCon->theCompletionStatus = CompletedFailure;
- } else if (sendStatus == sendTC_ROLLBACK) {
+ localCon->theCompletionStatus = NdbConnection::CompletedFailure;
+ } else if (sendStatus == NdbConnection::sendTC_ROLLBACK) {
/*
We aimed for abort and abort we got even if it was by a node
failure. We will thus report it as a success.
*/
- localCon->theCompletionStatus = CompletedSuccess;
+ localCon->theCompletionStatus = NdbConnection::CompletedSuccess;
} else {
#ifdef VM_TRACE
printState("abortTransactionsAfterNodeFailure %x", this);
@@ -281,7 +280,7 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
intact since the node was failing and they were aborted. Thus we
set commit state to Aborted and set state to release on close.
*/
- localCon->theCommitStatus = Aborted;
+ localCon->theCommitStatus = NdbConnection::Aborted;
localCon->theReleaseOnClose = true;
completedTransaction(localCon);
}//if
@@ -328,7 +327,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == sendTC_OP)) {
+ (tCon->theSendStatus == NdbConnection::sendTC_OP)) {
tReturnCode = tCon->receiveTCKEYCONF(keyConf, aSignal->getLength());
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -356,7 +355,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber() == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == sendTC_OP) {
+ if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
tReturnCode = tOp->receiveREAD_CONF(tDataPtr,
aSignal->getLength());
if (tReturnCode != -1) {
@@ -381,7 +380,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber() == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == sendTC_OP) {
+ if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
tReturnCode = tOp->receiveTRANSID_AI(tDataPtr,
aSignal->getLength());
if (tReturnCode != -1) {
@@ -398,7 +397,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber() == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == sendTC_OP) {
+ if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
tReturnCode = tOp->receiveTRANSID_AI(tDataPtr,
aSignal->getLength());
if (tReturnCode != -1) {
@@ -442,8 +441,8 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber() == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if ((tCon->theSendStatus == sendTC_OP) ||
- (tCon->theSendStatus == sendTC_COMMIT)) {
+ if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
+ (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -469,8 +468,8 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber() == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if ((tCon->theSendStatus == sendTC_OP) ||
- (tCon->theSendStatus == sendTC_ROLLBACK)) {
+ if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
+ (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -490,7 +489,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber() == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == sendTC_OP) {
+ if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
tReturnCode = tOp->receiveTCKEYREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -512,7 +511,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == sendTC_COMMIT)) {
+ (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
tReturnCode = tCon->receiveTC_COMMITCONF(commitConf);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -537,7 +536,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == sendTC_COMMIT)) {
+ (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
tReturnCode = tCon->receiveTC_COMMITREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -553,7 +552,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == sendTC_ROLLBACK)) {
+ (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
tReturnCode = tCon->receiveTCROLLBACKCONF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -568,7 +567,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == sendTC_ROLLBACK)) {
+ (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
tReturnCode = tCon->receiveTCROLLBACKREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -789,7 +788,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
const BlockReference aTCRef = aSignal->theSendersBlockRef;
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == sendTC_OP)) {
+ (tCon->theSendStatus == NdbConnection::sendTC_OP)) {
tReturnCode = tCon->receiveTCINDXCONF(indxConf, aSignal->getLength());
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -812,7 +811,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tIndexOp->checkMagicNumber() == 0) {
tCon = tIndexOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == sendTC_OP) {
+ if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
tReturnCode = tIndexOp->receiveTCINDXREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -866,7 +865,8 @@ Ndb::completedTransaction(NdbConnection* aCon)
Uint32 tTransArrayIndex = aCon->theTransArrayIndex;
Uint32 tNoSentTransactions = theNoOfSentTransactions;
Uint32 tNoCompletedTransactions = theNoOfCompletedTransactions;
- if ((tNoSentTransactions > 0) && (aCon->theListState == InSendList) &&
+ if ((tNoSentTransactions > 0) &&
+ (aCon->theListState == NdbConnection::InSendList) &&
(tTransArrayIndex < tNoSentTransactions)) {
NdbConnection* tMoveCon = theSentTransactionsArray[tNoSentTransactions - 1];
@@ -880,7 +880,7 @@ Ndb::completedTransaction(NdbConnection* aCon)
theNoOfCompletedTransactions = tNoCompletedTransactions + 1;
theNoOfSentTransactions = tNoSentTransactions - 1;
- aCon->theListState = InCompletedList;
+ aCon->theListState = NdbConnection::InCompletedList;
aCon->handleExecuteCompletion();
if ((theMinNoOfEventsToWakeUp != 0) &&
(theNoOfCompletedTransactions >= theMinNoOfEventsToWakeUp)) {
@@ -915,7 +915,7 @@ Ndb::reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfCompletedTrans)
NdbAsynchCallback aCallback = aCopyArray[i]->theCallbackFunction;
int tResult = 0;
if (aCallback != NULL) {
- if (aCopyArray[i]->theReturnStatus == ReturnFailure) {
+ if (aCopyArray[i]->theReturnStatus == NdbConnection::ReturnFailure) {
tResult = -1;
}//if
(*aCallback)(tResult, aCopyArray[i], anyObject);
@@ -939,13 +939,13 @@ Ndb::pollCompleted(NdbConnection** aCopyArray)
if (tNoCompletedTransactions > 0) {
for (i = 0; i < tNoCompletedTransactions; i++) {
aCopyArray[i] = theCompletedTransactionsArray[i];
- if (aCopyArray[i]->theListState != InCompletedList) {
+ if (aCopyArray[i]->theListState != NdbConnection::InCompletedList) {
ndbout << "pollCompleted error ";
ndbout << aCopyArray[i]->theListState << endl;
abort();
}//if
theCompletedTransactionsArray[i] = NULL;
- aCopyArray[i]->theListState = NotInList;
+ aCopyArray[i]->theListState = NdbConnection::NotInList;
}//for
}//if
theNoOfCompletedTransactions = 0;
@@ -967,8 +967,8 @@ Ndb::check_send_timeout()
a_con->printState();
#endif
a_con->setOperationErrorCodeAbort(4012);
- a_con->theCommitStatus = Aborted;
- a_con->theCompletionStatus = CompletedFailure;
+ a_con->theCommitStatus = NdbConnection::Aborted;
+ a_con->theCompletionStatus = NdbConnection::CompletedFailure;
a_con->handleExecuteCompletion();
remove_sent_list(i);
insert_completed_list(a_con);
@@ -997,7 +997,7 @@ Ndb::insert_completed_list(NdbConnection* a_con)
Uint32 no_of_comp = theNoOfCompletedTransactions;
theCompletedTransactionsArray[no_of_comp] = a_con;
theNoOfCompletedTransactions = no_of_comp + 1;
- a_con->theListState = InCompletedList;
+ a_con->theListState = NdbConnection::InCompletedList;
a_con->theTransArrayIndex = no_of_comp;
return no_of_comp;
}
@@ -1008,7 +1008,7 @@ Ndb::insert_sent_list(NdbConnection* a_con)
Uint32 no_of_sent = theNoOfSentTransactions;
theSentTransactionsArray[no_of_sent] = a_con;
theNoOfSentTransactions = no_of_sent + 1;
- a_con->theListState = InSendList;
+ a_con->theListState = NdbConnection::InSendList;
a_con->theTransArrayIndex = no_of_sent;
return no_of_sent;
}
@@ -1046,10 +1046,10 @@ Ndb::sendPrepTrans(int forceSend)
if ((tp->getNodeSequence(node_id) == a_con->theNodeSequence) &&
tp->get_node_alive(node_id) ||
(tp->get_node_stopping(node_id) &&
- ((a_con->theSendStatus == sendABORT) ||
- (a_con->theSendStatus == sendABORTfail) ||
- (a_con->theSendStatus == sendCOMMITstate) ||
- (a_con->theSendStatus == sendCompleted)))) {
+ ((a_con->theSendStatus == NdbConnection::sendABORT) ||
+ (a_con->theSendStatus == NdbConnection::sendABORTfail) ||
+ (a_con->theSendStatus == NdbConnection::sendCOMMITstate) ||
+ (a_con->theSendStatus == NdbConnection::sendCompleted)))) {
/*
We will send if
1) Node is alive and sequences are correct OR
@@ -1081,13 +1081,13 @@ Ndb::sendPrepTrans(int forceSend)
again and will thus set the state to Aborted to avoid a more or
less eternal loop of tries.
*/
- if (a_con->theSendStatus == sendOperations) {
+ if (a_con->theSendStatus == NdbConnection::sendOperations) {
a_con->setOperationErrorCodeAbort(4021);
- a_con->theCommitStatus = NeedAbort;
+ a_con->theCommitStatus = NdbConnection::NeedAbort;
TRACE_DEBUG("Send buffer full and sendOperations");
} else {
a_con->setOperationErrorCodeAbort(4026);
- a_con->theCommitStatus = Aborted;
+ a_con->theCommitStatus = NdbConnection::Aborted;
TRACE_DEBUG("Send buffer full, set state to Aborted");
}//if
}//if
@@ -1104,7 +1104,7 @@ Ndb::sendPrepTrans(int forceSend)
*/
TRACE_DEBUG("Abort a transaction when stopping a node");
a_con->setOperationErrorCodeAbort(4023);
- a_con->theCommitStatus = NeedAbort;
+ a_con->theCommitStatus = NdbConnection::NeedAbort;
} else {
/*
The node is hard dead and we cannot continue. We will also release
@@ -1114,10 +1114,10 @@ Ndb::sendPrepTrans(int forceSend)
a_con->setOperationErrorCodeAbort(4025);
a_con->theReleaseOnClose = true;
a_con->theTransactionIsStarted = false;
- a_con->theCommitStatus = Aborted;
+ a_con->theCommitStatus = NdbConnection::Aborted;
}//if
}//if
- a_con->theCompletionStatus = CompletedFailure;
+ a_con->theCompletionStatus = NdbConnection::CompletedFailure;
a_con->handleExecuteCompletion();
insert_completed_list(a_con);
}//for
diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp
index be7acc48d7a..f451ba885d4 100644
--- a/ndb/src/ndbapi/Ndbinit.cpp
+++ b/ndb/src/ndbapi/Ndbinit.cpp
@@ -15,10 +15,12 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <ndb_global.h>
+
#include "NdbApiSignal.hpp"
#include "NdbImpl.hpp"
-#include "NdbSchemaOp.hpp"
-#include "NdbSchemaCon.hpp"
+//#include "NdbSchemaOp.hpp"
+//#include "NdbSchemaCon.hpp"
#include "NdbOperation.hpp"
#include "NdbConnection.hpp"
#include "NdbRecAttr.hpp"
@@ -54,7 +56,7 @@ Ndb(const char* aDataBase);
Parameters: aDataBase : Name of the database.
Remark: Connect to the database.
***************************************************************************/
-Ndb::Ndb( const char* aDataBase , const char* aDataBaseSchema) :
+Ndb::Ndb( const char* aDataBase , const char* aSchema) :
theNdbObjectIdMap(0),
thePreparedTransactionsArray(NULL),
theSentTransactionsArray(NULL),
@@ -72,8 +74,8 @@ Ndb::Ndb( const char* aDataBase , const char* aDataBaseSchema) :
theOpIdleList(NULL),
theScanOpIdleList(NULL),
theIndexOpIdleList(NULL),
- theSchemaConIdleList(NULL),
- theSchemaConToNdbList(NULL),
+// theSchemaConIdleList(NULL),
+// theSchemaConToNdbList(NULL),
theTransactionList(NULL),
theConnectionArray(NULL),
theRecAttrIdleList(NULL),
@@ -83,6 +85,7 @@ Ndb::Ndb( const char* aDataBase , const char* aDataBaseSchema) :
theSubroutineList(NULL),
theCallList(NULL),
theScanList(NULL),
+ theNdbBlobIdleList(NULL),
theNoOfDBnodes(0),
theDBnodes(NULL),
the_release_ind(NULL),
@@ -92,6 +95,8 @@ Ndb::Ndb( const char* aDataBase , const char* aDataBaseSchema) :
theNdbBlockNumber(-1),
theInitState(NotConstructed)
{
+ fullyQualifiedNames = true;
+
cgetSignals =0;
cfreeSignals = 0;
cnewSignals = 0;
@@ -116,28 +121,22 @@ Ndb::Ndb( const char* aDataBase , const char* aDataBaseSchema) :
theLastTupleId[i] = 0;
}//for
- if (aDataBase)
- strncpy(theDataBase, aDataBase, NDB_MAX_DATABASE_NAME_SIZE);
- else
- memset(theDataBase, 0, sizeof(theDataBase));
- strncpy(theDataBaseSchema, aDataBaseSchema, NDB_MAX_SCHEMA_NAME_SIZE);
- // Prepare prefix for faster operations
- uint db_len = MIN(strlen(theDataBase), NDB_MAX_DATABASE_NAME_SIZE - 1);
- uint schema_len =
- MIN(strlen(theDataBaseSchema), NDB_MAX_SCHEMA_NAME_SIZE - 1);
- strncpy(prefixName, theDataBase, NDB_MAX_DATABASE_NAME_SIZE - 1);
- prefixName[db_len] = '/';
- strncpy(prefixName+db_len+1, theDataBaseSchema,
- NDB_MAX_SCHEMA_NAME_SIZE - 1);
- prefixName[db_len+schema_len+1] = '/';
- prefixName[db_len+schema_len+2] = '\0';
- prefixEnd = prefixName + db_len+schema_len + 2;
+ snprintf(theDataBase, sizeof(theDataBase), "%s",
+ aDataBase ? aDataBase : "");
+ snprintf(theDataBaseSchema, sizeof(theDataBaseSchema), "%s",
+ aSchema ? aSchema : "");
+
+ int len = snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
+ theDataBase, table_name_separator,
+ theDataBaseSchema, table_name_separator);
+ prefixEnd = prefixName + (len < sizeof(prefixName) ? len :
+ sizeof(prefixName) - 1);
NdbMutex_Lock(&createNdbMutex);
TransporterFacade * m_facade = 0;
if(theNoOfNdbObjects == 0){
- if ((m_facade = TransporterFacade::start_instance(0,ndbConnectString)) == 0)
+ if ((m_facade = TransporterFacade::start_instance(ndbConnectString)) == 0)
theInitState = InitConfigError;
} else {
m_facade = TransporterFacade::instance();
@@ -207,8 +206,8 @@ Ndb::~Ndb()
NdbMutex_Unlock(&createNdbMutex);
- if (theSchemaConToNdbList != NULL)
- closeSchemaTransaction(theSchemaConToNdbList);
+// if (theSchemaConToNdbList != NULL)
+// closeSchemaTransaction(theSchemaConToNdbList);
while ( theConIdleList != NULL )
freeNdbCon();
while ( theSignalIdleList != NULL )
@@ -231,6 +230,8 @@ Ndb::~Ndb()
freeNdbCall();
while (theScanList != NULL)
freeNdbScanRec();
+ while (theNdbBlobIdleList != NULL)
+ freeNdbBlob();
releaseTransactionArrays();
startTransactionNodeSelectionData.release();
diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp
index 3839cc3291b..e557fdc0a5f 100644
--- a/ndb/src/ndbapi/Ndblist.cpp
+++ b/ndb/src/ndbapi/Ndblist.cpp
@@ -16,8 +16,8 @@
#include <NdbOut.hpp>
#include "Ndb.hpp"
-#include "NdbSchemaOp.hpp"
-#include "NdbSchemaCon.hpp"
+//#include "NdbSchemaOp.hpp"
+//#include "NdbSchemaCon.hpp"
#include "NdbOperation.hpp"
#include "NdbScanOperation.hpp"
#include "NdbIndexOperation.hpp"
@@ -27,6 +27,7 @@
#include "NdbScanReceiver.hpp"
#include "NdbUtil.hpp"
#include "API.hpp"
+#include "NdbBlob.hpp"
void
Ndb::checkFailedNode()
@@ -104,7 +105,7 @@ Ndb::createConIdleList(int aNrOfCon)
tNdbCon->next(theConIdleList);
theConIdleList = tNdbCon;
}
- tNdbCon->Status(NotConnected);
+ tNdbCon->Status(NdbConnection::NotConnected);
}
theNoOfAllocatedTransactions = aNrOfCon;
return aNrOfCon;
@@ -435,6 +436,19 @@ Ndb::getSignal()
return tSignal;
}
+NdbBlob*
+Ndb::getNdbBlob()
+{
+ NdbBlob* tBlob = theNdbBlobIdleList;
+ if (tBlob != NULL) {
+ theNdbBlobIdleList = tBlob->theNext;
+ tBlob->init();
+ } else {
+ tBlob = new NdbBlob;
+ }
+ return tBlob;
+}
+
/***************************************************************************
void releaseNdbBranch(NdbBranch* aNdbBranch);
@@ -601,6 +615,14 @@ Ndb::releaseSignalsInList(NdbApiSignal** pList){
}
}
+void
+Ndb::releaseNdbBlob(NdbBlob* aBlob)
+{
+ aBlob->release();
+ aBlob->theNext = theNdbBlobIdleList;
+ theNdbBlobIdleList = aBlob;
+}
+
/***************************************************************************
void freeOperation();
@@ -745,6 +767,14 @@ Ndb::freeSignal()
cfreeSignals++;
}
+void
+Ndb::freeNdbBlob()
+{
+ NdbBlob* tBlob = theNdbBlobIdleList;
+ theNdbBlobIdleList = tBlob->theNext;
+ delete tBlob;
+}
+
/****************************************************************************
int releaseConnectToNdb(NdbConnection* aConnectConnection);
@@ -770,7 +800,7 @@ Ndb::releaseConnectToNdb(NdbConnection* a_con)
tSignal.setData((tConPtr = a_con->getTC_ConnectPtr()), 1);
tSignal.setData(theMyRef, 2);
tSignal.setData(a_con->ptr2int(), 3);
- a_con->Status(DisConnecting);
+ a_con->Status(NdbConnection::DisConnecting);
a_con->theMagicNumber = 0x37412619;
int ret_code = sendRecSignal(node_id,
WAIT_TC_RELEASE,
diff --git a/ndb/src/ndbapi/TransporterFacade.cpp b/ndb/src/ndbapi/TransporterFacade.cpp
index f4a3ae3e87d..e725144a8f8 100644
--- a/ndb/src/ndbapi/TransporterFacade.cpp
+++ b/ndb/src/ndbapi/TransporterFacade.cpp
@@ -16,7 +16,6 @@
#include <ndb_global.h>
#include <ndb_limits.h>
-#include <AttrType.hpp>
#include "TransporterFacade.hpp"
#include "ClusterMgr.hpp"
#include <IPCConfig.hpp>
@@ -29,6 +28,8 @@
#include "API.hpp"
#include <ConfigRetriever.hpp>
+#include <mgmapi_config_parameters.h>
+#include <mgmapi_configuration.hpp>
#include <NdbConfig.h>
#include <ndb_version.h>
#include <SignalLoggerManager.hpp>
@@ -332,39 +333,40 @@ atexit_stop_instance(){
* Which is protected by a mutex
*/
TransporterFacade*
-TransporterFacade::start_instance(Properties* props, const char *connectString)
-{
- bool ownProps = false;
- if (props == NULL) {
- // TransporterFacade used from API get config from mgmt srvr
- ConfigRetriever configRetriever;
- configRetriever.setConnectString(connectString);
- props = configRetriever.getConfig("API", NDB_VERSION);
- if (props == 0) {
- ndbout << "Configuration error: ";
- const char* erString = configRetriever.getErrorString();
- if (erString == 0) {
- erString = "No error specified!";
- }
- ndbout << erString << endl;
- return NULL;
+TransporterFacade::start_instance(const char * connectString){
+
+ // TransporterFacade used from API get config from mgmt srvr
+ ConfigRetriever configRetriever;
+ configRetriever.setConnectString(connectString);
+ ndb_mgm_configuration * props = configRetriever.getConfig(NDB_VERSION,
+ NODE_TYPE_API);
+ if (props == 0) {
+ ndbout << "Configuration error: ";
+ const char* erString = configRetriever.getErrorString();
+ if (erString == 0) {
+ erString = "No error specified!";
}
- props->put("LocalNodeId", configRetriever.getOwnNodeId());
- props->put("LocalNodeType", "API");
-
- ownProps = true;
+ ndbout << erString << endl;
+ return 0;
}
- TransporterFacade* tf = new TransporterFacade();
+ const int nodeId = configRetriever.getOwnNodeId();
- if (! tf->init(props)) {
+ TransporterFacade * tf = start_instance(nodeId, props);
+
+ free(props);
+ return tf;
+}
+
+TransporterFacade*
+TransporterFacade::start_instance(int nodeId,
+ const ndb_mgm_configuration* props)
+{
+ TransporterFacade* tf = new TransporterFacade();
+ if (! tf->init(nodeId, props)) {
delete tf;
return NULL;
}
- if (ownProps) {
- delete props;
- }
-
/**
* Install atexit handler
*/
@@ -499,61 +501,65 @@ TransporterFacade::TransporterFacade() :
}
bool
-TransporterFacade::init(Properties* props)
+TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props)
{
- IPCConfig config(props);
-
- if (config.init() != 0) {
- TRP_DEBUG( "IPCConfig object config failed to init()" );
- return false;
- }
- theOwnId = config.ownId();
-
+ theOwnId = nodeId;
theTransporterRegistry = new TransporterRegistry(this);
- if(config.configureTransporters(theTransporterRegistry) <= 0) {
+
+ const int res = IPCConfig::configureTransporters(nodeId,
+ * props,
+ * theTransporterRegistry);
+ if(res <= 0){
TRP_DEBUG( "configureTransporters returned 0 or less" );
return false;
}
+ ndb_mgm_configuration_iterator iter(* props, CFG_SECTION_NODE);
+ iter.first();
theClusterMgr = new ClusterMgr(* this);
- theClusterMgr->init(config);
-
- theReceiveThread = NdbThread_Create(runReceiveResponse_C,
- (void**)this,
- 32768,
- "ndb_receive",
- NDB_THREAD_PRIO_LOW);
-
- theSendThread = NdbThread_Create(runSendRequest_C,
- (void**)this,
- 32768,
- "ndb_send",
- NDB_THREAD_PRIO_LOW);
-
- theClusterMgr->startThread();
+ theClusterMgr->init(iter);
/**
* Unless there is a "Name", the initiated transporter is within
* an NDB Cluster. (If "Name" is defined, then the transporter
* is used to connect to a different system, i.e. NDB Cluster.)
*/
+#if 0
if (!props->contains("Name")) {
- const Properties* p = 0;
- if(!props->get("Node", ownId(), &p)) {
+#endif
+ iter.first();
+ if(iter.find(CFG_NODE_ID, nodeId)){
TRP_DEBUG( "Node info missing from config." );
return false;
}
Uint32 rank = 0;
- if (p->get("ArbitrationRank", &rank) && rank > 0) {
+ if(!iter.get(CFG_NODE_ARBIT_RANK, &rank) && rank>0){
theArbitMgr = new ArbitMgr(* this);
theArbitMgr->setRank(rank);
Uint32 delay = 0;
- p->get("ArbitrationDelay", &delay);
+ iter.get(CFG_NODE_ARBIT_DELAY, &delay);
theArbitMgr->setDelay(delay);
}
+
+#if 0
}
+#endif
+
+ theReceiveThread = NdbThread_Create(runReceiveResponse_C,
+ (void**)this,
+ 32768,
+ "ndb_receive",
+ NDB_THREAD_PRIO_LOW);
+
+ theSendThread = NdbThread_Create(runSendRequest_C,
+ (void**)this,
+ 32768,
+ "ndb_send",
+ NDB_THREAD_PRIO_LOW);
+ theClusterMgr->startThread();
+
#ifdef API_TRACE
signalLogger.logOn(true, 0, SignalLoggerManager::LogInOut);
#endif
diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp
index d9d2dbbcf0f..4b76cbe864a 100644
--- a/ndb/src/ndbapi/TransporterFacade.hpp
+++ b/ndb/src/ndbapi/TransporterFacade.hpp
@@ -17,7 +17,6 @@
#ifndef TransporterFacade_H
#define TransporterFacade_H
-#include <AttrType.hpp>
#include <kernel_types.h>
#include <ndb_limits.h>
#include <NdbThread.h>
@@ -28,8 +27,8 @@
class ClusterMgr;
class ArbitMgr;
-class Properties;
class IPCConfig;
+struct ndb_mgm_configuration;
class Ndb;
class NdbApiSignal;
@@ -43,15 +42,20 @@ extern "C" {
void atexit_stop_instance();
}
+/**
+ * Max number of Ndb objects in different threads.
+ * (Ndb objects should not be shared by different threads.)
+ */
class TransporterFacade
{
public:
TransporterFacade();
virtual ~TransporterFacade();
- bool init(Properties* props);
+ bool init(Uint32, const ndb_mgm_configuration *);
static TransporterFacade* instance();
- static TransporterFacade* start_instance(Properties* ipcConfig, const char *connectString);
+ static TransporterFacade* start_instance(int, const ndb_mgm_configuration*);
+ static TransporterFacade* start_instance(const char *connectString);
static void stop_instance();
/**
@@ -76,7 +80,7 @@ public:
// Is node available for running transactions
bool get_node_alive(NodeId nodeId) const;
bool get_node_stopping(NodeId nodeId) const;
- bool getIsNodeDefined(NodeId nodeId) const;
+ bool getIsDbNode(NodeId nodeId) const;
bool getIsNodeSendable(NodeId nodeId) const;
Uint32 getNodeGrp(NodeId nodeId) const;
Uint32 getNodeSequence(NodeId nodeId) const;
@@ -156,6 +160,8 @@ private:
/**
* Block number handling
*/
+ static const unsigned MAX_NO_THREADS = 4711;
+
struct ThreadData {
static const Uint32 ACTIVE = (1 << 16) | 1;
static const Uint32 INACTIVE = (1 << 16);
@@ -250,8 +256,10 @@ TransporterFacade::check_send_size(Uint32 node_id, Uint32 send_size)
inline
bool
-TransporterFacade::getIsNodeDefined(NodeId n) const {
- return theClusterMgr->getNodeInfo(n).defined;
+TransporterFacade::getIsDbNode(NodeId n) const {
+ return
+ theClusterMgr->getNodeInfo(n).defined &&
+ theClusterMgr->getNodeInfo(n).m_info.m_type == NodeInfo::DB;
}
inline
diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c
index ea7cf4de426..760322d669d 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -418,8 +418,14 @@ ErrorBundle ErrorCodes[] = {
{ 4259, AE, "Invalid set of range scan bounds" },
{ 4260, UD, "NdbScanFilter: Operator is not defined in NdbScanFilter::Group"},
{ 4261, UD, "NdbScanFilter: Column is NULL"},
- { 4262, UD, "NdbScanFilter: Condition is out of bounds"}
-
+ { 4262, UD, "NdbScanFilter: Condition is out of bounds"},
+ { 4263, IE, "Invalid blob attributes or invalid blob parts table" },
+ { 4264, AE, "Invalid usage of blob attribute" },
+ { 4265, AE, "Method is not valid in current blob state" },
+ { 4266, AE, "Invalid blob seek position" },
+ { 4267, IE, "Corrupted blob value" },
+ { 4268, IE, "Error in blob head update forced rollback of transaction" },
+ { 4268, IE, "Unknown blob error" }
};
static
diff --git a/ndb/src/ndbapi/signal-sender/SignalSender.cpp b/ndb/src/ndbapi/signal-sender/SignalSender.cpp
index e642848dcee..680d0c23b4a 100644
--- a/ndb/src/ndbapi/signal-sender/SignalSender.cpp
+++ b/ndb/src/ndbapi/signal-sender/SignalSender.cpp
@@ -71,7 +71,7 @@ SimpleSignal::print(FILE * out){
SignalSender::SignalSender(const char * connectString){
m_cond = NdbCondition_Create();
- theFacade = TransporterFacade::start_instance(0,connectString);
+ theFacade = TransporterFacade::start_instance(connectString);
m_blockNo = theFacade->open(this, execSignal, execNodeStatus);
assert(m_blockNo > 0);
}
diff --git a/ndb/src/newtonapi/dba_schema.cpp b/ndb/src/newtonapi/dba_schema.cpp
deleted file mode 100644
index 9fa99cb5d43..00000000000
--- a/ndb/src/newtonapi/dba_schema.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "dba_internal.hpp"
-
-static bool getNdbAttr(DBA_DataTypes_t,
- Size_t,
- int * attrSize,
- int * arraySize,
- AttrType * attrType);
-
-extern "C"
-DBA_Error_t
-DBA_CreateTable(const char* TableName,
- int NbColumns,
- const DBA_ColumnDesc_t Columns[] ){
-
- if(DBA_TableExists(TableName))
- return DBA_NO_ERROR;
-
- NdbSchemaCon * schemaCon = DBA__TheNdb->startSchemaTransaction();
- if(schemaCon == 0){
- DBA__SetLatestError(DBA_NDB_ERROR, 0,
- "Internal NDB error: No schema transaction");
- return DBA_NDB_ERROR;
- }
-
- NdbSchemaOp * schemaOp = schemaCon->getNdbSchemaOp();
- if(schemaOp == 0){
- DBA__TheNdb->closeSchemaTransaction(schemaCon);
- DBA__SetLatestError(DBA_NDB_ERROR, 0,
- "Internal NDB error: No schema op");
- return DBA_NDB_ERROR;
- }
-
- if(schemaOp->createTable( TableName,
- 8, // Data Size
- TupleKey,
- 2, // Index size
- All,
- 6,
- 78,
- 80,
- 1,
- false) == -1){
- DBA__TheNdb->closeSchemaTransaction(schemaCon);
- DBA__SetLatestError(DBA_NDB_ERROR, 0,
- "Internal NDB error: Create table failed");
- return DBA_NDB_ERROR;
- }
-
- for (int i = 0; i < NbColumns; i++){
- int attrSize;
- int arraySize;
- AttrType attrType;
-
- if(!getNdbAttr(Columns[i].DataType, Columns[i].Size,
- &attrSize,
- &arraySize,
- &attrType)){
- DBA__TheNdb->closeSchemaTransaction(schemaCon);
- DBA__SetLatestError(DBA_APPLICATION_ERROR, 0,
- "Invalid datatype/size combination");
- return DBA_APPLICATION_ERROR;
- }
-
- if(schemaOp->createAttribute( Columns[i].Name,
- Columns[i].IsKey ? TupleKey : NoKey,
- attrSize,
- arraySize,
- attrType) == -1){
- DBA__TheNdb->closeSchemaTransaction(schemaCon);
- DBA__SetLatestError(DBA_NDB_ERROR, 0,
- "Internal NDB error: Create attribute failed");
- return DBA_NDB_ERROR;
- }
- }
-
- if(schemaCon->execute() == -1){
- DBA__TheNdb->closeSchemaTransaction(schemaCon);
- DBA__SetLatestError(DBA_NDB_ERROR, 0,
- "Internal NDB error: Execute schema failed");
- return DBA_NDB_ERROR;
- }
-
- DBA__TheNdb->closeSchemaTransaction(schemaCon);
-
- return DBA_NO_ERROR;
-}
-
-DBA_Error_t
-DBA_DropTable( char* TableName ){
- return DBA_NOT_IMPLEMENTED;
-}
-
-Boolean_t
-DBA_TableExists( const char* TableName ){
- NdbDictionary::Dictionary * dict = DBA__TheNdb->getDictionary();
- if(dict == 0){
- return 0;
- }
-
- const NdbDictionary::Table * tab = dict->getTable(TableName);
- if(tab == 0){
- return 0;
- }
- return 1;
-}
-
-static
-bool
-getNdbAttr(DBA_DataTypes_t type,
- Size_t size,
- int * attrSize,
- int * arraySize,
- AttrType * attrType) {
-
- if(type == DBA_CHAR){
- * attrType = String;
- * attrSize = 8;
- * arraySize = size;
- return true;
- }
-
- * attrType = Signed;
- if((size % 4) == 0){
- * attrSize = 32;
- * arraySize = size / 4;
- return true;
- }
-
- * attrSize = 8;
- * arraySize = size;
-
- return true;
-}
diff --git a/ndb/src/client/Makefile b/ndb/src/old_files/client/Makefile
index 1751a98bdfe..1751a98bdfe 100644
--- a/ndb/src/client/Makefile
+++ b/ndb/src/old_files/client/Makefile
diff --git a/ndb/src/client/odbc/Extra.mk b/ndb/src/old_files/client/odbc/Extra.mk
index 762fb0bedd0..762fb0bedd0 100644
--- a/ndb/src/client/odbc/Extra.mk
+++ b/ndb/src/old_files/client/odbc/Extra.mk
diff --git a/ndb/src/client/odbc/Makefile b/ndb/src/old_files/client/odbc/Makefile
index 2da683e7d86..2da683e7d86 100644
--- a/ndb/src/client/odbc/Makefile
+++ b/ndb/src/old_files/client/odbc/Makefile
diff --git a/ndb/src/client/odbc/NdbOdbc.cpp b/ndb/src/old_files/client/odbc/NdbOdbc.cpp
index 67c6b5e0004..67c6b5e0004 100755
--- a/ndb/src/client/odbc/NdbOdbc.cpp
+++ b/ndb/src/old_files/client/odbc/NdbOdbc.cpp
diff --git a/ndb/src/client/odbc/NdbOdbc.def b/ndb/src/old_files/client/odbc/NdbOdbc.def
index 85619b91915..85619b91915 100755
--- a/ndb/src/client/odbc/NdbOdbc.def
+++ b/ndb/src/old_files/client/odbc/NdbOdbc.def
diff --git a/ndb/src/client/odbc/codegen/CodeGen.cpp b/ndb/src/old_files/client/odbc/codegen/CodeGen.cpp
index 6be78b62bd9..6be78b62bd9 100644
--- a/ndb/src/client/odbc/codegen/CodeGen.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/CodeGen.cpp
diff --git a/ndb/src/client/odbc/codegen/CodeGen.hpp b/ndb/src/old_files/client/odbc/codegen/CodeGen.hpp
index ae61dab0c2a..ae61dab0c2a 100644
--- a/ndb/src/client/odbc/codegen/CodeGen.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/CodeGen.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_base.cpp b/ndb/src/old_files/client/odbc/codegen/Code_base.cpp
index dc02e071156..dc02e071156 100644
--- a/ndb/src/client/odbc/codegen/Code_base.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_base.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_base.hpp b/ndb/src/old_files/client/odbc/codegen/Code_base.hpp
index c67c0ca7adb..c67c0ca7adb 100644
--- a/ndb/src/client/odbc/codegen/Code_base.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_base.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_column.cpp b/ndb/src/old_files/client/odbc/codegen/Code_column.cpp
index c4c0480a5e7..c4c0480a5e7 100644
--- a/ndb/src/client/odbc/codegen/Code_column.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_column.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_column.hpp b/ndb/src/old_files/client/odbc/codegen/Code_column.hpp
index af0dcea690d..af0dcea690d 100644
--- a/ndb/src/client/odbc/codegen/Code_column.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_column.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_comp_op.cpp b/ndb/src/old_files/client/odbc/codegen/Code_comp_op.cpp
index 7782ed1ea2a..7782ed1ea2a 100644
--- a/ndb/src/client/odbc/codegen/Code_comp_op.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_comp_op.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_comp_op.hpp b/ndb/src/old_files/client/odbc/codegen/Code_comp_op.hpp
index 0585ab1dabf..0585ab1dabf 100644
--- a/ndb/src/client/odbc/codegen/Code_comp_op.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_comp_op.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_create_index.cpp b/ndb/src/old_files/client/odbc/codegen/Code_create_index.cpp
index 84f319338a4..84f319338a4 100644
--- a/ndb/src/client/odbc/codegen/Code_create_index.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_create_index.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_create_index.hpp b/ndb/src/old_files/client/odbc/codegen/Code_create_index.hpp
index ebd757e1118..ebd757e1118 100644
--- a/ndb/src/client/odbc/codegen/Code_create_index.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_create_index.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_create_row.cpp b/ndb/src/old_files/client/odbc/codegen/Code_create_row.cpp
index 5b90b658ed7..5b90b658ed7 100644
--- a/ndb/src/client/odbc/codegen/Code_create_row.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_create_row.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_create_row.hpp b/ndb/src/old_files/client/odbc/codegen/Code_create_row.hpp
index f03455ff28e..f03455ff28e 100644
--- a/ndb/src/client/odbc/codegen/Code_create_row.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_create_row.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_create_table.cpp b/ndb/src/old_files/client/odbc/codegen/Code_create_table.cpp
index 14e4abbd7fe..14e4abbd7fe 100644
--- a/ndb/src/client/odbc/codegen/Code_create_table.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_create_table.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_create_table.hpp b/ndb/src/old_files/client/odbc/codegen/Code_create_table.hpp
index cbb2189d8ce..cbb2189d8ce 100644
--- a/ndb/src/client/odbc/codegen/Code_create_table.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_create_table.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_data_type.cpp b/ndb/src/old_files/client/odbc/codegen/Code_data_type.cpp
index 1ff0fcebcbe..1ff0fcebcbe 100644
--- a/ndb/src/client/odbc/codegen/Code_data_type.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_data_type.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_data_type.hpp b/ndb/src/old_files/client/odbc/codegen/Code_data_type.hpp
index 735dc05014f..735dc05014f 100644
--- a/ndb/src/client/odbc/codegen/Code_data_type.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_data_type.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_ddl.cpp b/ndb/src/old_files/client/odbc/codegen/Code_ddl.cpp
index 2ba4291a0e8..2ba4291a0e8 100644
--- a/ndb/src/client/odbc/codegen/Code_ddl.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_ddl.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_ddl.hpp b/ndb/src/old_files/client/odbc/codegen/Code_ddl.hpp
index 1ceca62d55d..1ceca62d55d 100644
--- a/ndb/src/client/odbc/codegen/Code_ddl.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_ddl.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_ddl_column.cpp b/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.cpp
index ee037e54c1f..ee037e54c1f 100644
--- a/ndb/src/client/odbc/codegen/Code_ddl_column.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_ddl_column.hpp b/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.hpp
index 7d089d37440..7d089d37440 100644
--- a/ndb/src/client/odbc/codegen/Code_ddl_column.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_ddl_constr.cpp b/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.cpp
index 78c23e38d97..78c23e38d97 100644
--- a/ndb/src/client/odbc/codegen/Code_ddl_constr.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_ddl_constr.hpp b/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.hpp
index ea7808b37cb..ea7808b37cb 100644
--- a/ndb/src/client/odbc/codegen/Code_ddl_constr.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_ddl_row.cpp b/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.cpp
index 87589ebbaa0..87589ebbaa0 100644
--- a/ndb/src/client/odbc/codegen/Code_ddl_row.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_ddl_row.hpp b/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.hpp
index ac3eded1b2e..ac3eded1b2e 100644
--- a/ndb/src/client/odbc/codegen/Code_ddl_row.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_delete.cpp b/ndb/src/old_files/client/odbc/codegen/Code_delete.cpp
index 35b3daa1aca..35b3daa1aca 100644
--- a/ndb/src/client/odbc/codegen/Code_delete.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_delete.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_delete.hpp b/ndb/src/old_files/client/odbc/codegen/Code_delete.hpp
index c7fa245497b..c7fa245497b 100644
--- a/ndb/src/client/odbc/codegen/Code_delete.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_delete.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_delete_index.cpp b/ndb/src/old_files/client/odbc/codegen/Code_delete_index.cpp
index 8f2c3be2848..8f2c3be2848 100644
--- a/ndb/src/client/odbc/codegen/Code_delete_index.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_delete_index.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_delete_index.hpp b/ndb/src/old_files/client/odbc/codegen/Code_delete_index.hpp
index 1aaaa18abcb..1aaaa18abcb 100644
--- a/ndb/src/client/odbc/codegen/Code_delete_index.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_delete_index.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_delete_lookup.cpp b/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.cpp
index 4a6dec64654..4a6dec64654 100644
--- a/ndb/src/client/odbc/codegen/Code_delete_lookup.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_delete_lookup.hpp b/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.hpp
index 4138baefa4c..4138baefa4c 100644
--- a/ndb/src/client/odbc/codegen/Code_delete_lookup.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_delete_scan.cpp b/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.cpp
index fed7244a026..fed7244a026 100644
--- a/ndb/src/client/odbc/codegen/Code_delete_scan.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_delete_scan.hpp b/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.hpp
index eb013a8257e..eb013a8257e 100644
--- a/ndb/src/client/odbc/codegen/Code_delete_scan.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_dml.cpp b/ndb/src/old_files/client/odbc/codegen/Code_dml.cpp
index 44fd4478646..44fd4478646 100644
--- a/ndb/src/client/odbc/codegen/Code_dml.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_dml.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_dml.hpp b/ndb/src/old_files/client/odbc/codegen/Code_dml.hpp
index 0618f583984..0618f583984 100644
--- a/ndb/src/client/odbc/codegen/Code_dml.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_dml.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_dml_column.cpp b/ndb/src/old_files/client/odbc/codegen/Code_dml_column.cpp
index 808e2ac8c4b..808e2ac8c4b 100644
--- a/ndb/src/client/odbc/codegen/Code_dml_column.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_dml_column.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_dml_column.hpp b/ndb/src/old_files/client/odbc/codegen/Code_dml_column.hpp
index 0fb33944a3a..0fb33944a3a 100644
--- a/ndb/src/client/odbc/codegen/Code_dml_column.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_dml_column.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_dml_row.cpp b/ndb/src/old_files/client/odbc/codegen/Code_dml_row.cpp
index ceb63a9f7b9..ceb63a9f7b9 100644
--- a/ndb/src/client/odbc/codegen/Code_dml_row.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_dml_row.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_dml_row.hpp b/ndb/src/old_files/client/odbc/codegen/Code_dml_row.hpp
index 6c7e46ba9af..6c7e46ba9af 100644
--- a/ndb/src/client/odbc/codegen/Code_dml_row.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_dml_row.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_drop_index.cpp b/ndb/src/old_files/client/odbc/codegen/Code_drop_index.cpp
index b6bae88e270..b6bae88e270 100644
--- a/ndb/src/client/odbc/codegen/Code_drop_index.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_drop_index.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_drop_index.hpp b/ndb/src/old_files/client/odbc/codegen/Code_drop_index.hpp
index 99891c9a52f..99891c9a52f 100644
--- a/ndb/src/client/odbc/codegen/Code_drop_index.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_drop_index.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_drop_table.cpp b/ndb/src/old_files/client/odbc/codegen/Code_drop_table.cpp
index f20bf9fdae0..f20bf9fdae0 100644
--- a/ndb/src/client/odbc/codegen/Code_drop_table.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_drop_table.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_drop_table.hpp b/ndb/src/old_files/client/odbc/codegen/Code_drop_table.hpp
index 849a472ed94..849a472ed94 100644
--- a/ndb/src/client/odbc/codegen/Code_drop_table.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_drop_table.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr.cpp b/ndb/src/old_files/client/odbc/codegen/Code_expr.cpp
index 4afa75986a0..4afa75986a0 100644
--- a/ndb/src/client/odbc/codegen/Code_expr.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr.hpp b/ndb/src/old_files/client/odbc/codegen/Code_expr.hpp
index b6f07471b4d..b6f07471b4d 100644
--- a/ndb/src/client/odbc/codegen/Code_expr.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_column.cpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_column.cpp
index 17a9a502d4c..17a9a502d4c 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_column.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_column.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_column.hpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_column.hpp
index 2ce7c441e45..2ce7c441e45 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_column.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_column.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_const.cpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_const.cpp
index 564d307a4f8..564d307a4f8 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_const.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_const.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_const.hpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_const.hpp
index 2e26c637a23..2e26c637a23 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_const.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_const.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_conv.cpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.cpp
index bc89482fedc..bc89482fedc 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_conv.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_conv.hpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.hpp
index 3294960c7b3..3294960c7b3 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_conv.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_func.cpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_func.cpp
index 96b461a72d9..96b461a72d9 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_func.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_func.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_func.hpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_func.hpp
index 856d7529875..856d7529875 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_func.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_func.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_op.cpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_op.cpp
index 7e8314c1741..7e8314c1741 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_op.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_op.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_op.hpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_op.hpp
index f9686cad151..f9686cad151 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_op.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_op.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_param.cpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_param.cpp
index 93892cae5e6..93892cae5e6 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_param.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_param.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_param.hpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_param.hpp
index 783e5c087b4..783e5c087b4 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_param.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_param.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_row.cpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_row.cpp
index da1751d41d1..da1751d41d1 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_row.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_row.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_expr_row.hpp b/ndb/src/old_files/client/odbc/codegen/Code_expr_row.hpp
index 94527931dba..94527931dba 100644
--- a/ndb/src/client/odbc/codegen/Code_expr_row.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_expr_row.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_idx_column.cpp b/ndb/src/old_files/client/odbc/codegen/Code_idx_column.cpp
index 584ffef3e01..584ffef3e01 100644
--- a/ndb/src/client/odbc/codegen/Code_idx_column.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_idx_column.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_idx_column.hpp b/ndb/src/old_files/client/odbc/codegen/Code_idx_column.hpp
index 209ed705b48..209ed705b48 100644
--- a/ndb/src/client/odbc/codegen/Code_idx_column.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_idx_column.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_insert.cpp b/ndb/src/old_files/client/odbc/codegen/Code_insert.cpp
index c442186c181..c442186c181 100644
--- a/ndb/src/client/odbc/codegen/Code_insert.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_insert.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_insert.hpp b/ndb/src/old_files/client/odbc/codegen/Code_insert.hpp
index 748b092e33a..748b092e33a 100644
--- a/ndb/src/client/odbc/codegen/Code_insert.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_insert.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_pred.cpp b/ndb/src/old_files/client/odbc/codegen/Code_pred.cpp
index fe7cac7606e..fe7cac7606e 100644
--- a/ndb/src/client/odbc/codegen/Code_pred.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_pred.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_pred.hpp b/ndb/src/old_files/client/odbc/codegen/Code_pred.hpp
index a77c1161fa1..a77c1161fa1 100644
--- a/ndb/src/client/odbc/codegen/Code_pred.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_pred.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_pred_op.cpp b/ndb/src/old_files/client/odbc/codegen/Code_pred_op.cpp
index 29736e45818..29736e45818 100644
--- a/ndb/src/client/odbc/codegen/Code_pred_op.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_pred_op.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_pred_op.hpp b/ndb/src/old_files/client/odbc/codegen/Code_pred_op.hpp
index 9130bc3cb81..9130bc3cb81 100644
--- a/ndb/src/client/odbc/codegen/Code_pred_op.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_pred_op.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query.cpp
index 9e983942601..9e983942601 100644
--- a/ndb/src/client/odbc/codegen/Code_query.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query.hpp
index 97f98f859ff..97f98f859ff 100644
--- a/ndb/src/client/odbc/codegen/Code_query.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_count.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_count.cpp
index f52c41df802..f52c41df802 100644
--- a/ndb/src/client/odbc/codegen/Code_query_count.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_count.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_count.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_count.hpp
index a094eba4519..a094eba4519 100644
--- a/ndb/src/client/odbc/codegen/Code_query_count.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_count.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_distinct.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.cpp
index 4cbfbfe812d..4cbfbfe812d 100644
--- a/ndb/src/client/odbc/codegen/Code_query_distinct.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_distinct.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.hpp
index 62c46bda901..62c46bda901 100644
--- a/ndb/src/client/odbc/codegen/Code_query_distinct.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_filter.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_filter.cpp
index 934a24d182d..934a24d182d 100644
--- a/ndb/src/client/odbc/codegen/Code_query_filter.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_filter.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_filter.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_filter.hpp
index 60cbf0f86a7..60cbf0f86a7 100644
--- a/ndb/src/client/odbc/codegen/Code_query_filter.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_filter.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_group.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_group.cpp
index c3019efaa85..c3019efaa85 100644
--- a/ndb/src/client/odbc/codegen/Code_query_group.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_group.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_group.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_group.hpp
index e79022c5284..e79022c5284 100644
--- a/ndb/src/client/odbc/codegen/Code_query_group.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_group.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_index.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_index.cpp
index ee19d6123cc..ee19d6123cc 100644
--- a/ndb/src/client/odbc/codegen/Code_query_index.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_index.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_index.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_index.hpp
index 87affd50580..87affd50580 100644
--- a/ndb/src/client/odbc/codegen/Code_query_index.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_index.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_join.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_join.cpp
index 89aafe13610..89aafe13610 100644
--- a/ndb/src/client/odbc/codegen/Code_query_join.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_join.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_join.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_join.hpp
index f6ac9205329..f6ac9205329 100644
--- a/ndb/src/client/odbc/codegen/Code_query_join.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_join.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_lookup.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.cpp
index bad4199190b..bad4199190b 100644
--- a/ndb/src/client/odbc/codegen/Code_query_lookup.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_lookup.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.hpp
index e66623d4030..e66623d4030 100644
--- a/ndb/src/client/odbc/codegen/Code_query_lookup.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_project.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_project.cpp
index 54043ce3d5d..54043ce3d5d 100644
--- a/ndb/src/client/odbc/codegen/Code_query_project.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_project.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_project.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_project.hpp
index 545685ab9df..545685ab9df 100644
--- a/ndb/src/client/odbc/codegen/Code_query_project.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_project.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_range.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_range.cpp
index 5d29c5af315..5d29c5af315 100644
--- a/ndb/src/client/odbc/codegen/Code_query_range.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_range.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_range.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_range.hpp
index 4438189522c..4438189522c 100644
--- a/ndb/src/client/odbc/codegen/Code_query_range.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_range.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_repeat.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.cpp
index 8b295a97916..8b295a97916 100644
--- a/ndb/src/client/odbc/codegen/Code_query_repeat.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_repeat.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.hpp
index 90d6ef55104..90d6ef55104 100644
--- a/ndb/src/client/odbc/codegen/Code_query_repeat.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_scan.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_scan.cpp
index 1c0f58980e5..1c0f58980e5 100644
--- a/ndb/src/client/odbc/codegen/Code_query_scan.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_scan.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_scan.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_scan.hpp
index d6d1630ddf8..d6d1630ddf8 100644
--- a/ndb/src/client/odbc/codegen/Code_query_scan.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_scan.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_sort.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_sort.cpp
index 4ea6db8c4e2..4ea6db8c4e2 100644
--- a/ndb/src/client/odbc/codegen/Code_query_sort.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_sort.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_sort.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_sort.hpp
index d1aa03d9aef..d1aa03d9aef 100644
--- a/ndb/src/client/odbc/codegen/Code_query_sort.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_sort.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_sys.cpp b/ndb/src/old_files/client/odbc/codegen/Code_query_sys.cpp
index affe3dc1264..affe3dc1264 100644
--- a/ndb/src/client/odbc/codegen/Code_query_sys.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_sys.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_query_sys.hpp b/ndb/src/old_files/client/odbc/codegen/Code_query_sys.hpp
index 8eb069d0413..8eb069d0413 100644
--- a/ndb/src/client/odbc/codegen/Code_query_sys.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_query_sys.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_root.cpp b/ndb/src/old_files/client/odbc/codegen/Code_root.cpp
index 4f45bdffdaf..4f45bdffdaf 100644
--- a/ndb/src/client/odbc/codegen/Code_root.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_root.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_root.hpp b/ndb/src/old_files/client/odbc/codegen/Code_root.hpp
index 4f0f96725e3..4f0f96725e3 100644
--- a/ndb/src/client/odbc/codegen/Code_root.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_root.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_select.cpp b/ndb/src/old_files/client/odbc/codegen/Code_select.cpp
index 611b491968d..611b491968d 100644
--- a/ndb/src/client/odbc/codegen/Code_select.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_select.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_select.hpp b/ndb/src/old_files/client/odbc/codegen/Code_select.hpp
index eaa9b801f29..eaa9b801f29 100644
--- a/ndb/src/client/odbc/codegen/Code_select.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_select.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_set_row.cpp b/ndb/src/old_files/client/odbc/codegen/Code_set_row.cpp
index dd13ba0c3f7..dd13ba0c3f7 100644
--- a/ndb/src/client/odbc/codegen/Code_set_row.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_set_row.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_set_row.hpp b/ndb/src/old_files/client/odbc/codegen/Code_set_row.hpp
index 10d62826ac7..10d62826ac7 100644
--- a/ndb/src/client/odbc/codegen/Code_set_row.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_set_row.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_stmt.cpp b/ndb/src/old_files/client/odbc/codegen/Code_stmt.cpp
index d790f667b84..d790f667b84 100644
--- a/ndb/src/client/odbc/codegen/Code_stmt.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_stmt.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_stmt.hpp b/ndb/src/old_files/client/odbc/codegen/Code_stmt.hpp
index 20b7fb965fb..20b7fb965fb 100644
--- a/ndb/src/client/odbc/codegen/Code_stmt.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_stmt.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_table.cpp b/ndb/src/old_files/client/odbc/codegen/Code_table.cpp
index ee3c2a2ed07..ee3c2a2ed07 100644
--- a/ndb/src/client/odbc/codegen/Code_table.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_table.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_table.hpp b/ndb/src/old_files/client/odbc/codegen/Code_table.hpp
index 8a95b8fa26c..8a95b8fa26c 100644
--- a/ndb/src/client/odbc/codegen/Code_table.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_table.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_table_list.cpp b/ndb/src/old_files/client/odbc/codegen/Code_table_list.cpp
index ea9f4fdc26e..ea9f4fdc26e 100644
--- a/ndb/src/client/odbc/codegen/Code_table_list.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_table_list.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_table_list.hpp b/ndb/src/old_files/client/odbc/codegen/Code_table_list.hpp
index 47989166cac..47989166cac 100644
--- a/ndb/src/client/odbc/codegen/Code_table_list.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_table_list.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_update.cpp b/ndb/src/old_files/client/odbc/codegen/Code_update.cpp
index 0b33cd628b4..0b33cd628b4 100644
--- a/ndb/src/client/odbc/codegen/Code_update.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_update.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_update.hpp b/ndb/src/old_files/client/odbc/codegen/Code_update.hpp
index 380b651518b..380b651518b 100644
--- a/ndb/src/client/odbc/codegen/Code_update.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_update.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_update_index.cpp b/ndb/src/old_files/client/odbc/codegen/Code_update_index.cpp
index 6f74db0d913..6f74db0d913 100644
--- a/ndb/src/client/odbc/codegen/Code_update_index.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_update_index.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_update_index.hpp b/ndb/src/old_files/client/odbc/codegen/Code_update_index.hpp
index bbad822650a..bbad822650a 100644
--- a/ndb/src/client/odbc/codegen/Code_update_index.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_update_index.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_update_lookup.cpp b/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.cpp
index 7525fb72692..7525fb72692 100644
--- a/ndb/src/client/odbc/codegen/Code_update_lookup.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_update_lookup.hpp b/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.hpp
index fc4341880dd..fc4341880dd 100644
--- a/ndb/src/client/odbc/codegen/Code_update_lookup.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.hpp
diff --git a/ndb/src/client/odbc/codegen/Code_update_scan.cpp b/ndb/src/old_files/client/odbc/codegen/Code_update_scan.cpp
index 9fac1728469..9fac1728469 100644
--- a/ndb/src/client/odbc/codegen/Code_update_scan.cpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_update_scan.cpp
diff --git a/ndb/src/client/odbc/codegen/Code_update_scan.hpp b/ndb/src/old_files/client/odbc/codegen/Code_update_scan.hpp
index d742883e561..d742883e561 100644
--- a/ndb/src/client/odbc/codegen/Code_update_scan.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/Code_update_scan.hpp
diff --git a/ndb/src/client/odbc/codegen/Makefile b/ndb/src/old_files/client/odbc/codegen/Makefile
index 49e5439556d..49e5439556d 100644
--- a/ndb/src/client/odbc/codegen/Makefile
+++ b/ndb/src/old_files/client/odbc/codegen/Makefile
diff --git a/ndb/src/old_files/client/odbc/codegen/SimpleGram.ypp b/ndb/src/old_files/client/odbc/codegen/SimpleGram.ypp
new file mode 100644
index 00000000000..07d8017e5ed
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/codegen/SimpleGram.ypp
@@ -0,0 +1,1649 @@
+%{
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include <common/DataRow.hpp>
+#include "CodeGen.hpp"
+#include <FlexLexer.h>
+#include "SimpleParser.hpp"
+
+/* redefine globals after headers */
+#define yyparse SimpleParser_yyparse
+#if YYDEBUG
+#define yydebug SimpleParser_yydebug
+#endif
+
+#define YYLEX_PARAM simpleParserPtr
+#define YYPARSE_PARAM simpleParserPtr
+#define simpleParser (*static_cast<SimpleParser*>(simpleParserPtr))
+
+static int yylex(YYSTYPE* lvalp, void* simpleParserPtr);
+
+#define yyerror(s) simpleParser.parseError(s)
+
+#if YYDEBUG
+// does not work in bison 1.75
+#undef stderr
+#define stderr 0
+#define YYFPRINTF simpleParser.ctx().print
+#endif
+
+// scanner states
+
+#define pushState(sc) simpleParser.pushState(sc)
+#define popState() simpleParser.popState()
+
+#define StateEval SimpleParser_stateEval
+#define StateType SimpleParser_stateType
+#define StatePhys SimpleParser_statePhys
+extern int SimpleParser_stateEval;
+extern int SimpleParser_stateType;
+extern int SimpleParser_statePhys;
+
+struct LimitPair { int off; int cnt; };
+
+struct PhysAttr { int storage; int logging; };
+
+%}
+
+%defines
+%pure-parser
+%verbose
+
+%union {
+ Plan_root* m_root;
+ Plan_stmt* m_stmt;
+ Plan_select* m_select;
+ Insert_op m_insert_op;
+ Plan_insert* m_insert;
+ Plan_update* m_update;
+ Plan_delete* m_delete;
+ Plan_create_table* m_create_table;
+ Plan_create_index* m_create_index;
+ NdbDictionary::Object::Type m_index_type;
+ Plan_create_row* m_create_row;
+ Plan_ddl_row* m_ddl_row;
+ Plan_ddl_column* m_ddl_column;
+ Plan_ddl_constr* m_ddl_constr;
+ Plan_idx_column* m_idx_column;
+ Plan_data_type* m_data_type;
+ Plan_drop_table* m_drop_table;
+ Plan_drop_index* m_drop_index;
+ Plan_set_row* m_set_row;
+ Plan_expr_row* m_expr_row;
+ bool m_asc_desc;
+ Plan_pred* m_pred;
+ Pred_op::Opcode m_pred_opcode;
+ Comp_op::Opcode m_comp_opcode;
+ Plan_expr* m_expr;
+ Expr_op::Opcode m_expr_opcode;
+ Plan_dml_row* m_dml_row;
+ Plan_dml_column* m_dml_column;
+ Plan_table* m_table;
+ Plan_table_list* m_table_list;
+ const char* m_string;
+ struct LimitPair* m_limit;
+ int m_signed_integer;
+ bool m_distinct;
+ struct PhysAttr* m_phys_attr;
+ NdbDictionary::Object::FragmentType m_storage_attr;
+ bool m_logging_attr;
+ SqlType::Type m_sql_type;
+}
+
+/* keywords */
+%token
+ T_AND
+ T_ASC
+ T_AUTO_INCREMENT
+ T_BIGINT
+ T_BINARY
+ T_BLOB
+ T_BY
+ T_CHAR
+ T_CLOB
+ T_CONSTRAINT
+ T_CREATE
+ T_DATETIME
+ T_DEFAULT
+ T_DELETE
+ T_DESC
+ T_DISTINCT
+ T_DOUBLE
+ T_DROP
+ T_FLOAT
+ T_FOREIGN
+ T_FROM
+ T_GROUP
+ T_HASH
+ T_HAVING
+ T_IN
+ T_INDEX
+ T_INSERT
+ T_INT
+ T_INTEGER
+ T_INTO
+ T_IS
+ T_KEY
+ T_LARGE
+ T_LIKE
+ T_LIMIT
+ T_LOGGING
+ T_LONGBLOB
+ T_LONGCLOB
+ T_MEDIUM
+ T_NOLOGGING
+ T_NOT
+ T_NULL
+ T_OFFSET
+ T_ON
+ T_OR
+ T_ORDER
+ T_PRECISION
+ T_PRIMARY
+ T_REAL
+ T_REFERENCES
+ T_ROWNUM
+ T_SELECT
+ T_SET
+ T_SINGLE
+ T_SMALL
+ T_SMALLINT
+ T_STORAGE
+ T_SYSDATE
+ T_TABLE
+ T_UNIQUE
+ T_UNSIGNED
+ T_UPDATE
+ T_VALUES
+ T_VARBINARY
+ T_VARCHAR
+ T_WHERE
+ T_WRITE
+
+/* identifiers and constants */
+%token
+ <m_string> T_IDENTIFIER
+ <m_string> T_LINTEGER
+ <m_string> T_LDECIMAL
+ <m_string> T_LREAL
+ <m_string> T_STRING
+
+/* expressions and predicates */
+%token
+ T_PLUS
+ T_MINUS
+ T_TIMES
+ T_DIVIDE
+ T_EQ
+ T_NOTEQ
+ T_LT
+ T_LTEQ
+ T_GT
+ T_GTEQ
+ T_QUES
+
+/* common special symbols */
+%token
+ T_PERIOD
+ T_COMMA
+ T_PARENLEFT
+ T_PARENRIGHT
+ T_ASTERISK
+ T_ASSIGN
+
+%type <m_root> root
+%type <m_stmt> stmt
+%type <m_select> stmt_select
+%type <m_insert> stmt_insert
+%type <m_insert_op> insert_op
+%type <m_update> stmt_update
+%type <m_delete> stmt_delete
+%type <m_create_table> create_table
+%type <m_create_index> create_index
+%type <m_index_type> index_type
+%type <m_create_row> create_row
+%type <m_ddl_column> create_column
+%type <m_ddl_constr> create_constr
+%type <m_idx_column> idx_column
+%type <m_data_type> data_type
+%type <m_ddl_row> ddl_row
+%type <m_ddl_column> ddl_column
+%type <m_drop_table> drop_table
+%type <m_drop_index> drop_index
+%type <m_asc_desc> asc_desc
+%type <m_set_row> set_row
+%type <m_expr_row> expr_row
+%type <m_expr_row> sort_row
+%type <m_pred> where_clause
+%type <m_expr_row> order_clause
+%type <m_pred> pred
+%type <m_pred> pred1
+%type <m_pred_opcode> pred1_op
+%type <m_pred> pred2
+%type <m_pred_opcode> pred2_op
+%type <m_pred> pred3
+%type <m_pred_opcode> pred3_op
+%type <m_pred> pred4
+%type <m_comp_opcode> comp_op
+%type <m_expr> expr
+%type <m_expr> expr1
+%type <m_expr_opcode> expr1_op
+%type <m_expr> expr2
+%type <m_expr_opcode> expr2_op
+%type <m_expr> expr3
+%type <m_expr_opcode> expr3_op
+%type <m_expr> expr4
+%type <m_expr> expr_column
+%type <m_dml_row> dml_row
+%type <m_dml_column> dml_column
+%type <m_expr_row> value_row
+%type <m_expr> value_expr
+%type <m_table> table
+%type <m_table_list> table_list
+%type <m_string> dot_identifier
+%type <m_limit> limit_clause
+%type <m_signed_integer> signed_integer
+%type <m_distinct> distinct_clause
+%type <m_expr_row> group_clause
+%type <m_pred> having_clause
+%type <m_phys_attr> phys_attr
+%type <m_phys_attr> phys_attr2
+%type <m_storage_attr> storage_attr
+%type <m_logging_attr> logging_attr
+%type <m_sql_type> blob_type
+
+%%
+
+root:
+ stmt
+ {
+ Plan_root* root = simpleParser.root();
+ root->setStmt($1);
+ }
+ ;
+stmt:
+ stmt_select
+ {
+ $$ = $1;
+ }
+ |
+ stmt_insert
+ {
+ $$ = $1;
+ }
+ |
+ stmt_update
+ {
+ $$ = $1;
+ }
+ |
+ stmt_delete
+ {
+ $$ = $1;
+ }
+ |
+ create_table
+ {
+ $$ = $1;
+ }
+ |
+ create_index
+ {
+ $$ = $1;
+ }
+ |
+ drop_table
+ {
+ $$ = $1;
+ }
+ |
+ drop_index
+ {
+ $$ = $1;
+ }
+ ;
+stmt_select:
+ T_SELECT distinct_clause expr_row T_FROM table_list where_clause group_clause having_clause order_clause limit_clause
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_select* stmt = new Plan_select(root);
+ root->saveNode(stmt);
+ stmt->setDistinct($2);
+ stmt->setRow($3);
+ stmt->setList($5);
+ if ($6 != 0)
+ stmt->setPred($6);
+ if ($7 != 0)
+ stmt->setGroup($7);
+ if ($8 != 0)
+ stmt->setHaving($8);
+ if ($9 != 0)
+ stmt->setSort($9);
+ if ($10 != 0) {
+ stmt->setLimit($10->off, $10->cnt);
+ delete $10;
+ }
+ $$ = stmt;
+ }
+ ;
+stmt_insert:
+ insert_op T_INTO table T_VALUES T_PARENLEFT value_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setExprRow($6);
+ $$ = stmt;
+ }
+ |
+ insert_op T_INTO table T_PARENLEFT dml_row T_PARENRIGHT T_VALUES T_PARENLEFT value_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setDmlRow($5);
+ stmt->setExprRow($9);
+ $$ = stmt;
+ }
+ |
+ insert_op T_INTO table stmt_select
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setSelect($4);
+ $$ = stmt;
+ }
+ |
+ insert_op T_INTO table T_PARENLEFT dml_row T_PARENRIGHT stmt_select
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setDmlRow($5);
+ stmt->setSelect($7);
+ $$ = stmt;
+ }
+ |
+ insert_op T_INTO table T_SET set_row
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setMysqlRow($5);
+ $$ = stmt;
+ }
+ ;
+insert_op:
+ T_INSERT
+ {
+ $$ = Insert_op_insert;
+ }
+ |
+ T_WRITE
+ {
+ $$ = Insert_op_write;
+ }
+ ;
+stmt_update:
+ T_UPDATE table T_SET set_row where_clause
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_update* stmt = new Plan_update(root);
+ root->saveNode(stmt);
+ stmt->setTable($2);
+ stmt->setRow($4);
+ if ($5 != 0)
+ stmt->setPred($5);
+ $$ = stmt;
+ }
+ ;
+stmt_delete:
+ T_DELETE T_FROM table where_clause
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_delete* stmt = new Plan_delete(root);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ if ($4 != 0)
+ stmt->setPred($4);
+ $$ = stmt;
+ }
+ ;
+create_table:
+ T_CREATE T_TABLE dot_identifier T_PARENLEFT create_row T_PARENRIGHT phys_attr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_create_table* stmt = new Plan_create_table(root, $3);
+ root->saveNode(stmt);
+ delete[] $3;
+ stmt->setCreateRow($5);
+ if ($7->storage != -1)
+ stmt->setFragmentType((NdbDictionary::Object::FragmentType)$7->storage);
+ if ($7->logging != -1)
+ stmt->setLogging($7->logging);
+ delete $7;
+ $$ = stmt;
+ }
+ ;
+create_row:
+ create_column
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_create_row* createRow = new Plan_create_row(root);
+ root->saveNode(createRow);
+ createRow->addColumn($1);
+ $$ = createRow;
+ }
+ |
+ create_constr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_create_row* createRow = new Plan_create_row(root);
+ root->saveNode(createRow);
+ createRow->addConstr($1);
+ $$ = createRow;
+ }
+ |
+ create_row T_COMMA create_column
+ {
+ Plan_create_row* createRow = $1;
+ createRow->addColumn($3);
+ $$ = createRow;
+ }
+ |
+ create_row T_COMMA create_constr
+ {
+ Plan_create_row* createRow = $1;
+ createRow->addConstr($3);
+ $$ = createRow;
+ }
+ |
+ create_row T_COMMA create_ignore
+ {
+ $$ = $1;
+ }
+ ;
+create_column:
+ T_IDENTIFIER { pushState(StateType); } data_type { popState(); }
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_column* ddlColumn = new Plan_ddl_column(root, $1);
+ root->saveNode(ddlColumn);
+ delete[] $1;
+ ddlColumn->setType($3);
+ simpleParser.curr(ddlColumn);
+ }
+ create_column_rest
+ {
+ $$ = simpleParser.curr((Plan_ddl_column*)0);
+ }
+ ;
+data_type:
+ T_CHAR T_PARENLEFT T_LINTEGER T_PARENRIGHT dummy_binary
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(simpleParser.ctx(), SqlType::Char, atoi($3), true);
+ delete[] $3;
+ if (! simpleParser.ctx().ok()) {
+ YYABORT;
+ }
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_BINARY T_PARENLEFT T_LINTEGER T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(simpleParser.ctx(), SqlType::Binary, atoi($3), true);
+ delete[] $3;
+ if (! simpleParser.ctx().ok()) {
+ YYABORT;
+ }
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_VARCHAR T_PARENLEFT T_LINTEGER T_PARENRIGHT dummy_binary
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(simpleParser.ctx(), SqlType::Varchar, atoi($3), true);
+ delete[] $3;
+ if (! simpleParser.ctx().ok()) {
+ YYABORT;
+ }
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_VARBINARY T_PARENLEFT T_LINTEGER T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(simpleParser.ctx(), SqlType::Varbinary, atoi($3), true);
+ delete[] $3;
+ if (! simpleParser.ctx().ok()) {
+ YYABORT;
+ }
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_SMALLINT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Smallint, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_INTEGER
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Integer, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_INT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Integer, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_BIGINT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Bigint, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_REAL
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Real, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_FLOAT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Double, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_DOUBLE T_PRECISION
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Double, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_DATETIME
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Datetime, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ blob_type
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType($1, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ ;
+dummy_binary:
+ /* empty */
+ |
+ T_BINARY
+ ;
+blob_type:
+ T_BLOB
+ {
+ $$ = SqlType::Blob;
+ }
+ |
+ T_LONGBLOB
+ {
+ $$ = SqlType::Blob;
+ }
+ |
+ T_CLOB
+ {
+ $$ = SqlType::Clob;
+ }
+ |
+ T_LONGCLOB
+ {
+ $$ = SqlType::Clob;
+ }
+ ;
+create_column_rest:
+ /* empty */
+ |
+ data_constr_list
+ ;
+data_constr_list:
+ data_constr
+ |
+ data_constr_list data_constr
+ ;
+data_constr:
+ T_NULL
+ |
+ T_NOT T_NULL
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setNotNull();
+ }
+ |
+ T_UNSIGNED
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setUnSigned();
+ }
+ |
+ T_PRIMARY T_KEY
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setPrimaryKey();
+ }
+ |
+ T_AUTO_INCREMENT
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setAutoIncrement();
+ }
+ |
+ T_DEFAULT expr
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setDefaultValue($2);
+ }
+ ;
+create_constr:
+ T_PRIMARY T_KEY T_PARENLEFT ddl_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_constr* ddlConstr = new Plan_ddl_constr(root);
+ root->saveNode(ddlConstr);
+ ddlConstr->setRow($4);
+ $$ = ddlConstr;
+ }
+ |
+ T_CONSTRAINT dot_identifier T_PRIMARY T_KEY T_PARENLEFT ddl_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_constr* ddlConstr = new Plan_ddl_constr(root);
+ root->saveNode(ddlConstr);
+ ddlConstr->setRow($6);
+ $$ = ddlConstr;
+ }
+ ;
+create_ignore:
+ T_INDEX dot_identifier T_PARENLEFT ddl_row T_PARENRIGHT
+ |
+ T_FOREIGN T_KEY T_PARENLEFT ddl_row T_PARENRIGHT T_REFERENCES dot_identifier T_PARENLEFT ddl_row T_PARENRIGHT
+ ;
+ddl_row:
+ ddl_column
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_row* ddlRow = new Plan_ddl_row(root);
+ root->saveNode(ddlRow);
+ ddlRow->addColumn($1);
+ $$ = ddlRow;
+ }
+ |
+ ddl_row T_COMMA ddl_column
+ {
+ Plan_ddl_row* ddlRow = $1;
+ ddlRow->addColumn($3);
+ $$ = ddlRow;
+ }
+ ;
+ddl_column:
+ T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_column* column = new Plan_ddl_column(root, $1);
+ root->saveNode(column);
+ delete[] $1;
+ $$ = column;
+ }
+ ;
+create_index:
+ T_CREATE index_type T_INDEX dot_identifier T_ON table
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_create_index* stmt = new Plan_create_index(root, $4);
+ root->saveNode(stmt);
+ delete[] $4;
+ stmt->setType($2);
+ stmt->setTable($6);
+ simpleParser.curr(stmt);
+ }
+ T_PARENLEFT idx_row T_PARENRIGHT phys_attr
+ {
+ $$ = simpleParser.curr((Plan_create_index*)0);
+ if ($11->storage != -1)
+ $$->setFragmentType((NdbDictionary::Object::FragmentType)$11->storage);
+ if ($11->logging != -1)
+ $$->setLogging($11->logging);
+ delete $11;
+ }
+ ;
+index_type:
+ T_HASH
+ {
+ $$ = NdbDictionary::Object::HashIndex;
+ }
+ |
+ T_UNIQUE T_HASH
+ {
+ $$ = NdbDictionary::Object::UniqueHashIndex;
+ }
+ |
+ /* empty */
+ {
+ $$ = NdbDictionary::Object::OrderedIndex;
+ }
+ |
+ T_UNIQUE
+ {
+ $$ = NdbDictionary::Object::UniqueOrderedIndex;
+ }
+ ;
+idx_row:
+ idx_column
+ {
+ }
+ |
+ idx_row T_COMMA idx_column
+ {
+ }
+ ;
+idx_column:
+ T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_idx_column* column = new Plan_idx_column(root, $1);
+ root->saveNode(column);
+ delete[] $1;
+ Plan_create_index* stmt = simpleParser.curr((Plan_create_index*)0);
+ stmt->addColumn(column);
+ }
+ ;
+phys_attr:
+ { pushState(StatePhys); } phys_attr2 { popState(); }
+ {
+ $$ = $2;
+ }
+ ;
+phys_attr2:
+ /* empty */
+ {
+ $$ = new PhysAttr();
+ $$->storage = $$->logging = -1;
+ }
+ |
+ phys_attr2 storage_attr
+ {
+ if ($1->storage != -1 && $1->storage != $2) {
+ simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "conflicting STORAGE clauses");
+ YYABORT;
+ }
+ $$->storage = $2;
+ }
+ |
+ phys_attr2 logging_attr
+ {
+ if ($1->logging != -1 && $1->logging != $2) {
+ simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "conflicting LOGGING clauses");
+ YYABORT;
+ }
+ $$->logging = $2;
+ }
+ ;
+logging_attr:
+ T_LOGGING
+ {
+ $$ = true;
+ }
+ |
+ T_NOLOGGING
+ {
+ $$ = false;
+ }
+ ;
+storage_attr:
+ T_STORAGE T_PARENLEFT T_SINGLE T_PARENRIGHT
+ {
+ $$ = NdbDictionary::Object::FragSingle;
+ }
+ |
+ T_STORAGE T_PARENLEFT T_SMALL T_PARENRIGHT
+ {
+ $$ = NdbDictionary::Object::FragAllSmall;
+ }
+ |
+ T_STORAGE T_PARENLEFT T_MEDIUM T_PARENRIGHT
+ {
+ $$ = NdbDictionary::Object::FragAllMedium;
+ }
+ |
+ T_STORAGE T_PARENLEFT T_LARGE T_PARENRIGHT
+ {
+ $$ = NdbDictionary::Object::FragAllLarge;
+ }
+ ;
+drop_table:
+ T_DROP T_TABLE dot_identifier
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_drop_table* stmt = new Plan_drop_table(root, $3);
+ root->saveNode(stmt);
+ delete[] $3;
+ $$ = stmt;
+ }
+ ;
+drop_index:
+ T_DROP T_INDEX dot_identifier
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_drop_index* stmt = new Plan_drop_index(root, $3);
+ root->saveNode(stmt);
+ delete[] $3;
+ $$ = stmt;
+ }
+ |
+ T_DROP T_INDEX dot_identifier T_ON dot_identifier
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_drop_index* stmt = new Plan_drop_index(root, $3, $5);
+ root->saveNode(stmt);
+ delete[] $3;
+ delete[] $5;
+ $$ = stmt;
+ }
+ ;
+distinct_clause:
+ /* empty */
+ {
+ $$ = false;
+ }
+ |
+ T_DISTINCT
+ {
+ $$ = true;
+ }
+ ;
+where_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_WHERE pred
+ {
+ $$ = $2;
+ }
+ ;
+group_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_GROUP T_BY value_row
+ {
+ $$ = $3;
+ }
+ ;
+having_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_HAVING pred
+ {
+ $$ = $2;
+ }
+ ;
+order_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_ORDER T_BY sort_row
+ {
+ $$ = $3;
+ }
+ ;
+limit_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_LIMIT signed_integer
+ {
+ LimitPair* p = new LimitPair;
+ p->off = 0;
+ p->cnt = $2;
+ $$ = p;
+ }
+ |
+ T_LIMIT signed_integer T_COMMA signed_integer
+ {
+ LimitPair* p = new LimitPair;
+ p->off = $2,
+ p->cnt = $4;
+ $$ = p;
+ }
+ |
+ T_LIMIT signed_integer T_OFFSET signed_integer
+ {
+ LimitPair* p = new LimitPair;
+ p->off = $4;
+ p->cnt = $2;
+ $$ = p;
+ }
+ ;
+signed_integer:
+ T_LINTEGER
+ {
+ $$ = atoi($1);
+ delete[] $1;
+ }
+ |
+ T_MINUS T_LINTEGER
+ {
+ $$ = (-1) * atoi($2);
+ delete[] $2;
+ }
+ ;
+set_row:
+ dml_column T_ASSIGN expr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_set_row* row = new Plan_set_row(root);
+ root->saveNode(row);
+ row->addColumn($1);
+ row->addExpr($3);
+ $$ = row;
+ }
+ |
+ set_row T_COMMA dml_column T_ASSIGN expr
+ {
+ Plan_set_row* row = $1;
+ row->addColumn($3);
+ row->addExpr($5);
+ $$ = row;
+ }
+ ;
+dml_row:
+ dml_column
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_dml_row* row = new Plan_dml_row(root);
+ root->saveNode(row);
+ row->addColumn($1);
+ $$ = row;
+ }
+ |
+ dml_row T_COMMA dml_column
+ {
+ Plan_dml_row* row = $1;
+ row->addColumn($3);
+ $$ = row;
+ }
+ ;
+dml_column:
+ T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_dml_column* column = new Plan_dml_column(root, $1);
+ root->saveNode(column);
+ delete[] $1;
+ $$ = column;
+ }
+ ;
+value_row:
+ value_expr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->addExpr($1);
+ $$ = row;
+ }
+ |
+ value_row T_COMMA value_expr
+ {
+ Plan_expr_row* row = $1;
+ row->addExpr($3);
+ $$ = row;
+ }
+ ;
+value_expr:
+ expr
+ {
+ $$ = $1;
+ }
+ ;
+sort_row:
+ expr asc_desc
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->addExpr($1, $2);
+ $$ = row;
+ }
+ |
+ sort_row T_COMMA expr asc_desc
+ {
+ Plan_expr_row* row = $1;
+ row->addExpr($3, $4);
+ $$ = row;
+ }
+ ;
+asc_desc:
+ /* empty */
+ {
+ $$ = true;
+ }
+ |
+ T_ASC
+ {
+ $$ = true;
+ }
+ |
+ T_DESC
+ {
+ $$ = false;
+ }
+ ;
+expr_row:
+ T_ASTERISK
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->setAsterisk();
+ $$ = row;
+ }
+ |
+ T_TIMES /* XXX fix scanner state */
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->setAsterisk();
+ $$ = row;
+ }
+ |
+ expr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->addExpr($1);
+ $$ = row;
+ }
+ |
+ expr T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->addExpr($1, BaseString($2));
+ $$ = row;
+ }
+ |
+ expr_row T_COMMA expr
+ {
+ Plan_expr_row* row = $1;
+ row->addExpr($3);
+ $$ = row;
+ }
+ |
+ expr_row T_COMMA expr T_IDENTIFIER
+ {
+ Plan_expr_row* row = $1;
+ row->addExpr($3, BaseString($4));
+ $$ = row;
+ }
+ ;
+pred:
+ { pushState(StateEval); } pred1 { popState(); }
+ {
+ $$ = $2;
+ }
+ ;
+pred1:
+ pred2
+ {
+ $$ = $1;
+ }
+ |
+ pred1 pred1_op pred2
+ {
+ Plan_root* root = simpleParser.root();
+ Pred_op op($2);
+ Plan_pred_op* pred = new Plan_pred_op(root, op);
+ root->saveNode(pred);
+ pred->setPred(1, $1);
+ pred->setPred(2, $3);
+ $$ = pred;
+ }
+ ;
+pred1_op:
+ T_OR
+ {
+ $$ = Pred_op::Or;
+ }
+ ;
+pred2:
+ pred3
+ {
+ $$ = $1;
+ }
+ |
+ pred2 pred2_op pred3
+ {
+ Plan_root* root = simpleParser.root();
+ Pred_op op($2);
+ Plan_pred_op* pred = new Plan_pred_op(root, op);
+ root->saveNode(pred);
+ pred->setPred(1, $1);
+ pred->setPred(2, $3);
+ $$ = pred;
+ }
+ ;
+pred2_op:
+ T_AND
+ {
+ $$ = Pred_op::And;
+ }
+ ;
+pred3:
+ pred4
+ {
+ $$ = $1;
+ }
+ |
+ pred3_op pred3
+ {
+ Plan_root* root = simpleParser.root();
+ Pred_op op($1);
+ Plan_pred_op* pred = new Plan_pred_op(root, op);
+ root->saveNode(pred);
+ pred->setPred(1, $2);
+ $$ = pred;
+ }
+ ;
+pred3_op:
+ T_NOT
+ {
+ $$ = Pred_op::Not;
+ }
+ ;
+pred4:
+ T_PARENLEFT pred1 T_PARENRIGHT
+ {
+ $$ = $2;
+ }
+ |
+ expr1 comp_op expr1
+ {
+ Plan_root* root = simpleParser.root();
+ Comp_op op($2);
+ Plan_comp_op* comp = new Plan_comp_op(root, op);
+ root->saveNode(comp);
+ comp->setExpr(1, $1);
+ comp->setExpr(2, $3);
+ $$ = comp;
+ }
+ |
+ expr1 T_IS T_NULL
+ {
+ Plan_root* root = simpleParser.root();
+ Comp_op op(Comp_op::Isnull);
+ Plan_comp_op* comp = new Plan_comp_op(root, op);
+ root->saveNode(comp);
+ comp->setExpr(1, $1);
+ $$ = comp;
+ }
+ |
+ expr1 T_IS T_NOT T_NULL
+ {
+ Plan_root* root = simpleParser.root();
+ Comp_op op(Comp_op::Isnotnull);
+ Plan_comp_op* comp = new Plan_comp_op(root, op);
+ root->saveNode(comp);
+ comp->setExpr(1, $1);
+ $$ = comp;
+ }
+ |
+ expr1 T_IN T_PARENLEFT value_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_pred* predOut = 0; // hack directly into Or of Eq
+ Plan_expr* exprLeft = $1;
+ Plan_expr_row* row = $4;
+ for (unsigned i = row->getSize(); i >= 1; i--) {
+ Plan_expr* exprRight = row->getExpr(i);
+ Plan_comp_op* comp = new Plan_comp_op(root, Comp_op::Eq);
+ root->saveNode(comp);
+ comp->setExpr(1, exprLeft);
+ comp->setExpr(2, exprRight);
+ if (predOut == 0) {
+ predOut = comp;
+ } else {
+ Plan_pred_op* pred = new Plan_pred_op(root, Pred_op::Or);
+ root->saveNode(pred);
+ pred->setPred(1, predOut);
+ pred->setPred(2, comp);
+ predOut = pred;
+ }
+ }
+ $$ = predOut;
+ }
+ |
+ expr1 T_NOT T_IN T_PARENLEFT value_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_pred* predOut = 0; // hack directly into And of Noteq
+ Plan_expr* exprLeft = $1;
+ Plan_expr_row* row = $5;
+ for (unsigned i = row->getSize(); i >= 1; i--) {
+ Plan_expr* exprRight = row->getExpr(i);
+ Plan_comp_op* comp = new Plan_comp_op(root, Comp_op::Noteq);
+ root->saveNode(comp);
+ comp->setExpr(1, exprLeft);
+ comp->setExpr(2, exprRight);
+ if (predOut == 0) {
+ predOut = comp;
+ } else {
+ Plan_pred_op* pred = new Plan_pred_op(root, Pred_op::And);
+ root->saveNode(pred);
+ pred->setPred(1, predOut);
+ pred->setPred(2, comp);
+ predOut = pred;
+ }
+ }
+ $$ = predOut;
+ }
+ ;
+comp_op:
+ T_EQ
+ {
+ $$ = Comp_op::Eq;
+ }
+ |
+ T_NOTEQ
+ {
+ $$ = Comp_op::Noteq;
+ }
+ |
+ T_LT
+ {
+ $$ = Comp_op::Lt;
+ }
+ |
+ T_LTEQ
+ {
+ $$ = Comp_op::Lteq;
+ }
+ |
+ T_GT
+ {
+ $$ = Comp_op::Gt;
+ }
+ |
+ T_GTEQ
+ {
+ $$ = Comp_op::Gteq;
+ }
+ |
+ T_LIKE
+ {
+ $$ = Comp_op::Like;
+ }
+ |
+ T_NOT T_LIKE
+ {
+ $$ = Comp_op::Notlike;
+ }
+ ;
+expr:
+ { pushState(StateEval); } expr1 { popState(); }
+ {
+ $$ = $2;
+ }
+ ;
+expr1:
+ expr2
+ {
+ $$ = $1;
+ }
+ |
+ expr1 expr1_op expr2
+ {
+ Plan_root* root = simpleParser.root();
+ Expr_op op($2);
+ Plan_expr_op* expr = new Plan_expr_op(root, op);
+ root->saveNode(expr);
+ expr->setExpr(1, $1);
+ expr->setExpr(2, $3);
+ $$ = expr;
+ }
+ ;
+expr1_op:
+ T_PLUS
+ {
+ $$ = Expr_op::Add;
+ }
+ |
+ T_MINUS
+ {
+ $$ = Expr_op::Subtract;
+ }
+ ;
+expr2:
+ expr3
+ {
+ $$ = $1;
+ }
+ |
+ expr2 expr2_op expr3
+ {
+ Plan_root* root = simpleParser.root();
+ Expr_op op($2);
+ Plan_expr_op* expr = new Plan_expr_op(root, op);
+ root->saveNode(expr);
+ expr->setExpr(1, $1);
+ expr->setExpr(2, $3);
+ $$ = expr;
+ }
+ ;
+expr2_op:
+ T_TIMES
+ {
+ $$ = Expr_op::Multiply;
+ }
+ |
+ T_DIVIDE
+ {
+ $$ = Expr_op::Divide;
+ }
+ ;
+expr3:
+ expr4
+ {
+ $$ = $1;
+ }
+ |
+ expr3_op expr3
+ {
+ Plan_root* root = simpleParser.root();
+ Expr_op op($1);
+ Plan_expr_op* expr = new Plan_expr_op(root, op);
+ root->saveNode(expr);
+ expr->setExpr(1, $2);
+ $$ = expr;
+ }
+ ;
+expr3_op:
+ T_PLUS
+ {
+ $$ = Expr_op::Plus;
+ }
+ |
+ T_MINUS
+ {
+ $$ = Expr_op::Minus;
+ }
+ ;
+expr4:
+ T_PARENLEFT expr1 T_PARENRIGHT
+ {
+ $$ = $2;
+ }
+ |
+ T_IDENTIFIER T_PARENLEFT expr_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ const Expr_func& spec = Expr_func::find($1);
+ if (spec.m_name == 0) {
+ simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "unknown function %s", $1);
+ delete[] $1;
+ YYABORT;
+ }
+ Plan_expr_func* func = new Plan_expr_func(root, spec);
+ root->saveNode(func);
+ delete[] $1;
+ func->setArgs($3);
+ $$ = func;
+ }
+ |
+ T_ROWNUM
+ {
+ Plan_root* root = simpleParser.root();
+ const Expr_func& spec = Expr_func::find("ROWNUM");
+ ctx_assert(spec.m_name != 0);
+ Plan_expr_func* func = new Plan_expr_func(root, spec);
+ root->saveNode(func);
+ func->setArgs(0);
+ $$ = func;
+ }
+ |
+ T_SYSDATE
+ {
+ Plan_root* root = simpleParser.root();
+ const Expr_func& spec = Expr_func::find("SYSDATE");
+ ctx_assert(spec.m_name != 0);
+ Plan_expr_func* func = new Plan_expr_func(root, spec);
+ root->saveNode(func);
+ func->setArgs(0);
+ $$ = func;
+ }
+ |
+ expr_column
+ {
+ $$ = $1;
+ }
+ |
+ T_STRING
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Char);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
+ root->saveNode(expr);
+ delete[] $1;
+ $$ = expr;
+ }
+ |
+ T_LINTEGER
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Integer);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
+ root->saveNode(expr);
+ delete[] $1;
+ $$ = expr;
+ }
+ |
+ T_LDECIMAL
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Float);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
+ root->saveNode(expr);
+ delete[] $1;
+ $$ = expr;
+ }
+ |
+ T_LREAL
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Float);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
+ root->saveNode(expr);
+ delete[] $1;
+ $$ = expr;
+ }
+ |
+ T_NULL
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Null);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, "");
+ root->saveNode(expr);
+ $$ = expr;
+ }
+ |
+ T_QUES
+ {
+ Plan_root* root = simpleParser.root();
+ unsigned paramNumber = simpleParser.paramNumber();
+ ctx_assert(paramNumber != 0);
+ Plan_expr_param* expr = new Plan_expr_param(root, paramNumber);
+ root->saveNode(expr);
+ $$ = expr;
+ }
+ ;
+expr_column:
+ T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_column* column = new Plan_expr_column(root, $1);
+ root->saveNode(column);
+ delete[] $1;
+ $$ = column;
+ }
+ |
+ T_IDENTIFIER T_PERIOD T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_column* column = new Plan_expr_column(root, $3);
+ root->saveNode(column);
+ delete[] $3;
+ column->setCname($1);
+ $$ = column;
+ }
+ |
+ T_IDENTIFIER T_PERIOD T_IDENTIFIER T_PERIOD T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ BaseString str;
+ str.append($1);
+ str.append(".");
+ str.append($3);
+ delete[] $1;
+ delete[] $3;
+ Plan_expr_column* column = new Plan_expr_column(root, $5);
+ root->saveNode(column);
+ delete[] $5;
+ column->setCname(str);
+ $$ = column;
+ }
+ ;
+table_list:
+ table
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_table_list* tableList = new Plan_table_list(root);
+ root->saveNode(tableList);
+ tableList->addTable($1);
+ $$ = tableList;
+ }
+ |
+ table_list T_COMMA table
+ {
+ Plan_table_list* tableList = $1;
+ tableList->addTable($3);
+ $$ = tableList;
+ }
+ ;
+table:
+ dot_identifier
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_table* table = new Plan_table(root, $1);
+ root->saveNode(table);
+ delete[] $1;
+ $$ = table;
+ }
+ |
+ dot_identifier T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_table* table = new Plan_table(root, $1);
+ root->saveNode(table);
+ delete[] $1;
+ table->setCname($2);
+ delete[] $2;
+ $$ = table;
+ }
+ ;
+dot_identifier:
+ T_IDENTIFIER
+ {
+ $$ = $1;
+ }
+ |
+ T_IDENTIFIER T_PERIOD T_IDENTIFIER
+ {
+ char* s = new char[strlen($1) + 1 + strlen($3) + 1];
+ strcpy(s, $1);
+ strcat(s, ".");
+ strcat(s, $3);
+ delete[] $1;
+ delete[] $3;
+ $$ = s;
+ }
+ ;
+
+%%
+
+static int
+yylex(YYSTYPE* lvalp, void* simpleParserPtr)
+{
+ int ret = simpleParser.yylex();
+ *lvalp = simpleParser.yylval();
+ return ret;
+}
+
+/* vim: set filetype=yacc: */
diff --git a/ndb/src/old_files/client/odbc/codegen/SimpleParser.cpp b/ndb/src/old_files/client/odbc/codegen/SimpleParser.cpp
new file mode 100644
index 00000000000..a2418f49e37
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/codegen/SimpleParser.cpp
@@ -0,0 +1,96 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/common.hpp>
+#include <NdbMutex.h>
+#include <common/StmtArea.hpp>
+#include <FlexLexer.h>
+#include "SimpleParser.hpp"
+
+SimpleParser::~SimpleParser()
+{
+}
+
+#ifdef NDB_WIN32
+static NdbMutex & parse_mutex = * NdbMutex_Create();
+#else
+static NdbMutex parse_mutex = NDB_MUTEX_INITIALIZER;
+#endif
+
+void
+SimpleParser::yyparse()
+{
+ Ctx& ctx = this->ctx();
+ NdbMutex_Lock(&parse_mutex);
+ ctx_log2(("parse: %s", stmtArea().sqlText().c_str()));
+#if YYDEBUG
+ SimpleParser_yydebug = (m_ctx.logLevel() >= 5);
+#endif
+ SimpleParser_yyparse((void*)this);
+ NdbMutex_Unlock(&parse_mutex);
+}
+
+void
+SimpleParser::pushState(int sc)
+{
+ yy_push_state(sc);
+ m_stacksize++;
+}
+
+void
+SimpleParser::popState()
+{
+ ctx_assert(m_stacksize > 0);
+ yy_pop_state();
+ m_stacksize--;
+}
+
+void
+SimpleParser::parseError(const char* msg)
+{
+ ctx().pushStatus(Sqlstate::_42000, Error::Gen, "%s at '%*s' position %u", msg, yyleng, yytext, m_parsePos - yyleng);
+}
+
+int
+SimpleParser::LexerInput(char* buf, int max_size)
+{
+ const BaseString& text = stmtArea().sqlText();
+ int n = 0;
+ const char* const t = text.c_str();
+ const unsigned m = text.length();
+ while (n < max_size && m_textPos < m) {
+ buf[n++] = t[m_textPos++];
+ m_parsePos++; // XXX simple hack
+ break;
+ }
+ return n;
+}
+
+// XXX just a catch-all (scanner should match all input)
+void
+SimpleParser::LexerOutput(const char* buf, int size)
+{
+ if (! ctx().ok())
+ return;
+ const char* msg = "unrecognized input";
+ ctx().pushStatus(Sqlstate::_42000, Error::Gen, "%s at '%*s' position %u", msg, size, buf, m_parsePos);
+}
+
+void
+SimpleParser::LexerError(const char* msg)
+{
+ ctx().pushStatus(Sqlstate::_42000, Error::Gen, "%s at '%*s' position %u", msg, yyleng, yytext, m_parsePos);
+}
diff --git a/ndb/src/client/odbc/codegen/SimpleParser.hpp b/ndb/src/old_files/client/odbc/codegen/SimpleParser.hpp
index abadae8f905..abadae8f905 100644
--- a/ndb/src/client/odbc/codegen/SimpleParser.hpp
+++ b/ndb/src/old_files/client/odbc/codegen/SimpleParser.hpp
diff --git a/ndb/src/old_files/client/odbc/codegen/SimpleScan.lpp b/ndb/src/old_files/client/odbc/codegen/SimpleScan.lpp
new file mode 100644
index 00000000000..29aa876f669
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/codegen/SimpleScan.lpp
@@ -0,0 +1,243 @@
+%{
+#include <ctype.h>
+#include "SimpleParser.hpp"
+
+struct SqlKeyword {
+ const char* m_name;
+ int m_value;
+ int m_state;
+ static const SqlKeyword* find(Ctx& ctx, const char* name, int state);
+};
+
+%}
+
+%option c++
+%option yyclass="SimpleParser"
+%option stack
+%option noyywrap
+
+space [\040\t\n\r\f]
+digit [0-9]
+letter [A-Za-z_]
+special ("$")
+identifier ({letter}({letter}|{digit}|{special})*)
+integer {digit}++
+decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))
+real ((({digit}*\.{digit}+)|({digit}+\.{digit}*)|({digit}+))([Ee][-+]?{digit}+))
+
+%s StateEval
+%s StateType
+%s StatePhys
+%x StateString
+%x StateQuoted
+
+%%
+
+{space} {
+ }
+{identifier} {
+ const SqlKeyword* key = SqlKeyword::find(m_ctx, (char*)yytext, YYSTATE);
+ if (key != 0)
+ return key->m_value;
+ for (unsigned char* a = (unsigned char*)yytext; *a != 0; a++) {
+ if (islower(*a))
+ *a = toupper(*a);
+ }
+ m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
+ return T_IDENTIFIER;
+ }
+{integer} {
+ m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
+ return T_LINTEGER;
+ }
+{decimal} {
+ m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
+ return T_LDECIMAL;
+ }
+{real} {
+ m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
+ return T_LREAL;
+ }
+"--".* {
+ }
+"/*" {
+ int c = 0, d;
+ while (1) {
+ d = c;
+ if ((c = yyinput()) == EOF) {
+ parseError("unterminated comment");
+ yyterminate();
+ }
+ if (d == '*' && c == '/')
+ break;
+ }
+ }
+<StateEval>{
+"+" return T_PLUS;
+"-" return T_MINUS;
+"*" return T_TIMES;
+"/" return T_DIVIDE;
+"=" return T_EQ;
+"!=" return T_NOTEQ;
+"^=" return T_NOTEQ;
+"<>" return T_NOTEQ;
+"<" return T_LT;
+"<=" return T_LTEQ;
+">" return T_GT;
+">=" return T_GTEQ;
+"?" m_paramNumber++; return T_QUES;
+}
+
+"." return T_PERIOD;
+"," return T_COMMA;
+"(" return T_PARENLEFT;
+")" return T_PARENRIGHT;
+"*" return T_ASTERISK;
+"=" return T_ASSIGN;
+
+"'" {
+ pushState(StateString);
+ m_string.assign("");
+ }
+<StateString>{
+[^']* {
+ m_string.append(yytext);
+ }
+"''" {
+ m_string.append("'");
+ }
+"'" {
+ m_yylval.m_string = strcpy(new char[m_string.length() + 1], m_string.c_str());
+ popState();
+ return T_STRING;
+ }
+}
+
+\" {
+ pushState(StateQuoted);
+ m_string.assign("");
+ }
+<StateQuoted>{
+[^"]* {
+ m_string.append(yytext);
+ }
+\\\" {
+ m_string.append("\"");
+ }
+\" {
+ m_yylval.m_string = strcpy(new char[m_string.length() + 1], m_string.c_str());
+ popState();
+ return T_IDENTIFIER;
+ }
+}
+
+%%
+
+// scan states
+int SimpleParser_stateEval = StateEval;
+int SimpleParser_stateType = StateType;
+int SimpleParser_statePhys = StatePhys;
+
+// keep sorted
+
+static const SqlKeyword sqlKeyword[] = {
+ { "AND", T_AND, -1 },
+ { "ASC", T_ASC, -1 },
+ { "AUTO_INCREMENT", T_AUTO_INCREMENT, -1 },
+ { "BIGINT", T_BIGINT, StateType },
+ { "BINARY", T_BINARY, StateType },
+ { "BLOB", T_BLOB, StateType },
+ { "BY", T_BY, -1 },
+ { "CHAR", T_CHAR, StateType },
+ { "CLOB", T_CLOB, StateType },
+ { "CONSTRAINT", T_CONSTRAINT, -1 },
+ { "CREATE", T_CREATE, -1 },
+ { "DATETIME", T_DATETIME, StateType },
+ { "DEFAULT", T_DEFAULT, -1 },
+ { "DELETE", T_DELETE, -1 },
+ { "DESC", T_DESC, -1 },
+ { "DISTINCT", T_DISTINCT, -1 },
+ { "DOUBLE", T_DOUBLE, StateType },
+ { "DROP", T_DROP, -1 },
+ { "FLOAT", T_FLOAT, StateType },
+ { "FOREIGN", T_FOREIGN, -1 },
+ { "FROM", T_FROM, -1 },
+ { "GROUP", T_GROUP, -1 },
+ { "HASH", T_HASH, -1 },
+ { "HAVING", T_HAVING, -1 },
+ { "IN", T_IN, -1 },
+ { "INDEX", T_INDEX, -1 },
+ { "INSERT", T_INSERT, -1 },
+ { "INT", T_INT, StateType },
+ { "INTEGER", T_INTEGER, StateType },
+ { "INTO", T_INTO, -1 },
+ { "IS", T_IS, -1 },
+ { "KEY", T_KEY, -1 },
+ { "LARGE", T_LARGE, StatePhys },
+ { "LIKE", T_LIKE, -1 },
+ { "LIMIT", T_LIMIT, -1 },
+ { "LOGGING", T_LOGGING, StatePhys },
+ { "LONGBLOB", T_LONGBLOB, StateType },
+ { "LONGCLOB", T_LONGCLOB, StateType },
+ { "MEDIUM", T_MEDIUM, StatePhys },
+ { "NOLOGGING", T_NOLOGGING, StatePhys },
+ { "NOT", T_NOT, -1 },
+ { "NULL", T_NULL, -1 },
+ { "OFFSET", T_OFFSET, -1 },
+ { "ON", T_ON, -1 },
+ { "OR", T_OR, -1 },
+ { "ORDER", T_ORDER, -1 },
+ { "PRECISION", T_PRECISION, StateType },
+ { "PRIMARY", T_PRIMARY, -1 },
+ { "REAL", T_REAL, StateType },
+ { "REFERENCES", T_REFERENCES, -1 },
+ { "ROWNUM", T_ROWNUM, -1 },
+ { "SELECT", T_SELECT, -1 },
+ { "SET", T_SET, -1 },
+ { "SINGLE", T_SINGLE, StatePhys },
+ { "SMALL", T_SMALL, StatePhys },
+ { "SMALLINT", T_SMALLINT, StateType },
+ { "STORAGE", T_STORAGE, StatePhys },
+ { "SYSDATE", T_SYSDATE, -1 },
+ { "TABLE", T_TABLE, -1 },
+ { "UNIQUE", T_UNIQUE, -1 },
+ { "UNSIGNED", T_UNSIGNED, -1 },
+ { "UPDATE", T_UPDATE, -1 },
+ { "VALUES", T_VALUES, -1 },
+ { "VARBINARY", T_VARBINARY, StateType },
+ { "VARCHAR", T_VARCHAR, StateType },
+ { "WHERE", T_WHERE, -1 },
+ { "WRITE", T_WRITE, -1 }
+};
+
+static const unsigned sqlKeywordCount = sizeof(sqlKeyword) / sizeof(sqlKeyword[0]);
+
+const SqlKeyword*
+SqlKeyword::find(Ctx& ctx, const char* name, int state)
+{
+ ctx_log4(("find keyword '%s' lex state = %d", name, state));
+ const unsigned maxlen = 99;
+ char buf[maxlen + 1];
+ char* a = buf;
+ const char* b = name;
+ while (*b != 0) {
+ if (a >= buf + maxlen) // will not be found
+ break;
+ char c = *b++;
+ if ('a' <= c && c <= 'z') // locale independent
+ c -= 'a' - 'A';
+ *a++ = c;
+ }
+ *a = 0;
+ for (unsigned i = 0; i < sqlKeywordCount; i++) {
+ const SqlKeyword* key = &sqlKeyword[i];
+ if (strcmp(key->m_name, buf) == 0) {
+ if (key->m_state != -1 && key->m_state != state)
+ return 0;
+ return key;
+ }
+ }
+ return 0;
+}
+
+/* vim: set filetype=lex: */
diff --git a/ndb/src/client/odbc/common/AttrArea.cpp b/ndb/src/old_files/client/odbc/common/AttrArea.cpp
index ff9e085a7f6..ff9e085a7f6 100644
--- a/ndb/src/client/odbc/common/AttrArea.cpp
+++ b/ndb/src/old_files/client/odbc/common/AttrArea.cpp
diff --git a/ndb/src/client/odbc/common/AttrArea.hpp b/ndb/src/old_files/client/odbc/common/AttrArea.hpp
index 050cce719bf..050cce719bf 100644
--- a/ndb/src/client/odbc/common/AttrArea.hpp
+++ b/ndb/src/old_files/client/odbc/common/AttrArea.hpp
diff --git a/ndb/src/client/odbc/common/CodeTree.cpp b/ndb/src/old_files/client/odbc/common/CodeTree.cpp
index ebe4840c5f6..ebe4840c5f6 100644
--- a/ndb/src/client/odbc/common/CodeTree.cpp
+++ b/ndb/src/old_files/client/odbc/common/CodeTree.cpp
diff --git a/ndb/src/client/odbc/common/CodeTree.hpp b/ndb/src/old_files/client/odbc/common/CodeTree.hpp
index 1b0ae3199af..1b0ae3199af 100644
--- a/ndb/src/client/odbc/common/CodeTree.hpp
+++ b/ndb/src/old_files/client/odbc/common/CodeTree.hpp
diff --git a/ndb/src/client/odbc/common/ConnArea.cpp b/ndb/src/old_files/client/odbc/common/ConnArea.cpp
index d4d3be52a3c..d4d3be52a3c 100644
--- a/ndb/src/client/odbc/common/ConnArea.cpp
+++ b/ndb/src/old_files/client/odbc/common/ConnArea.cpp
diff --git a/ndb/src/client/odbc/common/ConnArea.hpp b/ndb/src/old_files/client/odbc/common/ConnArea.hpp
index 36367a39bae..36367a39bae 100644
--- a/ndb/src/client/odbc/common/ConnArea.hpp
+++ b/ndb/src/old_files/client/odbc/common/ConnArea.hpp
diff --git a/ndb/src/old_files/client/odbc/common/Ctx.cpp b/ndb/src/old_files/client/odbc/common/Ctx.cpp
new file mode 100644
index 00000000000..d6faa5cba77
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/common/Ctx.cpp
@@ -0,0 +1,355 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/common.hpp>
+#include "DiagArea.hpp"
+
+// ctor
+
+Ctx::Ctx() :
+ m_diagArea(0) // create on demand
+{
+ const char* p;
+ if ((p = getenv("NDB_ODBC_TRACE")) != 0)
+ m_logLevel = atoi(p);
+ if ((p = getenv("NDB_ODBC_TRACE_FILE")) != 0 && *p != 0)
+ strcpy(m_szTraceFile, p);
+}
+
+Ctx::~Ctx()
+{
+ delete m_diagArea;
+ m_diagArea = 0;
+}
+
+// handle exceptions
+
+CtxAssert::CtxAssert(const char* file, int line) :
+ m_file(file),
+ m_line(line)
+{
+ const char* p;
+ if ((p = getenv("NDB_ODBC_DEBUG")) != 0 && atoi(p) != 0) {
+ char buf[200];
+ snprintf(buf, sizeof(buf), "%s, line %d: assert failed\n", m_file, m_line);
+ if ((p = getenv("NDB_ODBC_TRACE_FILE")) != 0 && *p != 0) {
+ FILE* pFile = fopen(p, "a");
+ fprintf(pFile, buf);
+ fflush(pFile);
+ fclose(pFile);
+ } else {
+ fprintf(stderr, buf);
+ fflush(stderr);
+ }
+ abort();
+ exit(1);
+ }
+}
+
+void
+Ctx::handleEx(CtxAssert& ctxAssert)
+{
+ pushStatus(Sqlstate::_IM001, Error::Gen, "exception at %s line %d", ctxAssert.m_file, ctxAssert.m_line);
+}
+
+// logging methods
+
+int Ctx::m_logLevel = 0;
+char Ctx::m_szTraceFile[MAX_PATH];
+
+void
+Ctx::log(const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (m_szTraceFile[0]) {
+ FILE* pFile = fopen(m_szTraceFile, "a");
+ fprintf(pFile, "[NdbOdbc] ");
+ vfprintf(pFile, fmt, ap);
+ fprintf(pFile, "\n");
+ fflush(pFile);
+ fclose(pFile);
+ } else {
+ printf("[NdbOdbc] ");
+ vprintf(fmt, ap);
+ printf("\n");
+ fflush(stdout);
+ }
+ va_end(ap);
+}
+
+void
+Ctx::logSqlEnter(const char* sqlFunction)
+{
+ Ctx& ctx = *this;
+ snprintf(m_sqlFunction, sizeof(m_sqlFunction), "%s", sqlFunction);
+ ctx_log3(("%s", m_sqlFunction));
+}
+
+void
+Ctx::logSqlExit()
+{
+ Ctx& ctx = *this;
+ if (m_diagArea == 0) {
+ ctx_log3(("%s ret=%d", m_sqlFunction, getCode()));
+ return;
+ }
+ int logLevel = diagArea().numStatus() != 0 ? 2 : 3;
+ ctx_logN(logLevel, ("%s ret=%d diag=%d", m_sqlFunction, diagArea().getCode(), diagArea().numStatus()));
+ for (unsigned i = 1; i <= diagArea().numStatus(); i++) {
+ OdbcData state;
+ OdbcData message;
+ diagArea().getRecord(ctx, i, SQL_DIAG_SQLSTATE, state);
+ diagArea().getRecord(ctx, i, SQL_DIAG_MESSAGE_TEXT, message);
+ ctx_logN(logLevel, ("diag %u: %s - %s", i, state.sqlstate().state(), message.sqlchar()));
+ }
+}
+
+void
+Ctx::print(const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (m_szTraceFile[0]) {
+ FILE* pFile = fopen(m_szTraceFile, "a");
+ vfprintf(pFile, fmt, ap);
+ unsigned n = strlen(fmt);
+ if (n > 0 && fmt[n-1] == '\n')
+ fflush(pFile);
+ fclose(pFile);
+ } else {
+ vprintf(fmt, ap);
+ unsigned n = strlen(fmt);
+ if (n > 0 && fmt[n-1] == '\n')
+ fflush(stdout);
+ }
+ va_end(ap);
+}
+
+void
+Ctx::print(int level, const char* fmt, ...)
+{
+ if (level > m_logLevel)
+ return;
+ va_list ap;
+ va_start(ap, fmt);
+ if (m_szTraceFile[0]) {
+ FILE* pFile = fopen(m_szTraceFile, "a");
+ vfprintf(pFile, fmt, ap);
+ unsigned n = strlen(fmt);
+ if (n > 0 && fmt[n-1] == '\n')
+ fflush(pFile);
+ fclose(pFile);
+ } else {
+ vprintf(fmt, ap);
+ unsigned n = strlen(fmt);
+ if (n > 0 && fmt[n-1] == '\n')
+ fflush(stdout);
+ }
+ va_end(ap);
+}
+
+// diagnostics
+
+static const unsigned MessageSize = 512;
+
+DiagArea&
+Ctx::diagArea() const
+{
+ ctx_assert(m_diagArea != 0);
+ return *m_diagArea;
+}
+
+DiagArea&
+Ctx::diagArea()
+{
+ if (m_diagArea == 0)
+ m_diagArea = new DiagArea;
+ return *m_diagArea;
+}
+
+SQLRETURN
+Ctx::getCode() const
+{
+ if (m_diagArea == 0)
+ return SQL_SUCCESS;
+ return diagArea().getCode();
+}
+
+void
+Ctx::setCode(SQLRETURN ret)
+{
+ diagArea().setCode(ret);
+}
+
+void
+Ctx::pushStatus(const Sqlstate& state, SQLINTEGER code, const char* fmt, ...)
+{
+ char message[MessageSize];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(message, sizeof(message), fmt, ap);
+ va_end(ap);
+ Error error(state);
+ error.m_status = NdbError::PermanentError;
+ error.m_classification = NdbError::ApplicationError;
+ error.m_code = code;
+ error.m_message = message;
+ error.m_sqlFunction = m_sqlFunction;
+ diagArea().pushStatus(error);
+}
+
+void
+Ctx::pushStatus(SQLINTEGER code, const char* fmt, ...)
+{
+ char message[MessageSize];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(message, sizeof(message), fmt, ap);
+ va_end(ap);
+ Error error(Sqlstate::_IM000);
+ error.m_status = NdbError::PermanentError;
+ error.m_classification = NdbError::ApplicationError;
+ error.m_code = code;
+ error.m_message = message;
+ error.m_sqlFunction = m_sqlFunction;
+ diagArea().pushStatus(error);
+}
+
+void
+Ctx::pushStatus(const NdbError& ndbError, const char* fmt, ...)
+{
+ char message[MessageSize];
+ va_list ap;
+ va_start(ap, fmt);
+ snprintf(message, sizeof(message), "%s", ndbError.message);
+ snprintf(message + strlen(message), sizeof(message) - strlen(message), "%s", " - at ");
+ vsnprintf(message + strlen(message), sizeof(message) - strlen(message), fmt, ap);
+ va_end(ap);
+ Error error(Sqlstate::_IM000);
+ error.m_status = ndbError.status;
+ error.m_classification = ndbError.classification;
+ error.m_code = ndbError.code;
+ error.m_message = message;
+ error.m_sqlFunction = m_sqlFunction;
+ diagArea().pushStatus(error);
+}
+
+void
+Ctx::pushStatus(const Ndb* ndb, const char* fmt, ...)
+{
+ char message[MessageSize];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(message, sizeof(message), fmt, ap);
+ va_end(ap);
+ bool found = false;
+ if (ndb != 0) {
+ const NdbError& ndbError = ndb->getNdbError();
+ if (ndbError.code != 0) {
+ pushStatus(ndbError, "%s", message);
+ found = true;
+ }
+ }
+ if (! found) {
+ pushStatus(Error::Gen, "unknown NDB error");
+ }
+}
+
+void
+Ctx::pushStatus(const Ndb* ndb, const NdbConnection* tcon, const NdbOperation* op, const char* fmt, ...)
+{
+ char message[MessageSize];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(message, sizeof(message), fmt, ap);
+ va_end(ap);
+ bool found = false;
+ if (op != 0) {
+ const NdbError& ndbError = op->getNdbError();
+ if (ndbError.code != 0) {
+ pushStatus(ndbError, "%s", message);
+ found = true;
+ }
+ }
+ if (tcon != 0) {
+ const NdbError& ndbError = tcon->getNdbError();
+ if (ndbError.code != 0) {
+ pushStatus(ndbError, "%s", message);
+ found = true;
+ }
+ }
+ if (ndb != 0) {
+ const NdbError& ndbError = ndb->getNdbError();
+ if (ndbError.code != 0) {
+ pushStatus(ndbError, "%s", message);
+ found = true;
+ }
+ }
+ if (! found) {
+ pushStatus(Error::Gen, "unknown NDB error");
+ }
+}
+
+void
+Ctx::pushStatus(const Ndb* ndb, const NdbSchemaCon* scon, const NdbSchemaOp* op, const char* fmt, ...)
+{
+ char message[MessageSize];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(message, sizeof(message), fmt, ap);
+ va_end(ap);
+ bool found = false;
+ if (op != 0) {
+ const NdbError& ndbError = op->getNdbError();
+ if (ndbError.code != 0) {
+ pushStatus(ndbError, "%s", message);
+ found = true;
+ }
+ }
+ if (scon != 0) {
+ const NdbError& ndbError = scon->getNdbError();
+ if (ndbError.code != 0) {
+ pushStatus(ndbError, "%s", message);
+ found = true;
+ }
+ }
+ if (ndb != 0) {
+ const NdbError& ndbError = ndb->getNdbError();
+ if (ndbError.code != 0) {
+ pushStatus(ndbError, "%s", message);
+ found = true;
+ }
+ }
+ if (! found) {
+ pushStatus(Error::Gen, "unknown NDB error");
+ }
+}
+
+// check for error
+
+bool
+Ctx::ok()
+{
+ if (m_diagArea == 0)
+ return true;
+ if (diagArea().getCode() == SQL_SUCCESS)
+ return true;
+ if (diagArea().getCode() == SQL_SUCCESS_WITH_INFO)
+ return true;
+ return false;
+}
diff --git a/ndb/src/client/odbc/common/Ctx.hpp b/ndb/src/old_files/client/odbc/common/Ctx.hpp
index d25d45ff0c7..d25d45ff0c7 100644
--- a/ndb/src/client/odbc/common/Ctx.hpp
+++ b/ndb/src/old_files/client/odbc/common/Ctx.hpp
diff --git a/ndb/src/old_files/client/odbc/common/DataField.cpp b/ndb/src/old_files/client/odbc/common/DataField.cpp
new file mode 100644
index 00000000000..11aae7d893b
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/common/DataField.cpp
@@ -0,0 +1,3023 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "DataField.hpp"
+
+#ifndef INT_MAX
+#define INT_MAX (2147483647)
+#endif
+
+#ifndef INT_MIN
+#define INT_MIN (-INT_MAX - 1)
+#endif
+
+#ifndef UINT_MAX
+#define UINT_MAX 4294967295U
+#endif
+
+#ifndef FLT_MAX
+#define FLT_MAX (3.402823466E+38F)
+#endif
+#ifndef FLT_MIN
+#define FLT_MIN (1.175494351E-38F)
+#endif
+
+#ifdef NDB_WIN32
+#define FMT_I64 "%I64d"
+#define FMT_U64 "%I64u"
+#else
+#define FMT_I64 "%lld"
+#define FMT_U64 "%llu"
+#endif
+
+#ifdef NDB_WIN32
+#define strtoll(str, endptr, base) strtoint64(str, endptr, base)
+#define strtoull(str, endptr, base) strtouint64(str, endptr, base)
+
+static Int64
+strtoint64(const char *str, char **endptr, int base)
+{
+ Int64 x = 0;
+ while (*str == ' ')
+ str++;
+ const char* p = str;
+ while ('0' <= *p && *p <= '9')
+ x = 10 * x + *p++ - '0';
+ if (p == str) {
+ *endptr = 0;
+ return 0;
+ }
+ *endptr = (char*)p;
+ return x;
+}
+
+static Uint64
+strtouint64(const char *str, char **endptr, int base)
+{
+ Uint64 x = 0;
+ while (*str == ' ')
+ str++;
+ const char* p = str;
+ while ('0' <= *p && *p <= '9')
+ x = 10 * x + *p++ - '0';
+ if (p == str) {
+ *endptr = 0;
+ return 0;
+ }
+ *endptr = (char*)p;
+ return x;
+}
+#endif
+
+// LexSpec
+
+void
+LexSpec::convert(Ctx& ctx, const BaseString& value, SqlField& out)
+{
+ const SqlSpec& sqlSpec = out.sqlSpec();
+ const SqlType& sqlType = sqlSpec.sqlType();
+ out.alloc();
+ if (sqlType.type() == SqlType::Char) {
+ const SqlChar* s = (const SqlChar*)value.c_str();
+ out.sqlChar(s, SQL_NTS);
+ return;
+ }
+ if (sqlType.type() == SqlType::Bigint) {
+ char* endptr = 0;
+ SqlBigint n = static_cast<SqlBigint>(strtoll(value.c_str(), &endptr, 10));
+ if (endptr == 0 || *endptr != 0) {
+ ctx.pushStatus(Error::Gen, "cannot convert '%s' to integer", value.c_str());
+ return;
+ }
+ out.sqlBigint(n);
+ return;
+ }
+ if (sqlType.type() == SqlType::Double) {
+ char* endptr = 0;
+ SqlDouble x = static_cast<SqlDouble>(strtod(value.c_str(), &endptr));
+ if (endptr == 0 || *endptr != 0) {
+ ctx.pushStatus(Error::Gen, "cannot convert '%s' to number", value.c_str());
+ return;
+ }
+ out.sqlDouble(x);
+ return;
+ }
+ if (sqlType.type() == SqlType::Null) {
+ out.u_null.m_nullFlag = true;
+ return;
+ }
+ ctx_assert(false);
+}
+
+// SqlField
+
+void
+SqlField::alloc()
+{
+ ctx_assert(sqlSpec().store() == SqlSpec::Physical);
+ const SqlType& sqlType = sqlSpec().sqlType();
+ if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varchar)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ u_data.m_sqlChar = new SqlChar[n];
+ }
+ }
+ if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varbinary)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ u_data.m_sqlChar = new SqlChar[n];
+ }
+ }
+}
+
+void
+SqlField::alloc(const SqlField& sqlField)
+{
+ alloc();
+ const SqlType& sqlType = sqlSpec().sqlType();
+ if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varchar)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ memcpy(u_data.m_sqlChar, sqlField.u_data.m_sqlChar, n);
+ }
+ }
+ if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varbinary)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ memcpy(u_data.m_sqlChar, sqlField.u_data.m_sqlChar, n);
+ }
+ }
+}
+
+const void*
+SqlField::addr() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->addr();
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varchar)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ return static_cast<const void*>(u_data.m_sqlChar);
+ }
+ return static_cast<const void*>(u_data.m_sqlCharSmall);
+ }
+ if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varbinary)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ return static_cast<const void*>(u_data.m_sqlChar);
+ }
+ return static_cast<const void*>(u_data.m_sqlCharSmall);
+ }
+ if (sqlType.type() == SqlType::Smallint) {
+ return static_cast<const void*>(&u_data.m_sqlSmallint);
+ }
+ if (sqlType.type() == SqlType::Integer) {
+ return static_cast<const void*>(&u_data.m_sqlInteger);
+ }
+ if (sqlType.type() == SqlType::Bigint) {
+ return static_cast<const void*>(&u_data.m_sqlBigint);
+ }
+ if (sqlType.type() == SqlType::Real) {
+ return static_cast<const void*>(&u_data.m_sqlReal);
+ }
+ if (sqlType.type() == SqlType::Double) {
+ return static_cast<const void*>(&u_data.m_sqlDouble);
+ }
+ if (sqlType.type() == SqlType::Datetime) {
+ return static_cast<const void*>(&u_data.m_sqlDatetime);
+ }
+ ctx_assert(false); // SqlType::Null has no address
+ return 0;
+}
+
+void*
+SqlField::addr()
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varchar)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ return static_cast<void*>(u_data.m_sqlChar);
+ }
+ return static_cast<void*>(u_data.m_sqlCharSmall);
+ }
+ if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varbinary)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ return static_cast<void*>(u_data.m_sqlChar);
+ }
+ return static_cast<void*>(u_data.m_sqlCharSmall);
+ }
+ if (sqlType.type() == SqlType::Smallint) {
+ return static_cast<void*>(&u_data.m_sqlSmallint);
+ }
+ if (sqlType.type() == SqlType::Integer) {
+ return static_cast<void*>(&u_data.m_sqlInteger);
+ }
+ if (sqlType.type() == SqlType::Bigint) {
+ return static_cast<void*>(&u_data.m_sqlBigint);
+ }
+ if (sqlType.type() == SqlType::Real) {
+ return static_cast<void*>(&u_data.m_sqlReal);
+ }
+ if (sqlType.type() == SqlType::Double) {
+ return static_cast<void*>(&u_data.m_sqlDouble);
+ }
+ if (sqlType.type() == SqlType::Datetime) {
+ return static_cast<void*>(&u_data.m_sqlDatetime);
+ }
+ ctx_assert(false); // SqlType::Null has no address
+ return 0;
+}
+
+unsigned
+SqlField::allocSize() const
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ unsigned n = sqlType.size();
+ if (sqlType.type() == SqlType::Varchar || sqlType.type() == SqlType::Varbinary) {
+ n += 2;
+ }
+ return n;
+}
+
+void
+SqlField::free()
+{
+ ctx_assert(sqlSpec().store() == SqlSpec::Physical);
+ const SqlType& sqlType = sqlSpec().sqlType();
+ if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varchar)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ delete[] u_data.m_sqlChar;
+ u_data.m_sqlChar = 0; // safety since dtor used explicitly
+ }
+ }
+ if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
+ unsigned n = sqlType.length();
+ if (sqlType.type() == SqlType::Varbinary)
+ n += 2;
+ if (n > SqlField_CharSmall) {
+ delete[] u_data.m_sqlChar;
+ u_data.m_sqlChar = 0; // safety since dtor used explicitly
+ }
+ }
+}
+
+// get
+
+const SqlChar*
+SqlField::sqlChar() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlChar();
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Char);
+ if (sqlType.length() > SqlField_CharSmall)
+ return u_data.m_sqlChar;
+ return u_data.m_sqlCharSmall;
+}
+
+const SqlChar*
+SqlField::sqlVarchar(unsigned* length) const
+{
+#if NDB_VERSION_MAJOR >= 3
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlVarchar(length);
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Varchar);
+ const SqlChar* sqlChar;
+ unsigned n = sqlType.length();
+ if (2 + n > SqlField_CharSmall)
+ sqlChar = u_data.m_sqlChar;
+ else
+ sqlChar = u_data.m_sqlCharSmall;
+ if (length != 0)
+ *length = (sqlChar[0] << 8) | sqlChar[1]; // big-endian
+ return sqlChar + 2;
+#else
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlVarchar(length);
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Varchar);
+ const SqlChar* sqlChar;
+ unsigned n = sqlType.length();
+ if (n + 2 > SqlField_CharSmall)
+ sqlChar = u_data.m_sqlChar;
+ else
+ sqlChar = u_data.m_sqlCharSmall;
+ if (length != 0)
+ *length = (sqlChar[n + 0] << 8) | sqlChar[n + 1]; // big-endian
+ return sqlChar;
+#endif
+}
+
+const SqlChar*
+SqlField::sqlBinary() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlChar();
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Binary);
+ if (sqlType.length() > SqlField_CharSmall)
+ return u_data.m_sqlChar;
+ return u_data.m_sqlCharSmall;
+}
+
+const SqlChar*
+SqlField::sqlVarbinary(unsigned* length) const
+{
+#if NDB_VERSION_MAJOR >= 3
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlVarchar(length);
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Varbinary);
+ const SqlChar* sqlChar;
+ unsigned n = sqlType.length();
+ if (2 + n > SqlField_CharSmall)
+ sqlChar = u_data.m_sqlChar;
+ else
+ sqlChar = u_data.m_sqlCharSmall;
+ if (length != 0)
+ *length = (sqlChar[0] << 8) | sqlChar[1]; // big-endian
+ return sqlChar + 2;
+#else
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlVarchar(length);
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Varbinary);
+ const SqlChar* sqlChar;
+ unsigned n = sqlType.length();
+ if (n + 2 > SqlField_CharSmall)
+ sqlChar = u_data.m_sqlChar;
+ else
+ sqlChar = u_data.m_sqlCharSmall;
+ if (length != 0)
+ *length = (sqlChar[n + 0] << 8) | sqlChar[n + 1]; // big-endian
+ return sqlChar;
+#endif
+}
+
+SqlSmallint
+SqlField::sqlSmallint() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlSmallint();
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Smallint);
+ return u_data.m_sqlSmallint;
+}
+
+SqlInteger
+SqlField::sqlInteger() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlInteger();
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Integer);
+ return u_data.m_sqlInteger;
+}
+
+SqlBigint
+SqlField::sqlBigint() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlBigint();
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Bigint);
+ return u_data.m_sqlBigint;
+}
+
+SqlReal
+SqlField::sqlReal() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlReal();
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Real);
+ return u_data.m_sqlReal;
+}
+
+SqlDouble
+SqlField::sqlDouble() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlDouble();
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Double);
+ return u_data.m_sqlDouble;
+}
+
+SqlDatetime
+SqlField::sqlDatetime() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlDatetime();
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Datetime);
+ return u_data.m_sqlDatetime;
+}
+
+// set
+
+void
+SqlField::sqlChar(const SqlChar* value, int length)
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Char);
+ unsigned n = sqlType.length();
+ SqlChar* p = n > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
+ const SqlChar* q = value;
+ unsigned m = length == SQL_NTS ? strlen((const char*)q) : length;
+ ctx_assert(m <= n);
+ for (unsigned i = 0; i < m; i++)
+ *p++ = *q++;
+ for (unsigned i = m; i < n; i++)
+ *p++ = 0x20; // space
+ u_null.m_nullFlag = false;
+}
+
+void
+SqlField::sqlVarchar(const SqlChar* value, int length)
+{
+#if NDB_VERSION_MAJOR >= 3
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Varchar);
+ unsigned n = sqlType.length();
+ SqlChar* p = 2 + n > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
+ const SqlChar* q = value;
+ unsigned m = length == SQL_NTS ? strlen((const char*)q) : length;
+ ctx_assert(m <= n);
+ *p++ = (m >> 8) & 0xff; // big-endian
+ *p++ = (m & 0xff);
+ for (unsigned i = 0; i < m; i++)
+ *p++ = *q++;
+ for (unsigned i = m; i < n; i++)
+ *p++ = 0x0; // null
+ u_null.m_nullFlag = false;
+#else
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Varchar);
+ unsigned n = sqlType.length();
+ SqlChar* p = n + 2 > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
+ const SqlChar* q = value;
+ unsigned m = length == SQL_NTS ? strlen((const char*)q) : length;
+ ctx_assert(m <= n);
+ for (unsigned i = 0; i < m; i++)
+ *p++ = *q++;
+ for (unsigned i = m; i < n; i++)
+ *p++ = 0x0; // null
+ *p++ = (m >> 8) & 0xff; // big-endian
+ *p++ = (m & 0xff);
+ u_null.m_nullFlag = false;
+#endif
+}
+
+void
+SqlField::sqlBinary(const SqlChar* value, int length)
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Binary);
+ unsigned n = sqlType.length();
+ SqlChar* p = n > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
+ const SqlChar* q = value;
+ unsigned m = length;
+ ctx_assert(m <= n);
+ for (unsigned i = 0; i < m; i++)
+ *p++ = *q++;
+ for (unsigned i = m; i < n; i++)
+ *p++ = 0x0; // null
+ u_null.m_nullFlag = false;
+}
+
+void
+SqlField::sqlVarbinary(const SqlChar* value, int length)
+{
+#if NDB_VERSION_MAJOR >= 3
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Varbinary);
+ unsigned n = sqlType.length();
+ SqlChar* p = 2 + n > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
+ const SqlChar* q = value;
+ unsigned m = length;
+ ctx_assert(m <= n);
+ *p++ = (m >> 8) & 0xff; // big-endian
+ *p++ = (m & 0xff);
+ for (unsigned i = 0; i < m; i++)
+ *p++ = *q++;
+ for (unsigned i = m; i < n; i++)
+ *p++ = 0x0; // null
+ u_null.m_nullFlag = false;
+#else
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Varbinary);
+ unsigned n = sqlType.length();
+ SqlChar* p = n + 2 > SqlField_CharSmall ? u_data.m_sqlChar : u_data.m_sqlCharSmall;
+ const SqlChar* q = value;
+ unsigned m = length;
+ ctx_assert(m <= n);
+ for (unsigned i = 0; i < m; i++)
+ *p++ = *q++;
+ for (unsigned i = m; i < n; i++)
+ *p++ = 0x0; // null
+ *p++ = (m >> 8) & 0xff; // big-endian
+ *p++ = (m & 0xff);
+ u_null.m_nullFlag = false;
+#endif
+}
+
+void
+SqlField::sqlSmallint(SqlSmallint value)
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Smallint);
+ u_data.m_sqlSmallint = value;
+ u_null.m_nullFlag = false;
+}
+
+void
+SqlField::sqlInteger(SqlInteger value)
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Integer);
+ u_data.m_sqlInteger = value;
+ u_null.m_nullFlag = false;
+}
+
+void
+SqlField::sqlBigint(SqlBigint value)
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Bigint);
+ u_data.m_sqlBigint = value;
+ u_null.m_nullFlag = false;
+}
+
+void
+SqlField::sqlReal(SqlReal value)
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Real);
+ u_data.m_sqlReal = value;
+ u_null.m_nullFlag = false;
+}
+
+void
+SqlField::sqlDouble(SqlDouble value)
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Double);
+ u_data.m_sqlDouble = value;
+ u_null.m_nullFlag = false;
+}
+
+void
+SqlField::sqlDatetime(SqlDatetime value)
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ ctx_assert(sqlType.type() == SqlType::Datetime);
+ u_data.m_sqlDatetime = value;
+ u_null.m_nullFlag = false;
+}
+
+// get and and set null
+
+bool
+SqlField::sqlNull() const
+{
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ return u_data.m_sqlField->sqlNull();
+ }
+ return u_null.m_nullFlag;
+}
+
+void
+SqlField::sqlNull(bool value)
+{
+ u_null.m_nullFlag = value;
+}
+
+unsigned
+SqlField::trim() const
+{
+ const SqlType& sqlType = sqlSpec().sqlType();
+ unsigned n = 0;
+ const SqlChar* s = 0;
+ if (sqlType.type() == SqlType::Char) {
+ n = sqlType.length();
+ s = sqlChar();
+ } else if (sqlType.type() == SqlType::Varchar) {
+ s = sqlVarchar(&n);
+ } else {
+ ctx_assert(false);
+ return 0;
+ }
+ while (n > 0 && s[n - 1] == 0x20)
+ n--;
+ return n;
+}
+
+void
+SqlField::copy(Ctx& ctx, SqlField& out) const
+{
+ const SqlField& f1 = *this;
+ SqlField& f2 = out;
+ const SqlType& t1 = f1.sqlSpec().sqlType();
+ const SqlType& t2 = f2.sqlSpec().sqlType();
+ ctx_assert(t1.type() == t2.type());
+ if (f1.sqlNull()) {
+ f2.sqlNull(true);
+ return;
+ }
+ if (t1.type() == SqlType::Char) {
+ f2.sqlChar(f1.sqlChar(), t1.length());
+ return;
+ }
+ if (t1.type() == SqlType::Varchar) {
+ unsigned length;
+ const SqlChar* s1 = f1.sqlVarchar(&length);
+ f2.sqlVarchar(s1, length);
+ return;
+ }
+ if (t1.type() == SqlType::Binary) {
+ f2.sqlBinary(f1.sqlBinary(), t1.length());
+ return;
+ }
+ if (t1.type() == SqlType::Varbinary) {
+ unsigned length;
+ const SqlChar* s1 = f1.sqlVarbinary(&length);
+ f2.sqlVarbinary(s1, length);
+ return;
+ }
+ if (t1.type() == SqlType::Smallint) {
+ f2.sqlSmallint(f1.sqlSmallint());
+ return;
+ }
+ if (t1.type() == SqlType::Integer) {
+ f2.sqlInteger(f1.sqlInteger());
+ return;
+ }
+ if (t1.type() == SqlType::Bigint) {
+ f2.sqlBigint(f1.sqlBigint());
+ return;
+ }
+ if (t1.type() == SqlType::Real) {
+ f2.sqlReal(f1.sqlReal());
+ return;
+ }
+ if (t1.type() == SqlType::Double) {
+ f2.sqlDouble(f1.sqlDouble());
+ return;
+ }
+ if (t1.type() == SqlType::Datetime) {
+ f2.sqlDatetime(f1.sqlDatetime());
+ return;
+ }
+ ctx_assert(false);
+}
+
+bool
+SqlField::cast(Ctx& ctx, SqlField& out) const
+{
+ const SqlField& f1 = *this;
+ SqlField& f2 = out;
+ if (f1.sqlNull()) {
+ f2.sqlNull(true);
+ return true;
+ }
+ const SqlType& t1 = f1.sqlSpec().sqlType();
+ const SqlType& t2 = f2.sqlSpec().sqlType();
+ if (t1.type() == SqlType::Char) {
+ if (t2.type() == SqlType::Char) {
+ unsigned n1 = f1.trim();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlChar(f1.sqlChar(), n1);
+ return true;
+ }
+ if (t2.type() == SqlType::Varchar) {
+ unsigned n1 = t1.length();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlVarchar(f1.sqlChar(), n1);
+ return true;
+ }
+ if (t2.type() == SqlType::Binary) {
+ unsigned n1 = t1.length();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlBinary(f1.sqlChar(), n1);
+ return true;
+ }
+ if (t2.type() == SqlType::Varbinary) {
+ unsigned n1 = t1.length();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlVarbinary(f1.sqlChar(), n1);
+ return true;
+ }
+ ctx_assert(false);
+ return false;
+ }
+ if (t1.type() == SqlType::Varchar) {
+ if (t2.type() == SqlType::Char) {
+ unsigned n1 = f1.trim();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlChar(f1.sqlVarchar(0), n1);
+ return true;
+ }
+ if (t2.type() == SqlType::Varchar) {
+ unsigned n1 = f1.trim();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlVarchar(f1.sqlVarchar(0), n1);
+ return true;
+ }
+ if (t2.type() == SqlType::Binary) {
+ unsigned n1 = t1.length();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlBinary(f1.sqlVarchar(0), n1);
+ return true;
+ }
+ if (t2.type() == SqlType::Varbinary) {
+ unsigned n1 = t1.length();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlVarbinary(f1.sqlVarchar(0), n1);
+ return true;
+ }
+ ctx_assert(false);
+ return false;
+ }
+ if (t1.type() == SqlType::Binary) {
+ if (t2.type() == SqlType::Binary) {
+ unsigned n1 = t1.length();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlBinary(f1.sqlBinary(), n1);
+ return true;
+ }
+ if (t2.type() == SqlType::Varbinary) {
+ unsigned n1 = t1.length();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlVarbinary(f1.sqlBinary(), n1);
+ return true;
+ }
+ ctx_assert(false);
+ return false;
+ }
+ if (t1.type() == SqlType::Varbinary) {
+ if (t2.type() == SqlType::Binary) {
+ unsigned n1 = t1.length();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlBinary(f1.sqlVarbinary(0), n1);
+ return true;
+ }
+ if (t2.type() == SqlType::Varbinary) {
+ unsigned n1 = t1.length();
+ if (n1 > t2.length())
+ return false;
+ f2.sqlVarbinary(f1.sqlVarbinary(0), n1);
+ return true;
+ }
+ ctx_assert(false);
+ return false;
+ }
+ if (t1.type() == SqlType::Smallint) {
+ if (! t2.unSigned()) {
+ SqlSmallint x1 = f1.sqlSmallint();
+ if (t2.type() == SqlType::Smallint) {
+ f2.sqlSmallint(x1);
+ return true;
+ }
+ if (t2.type() == SqlType::Integer) {
+ SqlInteger x2 = static_cast<SqlInteger>(x1);
+ f2.sqlInteger(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Bigint) {
+ SqlBigint x2 = static_cast<SqlBigint>(x1);
+ f2.sqlBigint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Real) {
+ SqlReal x2 = static_cast<SqlReal>(x1);
+ f2.sqlReal(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Double) {
+ SqlDouble x2 = static_cast<SqlDouble>(x1);
+ f2.sqlDouble(x2);
+ return true;
+ }
+ } else {
+ SqlUsmallint x1 = f1.sqlSmallint();
+ if (t2.type() == SqlType::Smallint) {
+ f2.sqlSmallint(x1);
+ return true;
+ }
+ if (t2.type() == SqlType::Integer) {
+ SqlUinteger x2 = static_cast<SqlUinteger>(x1);
+ f2.sqlInteger(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Bigint) {
+ SqlUbigint x2 = static_cast<SqlUbigint>(x1);
+ f2.sqlBigint(x2);
+ return true;
+ }
+ }
+ ctx_assert(false);
+ return false;
+ }
+ if (t1.type() == SqlType::Integer) {
+ if (! t2.unSigned()) {
+ SqlInteger x1 = f1.sqlInteger();
+ if (t2.type() == SqlType::Smallint) {
+ SqlSmallint x2 = static_cast<SqlSmallint>(x1);
+ if (x1 != static_cast<SqlInteger>(x2))
+ return false;
+ f2.sqlSmallint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Integer) {
+ f2.sqlInteger(x1);
+ return true;
+ }
+ if (t2.type() == SqlType::Bigint) {
+ SqlBigint x2 = static_cast<SqlBigint>(x1);
+ f2.sqlBigint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Real) {
+ SqlReal x2 = static_cast<SqlReal>(x1);
+ f2.sqlReal(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Double) {
+ SqlDouble x2 = static_cast<SqlDouble>(x1);
+ f2.sqlDouble(x2);
+ return true;
+ }
+ } else {
+ SqlUinteger x1 = f1.sqlInteger();
+ if (t2.type() == SqlType::Smallint) {
+ SqlUsmallint x2 = static_cast<SqlUsmallint>(x1);
+ if (x1 != static_cast<SqlUinteger>(x2))
+ return false;
+ f2.sqlSmallint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Integer) {
+ f2.sqlInteger(x1);
+ return true;
+ }
+ if (t2.type() == SqlType::Bigint) {
+ SqlUbigint x2 = static_cast<SqlUbigint>(x1);
+ f2.sqlBigint(x2);
+ return true;
+ }
+ }
+ ctx_assert(false);
+ return false;
+ }
+ if (t1.type() == SqlType::Bigint) {
+ if (! t2.unSigned()) {
+ SqlBigint x1 = f1.sqlBigint();
+ if (t2.type() == SqlType::Smallint) {
+ SqlSmallint x2 = static_cast<SqlSmallint>(x1);
+ if (x1 != static_cast<SqlBigint>(x2))
+ return false;
+ f2.sqlSmallint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Integer) {
+ SqlInteger x2 = static_cast<SqlInteger>(x1);
+ if (x1 != static_cast<SqlBigint>(x2))
+ return false;
+ f2.sqlInteger(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Bigint) {
+ f2.sqlBigint(x1);
+ return true;
+ }
+ if (t2.type() == SqlType::Real) {
+ SqlReal x2 = static_cast<SqlReal>(x1);
+ f2.sqlReal(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Double) {
+ SqlDouble x2 = static_cast<SqlDouble>(x1);
+ f2.sqlDouble(x2);
+ return true;
+ }
+ } else {
+ SqlUbigint x1 = f1.sqlBigint();
+ if (t2.type() == SqlType::Smallint) {
+ SqlUsmallint x2 = static_cast<SqlUsmallint>(x1);
+ if (x1 != static_cast<SqlUbigint>(x2))
+ return false;
+ f2.sqlSmallint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Integer) {
+ SqlUinteger x2 = static_cast<SqlUinteger>(x1);
+ if (x1 != static_cast<SqlUbigint>(x2))
+ return false;
+ f2.sqlInteger(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Bigint) {
+ f2.sqlBigint(x1);
+ return true;
+ }
+ }
+ ctx_assert(false);
+ return false;
+ }
+ if (t1.type() == SqlType::Real) {
+ SqlReal x1 = f1.sqlReal();
+ int off = 0;
+ if (x1 > 0.0 && x1 - floor(x1) >= 0.5)
+ off = 1;
+ if (x1 < 0.0 && x1 - floor(x1) <= 0.5)
+ off = -1;
+ bool b = (x1 - floor(x1) < 0.5);
+ if (t2.type() == SqlType::Smallint) {
+ SqlSmallint x2 = static_cast<SqlSmallint>(x1) + off;
+ if (fabs(x1 - static_cast<SqlReal>(x2)) >= 1.0)
+ return false;
+ f2.sqlSmallint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Integer) {
+ SqlInteger x2 = static_cast<SqlInteger>(x1) + off;
+ if (fabs(x1 - static_cast<SqlReal>(x2)) >= 1.0)
+ return false;
+ f2.sqlInteger(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Bigint) {
+ SqlBigint x2 = static_cast<SqlBigint>(x1) + off;
+ if (fabs(x1 - static_cast<SqlReal>(x2)) >= 1.0)
+ return false;
+ f2.sqlBigint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Real) {
+ f2.sqlReal(x1);
+ return true;
+ }
+ if (t2.type() == SqlType::Double) {
+ SqlDouble x2 = static_cast<SqlDouble>(x1);
+ f2.sqlDouble(x2);
+ return true;
+ }
+ ctx_assert(false);
+ return false;
+ }
+ if (t1.type() == SqlType::Double) {
+ SqlDouble x1 = f1.sqlDouble();
+ int off = 0;
+ if (x1 > 0.0 && x1 - floor(x1) >= 0.5)
+ off = 1;
+ if (x1 < 0.0 && x1 - floor(x1) <= 0.5)
+ off = -1;
+ bool b = (x1 - floor(x1) < 0.5);
+ if (t2.type() == SqlType::Smallint) {
+ SqlSmallint x2 = static_cast<SqlSmallint>(x1) + off;
+ if (fabs(x1 - static_cast<SqlDouble>(x2)) >= 1.0)
+ return false;
+ f2.sqlSmallint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Integer) {
+ SqlInteger x2 = static_cast<SqlInteger>(x1) + off;
+ if (fabs(x1 - static_cast<SqlDouble>(x2)) >= 1.0)
+ return false;
+ f2.sqlInteger(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Bigint) {
+ SqlBigint x2 = static_cast<SqlBigint>(x1) + off;
+ if (fabs(x1 - static_cast<SqlDouble>(x2)) >= 1.0)
+ return false;
+ f2.sqlBigint(x2);
+ return true;
+ }
+ if (t2.type() == SqlType::Real) {
+ SqlReal x2 = static_cast<SqlReal>(x1);
+ if (fabs(x1 - static_cast<SqlDouble>(x2)) >= 1.0) // XXX
+ return false;
+ f2.sqlReal(x1);
+ return true;
+ }
+ if (t2.type() == SqlType::Double) {
+ f2.sqlDouble(x1);
+ return true;
+ }
+ ctx_assert(false);
+ return false;
+ }
+ ctx_assert(false);
+ return false;
+}
+
+bool
+SqlField::less(const SqlField& sqlField) const
+{
+ const SqlField& f1 = *this;
+ const SqlField& f2 = sqlField;
+ const SqlType& t1 = f1.sqlSpec().sqlType();
+ const SqlType& t2 = f2.sqlSpec().sqlType();
+ ctx_assert(t1.type() == t2.type());
+ if (t1.type() == SqlType::Char) {
+ const SqlChar* s1 = f1.sqlChar();
+ const SqlChar* s2 = f2.sqlChar();
+ unsigned n1 = t1.length();
+ unsigned n2 = t2.length();
+ SqlChar c1 = 0;
+ SqlChar c2 = 0;
+ unsigned i = 0;
+ while (i < n1 || i < n2) {
+ c1 = i < n1 ? s1[i] : 0x20;
+ c2 = i < n2 ? s2[i] : 0x20;
+ if (c1 != c2)
+ break;
+ i++;
+ }
+ return (c1 < c2);
+ }
+ if (t1.type() == SqlType::Varchar) {
+ unsigned n1, n2;
+ const SqlChar* s1 = f1.sqlVarchar(&n1);
+ const SqlChar* s2 = f2.sqlVarchar(&n2);
+ SqlChar c1 = 0;
+ SqlChar c2 = 0;
+ unsigned i = 0;
+ while (i < n1 || i < n2) {
+ c1 = i < n1 ? s1[i] : 0x0;
+ c2 = i < n2 ? s2[i] : 0x0;
+ if (c1 != c2)
+ break;
+ i++;
+ }
+ return (c1 < c2);
+ }
+ if (t1.type() == SqlType::Smallint) {
+ ctx_assert(t1.unSigned() == t2.unSigned());
+ if (! t1.unSigned()) {
+ SqlSmallint x1 = f1.sqlSmallint();
+ SqlSmallint x2 = f2.sqlSmallint();
+ return (x1 < x2);
+ } else {
+ SqlUsmallint x1 = f1.sqlSmallint();
+ SqlUsmallint x2 = f2.sqlSmallint();
+ return (x1 < x2);
+ }
+ }
+ if (t1.type() == SqlType::Integer) {
+ ctx_assert(t1.unSigned() == t2.unSigned());
+ if (! t1.unSigned()) {
+ SqlInteger x1 = f1.sqlInteger();
+ SqlInteger x2 = f2.sqlInteger();
+ return (x1 < x2);
+ } else {
+ SqlUinteger x1 = f1.sqlInteger();
+ SqlUinteger x2 = f2.sqlInteger();
+ return (x1 < x2);
+ }
+ }
+ if (t1.type() == SqlType::Bigint) {
+ ctx_assert(t1.unSigned() == t2.unSigned());
+ if (! t1.unSigned()) {
+ SqlBigint x1 = f1.sqlBigint();
+ SqlBigint x2 = f2.sqlBigint();
+ return (x1 < x2);
+ } else {
+ SqlUbigint x1 = f1.sqlBigint();
+ SqlUbigint x2 = f2.sqlBigint();
+ return (x1 < x2);
+ }
+ }
+ if (t1.type() == SqlType::Real) {
+ SqlReal x1 = f1.sqlReal();
+ SqlReal x2 = f2.sqlReal();
+ return (x1 < x2);
+ }
+ if (t1.type() == SqlType::Double) {
+ SqlDouble x1 = f1.sqlDouble();
+ SqlDouble x2 = f2.sqlDouble();
+ return (x1 < x2);
+ }
+ if (t1.type() == SqlType::Datetime) {
+ SqlDatetime x1 = f1.sqlDatetime();
+ SqlDatetime x2 = f2.sqlDatetime();
+ return x1.less(x2);
+ }
+ ctx_assert(false);
+}
+
+// copy from external
+
+static bool
+copyin_char_char(Ctx& ctx, char* value, unsigned n, const char* ptr, const SQLINTEGER* ind, int* off, SqlChar* addr, int fieldId)
+{
+ if (off != 0 && *off >= 0) {
+ if ((unsigned)*off > n) {
+ ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d truncated (%u > %u)", fieldId, (unsigned)*off, n);
+ return false;
+ }
+ value += *off;
+ n -= *off;
+ }
+ unsigned m;
+ if (ind == 0 || *ind == SQL_NTS)
+ m = strlen(ptr);
+ else
+ m = *ind;
+ if (m > n) {
+ ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d truncated (%u > %u)", fieldId, m, n);
+ return false;
+ }
+ for (unsigned i = 0; i < m; i++)
+ value[i] = ptr[i];
+ if (off != 0 && *off >= 0)
+ *off += m;
+ for (unsigned i = m; i < n; i++)
+ value[i] = addr == 0 ? 0x20 : 0x0;
+ if (addr != 0) {
+ if (off != 0 && *off >= 0)
+ m = *off;
+ addr[0] = (m >> 8) & 0xff;
+ addr[1] = (m & 0xff);
+ }
+ return true;
+}
+
+static bool
+copyin_binary_binary(Ctx& ctx, char* value, unsigned n, const char* ptr, const SQLINTEGER* ind, int* off, SqlChar* addr, int fieldId)
+{
+ if (off != 0 && *off >= 0) {
+ if ((unsigned)*off > n) {
+ ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d truncated (%u > %u)", fieldId, (unsigned)*off, n);
+ return false;
+ }
+ value += *off;
+ n -= *off;
+ }
+ if (ind == 0) {
+ ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d missing length", fieldId);
+ return false;
+ }
+ if (*ind < 0) {
+ ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d invalid length %d", fieldId, (int)*ind);
+ return false;
+ }
+ unsigned m;
+ m = *ind;
+ if (m > n) {
+ ctx.pushStatus(Sqlstate::_22001, Error::Gen, "input parameter %d truncated (%u > %u)", fieldId, m, n);
+ return false;
+ }
+ for (unsigned i = 0; i < m; i++)
+ value[i] = ptr[i];
+ if (off != 0 && *off >= 0)
+ *off += m;
+ for (unsigned i = m; i < n; i++)
+ value[i] = addr == 0 ? 0x0 : 0x0; // just null
+ if (addr != 0) {
+ if (off != 0 && *off >= 0)
+ m = *off;
+ addr[0] = (m >> 8) & 0xff;
+ addr[1] = (m & 0xff);
+ }
+ return true;
+}
+
+static bool
+copyin_signed_char(Ctx& ctx, SqlBigint* value, const char* ptr, int fieldId)
+{
+ errno = 0;
+ char* endptr = 0;
+ SqlBigint x = strtoll(ptr, &endptr, 10);
+ if (endptr == 0 || *endptr != 0) {
+ errno = 0;
+ endptr = 0;
+ double y = strtod(ptr, &endptr);
+ if (endptr == 0 || *endptr != 0) {
+ ctx.pushStatus(Sqlstate::_22005, Error::Gen, "input parameter %d value %s not numeric", fieldId, ptr);
+ return false;
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "input parameter %d value %s overflow", fieldId, ptr);
+ return false;
+ }
+ // XXX should handle 123.000
+ ctx.pushStatus(Sqlstate::_01004, Error::Gen, "input parameter %d value %s truncated", fieldId, ptr);
+ x = static_cast<SqlBigint>(y);
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "input parameter %d value %s overflow", fieldId, ptr);
+ return false;
+ }
+ *value = x;
+ return true;
+}
+
+static bool
+copyin_double_char(Ctx& ctx, SqlDouble* value, const char* ptr, int fieldId)
+{
+ errno = 0;
+ char* endptr = 0;
+ double x = strtod(ptr, &endptr);
+ if (endptr == 0 || *endptr != 0) {
+ ctx.pushStatus(Sqlstate::_22005, Error::Gen, "input parameter %d value %s not numeric", fieldId, ptr);
+ return false;
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "input parameter %d value %s overflow", fieldId, ptr);
+ return false;
+ }
+ *value = x;
+ return true;
+}
+
+void
+SqlField::copyin(Ctx& ctx, ExtField& extField)
+{
+ ctx_assert(extField.extSpec().extType().type() != ExtType::Unbound);
+ ctx_assert(sqlSpec().store() == SqlSpec::Physical);
+ SQLINTEGER* indPtr = extField.m_indPtr;
+ const int fieldId = extField.fieldId();
+ if (indPtr != 0 && *indPtr == SQL_NULL_DATA) {
+ sqlNull(true);
+ return;
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ const ExtType& extType = extField.extSpec().extType();
+ if (extField.m_pos > 0) {
+ if (sqlType.type() == SqlType::Char && extType.type() == ExtType::Char)
+ ;
+ else if (sqlType.type() == SqlType::Varchar && extType.type() == ExtType::Char)
+ ;
+ else {
+ char buf[40];
+ sqlType.print(buf, sizeof(buf));
+ ctx.pushStatus(Sqlstate::_HY019, Error::Gen, "cannot send %s data in pieces", buf);
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
+ unsigned length = 0;
+ char* value = 0;
+ SqlChar* laddr = 0; // Varchar length address
+ if (sqlType.type() == SqlType::Char) {
+ length = sqlType.length();
+ if (length > SqlField_CharSmall)
+ value = reinterpret_cast<char *>(u_data.m_sqlChar);
+ else
+ value = reinterpret_cast<char *>(u_data.m_sqlCharSmall);
+ laddr = 0;
+ } else {
+#if NDB_VERSION_MAJOR >= 3
+ length = sqlType.length();
+ if (2 + length > SqlField_CharSmall)
+ value = reinterpret_cast<char *>(u_data.m_sqlChar + 2);
+ else
+ value = reinterpret_cast<char *>(u_data.m_sqlCharSmall + 2);
+ laddr = (SqlChar*)value - 2;
+#else
+ length = sqlType.length();
+ if (length + 2 > SqlField_CharSmall)
+ value = reinterpret_cast<char *>(u_data.m_sqlChar);
+ else
+ value = reinterpret_cast<char *>(u_data.m_sqlCharSmall);
+ laddr = (SqlChar*)value + length;
+#endif
+ }
+ if (extType.type() == ExtType::Char) {
+ const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ int* off = 0;
+ if (extField.m_pos >= 0)
+ off = &extField.m_pos;
+ if (! copyin_char_char(ctx, value, length, dataPtr, indPtr, off, laddr, fieldId))
+ return;
+ sqlNull(false);
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ const short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ char buf[100];
+ sprintf(buf, "%hd", *dataPtr);
+ if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
+ return;
+ sqlNull(false);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ const unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ char buf[100];
+ sprintf(buf, "%hu", *dataPtr);
+ if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
+ return;
+ sqlNull(false);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ const long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ char buf[100];
+ sprintf(buf, "%ld", *dataPtr);
+ if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
+ return;
+ sqlNull(false);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ const unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ char buf[100];
+ sprintf(buf, "%lu", *dataPtr);
+ if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
+ return;
+ sqlNull(false);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ const SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ char buf[100];
+ sprintf(buf, FMT_I64, *dataPtr);
+ if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
+ return;
+ sqlNull(false);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ const SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ char buf[100];
+ sprintf(buf, FMT_U64, *dataPtr);
+ if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
+ return;
+ sqlNull(false);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ const float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ char buf[100];
+ sprintf(buf, "%.7f", (double)*dataPtr);
+ if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
+ return;
+ sqlNull(false);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ const double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ char buf[100];
+ sprintf(buf, "%.14f", *dataPtr);
+ if (! copyin_char_char(ctx, value, length, buf, indPtr, 0, laddr, fieldId))
+ return;
+ sqlNull(false);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
+ unsigned length = 0;
+ char* value = 0;
+ SqlChar* laddr = 0; // Varbinary length address
+ if (sqlType.type() == SqlType::Binary) {
+ length = sqlType.length();
+ if (length > SqlField_CharSmall)
+ value = reinterpret_cast<char *>(u_data.m_sqlChar);
+ else
+ value = reinterpret_cast<char *>(u_data.m_sqlCharSmall);
+ laddr = 0;
+ } else {
+#if NDB_VERSION_MAJOR >= 3
+ length = sqlType.length();
+ if (2 + length > SqlField_CharSmall)
+ value = reinterpret_cast<char *>(u_data.m_sqlChar + 2);
+ else
+ value = reinterpret_cast<char *>(u_data.m_sqlCharSmall + 2);
+ laddr = (SqlChar*)value - 2;
+#else
+ length = sqlType.length();
+ if (length + 2 > SqlField_CharSmall)
+ value = reinterpret_cast<char *>(u_data.m_sqlChar);
+ else
+ value = reinterpret_cast<char *>(u_data.m_sqlCharSmall);
+ laddr = (SqlChar*)value + length;
+#endif
+ }
+ if (extType.type() == ExtType::Binary) {
+ const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ int* off = 0;
+ if (extField.m_pos >= 0)
+ off = &extField.m_pos;
+ if (! copyin_binary_binary(ctx, value, length, dataPtr, indPtr, off, laddr, fieldId))
+ return;
+ sqlNull(false);
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Smallint) {
+ SqlSmallint value;
+ if (extType.type() == ExtType::Char) {
+ const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ SqlBigint x;
+ if (! copyin_signed_char(ctx, &x, dataPtr, fieldId))
+ return;
+ value = x;
+ sqlSmallint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlSmallint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlSmallint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlSmallint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlSmallint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlSmallint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlSmallint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ value = (SqlSmallint)*dataPtr;
+ sqlSmallint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ value = (SqlSmallint)*dataPtr;
+ sqlSmallint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Integer) {
+ SqlInteger value;
+ if (extType.type() == ExtType::Char) {
+ const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ SqlBigint x;
+ if (! copyin_signed_char(ctx, &x, dataPtr, fieldId))
+ return;
+ value = x;
+ sqlInteger(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlInteger(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlInteger(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlInteger(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlInteger(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlInteger(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlInteger(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ value = (SqlInteger)*dataPtr;
+ sqlInteger(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ value = (SqlInteger)*dataPtr;
+ sqlInteger(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Bigint) {
+ SqlBigint value;
+ if (extType.type() == ExtType::Char) {
+ const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ SqlBigint x;
+ if (! copyin_signed_char(ctx, &x, dataPtr, fieldId))
+ return;
+ value = x;
+ sqlBigint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlBigint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlBigint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlBigint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlBigint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlBigint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlBigint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ value = (SqlBigint)*dataPtr;
+ sqlBigint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ value = (SqlBigint)*dataPtr;
+ sqlBigint(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Real) {
+ SqlReal value;
+ if (extType.type() == ExtType::Char) {
+ const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ SqlDouble x;
+ if (! copyin_double_char(ctx, &x, dataPtr, fieldId))
+ return;
+ value = x;
+ sqlReal(x);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlReal(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlReal(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlReal(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlReal(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlReal(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlReal(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlReal(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlReal(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Double) {
+ SqlDouble value;
+ if (extType.type() == ExtType::Char) {
+ const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ SqlDouble x;
+ if (! copyin_double_char(ctx, &x, dataPtr, fieldId))
+ return;
+ value = x;
+ sqlDouble(x);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlDouble(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlDouble(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlDouble(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlDouble(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlDouble(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlDouble(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlDouble(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ value = *dataPtr;
+ sqlDouble(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Datetime) {
+ SqlDatetime value;
+ if (extType.type() == ExtType::Char) {
+ // XXX replace sscanf by manual scan or regex
+ const char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ int cc = 0;
+ unsigned yy = 0, mm = 0, dd = 0, HH = 0, MM = 0, SS = 0, ff = 0;
+ bool setdate = false;
+ char dummy[10];
+ if (sscanf(dataPtr, "%2d%2u-%2u-%2u %2u:%2u:%2u.%4u%1s", &cc, &yy, &mm, &dd, &HH, &MM, &SS, &ff, dummy) == 8) {
+ ;
+ } else if (sscanf(dataPtr, "%2d%2u-%2u-%2u %2u:%2u:%2u%1s", &cc, &yy, &mm, &dd, &HH, &MM, &SS, dummy) == 7) {
+ ;
+ } else if (sscanf(dataPtr, "%2d%2u-%2u-%2u%1s", &cc, &yy, &mm, &dd, dummy) == 4) {
+ ;
+ } else if (sscanf(dataPtr, "%2u:%2u:%2u.%4u%1s", &HH, &MM, &SS, &ff, dummy) == 4) {
+ setdate = true;
+ } else if (sscanf(dataPtr, "%2u:%2u:%2u%1s", &HH, &MM, &SS, dummy) == 3) {
+ setdate = true;
+ } else {
+ ctx.pushStatus(Sqlstate::_22008, Error::Gen, "invalid timestamp format '%s'", dataPtr);
+ return;
+ }
+ if (setdate) {
+ time_t clock = time(0);
+ struct tm* t = localtime(&clock);
+ cc = (1900 + t->tm_year) / 100;
+ yy = (1900 + t->tm_year) % 100;
+ mm = 1 + t->tm_mon;
+ dd = t->tm_mday;
+ }
+ value.cc(cc);
+ value.yy(yy);
+ value.mm(mm);
+ value.dd(dd);
+ value.HH(HH);
+ value.MM(MM);
+ value.SS(SS);
+ value.ff(ff);
+ // XXX write date routines later
+ if (! value.valid()) {
+ ctx.pushStatus(Sqlstate::_22008, Error::Gen, "invalid timestamp values '%s'", dataPtr);
+ return;
+ }
+ sqlDatetime(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Timestamp) {
+ SQL_TIMESTAMP_STRUCT* dataPtr = static_cast<SQL_TIMESTAMP_STRUCT*>(extField.m_dataPtr);
+ // XXX assume same datatype
+ value.cc(dataPtr->year / 100);
+ value.yy(dataPtr->year / 100);
+ value.mm(dataPtr->month);
+ value.dd(dataPtr->day);
+ value.HH(dataPtr->hour);
+ value.MM(dataPtr->minute);
+ value.SS(dataPtr->second);
+ value.ff(dataPtr->fraction);
+ if (! value.valid()) {
+ ctx.pushStatus(Sqlstate::_22008, Error::Gen, "invalid timestamp struct");
+ return;
+ }
+ sqlDatetime(value);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ ctx_assert(false); // SqlType::Null not applicable
+}
+
+// copy to external
+
+static bool
+copyout_char_char(Ctx& ctx, const char* value, unsigned n, char* ptr, unsigned len, SQLINTEGER* ind, int* off)
+{
+ unsigned n2 = n;
+ if (off != 0 && *off >= 0) {
+ ctx_assert((unsigned)*off <= n2);
+ value += *off;
+ n2 -= *off;
+ if (len < n2 + 1) {
+ ctx.pushStatus(Sqlstate::_01004, Error::Gen, "more data at offset %d, current fetch %u, available %u", *off, len, n2);
+ n2 = len - 1;
+ }
+ } else {
+ if (len < n + 1) { // room for null byte
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "char value '%.*s' overflow (%u < %u)", (int)n, value, (unsigned)len, (unsigned)(len + 1));
+ return false;
+ }
+ }
+ memcpy(ptr, value, n2);
+ ptr[n2] = 0;
+ if (off != 0 && *off >= 0) {
+ if (ind != 0)
+ *ind = n - *off;
+ *off += n2;
+ } else {
+ if (ind != 0)
+ *ind = n;
+ }
+ return true;
+}
+
+static bool
+copyout_binary_binary(Ctx& ctx, const char* value, unsigned n, char* ptr, unsigned len, SQLINTEGER* ind, int* off)
+{
+ unsigned n2 = n;
+ if (off != 0 && *off >= 0) {
+ ctx_assert((unsigned)*off <= n2);
+ value += *off;
+ n2 -= *off;
+ if (len < n2 + 1) {
+ ctx.pushStatus(Sqlstate::_01004, Error::Gen, "more data at offset %d, current fetch %u, available %u", *off, len, n2);
+ n2 = len - 1;
+ }
+ } else {
+ if (len < n) { // no room for null byte
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "binary value '%.*s' overflow (%u < %u)", (int)n, value, (unsigned)len, (unsigned)n);
+ return false;
+ }
+ }
+ memcpy(ptr, value, n2);
+ ptr[n2] = 0;
+ if (off != 0 && *off >= 0) {
+ if (ind != 0)
+ *ind = n - *off;
+ *off += n2;
+ } else {
+ if (ind != 0)
+ *ind = n;
+ }
+ return true;
+}
+
+static bool
+copyout_char_signed(Ctx& ctx, const char* value, unsigned n, long* ptr)
+{
+ while (n > 0 && value[0] == 0x20) {
+ value++;
+ n--;
+ }
+ char buf[200];
+ if (n >= 200)
+ n = 200 - 1;
+ memcpy(buf, value, n);
+ buf[n] = 0;
+ errno = 0;
+ char* endptr = 0;
+ long x = strtol(buf, &endptr, 10);
+ if (endptr == 0 || *endptr != 0) {
+ errno = 0;
+ endptr = 0;
+ double y = strtod(buf, &endptr);
+ if (endptr == 0 || *endptr != 0) {
+ ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", buf);
+ return false;
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ // XXX should handle 123.000
+ ctx.pushStatus(Sqlstate::_01004, Error::Gen, "value %s truncated", buf);
+ x = static_cast<long>(y);
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ *ptr = x;
+ return true;
+}
+
+static bool
+copyout_char_bigsigned(Ctx& ctx, const char* value, unsigned n, SQLBIGINT* ptr)
+{
+ while (n > 0 && value[0] == 0x20) {
+ value++;
+ n--;
+ }
+ char buf[200];
+ if (n >= 200)
+ n = 200 - 1;
+ memcpy(buf, value, n);
+ buf[n] = 0;
+ errno = 0;
+ char* endptr = 0;
+ SQLBIGINT x = strtoll(buf, &endptr, 10);
+ if (endptr == 0 || *endptr != 0) {
+ errno = 0;
+ endptr = 0;
+ double y = strtod(buf, &endptr);
+ if (endptr == 0 || *endptr != 0) {
+ ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", buf);
+ return false;
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ // XXX should handle 123.000
+ ctx.pushStatus(Sqlstate::_01004, Error::Gen, "value %s truncated", buf);
+ x = static_cast<long>(y);
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ *ptr = x;
+ return true;
+}
+
+static bool
+copyout_char_unsigned(Ctx& ctx, const char* value, unsigned n, unsigned long* ptr)
+{
+ while (n > 0 && value[0] == 0x20) {
+ value++;
+ n--;
+ }
+ char buf[200];
+ if (n >= 200)
+ n = 200 - 1;
+ memcpy(buf, value, n);
+ buf[n] = 0;
+ errno = 0;
+ char* endptr = 0;
+ unsigned long x = strtoul(buf, &endptr, 10);
+ if (endptr == 0 || *endptr != 0) {
+ errno = 0;
+ endptr = 0;
+ double y = strtod(buf, &endptr);
+ if (endptr == 0 || *endptr != 0) {
+ ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", buf);
+ return false;
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ // XXX should handle 123.000
+ ctx.pushStatus(Sqlstate::_01004, Error::Gen, "value %s truncated", buf);
+ x = static_cast<unsigned long>(y);
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ *ptr = x;
+ return true;
+}
+
+static bool
+copyout_char_bigunsigned(Ctx& ctx, const char* value, unsigned n, SQLUBIGINT* ptr)
+{
+ while (n > 0 && value[0] == 0x20) {
+ value++;
+ n--;
+ }
+ char buf[200];
+ if (n >= 200)
+ n = 200 - 1;
+ memcpy(buf, value, n);
+ buf[n] = 0;
+ errno = 0;
+ char* endptr = 0;
+ SQLUBIGINT x = strtoull(buf, &endptr, 10);
+ if (endptr == 0 || *endptr != 0) {
+ errno = 0;
+ endptr = 0;
+ double y = strtod(buf, &endptr);
+ if (endptr == 0 || *endptr != 0) {
+ ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", buf);
+ return false;
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ // XXX should handle 123.000
+ ctx.pushStatus(Sqlstate::_01004, Error::Gen, "value %s truncated", buf);
+ x = static_cast<unsigned long>(y);
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ *ptr = x;
+ return true;
+}
+
+static bool
+copyout_char_double(Ctx& ctx, const char* value, unsigned n, double* ptr)
+{
+ while (n > 0 && value[0] == 0x20) {
+ value++;
+ n--;
+ }
+ char buf[200];
+ if (n >= 200)
+ n = 200 - 1;
+ memcpy(buf, value, n);
+ buf[n] = 0;
+ errno = 0;
+ char* endptr = 0;
+ double x = strtod(value, &endptr);
+ if (endptr == 0 || *endptr != 0) {
+ ctx.pushStatus(Sqlstate::_22005, Error::Gen, "value %s not numeric", value);
+ return false;
+ } else if (errno != 0) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", value);
+ return false;
+ }
+ *ptr = x;
+ return true;
+}
+
+static bool
+copyout_signed_char(Ctx& ctx, Int64 value, char* ptr, int len, SQLINTEGER* ind)
+{
+ char buf[100];
+ sprintf(buf, FMT_I64, value);
+ unsigned n = strlen(buf);
+ if (len <= 0) {
+ ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", len);
+ return false;
+ }
+ if ((unsigned)len < n + 1) { // room for null byte
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ strcpy(ptr, buf);
+ if (ind != 0)
+ *ind = n;
+ return true;
+}
+
+static bool
+copyout_unsigned_char(Ctx& ctx, Uint64 uvalue, char* ptr, int len, SQLINTEGER* ind)
+{
+ char buf[100];
+ sprintf(buf, FMT_U64, uvalue);
+ unsigned n = strlen(buf);
+ if (len <= 0) {
+ ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", len);
+ return false;
+ }
+ if ((unsigned)len < n + 1) { // room for null byte
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ strcpy(ptr, buf);
+ if (ind != 0)
+ *ind = n;
+ return true;
+}
+
+static bool
+copyout_double_char(Ctx& ctx, double value, unsigned prec, char* ptr, int len, SQLINTEGER* ind)
+{
+ char buf[100];
+ sprintf(buf, "%.*f", (int)prec, value);
+ char* p = buf + strlen(buf);
+ while (p > buf + prec)
+ *--p = 0;
+ while (p > buf && *(p - 1) == '0')
+ *--p = 0;
+ if (p > buf && *(p - 1) == '.') {
+ *p++ = '0';
+ *p = 0;
+ }
+ unsigned n = strlen(buf);
+ if (len <= 0) {
+ ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", len);
+ return false;
+ }
+ if ((unsigned)len < n + 1) { // room for null byte
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", buf);
+ return false;
+ }
+ strcpy(ptr, buf);
+ if (ind != 0)
+ *ind = n;
+ return true;
+}
+
+void
+SqlField::copyout(Ctx& ctx, ExtField& extField) const
+{
+ if (extField.extSpec().extType().type() == ExtType::Unbound) {
+ return; // output buffer may be unbound
+ }
+ if (sqlSpec().store() == SqlSpec::Reference) {
+ ctx_assert(u_data.m_sqlField != 0);
+ u_data.m_sqlField->copyout(ctx, extField);
+ return;
+ }
+ SQLINTEGER* indPtr = extField.m_indPtr;
+ if (u_null.m_nullFlag) {
+ if (extField.m_pos > 0) { // second time from SQLGetData
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ if (indPtr == 0) {
+ ctx.pushStatus(Sqlstate::_22002, Error::Gen, "indicator variable required");
+ return;
+ }
+ *indPtr = SQL_NULL_DATA;
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ const SqlType& sqlType = sqlSpec().sqlType();
+ const ExtType& extType = extField.extSpec().extType();
+ if (sqlType.type() == SqlType::Char || sqlType.type() == SqlType::Varchar) {
+ unsigned n = 0;
+ const char* value = 0;
+ if (sqlType.type() == SqlType::Char) {
+ n = sqlType.length();
+ value = reinterpret_cast<const char*>(sqlChar());
+ } else {
+ value = reinterpret_cast<const char*>(sqlVarchar(&n));
+ }
+ if (extType.type() == ExtType::Char) {
+ char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ if (extField.m_dataLen <= 0) {
+ ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", (int)extField.m_dataLen);
+ return;
+ }
+ int* off = 0;
+ if (extField.m_pos >= 0) {
+ off = &extField.m_pos;
+ if ((unsigned)*off >= n) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ }
+ if (! copyout_char_char(ctx, value, n, dataPtr, extField.m_dataLen, indPtr, off))
+ return;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ long x;
+ if (! copyout_char_signed(ctx, value, n, &x))
+ return;
+ if (x < SHRT_MIN || x > SHRT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", value);
+ return;
+ }
+ *dataPtr = static_cast<short>(x);
+ if (indPtr != 0)
+ *indPtr = sizeof(short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ unsigned long x;
+ if (! copyout_char_unsigned(ctx, value, n, &x))
+ return;
+ if (x > USHRT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", value);
+ return;
+ }
+ *dataPtr = static_cast<unsigned short>(x);
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ if (! copyout_char_signed(ctx, value, n, dataPtr))
+ return;
+ if (indPtr != 0)
+ *indPtr = sizeof(long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ if (! copyout_char_unsigned(ctx, value, n, dataPtr))
+ return;
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ if (! copyout_char_bigsigned(ctx, value, n, dataPtr))
+ return;
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ if (! copyout_char_bigunsigned(ctx, value, n, dataPtr))
+ return;
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLUBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ double x;
+ if (! copyout_char_double(ctx, value, n, &x))
+ return;
+ if (fabs(x) < FLT_MIN || fabs(x) > FLT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %s overflow", value);
+ return;
+ }
+ *dataPtr = static_cast<float>(x);
+ if (indPtr != 0)
+ *indPtr = sizeof(float);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ double x;
+ if (! copyout_char_double(ctx, value, n, &x))
+ return;
+ *dataPtr = static_cast<double>(x);
+ if (indPtr != 0)
+ *indPtr = sizeof(double);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Binary || sqlType.type() == SqlType::Varbinary) {
+ unsigned n = 0;
+ const char* value = 0;
+ if (sqlType.type() == SqlType::Binary) {
+ n = sqlType.length();
+ value = reinterpret_cast<const char*>(sqlBinary());
+ } else {
+ value = reinterpret_cast<const char*>(sqlVarbinary(&n));
+ }
+ if (extType.type() == ExtType::Binary) {
+ char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ if (extField.m_dataLen <= 0) {
+ ctx.pushStatus(Sqlstate::_HY090, Error::Gen, "invalid output buffer length %d", (int)extField.m_dataLen);
+ return;
+ }
+ int* off = 0;
+ if (extField.m_pos >= 0) {
+ off = &extField.m_pos;
+ if ((unsigned)*off >= n) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ }
+ if (! copyout_binary_binary(ctx, value, n, dataPtr, extField.m_dataLen, indPtr, off))
+ return;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Smallint) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ const SqlSmallint value = sqlSmallint();
+ const SqlUsmallint uvalue = value;
+ if (extType.type() == ExtType::Char) {
+ char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ if (! sqlType.unSigned()) {
+ if (! copyout_signed_char(ctx, value, dataPtr, extField.m_dataLen, indPtr))
+ return;
+ } else {
+ if (! copyout_unsigned_char(ctx, uvalue, dataPtr, extField.m_dataLen, indPtr))
+ return;
+ }
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ *dataPtr = static_cast<short>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ *dataPtr = static_cast<unsigned short>(uvalue);
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ *dataPtr = static_cast<long>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ *dataPtr = static_cast<unsigned long>(uvalue);
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLBIGINT>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLUBIGINT>(uvalue);
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLUBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ *dataPtr = static_cast<float>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(float);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ *dataPtr = static_cast<double>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(double);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Integer) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ const SqlInteger value = sqlInteger();
+ const SqlUinteger uvalue = value;
+ if (extType.type() == ExtType::Char) {
+ char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ if (! sqlType.unSigned()) {
+ if (! copyout_signed_char(ctx, value, dataPtr, extField.m_dataLen, indPtr))
+ return;
+ } else {
+ if (! copyout_unsigned_char(ctx, uvalue, dataPtr, extField.m_dataLen, indPtr))
+ return;
+ }
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ if (value < SHRT_MIN || value > SHRT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %d overflow", (int)value);
+ return;
+ }
+ *dataPtr = static_cast<short>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ if (uvalue > USHRT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %u overflow", uvalue);
+ return;
+ }
+ *dataPtr = static_cast<unsigned short>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ *dataPtr = static_cast<long>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ *dataPtr = static_cast<unsigned long>(uvalue);
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLBIGINT>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLUBIGINT>(uvalue);
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLUBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ *dataPtr = static_cast<float>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(float);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ *dataPtr = static_cast<double>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(double);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Bigint) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ const SqlBigint value = sqlBigint();
+ const SqlUbigint uvalue = value;
+ if (extType.type() == ExtType::Char) {
+ char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ if (! sqlType.unSigned()) {
+ if (! copyout_signed_char(ctx, value, dataPtr, extField.m_dataLen, indPtr))
+ return;
+ } else {
+ if (! copyout_unsigned_char(ctx, uvalue, dataPtr, extField.m_dataLen, indPtr))
+ return;
+ }
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ if (value < SHRT_MIN || value > SHRT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value " FMT_I64 " overflow", (Int64)value);
+ return;
+ }
+ *dataPtr = static_cast<short>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ if (uvalue > USHRT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value " FMT_U64 " overflow", (Uint64)uvalue);
+ return;
+ }
+ *dataPtr = static_cast<short>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ if (value < INT_MIN || value > INT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value " FMT_I64 " overflow", (Int64)value);
+ return;
+ }
+ *dataPtr = static_cast<long>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ if (uvalue > UINT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value " FMT_U64 " overflow", (Uint64)uvalue);
+ return;
+ }
+ *dataPtr = static_cast<unsigned long>(uvalue);
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLBIGINT>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLUBIGINT>(uvalue);
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLUBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ *dataPtr = static_cast<float>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(float);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ *dataPtr = static_cast<double>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(double);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Real) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ const SqlReal value = sqlReal();
+ if (extType.type() == ExtType::Char) {
+ char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ if (! copyout_double_char(ctx, value, 7, dataPtr, extField.m_dataLen, indPtr))
+ return;
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ *dataPtr = static_cast<short>(value); // XXX todo
+ if (indPtr != 0)
+ *indPtr = sizeof(short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ if (value < 0 || value > USHRT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %g overflow", (double)value);
+ return;
+ }
+ *dataPtr = static_cast<short>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ *dataPtr = static_cast<long>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ *dataPtr = static_cast<unsigned long>(value); // XXX todo
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLBIGINT>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLUBIGINT>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLUBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ *dataPtr = static_cast<float>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(float);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ *dataPtr = static_cast<double>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(double);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Double) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ SqlDouble value = sqlDouble();
+ if (extType.type() == ExtType::Char) {
+ char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ if (! copyout_double_char(ctx, value, 14, dataPtr, extField.m_dataLen, indPtr))
+ return;
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Short || extType.type() == ExtType::Sshort) {
+ short* dataPtr = static_cast<short*>(extField.m_dataPtr);
+ *dataPtr = static_cast<short>(value); // XXX todo
+ if (indPtr != 0)
+ *indPtr = sizeof(short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ushort) {
+ unsigned short* dataPtr = static_cast<unsigned short*>(extField.m_dataPtr);
+ if (value < 0 || value > USHRT_MAX) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "value %g overflow", (double)value);
+ return;
+ }
+ *dataPtr = static_cast<short>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned short);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Long || extType.type() == ExtType::Slong) {
+ long* dataPtr = static_cast<long*>(extField.m_dataPtr);
+ *dataPtr = static_cast<long>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ulong) {
+ unsigned long* dataPtr = static_cast<unsigned long*>(extField.m_dataPtr);
+ *dataPtr = static_cast<unsigned long>(value); // XXX todo
+ if (indPtr != 0)
+ *indPtr = sizeof(unsigned long);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Sbigint) {
+ SQLBIGINT* dataPtr = static_cast<SQLBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLBIGINT>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Ubigint) {
+ SQLUBIGINT* dataPtr = static_cast<SQLUBIGINT*>(extField.m_dataPtr);
+ *dataPtr = static_cast<SQLUBIGINT>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(SQLUBIGINT);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Float) {
+ float* dataPtr = static_cast<float*>(extField.m_dataPtr);
+ *dataPtr = static_cast<float>(value); // big enough
+ if (indPtr != 0)
+ *indPtr = sizeof(float);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Double) {
+ double* dataPtr = static_cast<double*>(extField.m_dataPtr);
+ *dataPtr = static_cast<double>(value);
+ if (indPtr != 0)
+ *indPtr = sizeof(double);
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ }
+ if (sqlType.type() == SqlType::Datetime) {
+ if (extField.m_pos > 0) {
+ ctx.setCode(SQL_NO_DATA);
+ return;
+ }
+ SqlDatetime value = sqlDatetime();
+ if (extType.type() == ExtType::Char) {
+ char* dataPtr = static_cast<char*>(extField.m_dataPtr);
+ char buf[100];
+ sprintf(buf, "%02d%02u-%02u-%02u\040%02u:%02u:%02u.%09u", value.cc(), value.yy(), value.mm(), value.dd(), value.HH(), value.MM(), value.SS(), value.ff());
+ int n = strlen(buf);
+ if (extField.m_dataLen < 20) {
+ ctx.pushStatus(Sqlstate::_22003, Error::Gen, "buffer too small for timestamp %s", buf);
+ return;
+ }
+ if (extField.m_dataLen < n) {
+ ctx.pushStatus(Sqlstate::_01004, Error::Gen, "truncating fractional part of timestamp %s", buf);
+ n = extField.m_dataLen;
+ }
+ if (! copyout_char_char(ctx, buf, n, dataPtr, extField.m_dataLen, indPtr, 0))
+ return;
+ if (extField.m_pos >= 0)
+ extField.m_pos = 1;
+ return;
+ }
+ if (extType.type() == ExtType::Timestamp) {
+ SQL_TIMESTAMP_STRUCT* dataPtr = static_cast<SQL_TIMESTAMP_STRUCT*>(extField.m_dataPtr);
+ // XXX assume same datatype
+ dataPtr->year = value.cc() * 100 + value.yy();
+ dataPtr->month = value.mm();
+ dataPtr->day = value.dd();
+ dataPtr->hour = value.HH();
+ dataPtr->minute = value.MM();
+ dataPtr->second = value.SS();
+ dataPtr->fraction = value.ff();
+ return;
+ }
+ }
+ ctx_assert(false); // SqlType::Null not applicable
+}
+
+void
+SqlField::print(char* buf, unsigned size) const
+{
+ Ctx ctx;
+ unsigned n = sqlSpec().sqlType().displaySize();
+ SQLINTEGER ind = 0;
+ ExtType extType(ExtType::Char);
+ ExtSpec extSpec(extType);
+ ExtField extField(extSpec, (SQLPOINTER)buf, size, &ind);
+ buf[0] = 0;
+ copyout(ctx, extField);
+ if (ind == SQL_NULL_DATA)
+ snprintf(buf, size, "NULL");
+}
diff --git a/ndb/src/client/odbc/common/DataField.hpp b/ndb/src/old_files/client/odbc/common/DataField.hpp
index 65138df25f1..65138df25f1 100644
--- a/ndb/src/client/odbc/common/DataField.hpp
+++ b/ndb/src/old_files/client/odbc/common/DataField.hpp
diff --git a/ndb/src/client/odbc/common/DataRow.cpp b/ndb/src/old_files/client/odbc/common/DataRow.cpp
index 509f2673e0d..509f2673e0d 100644
--- a/ndb/src/client/odbc/common/DataRow.cpp
+++ b/ndb/src/old_files/client/odbc/common/DataRow.cpp
diff --git a/ndb/src/client/odbc/common/DataRow.hpp b/ndb/src/old_files/client/odbc/common/DataRow.hpp
index 4a5a1e905b9..4a5a1e905b9 100644
--- a/ndb/src/client/odbc/common/DataRow.hpp
+++ b/ndb/src/old_files/client/odbc/common/DataRow.hpp
diff --git a/ndb/src/old_files/client/odbc/common/DataType.cpp b/ndb/src/old_files/client/odbc/common/DataType.cpp
new file mode 100644
index 00000000000..96f6a6e0877
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/common/DataType.cpp
@@ -0,0 +1,551 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "DataType.hpp"
+
+// SqlType
+
+SqlType::SqlType() :
+ m_type(Undef)
+{
+}
+
+SqlType::SqlType(Type type, bool nullable)
+{
+ Ctx ctx;
+ setType(ctx, type, nullable);
+ ctx_assert(ctx.ok());
+}
+
+SqlType::SqlType(Type type, unsigned length, bool nullable)
+{
+ Ctx ctx;
+ setType(ctx, type, length, nullable);
+ ctx_assert(ctx.ok());
+}
+
+SqlType::SqlType(Type type, unsigned precision, unsigned scale, bool nullable)
+{
+ Ctx ctx;
+ setType(ctx, type, precision, scale, nullable);
+ ctx_assert(ctx.ok());
+}
+
+SqlType::SqlType(Ctx& ctx, Type type, bool nullable)
+{
+ setType(ctx, type, nullable);
+}
+
+SqlType::SqlType(Ctx& ctx, Type type, unsigned length, bool nullable)
+{
+ setType(ctx, type, length, nullable);
+}
+
+SqlType::SqlType(Ctx& ctx, Type type, unsigned precision, unsigned scale, bool nullable)
+{
+ setType(ctx, type, precision, scale, nullable);
+}
+
+SqlType::SqlType(Ctx& ctx, const NdbDictionary::Column* ndbColumn)
+{
+ setType(ctx, ndbColumn);
+}
+
+void
+SqlType::setType(Ctx& ctx, Type type, bool nullable)
+{
+ switch (type) {
+ case Smallint:
+ case Integer:
+ case Bigint:
+ case Real:
+ case Double:
+ case Datetime:
+ break;
+ case Blob:
+ setType(ctx, Varbinary, FAKE_BLOB_SIZE, nullable); // XXX BLOB hack
+ return;
+ case Clob:
+ setType(ctx, Varchar, FAKE_BLOB_SIZE, nullable); // XXX BLOB hack
+ return;
+ case Null:
+ case Unbound:
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ }
+ m_type = type;
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 0;
+ m_nullable = nullable;
+ m_unSigned = false;
+}
+
+void
+SqlType::setType(Ctx& ctx, Type type, unsigned length, bool nullable)
+{
+ switch (type) {
+ case Char:
+ case Varchar:
+ case Binary:
+ case Varbinary:
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ }
+ m_type = type;
+ m_precision = 0;
+ m_scale = 0;
+ m_length = length;
+ m_nullable = nullable;
+ m_unSigned = false;
+}
+
+void
+SqlType::setType(Ctx& ctx, Type type, unsigned precision, unsigned scale, bool nullable)
+{
+ ctx_assert(false); // not yet
+}
+
+void
+SqlType::setType(Ctx& ctx, const NdbDictionary::Column* ndbColumn)
+{
+ NdbDictionary::Column::Type type = ndbColumn->getType();
+ unsigned length = ndbColumn->getLength();
+ unsigned precision = ndbColumn->getPrecision();
+ unsigned scale = ndbColumn->getScale();
+ bool nullable = ndbColumn->getNullable();
+ switch (type) {
+ case NdbDictionary::Column::Undefined:
+ break;
+ case NdbDictionary::Column::Int:
+ if (length == 1)
+ setType(ctx, Integer, nullable);
+ else
+ setType(ctx, Binary, length * sizeof(SqlInteger), nullable);
+ return;
+ case NdbDictionary::Column::Unsigned:
+ if (length == 1) {
+ setType(ctx, Integer, nullable);
+ unSigned(true);
+ } else
+ setType(ctx, Binary, length * sizeof(SqlUinteger), nullable);
+ return;
+ case NdbDictionary::Column::Bigint:
+ if (length == 1)
+ setType(ctx, Bigint, nullable);
+ else
+ setType(ctx, Binary, length * sizeof(SqlBigint), nullable);
+ return;
+ case NdbDictionary::Column::Bigunsigned:
+ if (length == 1) {
+ setType(ctx, Bigint, nullable);
+ unSigned(true);
+ } else
+ setType(ctx, Binary, length * sizeof(SqlBigint), nullable);
+ return;
+ case NdbDictionary::Column::Float:
+ if (length == 1)
+ setType(ctx, Real, nullable);
+ else
+ setType(ctx, Binary, length * sizeof(SqlReal), nullable);
+ return;
+ case NdbDictionary::Column::Double:
+ if (length == 1)
+ setType(ctx, Double, nullable);
+ else
+ setType(ctx, Binary, length * sizeof(SqlDouble), nullable);
+ return;
+ case NdbDictionary::Column::Decimal:
+ setType(ctx, Decimal, precision, scale, nullable);
+ return;
+ case NdbDictionary::Column::Char:
+ setType(ctx, Char, length, nullable);
+ return;
+ case NdbDictionary::Column::Varchar:
+ setType(ctx, Varchar, length, nullable);
+ return;
+ case NdbDictionary::Column::Binary:
+ setType(ctx, Binary, length, nullable);
+ return;
+ case NdbDictionary::Column::Varbinary:
+ setType(ctx, Varbinary, length, nullable);
+ return;
+ case NdbDictionary::Column::Datetime:
+ // XXX not yet
+ break;
+ case NdbDictionary::Column::Timespec:
+ setType(ctx, Datetime, nullable);
+ return;
+ case NdbDictionary::Column::Blob:
+ setType(ctx, Blob, nullable);
+ return;
+ case NdbDictionary::Column::Clob:
+ setType(ctx, Clob, nullable);
+ return;
+ default:
+ break;
+ }
+ ctx.pushStatus(Error::Gen, "unsupported NDB type %d", (signed)type);
+}
+
+bool
+SqlType::equal(const SqlType& sqlType) const
+{
+ return
+ m_type == sqlType.m_type &&
+ m_precision == sqlType.m_precision &&
+ m_scale == sqlType.m_scale &&
+ m_length == sqlType.m_length;
+}
+
+unsigned
+SqlType::size() const
+{
+ switch (m_type) {
+ case Char:
+ case Varchar:
+ case Binary:
+ case Varbinary:
+ return m_length;
+ case Smallint:
+ return sizeof(SqlSmallint);
+ case Integer:
+ return sizeof(SqlInteger);
+ case Bigint:
+ return sizeof(SqlBigint);
+ case Real:
+ return sizeof(SqlReal);
+ case Double:
+ return sizeof(SqlDouble);
+ case Datetime:
+ return sizeof(SqlDatetime);
+ case Null:
+ return 0;
+ default:
+ break;
+ }
+ ctx_assert(false);
+ return 0;
+}
+
+unsigned
+SqlType::displaySize() const
+{
+ switch (m_type) {
+ case Char:
+ case Varchar:
+ return m_length;
+ case Binary:
+ case Varbinary:
+ return m_length;
+ case Smallint:
+ return m_unSigned ? 5 : 6;
+ case Integer:
+ return m_unSigned ? 10 : 11;
+ case Bigint:
+ return m_unSigned ? 20 : 21;
+ case Real:
+ return 10;
+ case Double:
+ return 20;
+ case Datetime:
+ return 30;
+ case Null:
+ return 0;
+ default:
+ break;
+ }
+ ctx_assert(false);
+ return 0;
+}
+
+void
+SqlType::getType(Ctx& ctx, NdbDictionary::Column* ndbColumn) const
+{
+ switch (m_type) {
+ case Char:
+ ndbColumn->setType(NdbDictionary::Column::Char);
+ ndbColumn->setLength(m_length);
+ break;
+ case Varchar:
+ ndbColumn->setType(NdbDictionary::Column::Varchar);
+ ndbColumn->setLength(m_length);
+ break;
+ case Binary:
+ ndbColumn->setType(NdbDictionary::Column::Binary);
+ ndbColumn->setLength(m_length);
+ break;
+ case Varbinary:
+ ndbColumn->setType(NdbDictionary::Column::Varbinary);
+ ndbColumn->setLength(m_length);
+ break;
+ case Smallint:
+ break; // XXX
+ case Integer:
+ if (! m_unSigned)
+ ndbColumn->setType(NdbDictionary::Column::Int);
+ else
+ ndbColumn->setType(NdbDictionary::Column::Unsigned);
+ ndbColumn->setLength(1);
+ break;
+ case Bigint:
+ if (! m_unSigned)
+ ndbColumn->setType(NdbDictionary::Column::Bigint);
+ else
+ ndbColumn->setType(NdbDictionary::Column::Bigunsigned);
+ ndbColumn->setLength(1);
+ break;
+ case Real:
+ ndbColumn->setType(NdbDictionary::Column::Float);
+ ndbColumn->setLength(1);
+ break;
+ case Double:
+ ndbColumn->setType(NdbDictionary::Column::Double);
+ ndbColumn->setLength(1);
+ break;
+ case Datetime:
+ ndbColumn->setType(NdbDictionary::Column::Timespec);
+ ndbColumn->setLength(1);
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ }
+ ndbColumn->setNullable(m_nullable);
+}
+
+const char*
+SqlType::typeName() const
+{
+ switch (m_type) {
+ case Char:
+ return "CHAR";
+ case Varchar:
+ return "VARCHAR";
+ case Binary:
+ return "BINARY";
+ case Varbinary:
+ return "VARBINARY";
+ case Smallint:
+ return "SMALLINT";
+ case Integer:
+ return "INTEGER";
+ case Bigint:
+ return "BIGINT";
+ case Real:
+ return "REAL";
+ case Double:
+ return "FLOAT";
+ case Datetime:
+ return "DATETIME";
+ default:
+ break;
+ }
+ return "UNKNOWN";
+}
+
+void
+SqlType::print(char* buf, unsigned size) const
+{
+ switch (m_type) {
+ case Char:
+ snprintf(buf, size, "char(%d)", m_length);
+ break;
+ case Varchar:
+ snprintf(buf, size, "varchar(%d)", m_length);
+ break;
+ case Binary:
+ snprintf(buf, size, "binary(%d)", m_length);
+ break;
+ case Varbinary:
+ snprintf(buf, size, "varbinary(%d)", m_length);
+ break;
+ case Smallint:
+ snprintf(buf, size, "smallint%s", m_unSigned ? " unsigned" : "");
+ break;
+ case Integer:
+ snprintf(buf, size, "integer%s", m_unSigned ? " unsigned" : "");
+ break;
+ case Bigint:
+ snprintf(buf, size, "bigint%s", m_unSigned ? " unsigned" : "");
+ break;
+ case Real:
+ snprintf(buf, size, "real");
+ break;
+ case Double:
+ snprintf(buf, size, "double");
+ break;
+ case Datetime:
+ snprintf(buf, size, "datetime");
+ break;
+ case Null:
+ snprintf(buf, size, "null");
+ break;
+ case Unbound:
+ snprintf(buf, size, "unbound");
+ break;
+ default:
+ snprintf(buf, size, "sqltype(%d)", (int)m_type);
+ break;
+ }
+}
+
+// ExtType
+
+ExtType::ExtType() :
+ m_type(Undef)
+{
+}
+
+ExtType::ExtType(Type type)
+{
+ Ctx ctx;
+ setType(ctx, type);
+ ctx_assert(ctx.ok());
+}
+
+ExtType::ExtType(Ctx& ctx, Type type)
+{
+ setType(ctx, type);
+}
+
+void
+ExtType::setType(Ctx& ctx, Type type)
+{
+ switch (type) {
+ case Char:
+ case Short:
+ case Sshort:
+ case Ushort:
+ case Long:
+ case Slong:
+ case Ulong:
+ case Sbigint:
+ case Ubigint:
+ case Float:
+ case Double:
+ case Timestamp:
+ case Binary: // XXX BLOB hack
+ case Unbound:
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "unsupported external type %d", (int)type);
+ return;
+ }
+ m_type = type;
+}
+
+unsigned
+ExtType::size() const
+{
+ ctx_assert(false);
+ return 0;
+}
+
+// LexType
+
+LexType::LexType() :
+ m_type(Undef)
+{
+}
+
+LexType::LexType(Type type)
+{
+ Ctx ctx;
+ setType(ctx, type);
+ ctx_assert(ctx.ok());
+}
+
+LexType::LexType(Ctx& ctx, Type type)
+{
+ setType(ctx, type);
+}
+
+void
+LexType::setType(Ctx& ctx, Type type)
+{
+ switch (type) {
+ case Char:
+ case Integer:
+ case Float:
+ case Null:
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ }
+ m_type = type;
+}
+
+// convert types
+
+SQLSMALLINT
+SqlType::sqlcdefault(Ctx& ctx) const
+{
+ switch (m_type) {
+ case Char:
+ return SQL_C_CHAR;
+ case Varchar:
+ return SQL_C_CHAR;
+ case Binary:
+ return SQL_C_BINARY;
+ case Varbinary:
+ return SQL_C_BINARY;
+ case Smallint:
+ return m_unSigned ? SQL_C_USHORT : SQL_C_SSHORT;
+ case Integer:
+ return m_unSigned ? SQL_C_ULONG : SQL_C_SLONG;
+ case Bigint:
+ return SQL_C_CHAR;
+ // or maybe this
+ return m_unSigned ? SQL_C_UBIGINT : SQL_C_SBIGINT;
+ case Real:
+ return SQL_C_FLOAT;
+ case Double:
+ return SQL_C_DOUBLE;
+ case Datetime:
+ return SQL_C_TYPE_TIMESTAMP;
+ default:
+ break;
+ }
+ return SQL_C_DEFAULT; // no default
+}
+
+void
+LexType::convert(Ctx& ctx, SqlType& out, unsigned length) const
+{
+ switch (m_type) {
+ case Char:
+ out.setType(ctx, SqlType::Char, length, true);
+ return;
+ case Integer:
+ out.setType(ctx, SqlType::Bigint, false);
+ return;
+ case Float:
+ out.setType(ctx, SqlType::Double, false);
+ return;
+ case Null:
+ out.setType(ctx, SqlType::Null, true);
+ return;
+ default:
+ break;
+ }
+ ctx.pushStatus(Error::Gen, "unsupported lexical to SQL type conversion");
+}
diff --git a/ndb/src/old_files/client/odbc/common/DataType.hpp b/ndb/src/old_files/client/odbc/common/DataType.hpp
new file mode 100644
index 00000000000..e03e445cf05
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/common/DataType.hpp
@@ -0,0 +1,293 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_COMMON_DataType_hpp
+#define ODBC_COMMON_DataType_hpp
+
+#include <map>
+#include <ndb_types.h>
+#include <AttrType.hpp>
+#include <NdbDictionary.hpp>
+#include <common/common.hpp>
+
+/**
+ * Sql data exists in several formats:
+ *
+ * - as NDB data at the bottom
+ * - as SQL data during intermediary processing
+ * - as external data in user input and output buffers
+ * - as lexical constants in SQL statement text
+ *
+ * Each data format has specific types (e.g. number) and each
+ * type has specific attributes (e.g. precision).
+ */
+enum DataFormat {
+ Undef_format = 0,
+ Ndb_format = 1, // not used in NDB version >= v2.10
+ Sql_format = 2,
+ Ext_format = 3,
+ Lex_format = 4
+};
+
+#define UndefDataType 990
+#define NullDataType 991
+#define UnboundDataType 992
+
+class SqlType;
+class ExtType;
+class LexType;
+
+/**
+ * @class SqlType
+ * @brief Sql data type
+ */
+class SqlType {
+public:
+ enum Type {
+ Undef = UndefDataType,
+ Char = SQL_CHAR,
+ Varchar = SQL_VARCHAR,
+ Longvarchar = SQL_LONGVARCHAR,
+ Binary = SQL_BINARY,
+ Varbinary = SQL_VARBINARY,
+ Longvarbinary = SQL_LONGVARBINARY,
+ Decimal = SQL_DECIMAL,
+ Tinyint = SQL_TINYINT,
+ Smallint = SQL_SMALLINT,
+ Integer = SQL_INTEGER,
+ Bigint = SQL_BIGINT,
+ Real = SQL_REAL,
+ Double = SQL_DOUBLE,
+ Date = SQL_DATE,
+ Datetime = SQL_TYPE_TIMESTAMP,
+ Blob = SQL_BLOB,
+ Clob = SQL_CLOB,
+ Null = NullDataType, // not an ODBC SQL type
+ Unbound = UnboundDataType // special for placeholders
+ };
+ SqlType();
+ SqlType(Type type, bool nullable = true);
+ SqlType(Type type, unsigned length, bool nullable = true);
+ SqlType(Type type, unsigned precision, unsigned scale, bool nullable = true);
+ SqlType(Ctx& ctx, Type type, bool nullable = true);
+ SqlType(Ctx& ctx, Type type, unsigned length, bool nullable = true);
+ SqlType(Ctx& ctx, Type type, unsigned precision, unsigned scale, bool nullable = true);
+ SqlType(Ctx& ctx, const NdbDictionary::Column* ndbColumn);
+ Type type() const;
+ void setType(Ctx& ctx, Type type, bool nullable = true);
+ void setType(Ctx& ctx, Type type, unsigned length, bool nullable = true);
+ void setType(Ctx& ctx, Type type, unsigned precision, unsigned scale, bool nullable = true);
+ void setType(Ctx& ctx, const NdbDictionary::Column* ndbColumn);
+ bool equal(const SqlType& sqlType) const;
+ unsigned size() const;
+ unsigned displaySize() const;
+ const char* typeName() const;
+ unsigned length() const;
+ bool nullable() const;
+ void nullable(bool value);
+ bool unSigned() const;
+ void unSigned(bool value);
+ // forwards compatible
+ void getType(Ctx& ctx, NdbDictionary::Column* ndbColumn) const;
+ // type conversion
+ SQLSMALLINT sqlcdefault(Ctx& ctx) const;
+ // print for debugging
+ void print(char* buf, unsigned size) const;
+private:
+ friend class LexType;
+ Type m_type;
+ unsigned m_precision;
+ unsigned m_scale;
+ unsigned m_length;
+ bool m_nullable;
+ bool m_unSigned; // qualifier instead of separate types
+};
+
+inline SqlType::Type
+SqlType::type() const
+{
+ return m_type;
+}
+
+inline unsigned
+SqlType::length() const
+{
+ return m_length;
+}
+
+inline bool
+SqlType::nullable() const
+{
+ return m_nullable;
+}
+
+inline void
+SqlType::nullable(bool value)
+{
+ m_nullable = value;
+}
+
+inline bool
+SqlType::unSigned() const
+{
+ return m_unSigned;
+}
+
+inline void
+SqlType::unSigned(bool value)
+{
+ ctx_assert(m_type == Smallint || m_type == Integer || m_type == Bigint);
+ m_unSigned = value;
+}
+
+/**
+ * Actual SQL datatypes.
+ */
+typedef unsigned char SqlChar; // Char and Varchar via pointer
+typedef Int16 SqlSmallint;
+typedef Int32 SqlInteger;
+typedef Int64 SqlBigint;
+typedef Uint16 SqlUsmallint;
+typedef Uint32 SqlUinteger;
+typedef Uint64 SqlUbigint;
+typedef float SqlReal;
+typedef double SqlDouble;
+
+// datetime cc yy mm dd HH MM SS 00 ff ff ff ff stored as String(12)
+struct SqlDatetime {
+ int cc() const { return *(signed char*)&m_data[0]; }
+ void cc(int x) { *(signed char*)&m_data[0] = x; }
+ unsigned yy() const { return *(unsigned char*)&m_data[1]; }
+ void yy(unsigned x) { *(unsigned char*)&m_data[1] = x; }
+ unsigned mm() const { return *(unsigned char*)&m_data[2]; }
+ void mm(unsigned x) { *(unsigned char*)&m_data[2] = x; }
+ unsigned dd() const { return *(unsigned char*)&m_data[3]; }
+ void dd(unsigned x) { *(unsigned char*)&m_data[3] = x; }
+ unsigned HH() const { return *(unsigned char*)&m_data[4]; }
+ void HH(unsigned x) { *(unsigned char*)&m_data[4] = x; }
+ unsigned MM() const { return *(unsigned char*)&m_data[5]; }
+ void MM(unsigned x) { *(unsigned char*)&m_data[5] = x; }
+ unsigned SS() const { return *(unsigned char*)&m_data[6]; }
+ void SS(unsigned x) { *(unsigned char*)&m_data[6] = x; }
+ unsigned ff() const {
+ const unsigned char* p = (unsigned char*)&m_data[8];
+ unsigned x = 0;
+ x += *p++ << 24;
+ x += *p++ << 16;
+ x += *p++ << 8;
+ x += *p++;
+ return x;
+ }
+ void ff(unsigned x) {
+ unsigned char* p = (unsigned char*)&m_data[8];
+ *p++ = (x >> 24) & 0xff;
+ *p++ = (x >> 16) & 0xff;
+ *p++ = (x >> 8) & 0xff;
+ *p++ = x & 0xff;
+ }
+ bool valid() { return true; } // XXX later
+ bool less(const SqlDatetime t) const {
+ if (cc() != t.cc())
+ return cc() < t.cc();
+ if (yy() != t.yy())
+ return yy() < t.yy();
+ if (mm() != t.mm())
+ return mm() < t.mm();
+ if (dd() != t.dd())
+ return dd() < t.dd();
+ if (HH() != t.HH())
+ return HH() < t.HH();
+ if (MM() != t.MM())
+ return MM() < t.MM();
+ if (SS() != t.SS())
+ return SS() < t.SS();
+ if (ff() != t.ff())
+ return ff() < t.ff();
+ return false;
+ }
+private:
+ char m_data[12]; // use array to avoid gaps
+};
+
+/**
+ * @class ExtType
+ * @brief External data type
+ */
+class ExtType {
+public:
+ enum Type {
+ Undef = UndefDataType,
+ Char = SQL_C_CHAR,
+ Short = SQL_C_SHORT,
+ Sshort = SQL_C_SSHORT,
+ Ushort = SQL_C_USHORT,
+ Long = SQL_C_LONG, // for sun.jdbc.odbc
+ Slong = SQL_C_SLONG,
+ Ulong = SQL_C_ULONG,
+ Sbigint = SQL_C_SBIGINT,
+ Ubigint = SQL_C_UBIGINT,
+ Float = SQL_C_FLOAT,
+ Double = SQL_C_DOUBLE,
+ Timestamp = SQL_C_TYPE_TIMESTAMP,
+ Binary = SQL_C_BINARY, // XXX BLOB hack
+ Unbound = UnboundDataType
+ };
+ ExtType();
+ ExtType(Type type);
+ ExtType(Ctx& ctx, Type type);
+ Type type() const;
+ void setType(Ctx& ctx, Type type);
+ unsigned size() const;
+private:
+ Type m_type;
+};
+
+inline ExtType::Type
+ExtType::type() const
+{
+ return m_type;
+}
+
+/**
+ * @class LexType
+ * @class Lexical data type
+ */
+class LexType {
+public:
+ enum Type {
+ Undef = UndefDataType,
+ Char = 1,
+ Integer = 2,
+ Float = 3,
+ Null = 4
+ };
+ LexType();
+ LexType(Type type);
+ LexType(Ctx& ctx, Type type);
+ Type type() const;
+ void setType(Ctx& ctx, Type type);
+ void convert(Ctx& ctx, SqlType& out, unsigned length = 0) const;
+private:
+ Type m_type;
+};
+
+inline LexType::Type
+LexType::type() const
+{
+ return m_type;
+}
+
+#endif
diff --git a/ndb/src/client/odbc/common/DescArea.cpp b/ndb/src/old_files/client/odbc/common/DescArea.cpp
index bad9f23d3ef..bad9f23d3ef 100644
--- a/ndb/src/client/odbc/common/DescArea.cpp
+++ b/ndb/src/old_files/client/odbc/common/DescArea.cpp
diff --git a/ndb/src/client/odbc/common/DescArea.hpp b/ndb/src/old_files/client/odbc/common/DescArea.hpp
index e9f552d758d..e9f552d758d 100644
--- a/ndb/src/client/odbc/common/DescArea.hpp
+++ b/ndb/src/old_files/client/odbc/common/DescArea.hpp
diff --git a/ndb/src/client/odbc/common/DiagArea.cpp b/ndb/src/old_files/client/odbc/common/DiagArea.cpp
index 06e8da89495..06e8da89495 100644
--- a/ndb/src/client/odbc/common/DiagArea.cpp
+++ b/ndb/src/old_files/client/odbc/common/DiagArea.cpp
diff --git a/ndb/src/client/odbc/common/DiagArea.hpp b/ndb/src/old_files/client/odbc/common/DiagArea.hpp
index 79c03de6623..79c03de6623 100644
--- a/ndb/src/client/odbc/common/DiagArea.hpp
+++ b/ndb/src/old_files/client/odbc/common/DiagArea.hpp
diff --git a/ndb/src/client/odbc/common/Makefile b/ndb/src/old_files/client/odbc/common/Makefile
index 7ee29738d86..7ee29738d86 100644
--- a/ndb/src/client/odbc/common/Makefile
+++ b/ndb/src/old_files/client/odbc/common/Makefile
diff --git a/ndb/src/old_files/client/odbc/common/OdbcData.cpp b/ndb/src/old_files/client/odbc/common/OdbcData.cpp
new file mode 100644
index 00000000000..32400e07c7a
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/common/OdbcData.cpp
@@ -0,0 +1,560 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "OdbcData.hpp"
+
+OdbcData::OdbcData() :
+ m_type(Undef)
+{
+}
+
+OdbcData::OdbcData(Type type) :
+ m_type(type)
+{
+ switch (m_type) {
+ case Smallint:
+ m_smallint = 0;
+ break;
+ case Usmallint:
+ m_usmallint = 0;
+ break;
+ case Integer:
+ m_integer = 0;
+ break;
+ case Uinteger:
+ m_uinteger = 0;
+ break;
+ case Pointer:
+ m_pointer = 0;
+ break;
+ case SmallintPtr:
+ m_smallintPtr = 0;
+ break;
+ case UsmallintPtr:
+ m_usmallintPtr = 0;
+ break;
+ case IntegerPtr:
+ m_integerPtr = 0;
+ break;
+ case UintegerPtr:
+ m_uintegerPtr = 0;
+ break;
+ case PointerPtr:
+ m_pointerPtr = 0;
+ break;
+ case Sqlchar:
+ m_sqlchar = 0;
+ break;
+ case Sqlstate:
+ m_sqlstate = 0;
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ };
+}
+
+OdbcData::OdbcData(const OdbcData& odbcData) :
+ m_type(odbcData.m_type)
+{
+ switch (m_type) {
+ case Smallint:
+ m_smallint = odbcData.m_smallint;
+ break;
+ case Usmallint:
+ m_usmallint = odbcData.m_usmallint;
+ break;
+ case Integer:
+ m_integer = odbcData.m_integer;
+ break;
+ case Uinteger:
+ m_uinteger = odbcData.m_uinteger;
+ break;
+ case Pointer:
+ m_pointer = odbcData.m_pointer;
+ break;
+ case SmallintPtr:
+ m_smallintPtr = odbcData.m_smallintPtr;
+ break;
+ case UsmallintPtr:
+ m_usmallintPtr = odbcData.m_usmallintPtr;
+ break;
+ case IntegerPtr:
+ m_integerPtr = odbcData.m_integerPtr;
+ break;
+ case UintegerPtr:
+ m_uintegerPtr = odbcData.m_uintegerPtr;
+ break;
+ case PointerPtr:
+ m_pointerPtr = odbcData.m_pointerPtr;
+ break;
+ case Sqlchar: {
+ unsigned n = strlen(odbcData.m_sqlchar);
+ m_sqlchar = new char[n + 1];
+ memcpy(m_sqlchar, odbcData.m_sqlchar, n + 1);
+ break;
+ }
+ case Sqlstate:
+ m_sqlstate = odbcData.m_sqlstate;
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ };
+}
+
+OdbcData::~OdbcData()
+{
+ switch (m_type) {
+ case Sqlchar:
+ delete[] m_sqlchar;
+ break;
+ default:
+ break;
+ }
+}
+
+void
+OdbcData::setValue()
+{
+ m_type = Undef;
+}
+
+void
+OdbcData::setValue(Type type)
+{
+ if (m_type == Sqlchar) {
+ delete[] m_sqlchar;
+ m_sqlchar = 0;
+ }
+ switch (m_type) {
+ case Smallint:
+ m_smallint = 0;
+ break;
+ case Usmallint:
+ m_usmallint = 0;
+ break;
+ case Integer:
+ m_integer = 0;
+ break;
+ case Uinteger:
+ m_uinteger = 0;
+ break;
+ case Pointer:
+ m_pointer = 0;
+ break;
+ case SmallintPtr:
+ m_smallintPtr = 0;
+ break;
+ case UsmallintPtr:
+ m_usmallintPtr = 0;
+ break;
+ case IntegerPtr:
+ m_integerPtr = 0;
+ break;
+ case UintegerPtr:
+ m_uintegerPtr = 0;
+ break;
+ case PointerPtr:
+ m_pointerPtr = 0;
+ break;
+ case Sqlchar:
+ m_sqlchar = 0;
+ break;
+ case Sqlstate:
+ m_sqlstate = 0;
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ };
+}
+
+void
+OdbcData::setValue(const OdbcData odbcData)
+{
+ if (m_type == Sqlchar) {
+ delete[] m_sqlchar;
+ m_sqlchar = 0;
+ }
+ m_type = odbcData.m_type;
+ switch (m_type) {
+ case Smallint:
+ m_smallint = odbcData.m_smallint;
+ break;
+ case Usmallint:
+ m_usmallint = odbcData.m_usmallint;
+ break;
+ case Integer:
+ m_integer = odbcData.m_integer;
+ break;
+ case Uinteger:
+ m_uinteger = odbcData.m_uinteger;
+ break;
+ case Pointer:
+ m_pointer = odbcData.m_pointer;
+ break;
+ case SmallintPtr:
+ m_smallintPtr = odbcData.m_smallintPtr;
+ break;
+ case UsmallintPtr:
+ m_usmallintPtr = odbcData.m_usmallintPtr;
+ break;
+ case IntegerPtr:
+ m_integerPtr = odbcData.m_integerPtr;
+ break;
+ case UintegerPtr:
+ m_uintegerPtr = odbcData.m_uintegerPtr;
+ break;
+ case PointerPtr:
+ m_pointerPtr = odbcData.m_pointerPtr;
+ break;
+ case Sqlchar: {
+ unsigned n = strlen(odbcData.m_sqlchar);
+ m_sqlchar = new char[n + 1];
+ memcpy(m_sqlchar, odbcData.m_sqlchar, n + 1);
+ break;
+ }
+ case Sqlstate:
+ m_sqlstate = odbcData.m_sqlstate;
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ };
+}
+
+// copy in from user buffer
+
+void
+OdbcData::copyin(Ctx& ctx, Type type, SQLPOINTER buf, SQLINTEGER length)
+{
+ if (m_type == Sqlchar) {
+ delete[] m_sqlchar;
+ m_sqlchar = 0;
+ }
+ m_type = type;
+ switch (m_type) {
+ case Smallint: {
+ SQLSMALLINT val = 0;
+ switch (length) {
+ case 0:
+ case SQL_IS_SMALLINT:
+ val = (SQLSMALLINT)(SQLINTEGER)buf;
+ break;
+ case SQL_IS_USMALLINT:
+ val = (SQLUSMALLINT)(SQLUINTEGER)buf;
+ break;
+ case SQL_IS_INTEGER:
+ val = (SQLINTEGER)buf;
+ break;
+ case SQL_IS_UINTEGER:
+ val = (SQLUINTEGER)buf;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "smallint input - invalid length %d", (int)length);
+ return;
+ }
+ m_smallint = val;
+ break;
+ }
+ case Usmallint: {
+ SQLUSMALLINT val = 0;
+ switch (length) {
+ case SQL_IS_SMALLINT:
+ val = (SQLSMALLINT)(SQLINTEGER)buf;
+ break;
+ case 0:
+ case SQL_IS_USMALLINT:
+ val = (SQLUSMALLINT)(SQLUINTEGER)buf;
+ break;
+ case SQL_IS_INTEGER:
+ val = (SQLINTEGER)buf;
+ break;
+ case SQL_IS_UINTEGER:
+ val = (SQLUINTEGER)buf;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "unsigned smallint input - invalid length %d", (int)length);
+ return;
+ }
+ m_usmallint = val;
+ break;
+ }
+ case Integer: {
+ SQLINTEGER val = 0;
+ switch (length) {
+ case SQL_IS_SMALLINT:
+ val = (SQLSMALLINT)(SQLINTEGER)buf;
+ break;
+ case SQL_IS_USMALLINT:
+ val = (SQLUSMALLINT)(SQLUINTEGER)buf;
+ break;
+ case 0:
+ case SQL_IS_INTEGER:
+ val = (SQLINTEGER)buf;
+ break;
+ case SQL_IS_UINTEGER:
+ val = (SQLUINTEGER)buf;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "integer input - invalid length %d", (int)length);
+ return;
+ }
+ m_integer = val;
+ break;
+ }
+ case Uinteger: {
+ SQLUINTEGER val = 0;
+ switch (length) {
+ case SQL_IS_SMALLINT:
+ val = (SQLSMALLINT)(SQLINTEGER)buf;
+ break;
+ case SQL_IS_USMALLINT:
+ val = (SQLUSMALLINT)(SQLUINTEGER)buf;
+ break;
+ case SQL_IS_INTEGER:
+ val = (SQLINTEGER)buf;
+ break;
+ case 0:
+ case SQL_IS_UINTEGER:
+ val = (SQLUINTEGER)buf;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "unsigned integer input - invalid length %d", (int)length);
+ return;
+ }
+ m_uinteger = val;
+ break;
+ }
+ case Pointer: {
+ SQLPOINTER val = 0;
+ switch (length) {
+ case 0:
+ case SQL_IS_POINTER:
+ val = (SQLPOINTER)buf;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "pointer input - invalid length %d", (int)length);
+ return;
+ }
+ m_pointer = val;
+ break;
+ }
+ case SmallintPtr: {
+ SQLSMALLINT* val = 0;
+ switch (length) {
+ case 0:
+ case SQL_IS_POINTER:
+ val = (SQLSMALLINT*)buf;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "smallint pointer input - invalid length %d", (int)length);
+ return;
+ }
+ m_smallintPtr = val;
+ break;
+ }
+ case UsmallintPtr: {
+ SQLUSMALLINT* val = 0;
+ switch (length) {
+ case 0:
+ case SQL_IS_POINTER:
+ val = (SQLUSMALLINT*)buf;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "unsigned smallint pointer input - invalid length %d", (int)length);
+ return;
+ }
+ m_usmallintPtr = val;
+ break;
+ }
+ case IntegerPtr: {
+ SQLINTEGER* val = 0;
+ switch (length) {
+ case 0:
+ case SQL_IS_POINTER:
+ val = (SQLINTEGER*)buf;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "integer pointer input - invalid length %d", (int)length);
+ return;
+ }
+ m_integerPtr = val;
+ break;
+ }
+ case UintegerPtr: {
+ SQLUINTEGER* val = 0;
+ switch (length) {
+ case 0:
+ case SQL_IS_POINTER:
+ val = (SQLUINTEGER*)buf;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "unsigned integer pointer input - invalid length %d", (int)length);
+ return;
+ }
+ m_uintegerPtr = val;
+ break;
+ }
+ case Sqlchar: {
+ const char* val = (char*)buf;
+ if (val == 0) {
+ ctx.pushStatus(Sqlstate::_HY009, Error::Gen, "null string input");
+ return;
+ }
+ if (length < 0 && length != SQL_NTS) {
+ ctx.pushStatus(Error::Gen, "string input - invalid length %d", (int)length);
+ return;
+ }
+ if (length == SQL_NTS) {
+ m_sqlchar = strcpy(new char[strlen(val) + 1], val);
+ } else {
+ m_sqlchar = (char*)memcpy(new char[length + 1], val, length);
+ m_sqlchar[length] = 0;
+ }
+ break;
+ }
+ default:
+ ctx_assert(false);
+ break;
+ }
+}
+
+// copy out to user buffer
+
+void
+OdbcData::copyout(Ctx& ctx, SQLPOINTER buf, SQLINTEGER length, SQLINTEGER* total, SQLSMALLINT* total2)
+{
+ if (buf == 0) {
+ ctx.setCode(SQL_ERROR);
+ return;
+ }
+ switch (m_type) {
+ case Smallint: {
+ SQLSMALLINT* ptr = static_cast<SQLSMALLINT*>(buf);
+ *ptr = m_smallint;
+ break;
+ }
+ case Usmallint: {
+ SQLUSMALLINT* ptr = static_cast<SQLUSMALLINT*>(buf);
+ *ptr = m_usmallint;
+ break;
+ }
+ case Integer: {
+ SQLINTEGER* ptr = static_cast<SQLINTEGER*>(buf);
+ *ptr = m_integer;
+ break;
+ }
+ case Uinteger: {
+ SQLUINTEGER* ptr = static_cast<SQLUINTEGER*>(buf);
+ *ptr = m_uinteger;
+ break;
+ }
+ case Pointer: {
+ SQLPOINTER* ptr = static_cast<SQLPOINTER*>(buf);
+ *ptr = m_pointer;
+ break;
+ }
+ case Sqlchar: {
+ char* ptr = static_cast<char*>(buf);
+ if (length < 0 && length != SQL_NTS) {
+ ctx.setCode(SQL_ERROR);
+ return;
+ }
+ if (length == SQL_NTS) {
+ strcpy(ptr, m_sqlchar);
+ } else {
+ strncpy(ptr, m_sqlchar, length);
+ }
+ if (total != 0)
+ *total = strlen(m_sqlchar);
+ if (total2 != 0)
+ *total2 = strlen(m_sqlchar);
+ break;
+ }
+ case Sqlstate: {
+ char* ptr = static_cast<char*>(buf);
+ const char* state = m_sqlstate->state();
+ if (length < 0 && length != SQL_NTS) {
+ ctx.setCode(SQL_ERROR);
+ return;
+ }
+ if (length == SQL_NTS) {
+ strcpy(ptr, state);
+ } else {
+ strncpy(ptr, state, length);
+ }
+ if (total != 0)
+ *total = strlen(state);
+ if (total2 != 0)
+ *total2 = strlen(state);
+ break;
+ }
+ default:
+ ctx_assert(false);
+ break;
+ }
+}
+
+void
+OdbcData::print(char* buf, unsigned size) const
+{
+ switch (m_type) {
+ case Undef:
+ snprintf(buf, size, "undef");
+ break;
+ case Smallint:
+ snprintf(buf, size, "%d", (int)m_smallint);
+ break;
+ case Usmallint:
+ snprintf(buf, size, "%u", (unsigned)m_usmallint);
+ break;
+ case Integer:
+ snprintf(buf, size, "%ld", (long)m_integer);
+ break;
+ case Uinteger:
+ snprintf(buf, size, "%lu", (unsigned long)m_uinteger);
+ break;
+ case Pointer:
+ snprintf(buf, size, "0x%lx", (unsigned long)m_pointer);
+ break;
+ case SmallintPtr:
+ snprintf(buf, size, "0x%lx", (unsigned long)m_smallintPtr);
+ break;
+ case UsmallintPtr:
+ snprintf(buf, size, "0x%lx", (unsigned long)m_usmallintPtr);
+ break;
+ case IntegerPtr:
+ snprintf(buf, size, "0x%lx", (unsigned long)m_integerPtr);
+ break;
+ case UintegerPtr:
+ snprintf(buf, size, "0x%lx", (unsigned long)m_uintegerPtr);
+ break;
+ case PointerPtr:
+ snprintf(buf, size, "0x%lx", (unsigned long)m_pointerPtr);
+ break;
+ case Sqlchar:
+ snprintf(buf, size, "%s", m_sqlchar);
+ break;
+ case Sqlstate:
+ snprintf(buf, size, "%s", m_sqlstate->state());
+ break;
+ default:
+ snprintf(buf, size, "data(%d)", (int)m_type);
+ break;
+ };
+}
diff --git a/ndb/src/client/odbc/common/OdbcData.hpp b/ndb/src/old_files/client/odbc/common/OdbcData.hpp
index c1884507cfe..c1884507cfe 100644
--- a/ndb/src/client/odbc/common/OdbcData.hpp
+++ b/ndb/src/old_files/client/odbc/common/OdbcData.hpp
diff --git a/ndb/src/client/odbc/common/ResultArea.cpp b/ndb/src/old_files/client/odbc/common/ResultArea.cpp
index 79d7fb0ccc4..79d7fb0ccc4 100644
--- a/ndb/src/client/odbc/common/ResultArea.cpp
+++ b/ndb/src/old_files/client/odbc/common/ResultArea.cpp
diff --git a/ndb/src/client/odbc/common/ResultArea.hpp b/ndb/src/old_files/client/odbc/common/ResultArea.hpp
index d4890c44d99..d4890c44d99 100644
--- a/ndb/src/client/odbc/common/ResultArea.hpp
+++ b/ndb/src/old_files/client/odbc/common/ResultArea.hpp
diff --git a/ndb/src/client/odbc/common/Sqlstate.cpp b/ndb/src/old_files/client/odbc/common/Sqlstate.cpp
index 2d625a7c159..2d625a7c159 100644
--- a/ndb/src/client/odbc/common/Sqlstate.cpp
+++ b/ndb/src/old_files/client/odbc/common/Sqlstate.cpp
diff --git a/ndb/src/client/odbc/common/Sqlstate.hpp b/ndb/src/old_files/client/odbc/common/Sqlstate.hpp
index 3b4665dc6ca..3b4665dc6ca 100644
--- a/ndb/src/client/odbc/common/Sqlstate.hpp
+++ b/ndb/src/old_files/client/odbc/common/Sqlstate.hpp
diff --git a/ndb/src/client/odbc/common/StmtArea.cpp b/ndb/src/old_files/client/odbc/common/StmtArea.cpp
index 5ce2d47d31a..5ce2d47d31a 100644
--- a/ndb/src/client/odbc/common/StmtArea.cpp
+++ b/ndb/src/old_files/client/odbc/common/StmtArea.cpp
diff --git a/ndb/src/client/odbc/common/StmtArea.hpp b/ndb/src/old_files/client/odbc/common/StmtArea.hpp
index a88c6d36e6d..a88c6d36e6d 100644
--- a/ndb/src/client/odbc/common/StmtArea.hpp
+++ b/ndb/src/old_files/client/odbc/common/StmtArea.hpp
diff --git a/ndb/src/client/odbc/common/StmtInfo.cpp b/ndb/src/old_files/client/odbc/common/StmtInfo.cpp
index 3467fb5023e..3467fb5023e 100644
--- a/ndb/src/client/odbc/common/StmtInfo.cpp
+++ b/ndb/src/old_files/client/odbc/common/StmtInfo.cpp
diff --git a/ndb/src/client/odbc/common/StmtInfo.hpp b/ndb/src/old_files/client/odbc/common/StmtInfo.hpp
index 9cd489be6da..9cd489be6da 100644
--- a/ndb/src/client/odbc/common/StmtInfo.hpp
+++ b/ndb/src/old_files/client/odbc/common/StmtInfo.hpp
diff --git a/ndb/src/client/odbc/common/common.cpp b/ndb/src/old_files/client/odbc/common/common.cpp
index 73d14c82efe..73d14c82efe 100644
--- a/ndb/src/client/odbc/common/common.cpp
+++ b/ndb/src/old_files/client/odbc/common/common.cpp
diff --git a/ndb/src/old_files/client/odbc/common/common.hpp b/ndb/src/old_files/client/odbc/common/common.hpp
new file mode 100644
index 00000000000..d2f243b6437
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/common/common.hpp
@@ -0,0 +1,124 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_COMMON_common_hpp
+#define ODBC_COMMON_common_hpp
+
+#define stpcpy stpcpy
+#include <ndb_global.h>
+#undef swap
+
+// misc defs
+
+#ifdef NDB_GCC // only for odbc
+#define PRINTFLIKE(i,j) __attribute__ ((format (printf, i, j)))
+#else
+#define PRINTFLIKE(i,j)
+#endif
+
+// odbc defs
+
+#define ODBCVER 0x0351
+
+#ifdef NDB_WIN32
+#include <windows.h>
+#endif
+
+extern "C" {
+#include <sqlext.h>
+}
+// some types which may be missing
+#ifndef SQL_BLOB
+#define SQL_BLOB 30
+#endif
+#ifndef SQL_BLOB_LOCATOR
+#define SQL_BLOB_LOCATOR 31
+#endif
+#ifndef SQL_CLOB
+#define SQL_CLOB 40
+#endif
+#ifndef SQL_CLOB_LOCATOR
+#define SQL_CLOB_LOCATOR 41
+#endif
+
+// until real blobs use Varchar of this size
+#define FAKE_BLOB_SIZE 2000
+
+#define SQL_HANDLE_ROOT 0 // assume real handles != 0
+
+enum OdbcHandle {
+ Odbc_handle_root = 0, // not an odbc handle
+ Odbc_handle_env = 1,
+ Odbc_handle_dbc = 2,
+ Odbc_handle_stmt = 4,
+ Odbc_handle_desc = 8,
+ Odbc_handle_all = (1|2|4|8)
+};
+
+// ndb defs
+
+#undef BOOL
+#include <ndb_types.h>
+// this info not yet on api side
+#include <kernel/ndb_limits.h>
+#include <ndb_version.h>
+
+#ifndef MAX_TAB_NAME_SIZE
+#define MAX_TAB_NAME_SIZE 128
+#endif
+
+#ifndef MAX_ATTR_NAME_SIZE
+#define MAX_ATTR_NAME_SIZE 32
+#endif
+
+#ifndef MAX_ATTR_DEFAULT_VALUE_SIZE
+#define MAX_ATTR_DEFAULT_VALUE_SIZE 128
+#endif
+
+typedef Uint32 NdbAttrId;
+typedef Uint64 CountType;
+
+// ndb odbc defs
+
+#define NDB_ODBC_COMPONENT_VENDOR "[MySQL]"
+#define NDB_ODBC_COMPONENT_DRIVER "[ODBC driver]"
+#define NDB_ODBC_COMPONENT_DATABASE "[NDB Cluster]"
+
+#define NDB_ODBC_VERSION_MAJOR 0
+#define NDB_ODBC_VERSION_MINOR 22
+#define NDB_ODBC_VERSION_STRING "0.22"
+
+// reserved error codes for non-NDB errors
+#define NDB_ODBC_ERROR_MIN 5000
+#define NDB_ODBC_ERROR_MAX 5100
+
+// maximum log level compiled in
+#ifdef VM_TRACE
+#define NDB_ODBC_MAX_LOG_LEVEL 5
+#else
+#define NDB_ODBC_MAX_LOG_LEVEL 3
+#endif
+
+// driver specific statement attribute for number of NDB tuples fetched
+#define SQL_ATTR_NDB_TUPLES_FETCHED 66601
+
+#include <BaseString.hpp>
+#include <common/Sqlstate.hpp>
+#include <common/Ctx.hpp>
+
+#undef assert
+
+#endif
diff --git a/ndb/src/client/odbc/dictionary/DictCatalog.cpp b/ndb/src/old_files/client/odbc/dictionary/DictCatalog.cpp
index 433347c9a70..433347c9a70 100644
--- a/ndb/src/client/odbc/dictionary/DictCatalog.cpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictCatalog.cpp
diff --git a/ndb/src/client/odbc/dictionary/DictCatalog.hpp b/ndb/src/old_files/client/odbc/dictionary/DictCatalog.hpp
index 5452990a51b..5452990a51b 100644
--- a/ndb/src/client/odbc/dictionary/DictCatalog.hpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictCatalog.hpp
diff --git a/ndb/src/client/odbc/dictionary/DictColumn.cpp b/ndb/src/old_files/client/odbc/dictionary/DictColumn.cpp
index fa0128f1ddb..fa0128f1ddb 100644
--- a/ndb/src/client/odbc/dictionary/DictColumn.cpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictColumn.cpp
diff --git a/ndb/src/client/odbc/dictionary/DictColumn.hpp b/ndb/src/old_files/client/odbc/dictionary/DictColumn.hpp
index 945fb86367b..945fb86367b 100644
--- a/ndb/src/client/odbc/dictionary/DictColumn.hpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictColumn.hpp
diff --git a/ndb/src/client/odbc/dictionary/DictIndex.cpp b/ndb/src/old_files/client/odbc/dictionary/DictIndex.cpp
index 95d93318902..95d93318902 100644
--- a/ndb/src/client/odbc/dictionary/DictIndex.cpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictIndex.cpp
diff --git a/ndb/src/client/odbc/dictionary/DictIndex.hpp b/ndb/src/old_files/client/odbc/dictionary/DictIndex.hpp
index 7ba46daaae3..7ba46daaae3 100644
--- a/ndb/src/client/odbc/dictionary/DictIndex.hpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictIndex.hpp
diff --git a/ndb/src/client/odbc/dictionary/DictSchema.cpp b/ndb/src/old_files/client/odbc/dictionary/DictSchema.cpp
index 91939cb2f26..91939cb2f26 100644
--- a/ndb/src/client/odbc/dictionary/DictSchema.cpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictSchema.cpp
diff --git a/ndb/src/client/odbc/dictionary/DictSchema.hpp b/ndb/src/old_files/client/odbc/dictionary/DictSchema.hpp
index 099352edbb9..099352edbb9 100644
--- a/ndb/src/client/odbc/dictionary/DictSchema.hpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictSchema.hpp
diff --git a/ndb/src/client/odbc/dictionary/DictSys.cpp b/ndb/src/old_files/client/odbc/dictionary/DictSys.cpp
index 1ceef66ee57..1ceef66ee57 100644
--- a/ndb/src/client/odbc/dictionary/DictSys.cpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictSys.cpp
diff --git a/ndb/src/client/odbc/dictionary/DictSys.hpp b/ndb/src/old_files/client/odbc/dictionary/DictSys.hpp
index e6fa661fd59..e6fa661fd59 100644
--- a/ndb/src/client/odbc/dictionary/DictSys.hpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictSys.hpp
diff --git a/ndb/src/client/odbc/dictionary/DictTable.cpp b/ndb/src/old_files/client/odbc/dictionary/DictTable.cpp
index 4db7d3b3aec..4db7d3b3aec 100644
--- a/ndb/src/client/odbc/dictionary/DictTable.cpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictTable.cpp
diff --git a/ndb/src/client/odbc/dictionary/DictTable.hpp b/ndb/src/old_files/client/odbc/dictionary/DictTable.hpp
index 5cecfff9562..5cecfff9562 100644
--- a/ndb/src/client/odbc/dictionary/DictTable.hpp
+++ b/ndb/src/old_files/client/odbc/dictionary/DictTable.hpp
diff --git a/ndb/src/client/odbc/dictionary/Makefile b/ndb/src/old_files/client/odbc/dictionary/Makefile
index cdfd3b6ea0c..cdfd3b6ea0c 100644
--- a/ndb/src/client/odbc/dictionary/Makefile
+++ b/ndb/src/old_files/client/odbc/dictionary/Makefile
diff --git a/ndb/src/client/odbc/docs/class.fig b/ndb/src/old_files/client/odbc/docs/class.fig
index 38c24c1fba4..38c24c1fba4 100644
--- a/ndb/src/client/odbc/docs/class.fig
+++ b/ndb/src/old_files/client/odbc/docs/class.fig
diff --git a/ndb/src/client/odbc/docs/descfield.pl b/ndb/src/old_files/client/odbc/docs/descfield.pl
index 80fef22f303..80fef22f303 100644
--- a/ndb/src/client/odbc/docs/descfield.pl
+++ b/ndb/src/old_files/client/odbc/docs/descfield.pl
diff --git a/ndb/src/client/odbc/docs/diag.txt b/ndb/src/old_files/client/odbc/docs/diag.txt
index a9a0e0f42d0..a9a0e0f42d0 100644
--- a/ndb/src/client/odbc/docs/diag.txt
+++ b/ndb/src/old_files/client/odbc/docs/diag.txt
diff --git a/ndb/src/client/odbc/docs/getinfo.pl b/ndb/src/old_files/client/odbc/docs/getinfo.pl
index 34e26b47bab..34e26b47bab 100644
--- a/ndb/src/client/odbc/docs/getinfo.pl
+++ b/ndb/src/old_files/client/odbc/docs/getinfo.pl
diff --git a/ndb/src/client/odbc/docs/gettypeinfo.pl b/ndb/src/old_files/client/odbc/docs/gettypeinfo.pl
index 0a999fd7249..0a999fd7249 100644
--- a/ndb/src/client/odbc/docs/gettypeinfo.pl
+++ b/ndb/src/old_files/client/odbc/docs/gettypeinfo.pl
diff --git a/ndb/src/client/odbc/docs/handleattr.pl b/ndb/src/old_files/client/odbc/docs/handleattr.pl
index 892d34b105b..892d34b105b 100644
--- a/ndb/src/client/odbc/docs/handleattr.pl
+++ b/ndb/src/old_files/client/odbc/docs/handleattr.pl
diff --git a/ndb/src/client/odbc/docs/main.hpp b/ndb/src/old_files/client/odbc/docs/main.hpp
index ebb5b1f235a..ebb5b1f235a 100644
--- a/ndb/src/client/odbc/docs/main.hpp
+++ b/ndb/src/old_files/client/odbc/docs/main.hpp
diff --git a/ndb/src/client/odbc/docs/ndbodbc.html b/ndb/src/old_files/client/odbc/docs/ndbodbc.html
index 6be624dfa1b..6be624dfa1b 100644
--- a/ndb/src/client/odbc/docs/ndbodbc.html
+++ b/ndb/src/old_files/client/odbc/docs/ndbodbc.html
diff --git a/ndb/src/client/odbc/docs/select.fig b/ndb/src/old_files/client/odbc/docs/select.fig
index 4f51a2085b4..4f51a2085b4 100644
--- a/ndb/src/client/odbc/docs/select.fig
+++ b/ndb/src/old_files/client/odbc/docs/select.fig
diff --git a/ndb/src/client/odbc/docs/systables.pl b/ndb/src/old_files/client/odbc/docs/systables.pl
index 728d966a7a4..728d966a7a4 100644
--- a/ndb/src/client/odbc/docs/systables.pl
+++ b/ndb/src/old_files/client/odbc/docs/systables.pl
diff --git a/ndb/src/client/odbc/docs/type.txt b/ndb/src/old_files/client/odbc/docs/type.txt
index d7b391afc55..d7b391afc55 100644
--- a/ndb/src/client/odbc/docs/type.txt
+++ b/ndb/src/old_files/client/odbc/docs/type.txt
diff --git a/ndb/src/client/odbc/driver/Func.data b/ndb/src/old_files/client/odbc/driver/Func.data
index c32671e1135..c32671e1135 100644
--- a/ndb/src/client/odbc/driver/Func.data
+++ b/ndb/src/old_files/client/odbc/driver/Func.data
diff --git a/ndb/src/client/odbc/driver/Func.pl b/ndb/src/old_files/client/odbc/driver/Func.pl
index 1064a6a6c6e..1064a6a6c6e 100644
--- a/ndb/src/client/odbc/driver/Func.pl
+++ b/ndb/src/old_files/client/odbc/driver/Func.pl
diff --git a/ndb/src/client/odbc/driver/Makefile b/ndb/src/old_files/client/odbc/driver/Makefile
index 62f82371da4..62f82371da4 100644
--- a/ndb/src/client/odbc/driver/Makefile
+++ b/ndb/src/old_files/client/odbc/driver/Makefile
diff --git a/ndb/src/client/odbc/driver/SQLAllocConnect.cpp b/ndb/src/old_files/client/odbc/driver/SQLAllocConnect.cpp
index a7ffd8c89d1..a7ffd8c89d1 100644
--- a/ndb/src/client/odbc/driver/SQLAllocConnect.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLAllocConnect.cpp
diff --git a/ndb/src/client/odbc/driver/SQLAllocEnv.cpp b/ndb/src/old_files/client/odbc/driver/SQLAllocEnv.cpp
index a62dae61008..a62dae61008 100644
--- a/ndb/src/client/odbc/driver/SQLAllocEnv.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLAllocEnv.cpp
diff --git a/ndb/src/client/odbc/driver/SQLAllocHandle.cpp b/ndb/src/old_files/client/odbc/driver/SQLAllocHandle.cpp
index 9daf6ead946..9daf6ead946 100644
--- a/ndb/src/client/odbc/driver/SQLAllocHandle.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLAllocHandle.cpp
diff --git a/ndb/src/client/odbc/driver/SQLAllocHandleStd.cpp b/ndb/src/old_files/client/odbc/driver/SQLAllocHandleStd.cpp
index 61290e37b7b..61290e37b7b 100644
--- a/ndb/src/client/odbc/driver/SQLAllocHandleStd.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLAllocHandleStd.cpp
diff --git a/ndb/src/client/odbc/driver/SQLAllocStmt.cpp b/ndb/src/old_files/client/odbc/driver/SQLAllocStmt.cpp
index bf3f149f5de..bf3f149f5de 100644
--- a/ndb/src/client/odbc/driver/SQLAllocStmt.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLAllocStmt.cpp
diff --git a/ndb/src/client/odbc/driver/SQLBindCol.cpp b/ndb/src/old_files/client/odbc/driver/SQLBindCol.cpp
index 5562334e8cc..5562334e8cc 100644
--- a/ndb/src/client/odbc/driver/SQLBindCol.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLBindCol.cpp
diff --git a/ndb/src/client/odbc/driver/SQLBindParam.cpp b/ndb/src/old_files/client/odbc/driver/SQLBindParam.cpp
index 2fcc17b872f..2fcc17b872f 100644
--- a/ndb/src/client/odbc/driver/SQLBindParam.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLBindParam.cpp
diff --git a/ndb/src/client/odbc/driver/SQLBindParameter.cpp b/ndb/src/old_files/client/odbc/driver/SQLBindParameter.cpp
index e4ca5bbc731..e4ca5bbc731 100644
--- a/ndb/src/client/odbc/driver/SQLBindParameter.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLBindParameter.cpp
diff --git a/ndb/src/client/odbc/driver/SQLBrowseConnect.cpp b/ndb/src/old_files/client/odbc/driver/SQLBrowseConnect.cpp
index 7e629e199e5..7e629e199e5 100644
--- a/ndb/src/client/odbc/driver/SQLBrowseConnect.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLBrowseConnect.cpp
diff --git a/ndb/src/client/odbc/driver/SQLBulkOperations.cpp b/ndb/src/old_files/client/odbc/driver/SQLBulkOperations.cpp
index 7d256d66e3f..7d256d66e3f 100644
--- a/ndb/src/client/odbc/driver/SQLBulkOperations.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLBulkOperations.cpp
diff --git a/ndb/src/client/odbc/driver/SQLCancel.cpp b/ndb/src/old_files/client/odbc/driver/SQLCancel.cpp
index ac4e43c6e89..ac4e43c6e89 100644
--- a/ndb/src/client/odbc/driver/SQLCancel.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLCancel.cpp
diff --git a/ndb/src/client/odbc/driver/SQLCloseCursor.cpp b/ndb/src/old_files/client/odbc/driver/SQLCloseCursor.cpp
index 26d88c91e3b..26d88c91e3b 100644
--- a/ndb/src/client/odbc/driver/SQLCloseCursor.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLCloseCursor.cpp
diff --git a/ndb/src/client/odbc/driver/SQLColAttribute.cpp b/ndb/src/old_files/client/odbc/driver/SQLColAttribute.cpp
index 0e7e5446932..0e7e5446932 100644
--- a/ndb/src/client/odbc/driver/SQLColAttribute.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLColAttribute.cpp
diff --git a/ndb/src/client/odbc/driver/SQLColAttributes.cpp b/ndb/src/old_files/client/odbc/driver/SQLColAttributes.cpp
index 05a4c1d4d37..05a4c1d4d37 100644
--- a/ndb/src/client/odbc/driver/SQLColAttributes.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLColAttributes.cpp
diff --git a/ndb/src/client/odbc/driver/SQLColumnPrivileges.cpp b/ndb/src/old_files/client/odbc/driver/SQLColumnPrivileges.cpp
index cfbc9c2bc57..cfbc9c2bc57 100644
--- a/ndb/src/client/odbc/driver/SQLColumnPrivileges.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLColumnPrivileges.cpp
diff --git a/ndb/src/client/odbc/driver/SQLColumns.cpp b/ndb/src/old_files/client/odbc/driver/SQLColumns.cpp
index 4e0b646ee7d..4e0b646ee7d 100644
--- a/ndb/src/client/odbc/driver/SQLColumns.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLColumns.cpp
diff --git a/ndb/src/client/odbc/driver/SQLConnect.cpp b/ndb/src/old_files/client/odbc/driver/SQLConnect.cpp
index d8f30ed47e7..d8f30ed47e7 100644
--- a/ndb/src/client/odbc/driver/SQLConnect.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLConnect.cpp
diff --git a/ndb/src/client/odbc/driver/SQLCopyDesc.cpp b/ndb/src/old_files/client/odbc/driver/SQLCopyDesc.cpp
index b4d4b2e4122..b4d4b2e4122 100644
--- a/ndb/src/client/odbc/driver/SQLCopyDesc.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLCopyDesc.cpp
diff --git a/ndb/src/client/odbc/driver/SQLDataSources.cpp b/ndb/src/old_files/client/odbc/driver/SQLDataSources.cpp
index 6115e7175f9..6115e7175f9 100644
--- a/ndb/src/client/odbc/driver/SQLDataSources.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLDataSources.cpp
diff --git a/ndb/src/client/odbc/driver/SQLDescribeCol.cpp b/ndb/src/old_files/client/odbc/driver/SQLDescribeCol.cpp
index f15ce8962f1..f15ce8962f1 100644
--- a/ndb/src/client/odbc/driver/SQLDescribeCol.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLDescribeCol.cpp
diff --git a/ndb/src/client/odbc/driver/SQLDescribeParam.cpp b/ndb/src/old_files/client/odbc/driver/SQLDescribeParam.cpp
index beff41396fe..beff41396fe 100644
--- a/ndb/src/client/odbc/driver/SQLDescribeParam.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLDescribeParam.cpp
diff --git a/ndb/src/client/odbc/driver/SQLDisconnect.cpp b/ndb/src/old_files/client/odbc/driver/SQLDisconnect.cpp
index 75db5604da8..75db5604da8 100644
--- a/ndb/src/client/odbc/driver/SQLDisconnect.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLDisconnect.cpp
diff --git a/ndb/src/client/odbc/driver/SQLDriverConnect.cpp b/ndb/src/old_files/client/odbc/driver/SQLDriverConnect.cpp
index 340babd8523..340babd8523 100644
--- a/ndb/src/client/odbc/driver/SQLDriverConnect.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLDriverConnect.cpp
diff --git a/ndb/src/client/odbc/driver/SQLDrivers.cpp b/ndb/src/old_files/client/odbc/driver/SQLDrivers.cpp
index 9c52f900992..9c52f900992 100644
--- a/ndb/src/client/odbc/driver/SQLDrivers.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLDrivers.cpp
diff --git a/ndb/src/client/odbc/driver/SQLEndTran.cpp b/ndb/src/old_files/client/odbc/driver/SQLEndTran.cpp
index 20b0b2203f5..20b0b2203f5 100644
--- a/ndb/src/client/odbc/driver/SQLEndTran.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLEndTran.cpp
diff --git a/ndb/src/client/odbc/driver/SQLError.cpp b/ndb/src/old_files/client/odbc/driver/SQLError.cpp
index af78c931d37..af78c931d37 100644
--- a/ndb/src/client/odbc/driver/SQLError.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLError.cpp
diff --git a/ndb/src/client/odbc/driver/SQLExecDirect.cpp b/ndb/src/old_files/client/odbc/driver/SQLExecDirect.cpp
index 0ad99d29cd9..0ad99d29cd9 100644
--- a/ndb/src/client/odbc/driver/SQLExecDirect.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLExecDirect.cpp
diff --git a/ndb/src/client/odbc/driver/SQLExecute.cpp b/ndb/src/old_files/client/odbc/driver/SQLExecute.cpp
index 9c30d418f09..9c30d418f09 100644
--- a/ndb/src/client/odbc/driver/SQLExecute.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLExecute.cpp
diff --git a/ndb/src/client/odbc/driver/SQLExtendedFetch.cpp b/ndb/src/old_files/client/odbc/driver/SQLExtendedFetch.cpp
index e0dd078b5d0..e0dd078b5d0 100644
--- a/ndb/src/client/odbc/driver/SQLExtendedFetch.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLExtendedFetch.cpp
diff --git a/ndb/src/client/odbc/driver/SQLFetch.cpp b/ndb/src/old_files/client/odbc/driver/SQLFetch.cpp
index addba7b998c..addba7b998c 100644
--- a/ndb/src/client/odbc/driver/SQLFetch.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLFetch.cpp
diff --git a/ndb/src/client/odbc/driver/SQLFetchScroll.cpp b/ndb/src/old_files/client/odbc/driver/SQLFetchScroll.cpp
index cfbfc813fca..cfbfc813fca 100644
--- a/ndb/src/client/odbc/driver/SQLFetchScroll.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLFetchScroll.cpp
diff --git a/ndb/src/client/odbc/driver/SQLForeignKeys.cpp b/ndb/src/old_files/client/odbc/driver/SQLForeignKeys.cpp
index 886ac6bdaa5..886ac6bdaa5 100644
--- a/ndb/src/client/odbc/driver/SQLForeignKeys.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLForeignKeys.cpp
diff --git a/ndb/src/client/odbc/driver/SQLFreeConnect.cpp b/ndb/src/old_files/client/odbc/driver/SQLFreeConnect.cpp
index 9ac84710cce..9ac84710cce 100644
--- a/ndb/src/client/odbc/driver/SQLFreeConnect.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLFreeConnect.cpp
diff --git a/ndb/src/client/odbc/driver/SQLFreeEnv.cpp b/ndb/src/old_files/client/odbc/driver/SQLFreeEnv.cpp
index 7e35056feb5..7e35056feb5 100644
--- a/ndb/src/client/odbc/driver/SQLFreeEnv.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLFreeEnv.cpp
diff --git a/ndb/src/client/odbc/driver/SQLFreeHandle.cpp b/ndb/src/old_files/client/odbc/driver/SQLFreeHandle.cpp
index 284463cbb07..284463cbb07 100644
--- a/ndb/src/client/odbc/driver/SQLFreeHandle.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLFreeHandle.cpp
diff --git a/ndb/src/client/odbc/driver/SQLFreeStmt.cpp b/ndb/src/old_files/client/odbc/driver/SQLFreeStmt.cpp
index 7af6623a37a..7af6623a37a 100644
--- a/ndb/src/client/odbc/driver/SQLFreeStmt.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLFreeStmt.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetConnectAttr.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetConnectAttr.cpp
index 66c1f3827e1..66c1f3827e1 100644
--- a/ndb/src/client/odbc/driver/SQLGetConnectAttr.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetConnectAttr.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetConnectOption.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetConnectOption.cpp
index 514bedb12b9..514bedb12b9 100644
--- a/ndb/src/client/odbc/driver/SQLGetConnectOption.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetConnectOption.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetCursorName.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetCursorName.cpp
index d54bdf42005..d54bdf42005 100644
--- a/ndb/src/client/odbc/driver/SQLGetCursorName.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetCursorName.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetData.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetData.cpp
index 3b6987c515d..3b6987c515d 100644
--- a/ndb/src/client/odbc/driver/SQLGetData.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetData.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetDescField.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetDescField.cpp
index 6cc390a58ed..6cc390a58ed 100644
--- a/ndb/src/client/odbc/driver/SQLGetDescField.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetDescField.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetDescRec.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetDescRec.cpp
index c7e9631b075..c7e9631b075 100644
--- a/ndb/src/client/odbc/driver/SQLGetDescRec.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetDescRec.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetDiagField.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetDiagField.cpp
index 3eb34f7ebf6..3eb34f7ebf6 100644
--- a/ndb/src/client/odbc/driver/SQLGetDiagField.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetDiagField.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetDiagRec.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetDiagRec.cpp
index 448c5206d76..448c5206d76 100644
--- a/ndb/src/client/odbc/driver/SQLGetDiagRec.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetDiagRec.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetEnvAttr.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetEnvAttr.cpp
index c93870326e4..c93870326e4 100644
--- a/ndb/src/client/odbc/driver/SQLGetEnvAttr.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetEnvAttr.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetFunctions.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetFunctions.cpp
index 68416fab1a6..68416fab1a6 100644
--- a/ndb/src/client/odbc/driver/SQLGetFunctions.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetFunctions.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetInfo.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetInfo.cpp
index 8f0a0d67cfa..8f0a0d67cfa 100644
--- a/ndb/src/client/odbc/driver/SQLGetInfo.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetInfo.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetStmtAttr.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetStmtAttr.cpp
index 990ab68808a..990ab68808a 100644
--- a/ndb/src/client/odbc/driver/SQLGetStmtAttr.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetStmtAttr.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetStmtOption.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetStmtOption.cpp
index 0b5758b1212..0b5758b1212 100644
--- a/ndb/src/client/odbc/driver/SQLGetStmtOption.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetStmtOption.cpp
diff --git a/ndb/src/client/odbc/driver/SQLGetTypeInfo.cpp b/ndb/src/old_files/client/odbc/driver/SQLGetTypeInfo.cpp
index e6a016cc400..e6a016cc400 100644
--- a/ndb/src/client/odbc/driver/SQLGetTypeInfo.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLGetTypeInfo.cpp
diff --git a/ndb/src/client/odbc/driver/SQLMoreResults.cpp b/ndb/src/old_files/client/odbc/driver/SQLMoreResults.cpp
index d23d653a319..d23d653a319 100644
--- a/ndb/src/client/odbc/driver/SQLMoreResults.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLMoreResults.cpp
diff --git a/ndb/src/client/odbc/driver/SQLNativeSql.cpp b/ndb/src/old_files/client/odbc/driver/SQLNativeSql.cpp
index fb8a9bbf3d9..fb8a9bbf3d9 100644
--- a/ndb/src/client/odbc/driver/SQLNativeSql.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLNativeSql.cpp
diff --git a/ndb/src/client/odbc/driver/SQLNumParams.cpp b/ndb/src/old_files/client/odbc/driver/SQLNumParams.cpp
index 7b1a6a07aec..7b1a6a07aec 100644
--- a/ndb/src/client/odbc/driver/SQLNumParams.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLNumParams.cpp
diff --git a/ndb/src/client/odbc/driver/SQLNumResultCols.cpp b/ndb/src/old_files/client/odbc/driver/SQLNumResultCols.cpp
index 2e70897a9a2..2e70897a9a2 100644
--- a/ndb/src/client/odbc/driver/SQLNumResultCols.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLNumResultCols.cpp
diff --git a/ndb/src/client/odbc/driver/SQLParamData.cpp b/ndb/src/old_files/client/odbc/driver/SQLParamData.cpp
index 4eb38a010f4..4eb38a010f4 100644
--- a/ndb/src/client/odbc/driver/SQLParamData.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLParamData.cpp
diff --git a/ndb/src/client/odbc/driver/SQLParamOptions.cpp b/ndb/src/old_files/client/odbc/driver/SQLParamOptions.cpp
index 59b7dcf7fa9..59b7dcf7fa9 100644
--- a/ndb/src/client/odbc/driver/SQLParamOptions.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLParamOptions.cpp
diff --git a/ndb/src/client/odbc/driver/SQLPrepare.cpp b/ndb/src/old_files/client/odbc/driver/SQLPrepare.cpp
index b1205fa6e3a..b1205fa6e3a 100644
--- a/ndb/src/client/odbc/driver/SQLPrepare.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLPrepare.cpp
diff --git a/ndb/src/client/odbc/driver/SQLPrimaryKeys.cpp b/ndb/src/old_files/client/odbc/driver/SQLPrimaryKeys.cpp
index 2d562ae3e19..2d562ae3e19 100644
--- a/ndb/src/client/odbc/driver/SQLPrimaryKeys.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLPrimaryKeys.cpp
diff --git a/ndb/src/client/odbc/driver/SQLProcedureColumns.cpp b/ndb/src/old_files/client/odbc/driver/SQLProcedureColumns.cpp
index 2e42e428b87..2e42e428b87 100644
--- a/ndb/src/client/odbc/driver/SQLProcedureColumns.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLProcedureColumns.cpp
diff --git a/ndb/src/client/odbc/driver/SQLProcedures.cpp b/ndb/src/old_files/client/odbc/driver/SQLProcedures.cpp
index 1f3a9f89073..1f3a9f89073 100644
--- a/ndb/src/client/odbc/driver/SQLProcedures.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLProcedures.cpp
diff --git a/ndb/src/client/odbc/driver/SQLPutData.cpp b/ndb/src/old_files/client/odbc/driver/SQLPutData.cpp
index a4715a836d2..a4715a836d2 100644
--- a/ndb/src/client/odbc/driver/SQLPutData.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLPutData.cpp
diff --git a/ndb/src/client/odbc/driver/SQLRowCount.cpp b/ndb/src/old_files/client/odbc/driver/SQLRowCount.cpp
index d03f954386a..d03f954386a 100644
--- a/ndb/src/client/odbc/driver/SQLRowCount.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLRowCount.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetConnectAttr.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetConnectAttr.cpp
index 05bfce5e9cd..05bfce5e9cd 100644
--- a/ndb/src/client/odbc/driver/SQLSetConnectAttr.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetConnectAttr.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetConnectOption.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetConnectOption.cpp
index a4794316971..a4794316971 100644
--- a/ndb/src/client/odbc/driver/SQLSetConnectOption.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetConnectOption.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetCursorName.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetCursorName.cpp
index 291ad817d42..291ad817d42 100644
--- a/ndb/src/client/odbc/driver/SQLSetCursorName.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetCursorName.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetDescField.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetDescField.cpp
index 19d34c2f46d..19d34c2f46d 100644
--- a/ndb/src/client/odbc/driver/SQLSetDescField.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetDescField.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetDescRec.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetDescRec.cpp
index 80a00514a51..80a00514a51 100644
--- a/ndb/src/client/odbc/driver/SQLSetDescRec.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetDescRec.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetEnvAttr.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetEnvAttr.cpp
index 86364eac5e8..86364eac5e8 100644
--- a/ndb/src/client/odbc/driver/SQLSetEnvAttr.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetEnvAttr.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetParam.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetParam.cpp
index 03bde1076d8..03bde1076d8 100644
--- a/ndb/src/client/odbc/driver/SQLSetParam.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetParam.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetPos.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetPos.cpp
index 653030f90bc..653030f90bc 100644
--- a/ndb/src/client/odbc/driver/SQLSetPos.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetPos.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetScrollOptions.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetScrollOptions.cpp
index a5e89d8568b..a5e89d8568b 100644
--- a/ndb/src/client/odbc/driver/SQLSetScrollOptions.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetScrollOptions.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetStmtAttr.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetStmtAttr.cpp
index 9ed6a83b563..9ed6a83b563 100644
--- a/ndb/src/client/odbc/driver/SQLSetStmtAttr.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetStmtAttr.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSetStmtOption.cpp b/ndb/src/old_files/client/odbc/driver/SQLSetStmtOption.cpp
index b403fc8408c..b403fc8408c 100644
--- a/ndb/src/client/odbc/driver/SQLSetStmtOption.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSetStmtOption.cpp
diff --git a/ndb/src/client/odbc/driver/SQLSpecialColumns.cpp b/ndb/src/old_files/client/odbc/driver/SQLSpecialColumns.cpp
index 5dd92c86053..5dd92c86053 100644
--- a/ndb/src/client/odbc/driver/SQLSpecialColumns.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLSpecialColumns.cpp
diff --git a/ndb/src/client/odbc/driver/SQLStatistics.cpp b/ndb/src/old_files/client/odbc/driver/SQLStatistics.cpp
index 941fb6249a5..941fb6249a5 100644
--- a/ndb/src/client/odbc/driver/SQLStatistics.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLStatistics.cpp
diff --git a/ndb/src/client/odbc/driver/SQLTablePrivileges.cpp b/ndb/src/old_files/client/odbc/driver/SQLTablePrivileges.cpp
index 23c6ad9fc4b..23c6ad9fc4b 100644
--- a/ndb/src/client/odbc/driver/SQLTablePrivileges.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLTablePrivileges.cpp
diff --git a/ndb/src/client/odbc/driver/SQLTables.cpp b/ndb/src/old_files/client/odbc/driver/SQLTables.cpp
index b2496bfba87..b2496bfba87 100644
--- a/ndb/src/client/odbc/driver/SQLTables.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLTables.cpp
diff --git a/ndb/src/client/odbc/driver/SQLTransact.cpp b/ndb/src/old_files/client/odbc/driver/SQLTransact.cpp
index da8b46b1596..da8b46b1596 100644
--- a/ndb/src/client/odbc/driver/SQLTransact.cpp
+++ b/ndb/src/old_files/client/odbc/driver/SQLTransact.cpp
diff --git a/ndb/src/old_files/client/odbc/driver/driver.cpp b/ndb/src/old_files/client/odbc/driver/driver.cpp
new file mode 100644
index 00000000000..f992fa70878
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/driver/driver.cpp
@@ -0,0 +1,150 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "driver.hpp"
+#include <NdbMutex.h>
+
+#undef NDB_ODBC_SIG_DFL
+#ifdef NDB_ODBC_SIG_DFL
+#include <signal.h>
+#endif
+
+// The big mutex (just in case).
+
+#ifdef NDB_WIN32
+static NdbMutex & driver_mutex = * NdbMutex_Create();
+#else
+static NdbMutex driver_mutex = NDB_MUTEX_INITIALIZER;
+#endif
+
+static void
+driver_lock()
+{
+ NdbMutex_Lock(&driver_mutex);
+}
+
+static void
+driver_unlock()
+{
+ NdbMutex_Unlock(&driver_mutex);
+}
+
+// Hooks for function entry and exit.
+
+static inline void
+driver_enter(SQLUSMALLINT functionId)
+{
+ switch (functionId) {
+ default:
+ break;
+ }
+#ifdef NDB_ODBC_SIG_DFL
+ // XXX need to restore old sig
+ for (int i = 1; i <= 30; i++)
+ signal(i, SIG_DFL);
+#endif
+}
+
+static inline void
+driver_exit(SQLUSMALLINT functionId)
+{
+ switch (functionId) {
+ default:
+ break;
+ }
+}
+
+// Some C++ compilers (like gcc) cannot merge template code
+// in different files. So compile all in one file.
+
+#include "SQLAllocConnect.cpp"
+#include "SQLAllocEnv.cpp"
+#include "SQLAllocHandle.cpp"
+#include "SQLAllocHandleStd.cpp"
+#include "SQLAllocStmt.cpp"
+#include "SQLBindCol.cpp"
+#include "SQLBindParam.cpp"
+#include "SQLBindParameter.cpp"
+#include "SQLBrowseConnect.cpp"
+#include "SQLBulkOperations.cpp"
+#include "SQLCancel.cpp"
+#include "SQLCloseCursor.cpp"
+#include "SQLColAttribute.cpp"
+#include "SQLColAttributes.cpp"
+#include "SQLColumnPrivileges.cpp"
+#include "SQLColumns.cpp"
+#include "SQLConnect.cpp"
+#include "SQLCopyDesc.cpp"
+#include "SQLDataSources.cpp"
+#include "SQLDescribeCol.cpp"
+#include "SQLDescribeParam.cpp"
+#include "SQLDisconnect.cpp"
+#include "SQLDriverConnect.cpp"
+#include "SQLDrivers.cpp"
+#include "SQLEndTran.cpp"
+#include "SQLError.cpp"
+#include "SQLExecDirect.cpp"
+#include "SQLExecute.cpp"
+#include "SQLExtendedFetch.cpp"
+#include "SQLFetch.cpp"
+#include "SQLFetchScroll.cpp"
+#include "SQLForeignKeys.cpp"
+#include "SQLFreeConnect.cpp"
+#include "SQLFreeEnv.cpp"
+#include "SQLFreeHandle.cpp"
+#include "SQLFreeStmt.cpp"
+#include "SQLGetConnectAttr.cpp"
+#include "SQLGetConnectOption.cpp"
+#include "SQLGetCursorName.cpp"
+#include "SQLGetData.cpp"
+#include "SQLGetDescField.cpp"
+#include "SQLGetDescRec.cpp"
+#include "SQLGetDiagField.cpp"
+#include "SQLGetDiagRec.cpp"
+#include "SQLGetEnvAttr.cpp"
+#include "SQLGetFunctions.cpp"
+#include "SQLGetInfo.cpp"
+#include "SQLGetStmtAttr.cpp"
+#include "SQLGetStmtOption.cpp"
+#include "SQLGetTypeInfo.cpp"
+#include "SQLMoreResults.cpp"
+#include "SQLNativeSql.cpp"
+#include "SQLNumParams.cpp"
+#include "SQLNumResultCols.cpp"
+#include "SQLParamData.cpp"
+#include "SQLParamOptions.cpp"
+#include "SQLPrepare.cpp"
+#include "SQLPrimaryKeys.cpp"
+#include "SQLProcedureColumns.cpp"
+#include "SQLProcedures.cpp"
+#include "SQLPutData.cpp"
+#include "SQLRowCount.cpp"
+#include "SQLSetConnectAttr.cpp"
+#include "SQLSetConnectOption.cpp"
+#include "SQLSetCursorName.cpp"
+#include "SQLSetDescField.cpp"
+#include "SQLSetDescRec.cpp"
+#include "SQLSetEnvAttr.cpp"
+#include "SQLSetParam.cpp"
+#include "SQLSetPos.cpp"
+#include "SQLSetScrollOptions.cpp"
+#include "SQLSetStmtAttr.cpp"
+#include "SQLSetStmtOption.cpp"
+#include "SQLSpecialColumns.cpp"
+#include "SQLStatistics.cpp"
+#include "SQLTablePrivileges.cpp"
+#include "SQLTables.cpp"
+#include "SQLTransact.cpp"
diff --git a/ndb/src/client/odbc/driver/driver.hpp b/ndb/src/old_files/client/odbc/driver/driver.hpp
index 96d2e052c0d..96d2e052c0d 100644
--- a/ndb/src/client/odbc/driver/driver.hpp
+++ b/ndb/src/old_files/client/odbc/driver/driver.hpp
diff --git a/ndb/src/client/odbc/executor/Exec_comp_op.cpp b/ndb/src/old_files/client/odbc/executor/Exec_comp_op.cpp
index 40d3950a592..40d3950a592 100644
--- a/ndb/src/client/odbc/executor/Exec_comp_op.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_comp_op.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_create_index.cpp b/ndb/src/old_files/client/odbc/executor/Exec_create_index.cpp
index 3966c6d5db2..3966c6d5db2 100644
--- a/ndb/src/client/odbc/executor/Exec_create_index.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_create_index.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_create_table.cpp b/ndb/src/old_files/client/odbc/executor/Exec_create_table.cpp
index d6274119371..d6274119371 100644
--- a/ndb/src/client/odbc/executor/Exec_create_table.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_create_table.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_delete_index.cpp b/ndb/src/old_files/client/odbc/executor/Exec_delete_index.cpp
index 10814654a58..10814654a58 100644
--- a/ndb/src/client/odbc/executor/Exec_delete_index.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_delete_index.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_delete_lookup.cpp b/ndb/src/old_files/client/odbc/executor/Exec_delete_lookup.cpp
index d0795286122..d0795286122 100644
--- a/ndb/src/client/odbc/executor/Exec_delete_lookup.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_delete_lookup.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_delete_scan.cpp b/ndb/src/old_files/client/odbc/executor/Exec_delete_scan.cpp
index a0b3b8314b8..a0b3b8314b8 100644
--- a/ndb/src/client/odbc/executor/Exec_delete_scan.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_delete_scan.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_drop_index.cpp b/ndb/src/old_files/client/odbc/executor/Exec_drop_index.cpp
index 6bf451f6911..6bf451f6911 100644
--- a/ndb/src/client/odbc/executor/Exec_drop_index.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_drop_index.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_drop_table.cpp b/ndb/src/old_files/client/odbc/executor/Exec_drop_table.cpp
index 40d1d42fc61..40d1d42fc61 100644
--- a/ndb/src/client/odbc/executor/Exec_drop_table.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_drop_table.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_expr_conv.cpp b/ndb/src/old_files/client/odbc/executor/Exec_expr_conv.cpp
index 636bfda7d59..636bfda7d59 100644
--- a/ndb/src/client/odbc/executor/Exec_expr_conv.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_expr_conv.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_expr_func.cpp b/ndb/src/old_files/client/odbc/executor/Exec_expr_func.cpp
index 093d15c6e2b..093d15c6e2b 100644
--- a/ndb/src/client/odbc/executor/Exec_expr_func.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_expr_func.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_expr_op.cpp b/ndb/src/old_files/client/odbc/executor/Exec_expr_op.cpp
index fc8b6df9f5b..fc8b6df9f5b 100644
--- a/ndb/src/client/odbc/executor/Exec_expr_op.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_expr_op.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_insert.cpp b/ndb/src/old_files/client/odbc/executor/Exec_insert.cpp
index c2612c6aaab..c2612c6aaab 100644
--- a/ndb/src/client/odbc/executor/Exec_insert.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_insert.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_pred_op.cpp b/ndb/src/old_files/client/odbc/executor/Exec_pred_op.cpp
index 7caa4656473..7caa4656473 100644
--- a/ndb/src/client/odbc/executor/Exec_pred_op.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_pred_op.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_query_index.cpp b/ndb/src/old_files/client/odbc/executor/Exec_query_index.cpp
index 919743beac2..919743beac2 100644
--- a/ndb/src/client/odbc/executor/Exec_query_index.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_query_index.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_query_lookup.cpp b/ndb/src/old_files/client/odbc/executor/Exec_query_lookup.cpp
index 599e1a36461..599e1a36461 100644
--- a/ndb/src/client/odbc/executor/Exec_query_lookup.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_query_lookup.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_query_range.cpp b/ndb/src/old_files/client/odbc/executor/Exec_query_range.cpp
index 0bc878d760d..0bc878d760d 100644
--- a/ndb/src/client/odbc/executor/Exec_query_range.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_query_range.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_query_scan.cpp b/ndb/src/old_files/client/odbc/executor/Exec_query_scan.cpp
index 213dfdd616d..213dfdd616d 100644
--- a/ndb/src/client/odbc/executor/Exec_query_scan.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_query_scan.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_query_sys.cpp b/ndb/src/old_files/client/odbc/executor/Exec_query_sys.cpp
index acdc120e609..acdc120e609 100644
--- a/ndb/src/client/odbc/executor/Exec_query_sys.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_query_sys.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_update_index.cpp b/ndb/src/old_files/client/odbc/executor/Exec_update_index.cpp
index 35b6159d8ca..35b6159d8ca 100644
--- a/ndb/src/client/odbc/executor/Exec_update_index.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_update_index.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_update_lookup.cpp b/ndb/src/old_files/client/odbc/executor/Exec_update_lookup.cpp
index 2c801372de3..2c801372de3 100644
--- a/ndb/src/client/odbc/executor/Exec_update_lookup.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_update_lookup.cpp
diff --git a/ndb/src/client/odbc/executor/Exec_update_scan.cpp b/ndb/src/old_files/client/odbc/executor/Exec_update_scan.cpp
index a36fdd27142..a36fdd27142 100644
--- a/ndb/src/client/odbc/executor/Exec_update_scan.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Exec_update_scan.cpp
diff --git a/ndb/src/client/odbc/executor/Executor.cpp b/ndb/src/old_files/client/odbc/executor/Executor.cpp
index adabb28a4a5..adabb28a4a5 100644
--- a/ndb/src/client/odbc/executor/Executor.cpp
+++ b/ndb/src/old_files/client/odbc/executor/Executor.cpp
diff --git a/ndb/src/client/odbc/executor/Executor.hpp b/ndb/src/old_files/client/odbc/executor/Executor.hpp
index 5edb9d509ac..5edb9d509ac 100644
--- a/ndb/src/client/odbc/executor/Executor.hpp
+++ b/ndb/src/old_files/client/odbc/executor/Executor.hpp
diff --git a/ndb/src/client/odbc/executor/Makefile b/ndb/src/old_files/client/odbc/executor/Makefile
index d86781e212c..d86781e212c 100644
--- a/ndb/src/client/odbc/executor/Makefile
+++ b/ndb/src/old_files/client/odbc/executor/Makefile
diff --git a/ndb/src/client/odbc/handles/AttrDbc.cpp b/ndb/src/old_files/client/odbc/handles/AttrDbc.cpp
index 4768a8995a2..4768a8995a2 100644
--- a/ndb/src/client/odbc/handles/AttrDbc.cpp
+++ b/ndb/src/old_files/client/odbc/handles/AttrDbc.cpp
diff --git a/ndb/src/client/odbc/handles/AttrEnv.cpp b/ndb/src/old_files/client/odbc/handles/AttrEnv.cpp
index 3d57fddeb57..3d57fddeb57 100644
--- a/ndb/src/client/odbc/handles/AttrEnv.cpp
+++ b/ndb/src/old_files/client/odbc/handles/AttrEnv.cpp
diff --git a/ndb/src/client/odbc/handles/AttrRoot.cpp b/ndb/src/old_files/client/odbc/handles/AttrRoot.cpp
index d1b264835b6..d1b264835b6 100644
--- a/ndb/src/client/odbc/handles/AttrRoot.cpp
+++ b/ndb/src/old_files/client/odbc/handles/AttrRoot.cpp
diff --git a/ndb/src/client/odbc/handles/AttrStmt.cpp b/ndb/src/old_files/client/odbc/handles/AttrStmt.cpp
index ce9a9c03fd1..ce9a9c03fd1 100644
--- a/ndb/src/client/odbc/handles/AttrStmt.cpp
+++ b/ndb/src/old_files/client/odbc/handles/AttrStmt.cpp
diff --git a/ndb/src/client/odbc/handles/DescSpec.cpp b/ndb/src/old_files/client/odbc/handles/DescSpec.cpp
index 83905cf9822..83905cf9822 100644
--- a/ndb/src/client/odbc/handles/DescSpec.cpp
+++ b/ndb/src/old_files/client/odbc/handles/DescSpec.cpp
diff --git a/ndb/src/client/odbc/handles/FuncTab.cpp b/ndb/src/old_files/client/odbc/handles/FuncTab.cpp
index 6bd744d7a7f..6bd744d7a7f 100644
--- a/ndb/src/client/odbc/handles/FuncTab.cpp
+++ b/ndb/src/old_files/client/odbc/handles/FuncTab.cpp
diff --git a/ndb/src/client/odbc/handles/HandleBase.cpp b/ndb/src/old_files/client/odbc/handles/HandleBase.cpp
index 27379cdc3f8..27379cdc3f8 100644
--- a/ndb/src/client/odbc/handles/HandleBase.cpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleBase.cpp
diff --git a/ndb/src/client/odbc/handles/HandleBase.hpp b/ndb/src/old_files/client/odbc/handles/HandleBase.hpp
index fc35c2b559b..fc35c2b559b 100644
--- a/ndb/src/client/odbc/handles/HandleBase.hpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleBase.hpp
diff --git a/ndb/src/client/odbc/handles/HandleDbc.cpp b/ndb/src/old_files/client/odbc/handles/HandleDbc.cpp
index 2d5ded2cc21..2d5ded2cc21 100644
--- a/ndb/src/client/odbc/handles/HandleDbc.cpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleDbc.cpp
diff --git a/ndb/src/client/odbc/handles/HandleDbc.hpp b/ndb/src/old_files/client/odbc/handles/HandleDbc.hpp
index 130df08d02c..130df08d02c 100644
--- a/ndb/src/client/odbc/handles/HandleDbc.hpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleDbc.hpp
diff --git a/ndb/src/client/odbc/handles/HandleDesc.cpp b/ndb/src/old_files/client/odbc/handles/HandleDesc.cpp
index 4cff1bb8892..4cff1bb8892 100644
--- a/ndb/src/client/odbc/handles/HandleDesc.cpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleDesc.cpp
diff --git a/ndb/src/client/odbc/handles/HandleDesc.hpp b/ndb/src/old_files/client/odbc/handles/HandleDesc.hpp
index 9419697f134..9419697f134 100644
--- a/ndb/src/client/odbc/handles/HandleDesc.hpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleDesc.hpp
diff --git a/ndb/src/client/odbc/handles/HandleEnv.cpp b/ndb/src/old_files/client/odbc/handles/HandleEnv.cpp
index bc9d8b420a6..bc9d8b420a6 100644
--- a/ndb/src/client/odbc/handles/HandleEnv.cpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleEnv.cpp
diff --git a/ndb/src/client/odbc/handles/HandleEnv.hpp b/ndb/src/old_files/client/odbc/handles/HandleEnv.hpp
index 2b13b0256bc..2b13b0256bc 100644
--- a/ndb/src/client/odbc/handles/HandleEnv.hpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleEnv.hpp
diff --git a/ndb/src/old_files/client/odbc/handles/HandleRoot.cpp b/ndb/src/old_files/client/odbc/handles/HandleRoot.cpp
new file mode 100644
index 00000000000..13560d55028
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/handles/HandleRoot.cpp
@@ -0,0 +1,271 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/common.hpp>
+#include <NdbMutex.h>
+#include <common/DiagArea.hpp>
+#include "HandleRoot.hpp"
+#include "HandleEnv.hpp"
+#include "HandleDbc.hpp"
+#include "HandleStmt.hpp"
+#include "HandleDesc.hpp"
+#include "PoolNdb.hpp"
+
+HandleRoot::HandleRoot() :
+ m_attrArea(m_attrSpec)
+{
+ m_attrArea.setHandle(this);
+ m_poolNdb = new PoolNdb();
+}
+
+HandleRoot::~HandleRoot()
+{
+}
+
+#ifdef NDB_WIN32
+static NdbMutex & root_mutex = * NdbMutex_Create();
+#else
+static NdbMutex root_mutex = NDB_MUTEX_INITIALIZER;
+#endif
+
+HandleRoot*
+HandleRoot::instance()
+{
+ NdbMutex_Lock(&root_mutex);
+ if (m_instance == 0)
+ m_instance = new HandleRoot();
+ NdbMutex_Unlock(&root_mutex);
+ return m_instance;
+}
+
+void
+HandleRoot::lockHandle()
+{
+ NdbMutex_Lock(&root_mutex);
+}
+
+void
+HandleRoot::unlockHandle()
+{
+ NdbMutex_Unlock(&root_mutex);
+}
+
+// check and find handle types and handles
+
+SQLSMALLINT
+HandleRoot::findParentType(SQLSMALLINT childType)
+{
+ switch (childType) {
+ case SQL_HANDLE_ENV:
+ return SQL_HANDLE_ROOT;
+ case SQL_HANDLE_DBC:
+ return SQL_HANDLE_ENV;
+ case SQL_HANDLE_STMT:
+ return SQL_HANDLE_DBC;
+ case SQL_HANDLE_DESC:
+ return SQL_HANDLE_DBC;
+ }
+ return -1;
+}
+
+HandleBase*
+HandleRoot::findBase(SQLSMALLINT handleType, void* pHandle)
+{
+ switch (handleType) {
+ case SQL_HANDLE_ROOT:
+ return getRoot();
+ case SQL_HANDLE_ENV:
+ return findEnv(pHandle);
+ case SQL_HANDLE_DBC:
+ return findDbc(pHandle);
+ case SQL_HANDLE_STMT:
+ return findStmt(pHandle);
+ case SQL_HANDLE_DESC:
+ return findDesc(pHandle);
+ }
+ return 0;
+}
+
+HandleEnv*
+HandleRoot::findEnv(void* pHandle)
+{
+ lockHandle();
+ ValidList::iterator i = m_validList.find(pHandle);
+ if (i == m_validList.end() || (*i).second != SQL_HANDLE_ENV) {
+ unlockHandle();
+ return 0;
+ }
+ unlockHandle();
+ ctx_assert(pHandle != 0);
+ return static_cast<HandleEnv*>(pHandle);
+}
+
+HandleDbc*
+HandleRoot::findDbc(void* pHandle)
+{
+ lockHandle();
+ ValidList::iterator i = m_validList.find(pHandle);
+ if (i == m_validList.end() || (*i).second != SQL_HANDLE_DBC) {
+ unlockHandle();
+ return 0;
+ }
+ unlockHandle();
+ ctx_assert(pHandle != 0);
+ return static_cast<HandleDbc*>(pHandle);
+}
+
+HandleStmt*
+HandleRoot::findStmt(void* pHandle)
+{
+ lockHandle();
+ ValidList::iterator i = m_validList.find(pHandle);
+ if (i == m_validList.end() || (*i).second != SQL_HANDLE_STMT) {
+ unlockHandle();
+ return 0;
+ }
+ unlockHandle();
+ ctx_assert(pHandle != 0);
+ return static_cast<HandleStmt*>(pHandle);
+}
+
+HandleDesc*
+HandleRoot::findDesc(void* pHandle)
+{
+ lockHandle();
+ ValidList::iterator i = m_validList.find(pHandle);
+ if (i == m_validList.end() || (*i).second != SQL_HANDLE_DESC) {
+ unlockHandle();
+ return 0;
+ }
+ unlockHandle();
+ ctx_assert(pHandle != 0);
+ return static_cast<HandleDesc*>(pHandle);
+}
+
+// add or remove handle from validation list
+
+void
+HandleRoot::record(SQLSMALLINT handleType, HandleBase* pHandle, bool add)
+{
+ switch (handleType) {
+ case SQL_HANDLE_ENV:
+ case SQL_HANDLE_DBC:
+ case SQL_HANDLE_STMT:
+ case SQL_HANDLE_DESC:
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ }
+ ctx_assert(pHandle != 0);
+ lockHandle();
+ ValidList::iterator i = m_validList.find(pHandle);
+ if (add) {
+ if (i != m_validList.end()) {
+ unlockHandle();
+ ctx_assert(false);
+ }
+ m_validList.insert(ValidList::value_type(pHandle, handleType));
+ } else {
+ if (i == m_validList.end() || (*i).second != handleType) {
+ unlockHandle();
+ ctx_assert(false);
+ }
+ m_validList.erase(i);
+ }
+ unlockHandle();
+}
+
+// allocate and free handles
+
+void
+HandleRoot::sqlAllocEnv(Ctx& ctx, HandleEnv** ppEnv)
+{
+ if (ppEnv == 0) {
+ ctx.pushStatus(Sqlstate::_HY009, Error::Gen, "cannot allocate environment handle - null return address");
+ return;
+ }
+ HandleEnv* pEnv = new HandleEnv(this);
+ pEnv->ctor(ctx);
+ if (! ctx.ok()) {
+ pEnv->dtor(ctx);
+ delete pEnv;
+ return;
+ }
+ lockHandle();
+ m_listEnv.push_back(pEnv);
+ unlockHandle();
+ getRoot()->record(SQL_HANDLE_ENV, pEnv, true);
+ *ppEnv = pEnv;
+}
+
+void
+HandleRoot::sqlAllocHandle(Ctx& ctx, SQLSMALLINT childType, HandleBase** ppChild)
+{
+ switch (childType) {
+ case SQL_HANDLE_ENV:
+ sqlAllocEnv(ctx, (HandleEnv**)ppChild);
+ return;
+ }
+ ctx.pushStatus(Sqlstate::_HY092, Error::Gen, "invalid child handle type %d", (int)childType);
+}
+
+void
+HandleRoot::sqlFreeEnv(Ctx& ctx, HandleEnv* pEnv)
+{
+ pEnv->dtor(ctx);
+ if (! ctx.ok()) {
+ return;
+ }
+ lockHandle();
+ m_listEnv.remove(pEnv);
+ unlockHandle();
+ getRoot()->record(SQL_HANDLE_ENV, pEnv, false);
+ delete pEnv;
+}
+
+void
+HandleRoot::sqlFreeHandle(Ctx& ctx, SQLSMALLINT childType, HandleBase* pChild)
+{
+ switch (childType) {
+ case SQL_HANDLE_ENV:
+ sqlFreeEnv(ctx, (HandleEnv*)pChild);
+ return;
+ }
+ ctx.pushStatus(Sqlstate::_HY092, Error::Gen, "invalid child handle type %d", (int)childType);
+}
+
+// process-level attributes
+
+void
+HandleRoot::sqlSetRootAttr(Ctx& ctx, SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER stringLength)
+{
+ lockHandle();
+ baseSetHandleAttr(ctx, m_attrArea, attribute, value, stringLength);
+ unlockHandle();
+}
+
+void
+HandleRoot::sqlGetRootAttr(Ctx& ctx, SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* stringLength)
+{
+ lockHandle();
+ baseGetHandleAttr(ctx, m_attrArea, attribute, value, bufferLength, stringLength);
+ unlockHandle();
+}
+
+// the instance
+
+HandleRoot* HandleRoot::m_instance = 0;
diff --git a/ndb/src/client/odbc/handles/HandleRoot.hpp b/ndb/src/old_files/client/odbc/handles/HandleRoot.hpp
index 08a22b3e400..08a22b3e400 100644
--- a/ndb/src/client/odbc/handles/HandleRoot.hpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleRoot.hpp
diff --git a/ndb/src/client/odbc/handles/HandleStmt.cpp b/ndb/src/old_files/client/odbc/handles/HandleStmt.cpp
index d33d33dbd5b..d33d33dbd5b 100644
--- a/ndb/src/client/odbc/handles/HandleStmt.cpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleStmt.cpp
diff --git a/ndb/src/client/odbc/handles/HandleStmt.hpp b/ndb/src/old_files/client/odbc/handles/HandleStmt.hpp
index 0bee138bfc6..0bee138bfc6 100644
--- a/ndb/src/client/odbc/handles/HandleStmt.hpp
+++ b/ndb/src/old_files/client/odbc/handles/HandleStmt.hpp
diff --git a/ndb/src/client/odbc/handles/InfoTab.cpp b/ndb/src/old_files/client/odbc/handles/InfoTab.cpp
index 1a93c4da264..1a93c4da264 100644
--- a/ndb/src/client/odbc/handles/InfoTab.cpp
+++ b/ndb/src/old_files/client/odbc/handles/InfoTab.cpp
diff --git a/ndb/src/client/odbc/handles/Makefile b/ndb/src/old_files/client/odbc/handles/Makefile
index d37e7d286ba..d37e7d286ba 100644
--- a/ndb/src/client/odbc/handles/Makefile
+++ b/ndb/src/old_files/client/odbc/handles/Makefile
diff --git a/ndb/src/old_files/client/odbc/handles/PoolNdb.cpp b/ndb/src/old_files/client/odbc/handles/PoolNdb.cpp
new file mode 100644
index 00000000000..45d3c67ec77
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/handles/PoolNdb.cpp
@@ -0,0 +1,81 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/common.hpp>
+#include <NdbMutex.h>
+#include <NdbApi.hpp>
+#include "PoolNdb.hpp"
+
+#ifdef NDB_WIN32
+static NdbMutex & ndb_mutex = * NdbMutex_Create();
+#else
+static NdbMutex ndb_mutex = NDB_MUTEX_INITIALIZER;
+#endif
+
+PoolNdb::PoolNdb() :
+ m_cntUsed(0),
+ m_cntFree(0)
+{
+}
+
+PoolNdb::~PoolNdb()
+{
+}
+
+Ndb*
+PoolNdb::allocate(Ctx& ctx, int timeout)
+{
+ NdbMutex_Lock(&ndb_mutex);
+ Ndb* pNdb;
+ if (m_cntFree == 0) {
+ pNdb = new Ndb("TEST_DB");
+ pNdb->useFullyQualifiedNames(true);
+ if (pNdb->init(64) < 0) {
+ ctx.pushStatus(pNdb, "init");
+ delete pNdb;
+ NdbMutex_Unlock(&ndb_mutex);
+ return 0;
+ }
+ if (pNdb->waitUntilReady(timeout) < 0) {
+ ctx.pushStatus(Sqlstate::_HYT00, Error::Gen, "connection timeout after %d seconds", timeout);
+ ctx.pushStatus(pNdb, "waitUntilReady");
+ delete pNdb;
+ NdbMutex_Unlock(&ndb_mutex);
+ return 0;
+ }
+ m_listFree.push_back(pNdb);
+ m_cntFree++;
+ }
+ pNdb = m_listFree.front();
+ m_listFree.pop_front();
+ m_cntFree--;
+ m_cntUsed++;
+ ctx_log1(("alloc Ndb: used=%u free=%u", m_cntUsed, m_cntFree));
+ NdbMutex_Unlock(&ndb_mutex);
+ return pNdb;
+}
+
+void
+PoolNdb::release(Ctx& ctx, Ndb* pNdb)
+{
+ NdbMutex_Lock(&ndb_mutex);
+ m_listUsed.remove(pNdb);
+ m_listFree.push_back(pNdb);
+ m_cntFree++;
+ m_cntUsed--;
+ ctx_log1(("free Ndb: used=%u free=%u", m_cntUsed, m_cntFree));
+ NdbMutex_Unlock(&ndb_mutex);
+}
diff --git a/ndb/src/old_files/client/odbc/handles/PoolNdb.hpp b/ndb/src/old_files/client/odbc/handles/PoolNdb.hpp
new file mode 100644
index 00000000000..35eac055c30
--- /dev/null
+++ b/ndb/src/old_files/client/odbc/handles/PoolNdb.hpp
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_HANDLES_PoolNdb_hpp
+#define ODBC_HANDLES_PoolNdb_hpp
+
+#include <common/common.hpp>
+#include <list>
+
+class Ndb;
+
+/**
+ * @class PoolNdb
+ * @brief Pool of Ndb objects.
+ *
+ * A class implementing pool of Ndb objects.
+ */
+class PoolNdb {
+public:
+ PoolNdb();
+ ~PoolNdb();
+ Ndb* allocate(Ctx& ctx, int timeout);
+ void release(Ctx& ctx, Ndb* pNdb);
+private:
+ std::list<Ndb*> m_listUsed;
+ std::list<Ndb*> m_listFree;
+ unsigned m_cntUsed;
+ unsigned m_cntFree;
+};
+
+#endif
diff --git a/ndb/src/client/odbc/handles/handles.hpp b/ndb/src/old_files/client/odbc/handles/handles.hpp
index a9f0fcae888..a9f0fcae888 100644
--- a/ndb/src/client/odbc/handles/handles.hpp
+++ b/ndb/src/old_files/client/odbc/handles/handles.hpp
diff --git a/ndb/src/ndbbaseclient/Makefile b/ndb/src/old_files/ndbbaseclient/Makefile
index f4c49a95ffa..f4c49a95ffa 100644
--- a/ndb/src/ndbbaseclient/Makefile
+++ b/ndb/src/old_files/ndbbaseclient/Makefile
diff --git a/ndb/src/ndbbaseclient/ndbbaseclient_dummy.cpp b/ndb/src/old_files/ndbbaseclient/ndbbaseclient_dummy.cpp
index e69de29bb2d..e69de29bb2d 100644
--- a/ndb/src/ndbbaseclient/ndbbaseclient_dummy.cpp
+++ b/ndb/src/old_files/ndbbaseclient/ndbbaseclient_dummy.cpp
diff --git a/ndb/src/ndbclient/Makefile b/ndb/src/old_files/ndbclient/Makefile
index 2c597eccfa1..2c597eccfa1 100644
--- a/ndb/src/ndbclient/Makefile
+++ b/ndb/src/old_files/ndbclient/Makefile
diff --git a/ndb/src/ndbclient/ndbclient_dummy.cpp b/ndb/src/old_files/ndbclient/ndbclient_dummy.cpp
index e69de29bb2d..e69de29bb2d 100644
--- a/ndb/src/ndbclient/ndbclient_dummy.cpp
+++ b/ndb/src/old_files/ndbclient/ndbclient_dummy.cpp
diff --git a/ndb/src/newtonapi/Makefile b/ndb/src/old_files/newtonapi/Makefile
index bed179046a5..bed179046a5 100644
--- a/ndb/src/newtonapi/Makefile
+++ b/ndb/src/old_files/newtonapi/Makefile
diff --git a/ndb/src/newtonapi/dba_binding.cpp b/ndb/src/old_files/newtonapi/dba_binding.cpp
index 63e48110b1d..63e48110b1d 100644
--- a/ndb/src/newtonapi/dba_binding.cpp
+++ b/ndb/src/old_files/newtonapi/dba_binding.cpp
diff --git a/ndb/src/newtonapi/dba_bulkread.cpp b/ndb/src/old_files/newtonapi/dba_bulkread.cpp
index 1f75037046b..1f75037046b 100644
--- a/ndb/src/newtonapi/dba_bulkread.cpp
+++ b/ndb/src/old_files/newtonapi/dba_bulkread.cpp
diff --git a/ndb/src/newtonapi/dba_config.cpp b/ndb/src/old_files/newtonapi/dba_config.cpp
index d84386a9438..d84386a9438 100644
--- a/ndb/src/newtonapi/dba_config.cpp
+++ b/ndb/src/old_files/newtonapi/dba_config.cpp
diff --git a/ndb/src/newtonapi/dba_dac.cpp b/ndb/src/old_files/newtonapi/dba_dac.cpp
index fcb4e676e46..fcb4e676e46 100644
--- a/ndb/src/newtonapi/dba_dac.cpp
+++ b/ndb/src/old_files/newtonapi/dba_dac.cpp
diff --git a/ndb/src/newtonapi/dba_error.cpp b/ndb/src/old_files/newtonapi/dba_error.cpp
index f05446522b0..f05446522b0 100644
--- a/ndb/src/newtonapi/dba_error.cpp
+++ b/ndb/src/old_files/newtonapi/dba_error.cpp
diff --git a/ndb/src/newtonapi/dba_init.cpp b/ndb/src/old_files/newtonapi/dba_init.cpp
index aa5fef1171c..aa5fef1171c 100644
--- a/ndb/src/newtonapi/dba_init.cpp
+++ b/ndb/src/old_files/newtonapi/dba_init.cpp
diff --git a/ndb/src/newtonapi/dba_internal.hpp b/ndb/src/old_files/newtonapi/dba_internal.hpp
index 84ae7ba222b..84ae7ba222b 100644
--- a/ndb/src/newtonapi/dba_internal.hpp
+++ b/ndb/src/old_files/newtonapi/dba_internal.hpp
diff --git a/ndb/src/newtonapi/dba_process.cpp b/ndb/src/old_files/newtonapi/dba_process.cpp
index ddb6e62f180..ddb6e62f180 100644
--- a/ndb/src/newtonapi/dba_process.cpp
+++ b/ndb/src/old_files/newtonapi/dba_process.cpp
diff --git a/ndb/src/newtonapi/dba_process.hpp b/ndb/src/old_files/newtonapi/dba_process.hpp
index ef24fbd9142..ef24fbd9142 100644
--- a/ndb/src/newtonapi/dba_process.hpp
+++ b/ndb/src/old_files/newtonapi/dba_process.hpp
diff --git a/ndb/src/old_files/newtonapi/dba_schema.cpp b/ndb/src/old_files/newtonapi/dba_schema.cpp
new file mode 100644
index 00000000000..1bf21f1fe80
--- /dev/null
+++ b/ndb/src/old_files/newtonapi/dba_schema.cpp
@@ -0,0 +1,150 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "dba_internal.hpp"
+#include "NdbSchemaCon.hpp"
+
+static bool getNdbAttr(DBA_DataTypes_t,
+ Size_t,
+ int * attrSize,
+ int * arraySize,
+ AttrType * attrType);
+
+extern "C"
+DBA_Error_t
+DBA_CreateTable(const char* TableName,
+ int NbColumns,
+ const DBA_ColumnDesc_t Columns[] ){
+
+ if(DBA_TableExists(TableName))
+ return DBA_NO_ERROR;
+
+ NdbSchemaCon * schemaCon = NdbSchemaCon::startSchemaTrans(DBA__TheNdb);
+ if(schemaCon == 0){
+ DBA__SetLatestError(DBA_NDB_ERROR, 0,
+ "Internal NDB error: No schema transaction");
+ return DBA_NDB_ERROR;
+ }
+
+ NdbSchemaOp * schemaOp = schemaCon->getNdbSchemaOp();
+ if(schemaOp == 0){
+ NdbSchemaCon::closeSchemaTrans(schemaCon);
+ DBA__SetLatestError(DBA_NDB_ERROR, 0,
+ "Internal NDB error: No schema op");
+ return DBA_NDB_ERROR;
+ }
+
+ if(schemaOp->createTable( TableName,
+ 8, // Data Size
+ TupleKey,
+ 2, // Index size
+ All,
+ 6,
+ 78,
+ 80,
+ 1,
+ false) == -1){
+ NdbSchemaCon::closeSchemaTrans(schemaCon);
+ DBA__SetLatestError(DBA_NDB_ERROR, 0,
+ "Internal NDB error: Create table failed");
+ return DBA_NDB_ERROR;
+ }
+
+ for (int i = 0; i < NbColumns; i++){
+ int attrSize;
+ int arraySize;
+ AttrType attrType;
+
+ if(!getNdbAttr(Columns[i].DataType, Columns[i].Size,
+ &attrSize,
+ &arraySize,
+ &attrType)){
+ NdbSchemaCon::closeSchemaTrans(schemaCon);
+ DBA__SetLatestError(DBA_APPLICATION_ERROR, 0,
+ "Invalid datatype/size combination");
+ return DBA_APPLICATION_ERROR;
+ }
+
+ if(schemaOp->createAttribute( Columns[i].Name,
+ Columns[i].IsKey ? TupleKey : NoKey,
+ attrSize,
+ arraySize,
+ attrType) == -1){
+ NdbSchemaCon::closeSchemaTrans(schemaCon);
+ DBA__SetLatestError(DBA_NDB_ERROR, 0,
+ "Internal NDB error: Create attribute failed");
+ return DBA_NDB_ERROR;
+ }
+ }
+
+ if(schemaCon->execute() == -1){
+ NdbSchemaCon::closeSchemaTrans(schemaCon);
+ DBA__SetLatestError(DBA_NDB_ERROR, 0,
+ "Internal NDB error: Execute schema failed");
+ return DBA_NDB_ERROR;
+ }
+
+ NdbSchemaCon::closeSchemaTrans(schemaCon);
+
+ return DBA_NO_ERROR;
+}
+
+DBA_Error_t
+DBA_DropTable( char* TableName ){
+ return DBA_NOT_IMPLEMENTED;
+}
+
+Boolean_t
+DBA_TableExists( const char* TableName ){
+ NdbDictionary::Dictionary * dict = DBA__TheNdb->getDictionary();
+ if(dict == 0){
+ return 0;
+ }
+
+ const NdbDictionary::Table * tab = dict->getTable(TableName);
+ if(tab == 0){
+ return 0;
+ }
+ return 1;
+}
+
+static
+bool
+getNdbAttr(DBA_DataTypes_t type,
+ Size_t size,
+ int * attrSize,
+ int * arraySize,
+ AttrType * attrType) {
+
+ if(type == DBA_CHAR){
+ * attrType = String;
+ * attrSize = 8;
+ * arraySize = size;
+ return true;
+ }
+
+ * attrType = Signed;
+ if((size % 4) == 0){
+ * attrSize = 32;
+ * arraySize = size / 4;
+ return true;
+ }
+
+ * attrSize = 8;
+ * arraySize = size;
+
+ return true;
+}
diff --git a/ndb/src/rep/ExtSender.cpp b/ndb/src/old_files/rep/ExtSender.cpp
index cf31001a85f..cf31001a85f 100644
--- a/ndb/src/rep/ExtSender.cpp
+++ b/ndb/src/old_files/rep/ExtSender.cpp
diff --git a/ndb/src/rep/ExtSender.hpp b/ndb/src/old_files/rep/ExtSender.hpp
index 0bdabd68f37..0bdabd68f37 100644
--- a/ndb/src/rep/ExtSender.hpp
+++ b/ndb/src/old_files/rep/ExtSender.hpp
diff --git a/ndb/src/rep/Makefile b/ndb/src/old_files/rep/Makefile
index 9688a68ec74..9688a68ec74 100644
--- a/ndb/src/rep/Makefile
+++ b/ndb/src/old_files/rep/Makefile
diff --git a/ndb/src/rep/NodeConnectInfo.hpp b/ndb/src/old_files/rep/NodeConnectInfo.hpp
index 403f92a5999..403f92a5999 100644
--- a/ndb/src/rep/NodeConnectInfo.hpp
+++ b/ndb/src/old_files/rep/NodeConnectInfo.hpp
diff --git a/ndb/src/rep/README b/ndb/src/old_files/rep/README
index 7be5e230eb3..7be5e230eb3 100644
--- a/ndb/src/rep/README
+++ b/ndb/src/old_files/rep/README
diff --git a/ndb/src/rep/RepApiInterpreter.cpp b/ndb/src/old_files/rep/RepApiInterpreter.cpp
index 6e6f150713a..6e6f150713a 100644
--- a/ndb/src/rep/RepApiInterpreter.cpp
+++ b/ndb/src/old_files/rep/RepApiInterpreter.cpp
diff --git a/ndb/src/rep/RepApiInterpreter.hpp b/ndb/src/old_files/rep/RepApiInterpreter.hpp
index 78f190156b3..78f190156b3 100644
--- a/ndb/src/rep/RepApiInterpreter.hpp
+++ b/ndb/src/old_files/rep/RepApiInterpreter.hpp
diff --git a/ndb/src/rep/RepApiService.cpp b/ndb/src/old_files/rep/RepApiService.cpp
index d07f7a59375..d07f7a59375 100644
--- a/ndb/src/rep/RepApiService.cpp
+++ b/ndb/src/old_files/rep/RepApiService.cpp
diff --git a/ndb/src/rep/RepApiService.hpp b/ndb/src/old_files/rep/RepApiService.hpp
index e1137e53258..e1137e53258 100644
--- a/ndb/src/rep/RepApiService.hpp
+++ b/ndb/src/old_files/rep/RepApiService.hpp
diff --git a/ndb/src/rep/RepCommandInterpreter.cpp b/ndb/src/old_files/rep/RepCommandInterpreter.cpp
index a0daf9529ab..a0daf9529ab 100644
--- a/ndb/src/rep/RepCommandInterpreter.cpp
+++ b/ndb/src/old_files/rep/RepCommandInterpreter.cpp
diff --git a/ndb/src/rep/RepCommandInterpreter.hpp b/ndb/src/old_files/rep/RepCommandInterpreter.hpp
index 398a7c0318c..398a7c0318c 100644
--- a/ndb/src/rep/RepCommandInterpreter.hpp
+++ b/ndb/src/old_files/rep/RepCommandInterpreter.hpp
diff --git a/ndb/src/rep/RepComponents.cpp b/ndb/src/old_files/rep/RepComponents.cpp
index 04b2e0e5fa5..04b2e0e5fa5 100644
--- a/ndb/src/rep/RepComponents.cpp
+++ b/ndb/src/old_files/rep/RepComponents.cpp
diff --git a/ndb/src/rep/RepComponents.hpp b/ndb/src/old_files/rep/RepComponents.hpp
index ff0f29e2128..ff0f29e2128 100644
--- a/ndb/src/rep/RepComponents.hpp
+++ b/ndb/src/old_files/rep/RepComponents.hpp
diff --git a/ndb/src/rep/RepMain.cpp b/ndb/src/old_files/rep/RepMain.cpp
index d9f057be9a1..d9f057be9a1 100644
--- a/ndb/src/rep/RepMain.cpp
+++ b/ndb/src/old_files/rep/RepMain.cpp
diff --git a/ndb/src/rep/Requestor.cpp b/ndb/src/old_files/rep/Requestor.cpp
index 3c93a6394a4..3c93a6394a4 100644
--- a/ndb/src/rep/Requestor.cpp
+++ b/ndb/src/old_files/rep/Requestor.cpp
diff --git a/ndb/src/rep/Requestor.hpp b/ndb/src/old_files/rep/Requestor.hpp
index 735d2094bde..735d2094bde 100644
--- a/ndb/src/rep/Requestor.hpp
+++ b/ndb/src/old_files/rep/Requestor.hpp
diff --git a/ndb/src/rep/RequestorSubscriptions.cpp b/ndb/src/old_files/rep/RequestorSubscriptions.cpp
index 75b41fae037..75b41fae037 100644
--- a/ndb/src/rep/RequestorSubscriptions.cpp
+++ b/ndb/src/old_files/rep/RequestorSubscriptions.cpp
diff --git a/ndb/src/rep/SignalQueue.cpp b/ndb/src/old_files/rep/SignalQueue.cpp
index 9b356a14b7d..9b356a14b7d 100644
--- a/ndb/src/rep/SignalQueue.cpp
+++ b/ndb/src/old_files/rep/SignalQueue.cpp
diff --git a/ndb/src/old_files/rep/SignalQueue.hpp b/ndb/src/old_files/rep/SignalQueue.hpp
new file mode 100644
index 00000000000..697bca85893
--- /dev/null
+++ b/ndb/src/old_files/rep/SignalQueue.hpp
@@ -0,0 +1,117 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef __SIGNALQUEUE_HPP_INCLUDED__
+#define __SIGNALQUEUE_HPP_INCLUDED__
+
+#include <NdbApiSignal.hpp>
+#include <NdbMutex.h>
+#include <NdbCondition.h>
+#include <Vector.hpp>
+
+/* XXX Look for an already existing definition */
+#define DEFAULT_TIMEOUT 10000
+
+/**
+ * @class SignalQueue
+ * @brief
+ */
+class SignalQueue {
+public:
+ typedef void (* SignalHandler)(void *obj, int gsn, NdbApiSignal *signal);
+
+ SignalQueue();
+ ~SignalQueue();
+
+ /**
+ * Static wrapper making it possible to call receive without knowing the
+ * type of the receiver
+ */
+ static void receive(void *me, NdbApiSignal *signal);
+
+ /**
+ * Enqueues a signal, and notifies any thread waiting for signals.
+ */
+ void receive(NdbApiSignal *signal);
+
+ NdbApiSignal *waitFor(int gsn,
+ NodeId nodeid = 0,
+ Uint32 timeout = DEFAULT_TIMEOUT);
+ template<class T> bool waitFor(Vector<T> &t,
+ T *&handler,
+ NdbApiSignal *&signal,
+ Uint32 timeout);
+
+ /**
+ * size()
+ */
+
+ Uint32 size() {return m_queueSize;};
+
+private:
+ NdbMutex *m_mutex; /* Locks all data in SignalQueue */
+ NdbCondition *m_cond; /* Notifies about new signal in the queue */
+
+ /**
+ * Returns the last recently received signal.
+ * Must be called with m_mutex locked.
+ *
+ * The caller takes responsibility for deleting the returned object.
+ *
+ * @returns NULL if failed, or a received signal
+ */
+ NdbApiSignal *pop();
+
+ class QueueEntry {
+ public:
+ NdbApiSignal *signal;
+ QueueEntry *next;
+ };
+ QueueEntry *m_signalQueueHead; /** Head of the queue.
+ * New entries added on the tail
+ */
+ Uint32 m_queueSize;
+};
+
+template<class T> bool
+SignalQueue::waitFor(Vector<T> &t,
+ T *&handler,
+ NdbApiSignal *&signal,
+ Uint32 timeout) {
+ Guard g(m_mutex);
+
+ if(m_signalQueueHead == NULL)
+ NdbCondition_WaitTimeout(m_cond, m_mutex, timeout);
+
+ if(m_signalQueueHead == NULL)
+ return false;
+
+ for(size_t i = 0; i < t.size(); i++) {
+ if(t[i].check(m_signalQueueHead->signal)) {
+ handler = &t[i];
+ signal = pop();
+ return true;
+ }
+ }
+
+ ndbout_c("SignalQueue: Queued signal without true check function (GSN: %d)",
+ m_signalQueueHead->signal->theVerId_signalNumber);
+ abort();
+
+ return false;
+}
+
+#endif /* !__SIGNALQUEUE_HPP_INCLUDED__ */
diff --git a/ndb/src/rep/TODO b/ndb/src/old_files/rep/TODO
index a2462fae6cd..a2462fae6cd 100644
--- a/ndb/src/rep/TODO
+++ b/ndb/src/old_files/rep/TODO
diff --git a/ndb/src/old_files/rep/adapters/AppNDB.cpp b/ndb/src/old_files/rep/adapters/AppNDB.cpp
new file mode 100644
index 00000000000..05f6d52807f
--- /dev/null
+++ b/ndb/src/old_files/rep/adapters/AppNDB.cpp
@@ -0,0 +1,583 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "AppNDB.hpp"
+#include <ConfigRetriever.hpp>
+#include <AttributeHeader.hpp>
+#include <NdbOperation.hpp>
+#include <NdbDictionaryImpl.hpp>
+
+#include <signaldata/RepImpl.hpp>
+#include <TransporterFacade.hpp>
+#include <trigger_definitions.h>
+#include <rep/storage/GCIPage.hpp>
+#include <rep/storage/GCIBuffer.hpp>
+#include <rep/rep_version.hpp>
+
+/*****************************************************************************
+ * Constructor / Destructor / Init
+ *****************************************************************************/
+
+AppNDB::~AppNDB()
+{
+ delete m_tableInfoPs;
+ delete m_ndb;
+ m_tableInfoPs = 0;
+}
+
+AppNDB::AppNDB(GCIContainer * gciContainer, RepState * repState)
+{
+ m_gciContainer = gciContainer;
+ m_repState = repState;
+ m_cond = NdbCondition_Create();
+ m_started = true;
+}
+
+void
+AppNDB::init(const char* connectString) {
+
+ // NdbThread_SetConcurrencyLevel(1+ 2);
+ m_ndb = new Ndb("");
+
+ m_ndb->useFullyQualifiedNames(false);
+
+ m_ndb->setConnectString(connectString);
+ /**
+ * @todo Set proper max no of transactions?? needed?? Default 12??
+ */
+ m_ndb->init(2048);
+ m_dict = m_ndb->getDictionary();
+
+ m_ownNodeId = m_ndb->getNodeId();
+
+ ndbout << "-- NDB Cluster -- REP node " << m_ownNodeId << " -- Version "
+ << REP_VERSION_ID << " --" << endl;
+ ndbout_c("Connecting to NDB Cluster...");
+ if (m_ndb->waitUntilReady() != 0){
+ REPABORT("NDB Cluster not ready for connections");
+ }
+ ndbout_c("Phase 1 (AppNDB): Connection 1 to NDB Cluster opened (Applier)");
+
+ m_tableInfoPs = new TableInfoPs();
+
+ m_applierThread = NdbThread_Create(runAppNDB_C,
+ (void**)this,
+ 32768,
+ "AppNDBThread",
+ NDB_THREAD_PRIO_LOW);
+}
+
+
+/*****************************************************************************
+ * Threads
+ *****************************************************************************/
+
+extern "C"
+void*
+runAppNDB_C(void * me)
+{
+ ((AppNDB *) me)->threadMainAppNDB();
+ NdbThread_Exit(0);
+ return me;
+}
+
+void
+AppNDB::threadMainAppNDB() {
+ MetaRecord * mr;
+ LogRecord * lr;
+ GCIBuffer::iterator * itBuffer;
+ GCIPage::iterator * itPage;
+ GCIBuffer * buffer;
+ GCIPage * page;
+ Uint32 gci=0;
+
+ bool force;
+ while(true){
+
+ m_gciBufferList.lock();
+ if(m_gciBufferList.size()==0)
+ NdbCondition_Wait(m_cond, m_gciBufferList.getMutex());
+ m_gciBufferList.unlock();
+
+ /**
+ * Do nothing if we are not started!
+ */
+ if(!m_started)
+ continue;
+
+ if(m_gciBufferList.size()>0) {
+ m_gciBufferList.lock();
+ buffer = m_gciBufferList[0];
+ assert(buffer!=0);
+ if(buffer==0) {
+ m_gciBufferList.unlock();
+// stopApplier(GrepError::REP_APPLY_NULL_GCIBUFFER);
+ return;
+ }
+ m_gciBufferList.unlock();
+
+ RLOG(("Applying %d:[%d]", buffer->getId(), buffer->getGCI()));
+ gci = buffer->getGCI();
+ /**
+ * Do stuff with buffer
+ */
+
+ force = buffer->m_force;
+ itBuffer = new GCIBuffer::iterator(buffer);
+ page = itBuffer->first();
+
+ Record * record;
+ while(page!=0 && m_started) {
+
+ itPage = new GCIPage::iterator(page);
+ record = itPage->first();
+
+ while(record!=0 && m_started) {
+ switch(Record::RecordType(record->recordType)) {
+ case Record::META:
+ mr = (MetaRecord*)record;
+ if(applyMetaRecord(mr, gci) < 0){
+ /**
+ * If we fail with a meta record then
+ * we should fail the replication!
+ */
+ //stopApplier(GrepError::REP_APPLY_METARECORD_FAILED);
+ }
+ break;
+ case Record::LOG:
+ lr = (LogRecord*)record;
+ if(applyLogRecord(lr, force, gci) < 0) {
+ /**
+ * If we fail to apply a log record AND
+ * we have sent a ref to repstate event,
+ * then we should not try to apply another one!
+ */
+// stopApplier(GrepError::REP_APPLY_LOGRECORD_FAILED);
+ }
+ break;
+ default:
+ REPABORT("Illegal record type");
+ };
+ record = itPage->next();
+ }
+ delete itPage;
+ itPage = 0;
+ page = itBuffer->next();
+ }
+
+ m_gciBufferList.erase(0, true);
+ /**
+ * "callback" to RepState to send REP_INSERT_GCIBUFFER_CONF
+ */
+ m_repState->eventInsertConf(buffer->getGCI(), buffer->getId());
+ delete itBuffer;
+ itBuffer = 0;
+ mr = 0;
+ lr = 0;
+ page = 0;
+ buffer = 0;
+ }
+ }
+
+
+}
+
+void AppNDB::startApplier(){
+ m_started = true;
+}
+
+
+void AppNDB::stopApplier(GrepError::Code err){
+ m_started = false;
+ m_repState->eventInsertRef(0,0,0, err);
+}
+
+
+GrepError::Code
+AppNDB::applyBuffer(Uint32 nodeGrp, Uint32 epoch, Uint32 force)
+{
+ m_gciBufferList.lock();
+
+ GCIBuffer * buffer = m_gciContainer->getGCIBuffer(epoch, nodeGrp);
+ if (buffer == NULL) {
+ RLOG(("WARNING! Request to apply NULL buffer %d[%d]. Force %d",
+ nodeGrp, epoch, force));
+ return GrepError::NO_ERROR;
+ }
+ if (!buffer->isComplete()) {
+ RLOG(("WARNING! Request to apply non-complete buffer %d[%d]. Force %d",
+ nodeGrp, epoch, force));
+ return GrepError::REP_APPLY_NONCOMPLETE_GCIBUFFER;
+ }
+ buffer->m_force = force;
+
+ assert(buffer!=0);
+ m_gciBufferList.push_back(buffer, false);
+ NdbCondition_Broadcast(m_cond);
+ m_gciBufferList.unlock();
+ return GrepError::NO_ERROR;
+}
+
+int
+AppNDB::applyLogRecord(LogRecord* lr, bool force, Uint32 gci)
+{
+#if 0
+ RLOG(("Applying log record (force %d, Op %d, GCI %d)",
+ force, lr->operation, gci));
+#endif
+
+ int retries =0;
+ retry:
+ if(retries == 10) {
+ m_repState->eventInsertRef(gci, 0, lr->tableId,
+ GrepError::REP_APPLIER_EXECUTE_TRANSACTION);
+ return -1;
+ }
+ NdbConnection * trans = m_ndb->startTransaction();
+ if (trans == NULL) {
+ /**
+ * Transaction could not be started
+ * @todo Handle the error by:
+ * 1. Return error code
+ * 2. Print log message
+ * 3. On higher level indicate that DB has been tainted
+ */
+ ndbout_c("AppNDB: Send the following error msg to NDB Cluster support");
+ reportNdbError("Cannot start transaction!", trans->getNdbError());
+ m_repState->eventInsertRef(gci, 0, 0,
+ GrepError::REP_APPLIER_START_TRANSACTION);
+ REPABORT("Can not start transaction");
+ }
+
+ /**
+ * Resolve table name based on table id
+ */
+ const Uint32 tableId = lr->tableId;
+ const char * tableName = m_tableInfoPs->getTableName(tableId);
+
+ /**
+ * Close trans and return if it is systab_0.
+ */
+ if (tableId == 0) {
+ RLOG(("WARNING! System table log record received"));
+ m_ndb->closeTransaction(trans);
+ return -1;
+ }
+
+ if (tableName==0) {
+ /**
+ * Table probably does not exist
+ * (Under normal operation this should not happen
+ * since log records should not appear unless the
+ * table has been created.)
+ *
+ * @todo Perhaps the table is not cached due to a restart,
+ * so let's check in the dictionary if it exists.
+ */
+ m_ndb->closeTransaction(trans);
+ m_repState->eventInsertRef(gci, 0, tableId,
+ GrepError::REP_APPLIER_NO_TABLE);
+ return -1;
+ }
+
+ const NdbDictionary::Table * table = m_dict->getTable(tableName);
+
+ NdbOperation * op = trans->getNdbOperation(tableName);
+ if (op == NULL) {
+ ndbout_c("AppNDB: Send the following error msg to NDB Cluster support");
+ reportNdbError("Cannot get NdbOperation record",
+ trans->getNdbError());
+ m_repState->eventInsertRef(gci,0,tableId,
+ GrepError::REP_APPLIER_NO_OPERATION);
+ REPABORT("Can not get NdbOperation record");
+ }
+
+ int check=0;
+ switch(lr->operation) {
+ case TriggerEvent::TE_INSERT: // INSERT
+ check = op->insertTuple();
+ break;
+ case TriggerEvent::TE_DELETE: // DELETE
+ check = op->deleteTuple();
+ break;
+ case TriggerEvent::TE_UPDATE: // UPDATE
+ if (force) {
+ check = op->writeTuple();
+ } else {
+ check = op->updateTuple();
+ }
+ break;
+ case TriggerEvent::TE_CUSTOM: //SCAN
+ check = op->writeTuple();
+ break;
+ default:
+ m_ndb->closeTransaction(trans);
+ return -1;
+ };
+
+ if (check<0) {
+ ndbout_c("AppNDB: Something is weird");
+ }
+
+ /**
+ * @todo index inside LogRecord struct somewhat prettier
+ * Now it 4 (sizeof(Uint32)), and 9 the position inside the struct
+ * where the data starts.
+ */
+ AttributeHeader * ah=(AttributeHeader *)((char *)lr + sizeof(Uint32) * 9);
+ AttributeHeader *end = (AttributeHeader *)(ah + lr->attributeHeaderWSize);
+ Uint32 * dataPtr = (Uint32 *)(end);
+
+ /**
+ * @note attributeheader for operaration insert includes a duplicate
+ * p.k. The quick fix for this problem/bug is to skip the first set of
+ * of p.k, and start from the other set of P.Ks. Data is duplicated for
+ * the p.k.
+ */
+ if (lr->operation == 0) {
+ for(int i = 0; i< table->getNoOfPrimaryKeys(); i++) {
+ ah+=ah->getHeaderSize();
+ dataPtr = dataPtr + ah->getDataSize();
+ }
+ }
+
+ while (ah < end) {
+ const NdbDictionary::Column * column =
+ table->getColumn(ah->getAttributeId());
+ /**
+ * @todo: Here is a limitation. I don't care if it is a tuplekey
+ * that is autogenerated or an ordinary pk. I just whack it in.
+ * However, this must be examined.
+ */
+ if(column->getPrimaryKey()) {
+ if(op->equal(ah->getAttributeId(), (const char *)dataPtr) < 0) {
+ ndbout_c("AppNDB: Equal failed id %d op %d name %s, gci %d force %d",
+ ah->getAttributeId(),
+ lr->operation,
+ column->getName(), gci, force);
+ reportNdbError("Equal!", trans->getNdbError());
+ }
+
+ } else {
+ if(op->setValue(ah->getAttributeId(), (const char *)dataPtr) < 0)
+ ndbout_c("AppNDB: setvalue failed id %d op %d name %s, gci %d force %d",
+ ah->getAttributeId(),
+ lr->operation,
+ column->getName(), gci, force);
+ }
+
+ dataPtr = dataPtr + ah->getDataSize();
+ ah = ah + ah->getHeaderSize() ;
+ }
+
+ if(trans->execute(Commit) != 0) {
+ /**
+ * Transaction commit failure
+ */
+ const NdbError err = trans->getNdbError();
+ m_ndb->closeTransaction(trans);
+ switch(err.status){
+ case NdbError::Success:
+ {
+ m_repState->eventInsertRef(gci, 0, tableId,
+ GrepError::REP_APPLIER_EXECUTE_TRANSACTION);
+ return -1;
+ }
+ break;
+ case NdbError::TemporaryError:
+ {
+ NdbSleep_MilliSleep(50);
+ retries++;
+ goto retry;
+ }
+ break;
+ case NdbError::UnknownResult:
+ {
+ ndbout_c("AppNDB: Send the following error msg to NDB Cluster support");
+ reportNdbError("Execute transaction failed!",
+ trans->getNdbError());
+ m_repState->eventInsertRef(gci, 0, tableId,
+ GrepError::REP_APPLIER_EXECUTE_TRANSACTION);
+ return -1;
+ }
+ break;
+ case NdbError::PermanentError:
+ {
+ if(err.code == 626) {
+ if(force && lr->operation == TriggerEvent::TE_DELETE) /**delete*/ {
+ /**tuple was not found. Ignore this, since
+ * we are trying to apply a "delete a tuple"-log record before
+ * having applied the scan data.
+ */
+ return -1;
+ }
+ }
+
+ ndbout_c("AppNDB: Send the following error msg to NDB Cluster support"); reportNdbError("Execute transaction failed!",
+ trans->getNdbError());
+ ndbout_c("\n\nAppNDB: RepNode will now crash.");
+ m_ndb->closeTransaction(trans);
+ m_repState->eventInsertRef(gci, 0, tableId,
+ GrepError::REP_APPLIER_EXECUTE_TRANSACTION);
+ return -1;
+ }
+ break;
+ }
+ }
+
+ /**
+ * No errors. Close transaction and continue in applierThread.
+ */
+ m_ndb->closeTransaction(trans);
+ return 1;
+}
+
+
+int
+AppNDB::applyMetaRecord(MetaRecord* mr, Uint32 gci)
+{
+ /**
+ * Validate table id
+ */
+ Uint32 tableId = mr->tableId;
+ if (tableId==0) {
+ RLOG(("WARNING! Meta record contained record with tableId 0"));
+ return 0;
+ }
+
+ /**
+ * Prepare meta record
+ */
+ NdbDictionary::Table * table = prepareMetaRecord(mr);
+ if(table == 0) {
+ RLOG(("WARNING! Prepare table meta record failed for table %d", tableId));
+ m_dict->getNdbError();
+ m_repState->eventInsertRef(gci,0,tableId,
+ GrepError::REP_APPLIER_PREPARE_TABLE);
+ return -1;
+ }
+
+ /**
+ * Table does not exist in TableInfoPs -> add it
+ */
+ if(m_tableInfoPs->getTableName(tableId)==0) {
+ RLOG(("Table %d:%s added to m_tableInfoPs", tableId, table->getName()));
+ m_tableInfoPs->insert(tableId,table->getName());
+ }
+
+ /**
+ * Validate that table does not exist in Dict
+ */
+
+ const NdbDictionary::Table * tmpTable = m_dict->getTable(table->getName());
+ if(tmpTable !=0) {
+ /**
+ * Oops, a table with the same name exists
+ */
+ if(tmpTable->getObjectVersion()!=table->getObjectVersion()) {
+ char buf[100];
+ sprintf(buf,"WARNING! Another version of table %d:%s already exists."
+ "Currently, we dont support versions, so will abort now!",
+ tableId, table->getName());
+
+ REPABORT(buf);
+
+ }
+ RLOG(("WARNING! An identical table %d:%s already exists.",
+ tableId, table->getName()));
+ return -1;
+ }
+
+
+ /**
+ * @todo WARNING! Should scan table MR for columns that are not supported
+ */
+ /*
+ NdbDictionary::Column * column;
+
+ for(int i=0; i<table->getNoOfColumns(); i++) {
+ column = table->getColumn(i);
+ if(column->getAutoIncrement()) {
+ reportWarning(table->getName(), column->getName(),
+ "Uses AUTOINCREMENT of PK");
+ }
+ }
+ */
+
+
+ /**
+ * Create table
+ */
+ if(m_dict->createTable(*table)<0) {
+ ndbout_c("AppNDB: Send the following error msg to NDB Cluster support");
+ reportNdbError("Create table failed!", m_dict->getNdbError());
+ m_repState->eventCreateTableRef(gci,
+ tableId,
+ table->getName(),
+ GrepError::REP_APPLIER_CREATE_TABLE);
+ return -1;
+ }
+
+ RLOG(("Table %d:%s created", tableId, table->getName()));
+ return 0;
+}
+
+NdbDictionary::Table*
+AppNDB::prepareMetaRecord(MetaRecord* mr) {
+ NdbTableImpl * tmp = 0;
+ NdbDictionary::Table * table =0;
+ Uint32 * data =(Uint32*)( ((char*)mr + sizeof(Uint32)*6));
+ int res = NdbDictInterface::parseTableInfo(&tmp, data, mr->dataLen,
+ m_ndb->usingFullyQualifiedNames());
+ if(res == 0) {
+ table = tmp;
+ return table;
+ } else{
+ return 0;
+ }
+}
+
+void
+AppNDB::reportNdbError(const char * msg, const NdbError & err) {
+ ndbout_c("%s : Error code %d , error message %s",
+ msg, err.code,
+ (err.message ? err.message : ""));
+}
+
+void
+AppNDB::reportWarning(const char * tableName, const char * message) {
+ ndbout_c("WARNING: Table %s, %s", tableName, message);
+}
+
+void
+AppNDB::reportWarning(const char * tableName, const char * columnName,
+ const char * message) {
+ ndbout_c("WARNING: Table %s, column %s, %s", tableName, columnName,message);
+}
+
+int
+AppNDB::dropTable(Uint32 tableId)
+{
+ char * tableName = m_tableInfoPs->getTableName(tableId);
+ if(tableName == 0) return -1;
+ ndbout_c("AppNDB: Dropping table ");
+ if(m_dict->dropTable(tableName) != 0) {
+ reportNdbError("Failed dropping table",m_dict->getNdbError());
+ return -1;
+ }
+ m_tableInfoPs->del(tableId);
+ return 1;
+}
diff --git a/ndb/src/rep/adapters/AppNDB.hpp b/ndb/src/old_files/rep/adapters/AppNDB.hpp
index 9563a1e41ab..9563a1e41ab 100644
--- a/ndb/src/rep/adapters/AppNDB.hpp
+++ b/ndb/src/old_files/rep/adapters/AppNDB.hpp
diff --git a/ndb/src/rep/adapters/ExtAPI.cpp b/ndb/src/old_files/rep/adapters/ExtAPI.cpp
index 0dcd1e85465..0dcd1e85465 100644
--- a/ndb/src/rep/adapters/ExtAPI.cpp
+++ b/ndb/src/old_files/rep/adapters/ExtAPI.cpp
diff --git a/ndb/src/rep/adapters/ExtAPI.hpp b/ndb/src/old_files/rep/adapters/ExtAPI.hpp
index f10b6c7d682..f10b6c7d682 100644
--- a/ndb/src/rep/adapters/ExtAPI.hpp
+++ b/ndb/src/old_files/rep/adapters/ExtAPI.hpp
diff --git a/ndb/src/old_files/rep/adapters/ExtNDB.cpp b/ndb/src/old_files/rep/adapters/ExtNDB.cpp
new file mode 100644
index 00000000000..6642b750b57
--- /dev/null
+++ b/ndb/src/old_files/rep/adapters/ExtNDB.cpp
@@ -0,0 +1,559 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "ExtNDB.hpp"
+#include "ConfigRetriever.hpp"
+#include <NdbSleep.h>
+
+#include <NdbApiSignal.hpp>
+
+#include <signaldata/DictTabInfo.hpp>
+#include <signaldata/GetTabInfo.hpp>
+#include <signaldata/SumaImpl.hpp>
+#include <AttributeHeader.hpp>
+#include <rep/rep_version.hpp>
+#include <ndb_limits.h>
+
+/*****************************************************************************
+ * Constructor / Destructor / Init
+ *****************************************************************************/
+ExtNDB::ExtNDB(GCIContainerPS * gciContainer, ExtAPI * extAPI)
+{
+ m_grepSender = new ExtSender();
+ if (!m_grepSender) REPABORT("Could not allocate object");
+ m_gciContainerPS = gciContainer;
+
+ m_nodeGroupInfo = new NodeGroupInfo();
+ m_gciContainerPS->setNodeGroupInfo(m_nodeGroupInfo);
+
+ m_doneSetGrepSender = false;
+ m_subId = 0;
+ m_subKey = 0;
+ m_firstGCI = 0;
+ m_dataLogStarted = false;
+
+ m_extAPI = extAPI;
+ if (!m_extAPI) REPABORT("Could not allocate object");
+}
+
+ExtNDB::~ExtNDB()
+{
+ delete m_grepSender;
+ delete m_nodeGroupInfo;
+}
+
+void
+ExtNDB::signalErrorHandler(NdbApiSignal * signal, Uint32 nodeId)
+{
+ //const Uint32 gsn = signal->readSignalNumber();
+ //const Uint32 len = signal->getLength();
+ RLOG(("Send signal failed. Signal %p", signal));
+}
+
+bool
+ExtNDB::init(const char * connectString)
+{
+ m_signalExecThread = NdbThread_Create(signalExecThread_C,
+ (void **)this,
+ 32768,
+ "ExtNDB_Service",
+ NDB_THREAD_PRIO_LOW);
+
+#if 0
+ /**
+ * I don't see that this does anything
+ *
+ * Jonas 13/2-04
+ */
+ ConfigRetriever cr; cr.setConnectString(connectString);
+
+ ndb_mgm_configuration * config = cr.getConfig(NDB_VERSION, NODE_TYPE_REP);
+ if (config == 0) {
+ ndbout << "ExtNDB: Configuration error: ";
+ const char* erString = cr.getErrorString();
+ if (erString == 0) {
+ erString = "No error specified!";
+ }
+ ndbout << erString << endl;
+ return false;
+ }
+ NdbAutoPtr autoPtr(config);
+ m_ownNodeId = r.getOwnNodeId();
+
+ /**
+ * Check which GREPs to connect to (in configuration)
+ *
+ * @note SYSTEM LIMITATION: Only connects to one GREP
+ */
+ Uint32 noOfConnections=0;
+ NodeId grepNodeId=0;
+ const Properties * connection;
+
+ config->get("NoOfConnections", &noOfConnections);
+ for (Uint32 i=0; i<noOfConnections; i++) {
+ Uint32 nodeId1, nodeId2;
+ config->get("Connection", i, &connection);
+ connection->get("NodeId1", &nodeId1);
+ connection->get("NodeId2", &nodeId2);
+ if (!connection->contains("System1") &&
+ !connection->contains("System2") &&
+ (nodeId1 == m_ownNodeId || nodeId2 == m_ownNodeId)) {
+ /**
+ * Found connection
+ */
+ if (nodeId1 == m_ownNodeId) {
+ grepNodeId = nodeId2;
+ } else {
+ grepNodeId = nodeId1;
+ }
+ }
+ }
+#endif
+
+ m_transporterFacade = TransporterFacade::instance();
+
+ assert(m_transporterFacade != 0);
+
+ m_ownBlockNo = m_transporterFacade->open(this, execSignal, execNodeStatus);
+ assert(m_ownBlockNo > 0);
+ m_ownRef = numberToRef(m_ownBlockNo, m_ownNodeId);
+ ndbout_c("EXTNDB blockno %d ownref %d ", m_ownBlockNo, m_ownRef);
+ assert(m_ownNodeId == m_transporterFacade->ownId());
+
+ m_grepSender->setOwnRef(m_ownRef);
+ m_grepSender->setTransporterFacade(m_transporterFacade);
+
+ if(!m_grepSender->connected(50000)){
+ ndbout_c("ExtNDB: Failed to connect to DB nodes!");
+ ndbout_c("ExtNDB: Tried to create transporter as (node %d, block %d).",
+ m_ownNodeId, m_ownBlockNo);
+ ndbout_c("ExtNDB: Check that DB nodes are started.");
+ return false;
+ }
+ ndbout_c("Phase 3 (ExtNDB): Connection %d to NDB Cluster opened (Extractor)",
+ m_ownBlockNo);
+
+ for (Uint32 i=1; i<MAX_NDB_NODES; i++) {
+ if (m_transporterFacade->getIsDbNode(i) &&
+ m_transporterFacade->getIsNodeSendable(i))
+ {
+ Uint32 nodeGrp = m_transporterFacade->getNodeGrp(i);
+ m_nodeGroupInfo->addNodeToNodeGrp(i, true, nodeGrp);
+ Uint32 nodeId = m_nodeGroupInfo->getFirstConnectedNode(nodeGrp);
+ m_grepSender->setNodeId(nodeId);
+ if(m_nodeGroupInfo->getPrimaryNode(nodeGrp) == 0) {
+ m_nodeGroupInfo->setPrimaryNode(nodeGrp, nodeId);
+ }
+ m_doneSetGrepSender = true;
+#if 0
+ RLOG(("Added node %d to node group %d", i, nodeGrp));
+#endif
+ }
+ }
+
+ return true;
+}
+
+/*****************************************************************************
+ * Signal Queue Executor
+ *****************************************************************************/
+
+class SigMatch
+{
+public:
+ int gsn;
+ void (ExtNDB::* function)(NdbApiSignal *signal);
+
+ SigMatch() { gsn = 0; function = NULL; };
+
+ SigMatch(int _gsn, void (ExtNDB::* _function)(NdbApiSignal *signal)) {
+ gsn = _gsn;
+ function = _function;
+ };
+
+ bool check(NdbApiSignal *signal) {
+ if(signal->readSignalNumber() == gsn)
+ return true;
+ return false;
+ };
+};
+
+extern "C"
+void *signalExecThread_C(void *r)
+{
+ ExtNDB *grepps = (ExtNDB*)r;
+
+ grepps->signalExecThreadRun();
+
+ NdbThread_Exit(0);
+ /* NOTREACHED */
+ return 0;
+}
+
+
+void
+ExtNDB::signalExecThreadRun()
+{
+ Vector<SigMatch> sl;
+
+ /**
+ * Signals to be executed
+ */
+ sl.push_back(SigMatch(GSN_SUB_GCP_COMPLETE_REP,
+ &ExtNDB::execSUB_GCP_COMPLETE_REP));
+
+ /**
+ * Is also forwarded to SSCoord
+ */
+ sl.push_back(SigMatch(GSN_GREP_SUB_START_CONF,
+ &ExtNDB::execGREP_SUB_START_CONF));
+ sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_CONF,
+ &ExtNDB::execGREP_SUB_CREATE_CONF));
+ sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_CONF,
+ &ExtNDB::execGREP_SUB_REMOVE_CONF));
+ /**
+ * Signals to be forwarded
+ */
+ sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_CONF,
+ &ExtNDB::execGREP_CREATE_SUBID_CONF));
+
+ sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_CONF, &ExtNDB::sendSignalRep));
+
+ sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_REF, &ExtNDB::sendSignalRep));
+ sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_REF, &ExtNDB::sendSignalRep));
+ sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_REF, &ExtNDB::sendSignalRep));
+
+ sl.push_back(SigMatch(GSN_GREP_SUB_START_REF, &ExtNDB::sendSignalRep));
+ sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_REF, &ExtNDB::sendSignalRep));
+
+
+ while(1) {
+ SigMatch *handler = NULL;
+ NdbApiSignal *signal = NULL;
+
+ if(m_signalRecvQueue.waitFor(sl, handler, signal, DEFAULT_TIMEOUT)) {
+#if 0
+ RLOG(("Removed signal from queue (GSN: %d, QSize: %d)",
+ signal->readSignalNumber(), m_signalRecvQueue.size()));
+#endif
+ if(handler->function != 0) {
+ (this->*handler->function)(signal);
+ delete signal; signal = 0;
+ } else {
+ REPABORT("Illegal handler for signal");
+ }
+ }
+ }
+}
+
+void
+ExtNDB::sendSignalRep(NdbApiSignal * s)
+{
+ if(m_repSender->sendSignal(s) == -1)
+ {
+ signalErrorHandler(s, 0);
+ }
+}
+
+void
+ExtNDB::execSignal(void* executorObj, NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3])
+{
+ ExtNDB * executor = (ExtNDB*)executorObj;
+
+ const Uint32 gsn = signal->readSignalNumber();
+ const Uint32 len = signal->getLength();
+
+ NdbApiSignal * s = new NdbApiSignal(executor->m_ownRef);
+ switch(gsn){
+ case GSN_SUB_GCP_COMPLETE_REP:
+ case GSN_GREP_CREATE_SUBID_CONF:
+ case GSN_GREP_SUB_CREATE_CONF:
+ case GSN_GREP_SUB_START_CONF:
+ case GSN_GREP_SUB_SYNC_CONF:
+ case GSN_GREP_SUB_REMOVE_CONF:
+ case GSN_GREP_CREATE_SUBID_REF:
+ case GSN_GREP_SUB_CREATE_REF:
+ case GSN_GREP_SUB_START_REF:
+ case GSN_GREP_SUB_SYNC_REF:
+ case GSN_GREP_SUB_REMOVE_REF:
+ s->set(0, SSREPBLOCKNO, gsn, len);
+ memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
+ executor->m_signalRecvQueue.receive(s);
+ break;
+ case GSN_SUB_TABLE_DATA:
+ executor->execSUB_TABLE_DATA(signal, ptr);
+ delete s; s=0;
+ break;
+ case GSN_SUB_META_DATA:
+ executor->execSUB_META_DATA(signal, ptr);
+ delete s; s=0;
+ break;
+ default:
+ REPABORT1("Illegal signal received in execSignal", gsn);
+ }
+ s=0;
+#if 0
+ ndbout_c("ExtNDB: Inserted signal into queue (GSN: %d, Len: %d)",
+ signal->readSignalNumber(), len);
+#endif
+}
+
+void
+ExtNDB::execNodeStatus(void* obj, Uint16 nodeId, bool alive, bool nfCompleted)
+{
+ ExtNDB * thisObj = (ExtNDB*)obj;
+
+ RLOG(("Changed node status (Id %d, Alive %d, nfCompleted %d)",
+ nodeId, alive, nfCompleted));
+
+ if(alive) {
+ /**
+ * Connected
+ */
+ Uint32 nodeGrp = thisObj->m_transporterFacade->getNodeGrp(nodeId);
+ RLOG(("DB node %d of node group %d connected", nodeId, nodeGrp));
+
+ thisObj->m_nodeGroupInfo->addNodeToNodeGrp(nodeId, true, nodeGrp);
+ Uint32 firstNode = thisObj->m_nodeGroupInfo->getPrimaryNode(nodeGrp);
+
+ if(firstNode == 0)
+ thisObj->m_nodeGroupInfo->setPrimaryNode(nodeGrp, nodeId);
+
+ if (!thisObj->m_doneSetGrepSender) {
+ thisObj->m_grepSender->setNodeId(firstNode);
+ thisObj->m_doneSetGrepSender = true;
+ }
+
+ RLOG(("Connect: First connected node in nodegroup: %d",
+ thisObj->m_nodeGroupInfo->getPrimaryNode(nodeGrp)));
+
+ } else if (!nfCompleted) {
+
+ /**
+ * Set node as "disconnected" in m_nodeGroupInfo until
+ * node comes up again.
+ */
+ Uint32 nodeGrp = thisObj->m_transporterFacade->getNodeGrp(nodeId);
+ RLOG(("DB node %d of node group %d disconnected",
+ nodeId, nodeGrp));
+ thisObj->m_nodeGroupInfo->setConnectStatus(nodeId, false);
+ /**
+ * The node that crashed was also the primary node, the we must change
+ * primary node
+ */
+ if(nodeId == thisObj->m_nodeGroupInfo->getPrimaryNode(nodeGrp)) {
+ Uint32 node = thisObj->m_nodeGroupInfo->getFirstConnectedNode(nodeGrp);
+ if(node > 0) {
+ thisObj->m_grepSender->setNodeId(node);
+ thisObj->m_nodeGroupInfo->setPrimaryNode(nodeGrp, node);
+ }
+ else {
+ thisObj->sendDisconnectRep(nodeGrp);
+ }
+ }
+ RLOG(("Disconnect: First connected node in nodegroup: %d",
+ thisObj->m_nodeGroupInfo->getPrimaryNode(nodeGrp)));
+
+ } else if(nfCompleted) {
+ } else {
+ REPABORT("Function execNodeStatus with wrong parameters");
+ }
+}
+
+/*****************************************************************************
+ * Signal Receivers for LOG and SCAN
+ *****************************************************************************/
+
+/**
+ * Receive datalog/datascan from GREP/SUMA
+ */
+void
+ExtNDB::execSUB_TABLE_DATA(NdbApiSignal * signal, LinearSectionPtr ptr[3])
+{
+ SubTableData * const data = (SubTableData*)signal->getDataPtr();
+ Uint32 tableId = data->tableId;
+ Uint32 operation = data->operation;
+ Uint32 gci = data->gci;
+ Uint32 nodeId = refToNode(signal->theSendersBlockRef);
+
+ if((SubTableData::LogType)data->logType == SubTableData::SCAN)
+ {
+ Uint32 nodeGrp = m_nodeGroupInfo->findNodeGroup(nodeId);
+
+ NodeGroupInfo::iterator * it;
+ it = new NodeGroupInfo::iterator(nodeGrp, m_nodeGroupInfo);
+ for(NodeConnectInfo * nci=it->first(); it->exists();nci=it->next()) {
+ m_gciContainerPS->insertLogRecord(nci->nodeId, tableId,
+ operation, ptr, gci);
+ }
+ delete it; it = 0;
+ } else {
+ m_gciContainerPS->insertLogRecord(nodeId, tableId, operation, ptr, gci);
+ }
+}
+
+/**
+ * Receive metalog/metascan from GREP/SUMA
+ */
+void
+ExtNDB::execSUB_META_DATA(NdbApiSignal * signal, LinearSectionPtr ptr[3])
+{
+ Uint32 nodeId = refToNode(signal->theSendersBlockRef);
+ SubMetaData * const data = (SubMetaData*)signal->getDataPtr();
+ Uint32 tableId = data->tableId;
+ Uint32 gci = data->gci;
+
+ Uint32 nodeGrp = m_nodeGroupInfo->findNodeGroup(nodeId);
+
+ NodeGroupInfo::iterator * it;
+ it = new NodeGroupInfo::iterator(nodeGrp, m_nodeGroupInfo);
+ for(NodeConnectInfo * nci=it->first(); it->exists();nci=it->next()) {
+ m_gciContainerPS->insertMetaRecord(nci->nodeId, tableId, ptr, gci);
+ RLOG(("Received meta record in %d[%d]", nci->nodeId, gci));
+ }
+
+ delete it; it = 0;
+}
+
+
+/*****************************************************************************
+ * Signal Receivers (Signals that are actually just forwarded to SS REP)
+ *****************************************************************************/
+
+void
+ExtNDB::execGREP_CREATE_SUBID_CONF(NdbApiSignal * signal)
+{
+ CreateSubscriptionIdConf const * conf =
+ (CreateSubscriptionIdConf *)signal->getDataPtr();
+ Uint32 subId = conf->subscriptionId;
+ Uint32 subKey = conf->subscriptionKey;
+ ndbout_c("GREP_CREATE_SUBID_CONF m_extAPI=%p\n", m_extAPI);
+ m_extAPI->eventSubscriptionIdCreated(subId, subKey);
+}
+
+/*****************************************************************************
+ * Signal Receivers
+ *****************************************************************************/
+
+/**
+ * Receive information about completed GCI from GREP/SUMA
+ *
+ * GCI completed, i.e. no more unsent log records exists in SUMA
+ * @todo use node id to identify buffers?
+ */
+void
+ExtNDB::execSUB_GCP_COMPLETE_REP(NdbApiSignal * signal)
+{
+ SubGcpCompleteRep * const rep = (SubGcpCompleteRep*)signal->getDataPtr();
+ const Uint32 gci = rep->gci;
+ Uint32 nodeId = refToNode(rep->senderRef);
+
+ RLOG(("Epoch %d completed at node %d", gci, nodeId));
+ m_gciContainerPS->setCompleted(gci, nodeId);
+
+ if(m_firstGCI == gci && !m_dataLogStarted) {
+ sendGREP_SUB_START_CONF(signal, m_firstGCI);
+ m_dataLogStarted = true;
+ }
+}
+
+/**
+ * Send info that scan is competed to SS REP
+ *
+ * @todo Use node id to identify buffers?
+ */
+void
+ExtNDB::sendGREP_SUB_START_CONF(NdbApiSignal * signal, Uint32 gci)
+{
+ RLOG(("Datalog started (Epoch %d)", gci));
+ GrepSubStartConf * conf = (GrepSubStartConf *)signal->getDataPtrSend();
+ conf->firstGCI = gci;
+ conf->subscriptionId = m_subId;
+ conf->subscriptionKey = m_subKey;
+ conf->part = SubscriptionData::TableData;
+ signal->m_noOfSections = 0;
+ signal->set(0, SSREPBLOCKNO, GSN_GREP_SUB_START_CONF,
+ GrepSubStartConf::SignalLength);
+ sendSignalRep(signal);
+}
+
+/**
+ * Scan is completed... says SUMA/GREP
+ *
+ * @todo Use node id to identify buffers?
+ */
+void
+ExtNDB::execGREP_SUB_START_CONF(NdbApiSignal * signal)
+{
+ GrepSubStartConf * const conf = (GrepSubStartConf *)signal->getDataPtr();
+ Uint32 part = conf->part;
+ //Uint32 nodeId = refToNode(conf->senderRef);
+ m_firstGCI = conf->firstGCI;
+
+ if (part == SubscriptionData::TableData) {
+ RLOG(("Datalog started (Epoch %d)", m_firstGCI));
+ return;
+ }
+ RLOG(("Metalog started (Epoch %d)", m_firstGCI));
+
+ signal->set(0, SSREPBLOCKNO, GSN_GREP_SUB_START_CONF,
+ GrepSubStartConf::SignalLength);
+ sendSignalRep(signal);
+}
+
+/**
+ * Receive no of node groups that PS has and pass signal on to SS
+ */
+void
+ExtNDB::execGREP_SUB_CREATE_CONF(NdbApiSignal * signal)
+{
+ GrepSubCreateConf * conf = (GrepSubCreateConf *)signal->getDataPtrSend();
+ m_subId = conf->subscriptionId;
+ m_subKey = conf->subscriptionKey;
+
+ conf->noOfNodeGroups = m_nodeGroupInfo->getNoOfNodeGroups();
+ sendSignalRep(signal);
+}
+
+/**
+ * Receive conf that subscription has been remove in GREP/SUMA
+ *
+ * Pass signal on to TransPS
+ */
+void
+ExtNDB::execGREP_SUB_REMOVE_CONF(NdbApiSignal * signal)
+{
+ m_gciContainerPS->reset();
+ sendSignalRep(signal);
+}
+
+/**
+ * If all PS nodes has disconnected, then remove all epochs
+ * for this subscription.
+ */
+void
+ExtNDB::sendDisconnectRep(Uint32 nodeId)
+{
+ NdbApiSignal * signal = new NdbApiSignal(m_ownRef);
+ signal->set(0, SSREPBLOCKNO, GSN_REP_DISCONNECT_REP,
+ RepDisconnectRep::SignalLength);
+ RepDisconnectRep * rep = (RepDisconnectRep*) signal->getDataPtrSend();
+ rep->nodeId = nodeId;
+ rep->subId = m_subId;
+ rep->subKey = m_subKey;
+ sendSignalRep(signal);
+}
diff --git a/ndb/src/old_files/rep/adapters/ExtNDB.hpp b/ndb/src/old_files/rep/adapters/ExtNDB.hpp
new file mode 100644
index 00000000000..228c980fd06
--- /dev/null
+++ b/ndb/src/old_files/rep/adapters/ExtNDB.hpp
@@ -0,0 +1,118 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef EXTNDB_HPP
+#define EXTNDB_HPP
+
+#include <ndb_global.h>
+
+#include <TransporterDefinitions.hpp>
+#include <TransporterFacade.hpp>
+#include <ClusterMgr.hpp>
+#include <API.hpp>
+#include <Vector.hpp>
+
+#include <signaldata/RepImpl.hpp>
+#include <signaldata/GrepImpl.hpp>
+
+#include <rep/SignalQueue.hpp>
+#include <rep/ExtSender.hpp>
+
+#include <rep/storage/GCIContainerPS.hpp>
+#include "ExtAPI.hpp"
+
+extern "C" {
+static void * signalExecThread_C(void *);
+}
+
+/**
+ * @class ExtNDB
+ * @brief Class responsible for connection to primary system GREP
+ */
+class ExtNDB
+{
+public:
+ /***************************************************************************
+ * Constructor / Destructor
+ ***************************************************************************/
+ ExtNDB(GCIContainerPS * gciContainer, ExtAPI * extAPI);
+ ~ExtNDB();
+ bool init(const char * connectString = NULL);
+
+ /***************************************************************************
+ * Public Methods
+ ***************************************************************************/
+ void setGrepSender(ExtSender * es) { m_grepSender = es; };
+ ExtSender * getGrepSender() { return m_grepSender; };
+ void setRepSender(ExtSender * es) {
+ m_extAPI->setRepSender(es); m_repSender = es; };
+ void signalErrorHandler(NdbApiSignal * s, Uint32 nodeId);
+
+private:
+ friend void * signalExecThread_C(void *);
+ void signalExecThreadRun();
+
+ static void execSignal(void* signalSender, NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3]);
+
+ static void execNodeStatus(void* signalSender, NodeId,
+ bool alive, bool nfCompleted);
+
+ void sendSignalRep(NdbApiSignal *);
+ void sendDisconnectRep(Uint32 nodeId);
+
+ /***************************************************************************
+ * Signal Executors
+ ***************************************************************************/
+ void execSUB_GCP_COMPLETE_REP(NdbApiSignal*);
+ void execGREP_SUB_CREATE_CONF(NdbApiSignal * signal);
+ void execGREP_SUB_REMOVE_CONF(NdbApiSignal * signal);
+ void execGREP_SUB_START_CONF(NdbApiSignal * signal);
+ void sendGREP_SUB_START_CONF(NdbApiSignal * signal, Uint32 gci);
+ void execSUB_TABLE_DATA(NdbApiSignal * signal,LinearSectionPtr ptr[3]);
+ void execSUB_META_DATA(NdbApiSignal * signal,LinearSectionPtr ptr[3]);
+
+ // Signals that are actually just fowarded to REP
+ void execGREP_CREATE_SUBID_CONF(NdbApiSignal *);
+
+ /***************************************************************************
+ * Private Variables
+ ***************************************************************************/
+ struct NdbThread * m_signalExecThread;
+ class SignalQueue m_signalRecvQueue;
+
+ Uint32 m_ownNodeId; ///< NodeId of this node
+ Uint32 m_ownBlockNo; ///< BlockNo of this "block"
+ BlockReference m_ownRef; ///< Reference to this
+
+ ExtSender * m_grepSender; ///< Responsible send to GREP
+ ExtSender * m_repSender; ///< Responsible send to SS REP
+
+ NodeGroupInfo * m_nodeGroupInfo;
+ GCIContainerPS * m_gciContainerPS; ///< Interface to GCICotainer
+ ///< seen by PS
+ TransporterFacade * m_transporterFacade;
+
+ bool m_doneSetGrepSender; ///< Only done once
+ bool m_dataLogStarted;
+ Uint32 m_subId;
+ Uint32 m_subKey;
+ Uint32 m_firstGCI;
+
+ ExtAPI * m_extAPI;
+};
+
+#endif
diff --git a/ndb/src/rep/adapters/Makefile b/ndb/src/old_files/rep/adapters/Makefile
index bdd711510c3..bdd711510c3 100644
--- a/ndb/src/rep/adapters/Makefile
+++ b/ndb/src/old_files/rep/adapters/Makefile
diff --git a/ndb/src/rep/adapters/TableInfoPs.hpp b/ndb/src/old_files/rep/adapters/TableInfoPs.hpp
index 3fa25979255..3fa25979255 100644
--- a/ndb/src/rep/adapters/TableInfoPs.hpp
+++ b/ndb/src/old_files/rep/adapters/TableInfoPs.hpp
diff --git a/ndb/src/rep/dbug_hack.cpp b/ndb/src/old_files/rep/dbug_hack.cpp
index 74e5f080777..74e5f080777 100644
--- a/ndb/src/rep/dbug_hack.cpp
+++ b/ndb/src/old_files/rep/dbug_hack.cpp
diff --git a/ndb/src/rep/rep_version.hpp b/ndb/src/old_files/rep/rep_version.hpp
index 3830f9c351c..3830f9c351c 100644
--- a/ndb/src/rep/rep_version.hpp
+++ b/ndb/src/old_files/rep/rep_version.hpp
diff --git a/ndb/src/rep/repapi/Makefile b/ndb/src/old_files/rep/repapi/Makefile
index fdd153f1060..fdd153f1060 100644
--- a/ndb/src/rep/repapi/Makefile
+++ b/ndb/src/old_files/rep/repapi/Makefile
diff --git a/ndb/src/rep/repapi/repapi.cpp b/ndb/src/old_files/rep/repapi/repapi.cpp
index d34ab098c9c..d34ab098c9c 100644
--- a/ndb/src/rep/repapi/repapi.cpp
+++ b/ndb/src/old_files/rep/repapi/repapi.cpp
diff --git a/ndb/src/rep/repapi/repapi.h b/ndb/src/old_files/rep/repapi/repapi.h
index 170e493cd86..170e493cd86 100644
--- a/ndb/src/rep/repapi/repapi.h
+++ b/ndb/src/old_files/rep/repapi/repapi.h
diff --git a/ndb/src/old_files/rep/state/Channel.cpp b/ndb/src/old_files/rep/state/Channel.cpp
new file mode 100644
index 00000000000..a7f7b90d3fe
--- /dev/null
+++ b/ndb/src/old_files/rep/state/Channel.cpp
@@ -0,0 +1,487 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Channel.hpp"
+
+Channel::Channel()
+{
+ reset();
+}
+
+Channel::~Channel()
+{
+ /**
+ * Destroy list of selected tables
+ */
+ for(Uint32 i=0; i < m_selectedTables.size(); i++) {
+ delete m_selectedTables[i];
+ m_selectedTables[i] = 0;
+ }
+ m_selectedTables=0;
+}
+
+void
+Channel::reset()
+{
+ for (Uint32 i=0; i<MAX_NO_OF_NODE_GROUPS; i++) {
+ for (Uint32 j=0; j<NO_OF_POSITIONS; j++) {
+ state[i][j].set(1,0);
+ }
+ }
+ m_noOfNodeGroups = 0;
+ m_requestorEnabled = true;
+ m_transferEnabled = true;
+ m_applyEnabled = true;
+ m_deleteEnabled = true;
+ m_autoStartEnabled = false;
+ m_stopEpochId = intervalMax;
+ setSubKey(0);
+ setSubId(0);
+ m_stateSub = NO_SUBSCRIPTION_EXISTS;
+ m_stateRep = CONSISTENT;
+ m_metaScanEpochs = emptyInterval;
+ m_dataScanEpochs = emptyInterval;
+}
+
+bool
+Channel::requestTransfer(Uint32 nodeGrp, Interval * i)
+{
+ invariant();
+ Interval tmp1, tmp2;
+
+ // i = PS - SSReq - SS - App
+ intervalLeftMinus(state[nodeGrp][PS], state[nodeGrp][SSReq], &tmp1);
+ intervalLeftMinus(tmp1, state[nodeGrp][SS], &tmp2);
+ intervalLeftMinus(tmp2, state[nodeGrp][App], i);
+
+ i->onlyLeft(GREP_SYSTEM_TABLE_MAX_RANGE);
+ i->onlyUpToValue(m_stopEpochId);
+ if (i->isEmpty()) return false;
+
+ add(SSReq, nodeGrp, *i);
+ invariant();
+ return true;
+}
+
+bool
+Channel::requestApply(Uint32 nodeGrp, Uint32 * epoch)
+{
+ invariant();
+ Interval tmp1, tmp2;
+
+ // tmp2 = SS - AppReq - App
+ intervalLeftMinus(state[nodeGrp][SS], state[nodeGrp][AppReq], &tmp1);
+ intervalLeftMinus(tmp1, state[nodeGrp][App], &tmp2);
+
+ tmp2.onlyUpToValue(m_stopEpochId);
+ if (tmp2.isEmpty()) return false;
+ tmp2.onlyLeft(1);
+
+ // Check that all GCI Buffers for epoch exists in SS
+ for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
+ if (!state[nodeGrp][SS].inInterval(tmp2.first()))
+ return false;
+ }
+
+ invariant();
+ add(AppReq, nodeGrp, tmp2);
+ invariant();
+ *epoch = tmp2.first();
+ return true;
+}
+
+bool
+Channel::requestDelete(Uint32 nodeGrp, Interval * i)
+{
+ invariant();
+ Interval tmp1;
+
+ // i = (App cut PS) - DelReq
+ intervalCut(state[nodeGrp][App], state[nodeGrp][PS], &tmp1);
+ intervalLeftMinus(tmp1, state[nodeGrp][DelReq], i);
+
+ if (i->isEmpty()) return false;
+ i->onlyLeft(GREP_SYSTEM_TABLE_MAX_RANGE);
+
+ invariant();
+ add(DelReq, nodeGrp, *i);
+ invariant();
+ return true;
+}
+
+void
+Channel::add(Position pos, Uint32 nodeGrp, const Interval i)
+{
+ Interval r;
+ intervalAdd(state[nodeGrp][pos], i, &r);
+ state[nodeGrp][pos].set(r);
+}
+
+void
+Channel::clear(Position p, Uint32 nodeGrp, const Interval i)
+{
+ Interval r;
+ intervalLeftMinus(state[nodeGrp][p], i, &r);
+ state[nodeGrp][p].set(r);
+}
+
+bool
+Channel::isSynchable(Uint32 nodeGrp)
+{
+ return true;
+ /*
+ @todo This should be implemented...
+
+ Interval tmp1, tmp2;
+ intervalAdd(state[nodeGrp][PS], state[nodeGrp][SSReq], &tmp1);
+ intervalAdd(tmp1, state[nodeGrp][SSReq], &tmp2);
+ intervalAdd(tmp2, state[nodeGrp][SS], &tmp1);
+ intervalAdd(tmp1, state[nodeGrp][AppReq], &tmp2);
+ intervalAdd(tmp2, state[nodeGrp][App], &tmp1);
+ if (intervalInclude(state[nodeGrp][PS], tmp1.right()))
+ return true;
+ else
+ return false;
+ */
+}
+
+/**
+ * Return the cut of all App:s.
+ */
+void
+Channel::getFullyAppliedEpochs(Interval * interval)
+{
+ if (m_noOfNodeGroups < 1) {
+ *interval = emptyInterval;
+ return;
+ }
+
+ *interval = universeInterval;
+ for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
+ if (state[i][App].isEmpty()) {
+ *interval = emptyInterval;
+ return;
+ }
+
+ if (interval->first() < state[i][App].first()) {
+ interval->setFirst(state[i][App].first());
+ }
+ if (state[i][App].last() < interval->last()) {
+ interval->setLast(state[i][App].last());
+ }
+ }
+ interval->normalize();
+ return;
+}
+
+/**
+ * Return true if it is ok to remove the subscription and then stop channel
+ */
+bool
+Channel::isStoppable()
+{
+ /**
+ * Check that AppReq are empty for all nodegrps
+ */
+ for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
+ if (!state[i][AppReq].isEmpty()) {
+ RLOG(("Stop disallowed. AppReq is non-empty"));
+ return false;
+ }
+ }
+
+ /**
+ * If stop immediately, then it is ok to stop now
+ */
+ if (m_stopEpochId == 0) {
+ RLOG(("Stop allowed. AppReq empty and immediate stop requested"));
+ return true;
+ }
+
+ /**
+ * If stop on a certain epoch, then
+ * check that stopEpochId is equal to the last applied epoch
+ */
+ Interval interval;
+ getFullyAppliedEpochs(&interval);
+ if (m_stopEpochId > interval.last()) {
+ RLOG(("Stop disallowed. AppReq empty. Stop %d, LastApplied %d",
+ m_stopEpochId, interval.last()));
+ return false;
+ }
+
+ return true;
+}
+
+GrepError::Code
+Channel::setStopEpochId(Uint32 n)
+{
+ /**
+ * If n equal to zero, use next possible epoch (max(App, AppReq))
+ */
+ if (n == 0) {
+ for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
+ n = (state[i][App].last() > n) ? state[i][App].last() : n;
+ n = (state[i][AppReq].last() > n) ? state[i][AppReq].last() : n;
+ }
+ }
+
+ /**
+ * If n >= max(App, AppReq) then set value, else return error code
+ */
+ for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
+ if (n < state[i][App].last()) return GrepError::ILLEGAL_STOP_EPOCH_ID;
+ if (n < state[i][AppReq].last()) return GrepError::ILLEGAL_STOP_EPOCH_ID;
+ }
+
+ m_stopEpochId = n;
+ return GrepError::NO_ERROR;
+};
+
+bool
+Channel::shouldStop()
+{
+ /**
+ * If (m_stopEpochId == App) then channel should stop
+ */
+ for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
+ if(m_stopEpochId != state[i][App].last()) return false;
+ }
+ return true;
+}
+
+/*****************************************************************************
+ * SELECTIVE TABLE INTERFACE
+ *****************************************************************************/
+
+GrepError::Code
+Channel::addTable(const char * tableName)
+{
+ if(strlen(tableName)>MAX_TAB_NAME_SIZE)
+ return GrepError::REP_NOT_PROPER_TABLE;
+ /**
+ * No of separators are the number of table_name_separator found in tableName
+ * since a table is defined as <db>/<schema>/tablename.
+ * if noOfSeparators is not equal to 2, then it is not a valid
+ * table name.
+ */
+ Uint32 noOfSeps = 0;
+ if(strlen(tableName) < 5)
+ return GrepError::REP_NOT_PROPER_TABLE;
+ for(Uint32 i =0; i < strlen(tableName); i++)
+ if(tableName[i]==table_name_separator)
+ noOfSeps++;
+ if(noOfSeps!=2)
+ return GrepError::REP_NOT_PROPER_TABLE;
+ table * t= new table(tableName);
+ for(Uint32 i=0; i<m_selectedTables.size(); i++) {
+ if(strcmp(tableName, m_selectedTables[i]->tableName)==0)
+ return GrepError::REP_TABLE_ALREADY_SELECTED;
+ }
+ m_selectedTables.push_back(t);
+ return GrepError::NO_ERROR;
+}
+
+GrepError::Code
+Channel::removeTable(const char * tableName)
+{
+ if(strlen(tableName)>MAX_TAB_NAME_SIZE)
+ return GrepError::REP_NOT_PROPER_TABLE;
+ /**
+ * No of separators are the number of table_name_separator found in tableName
+ * since a table is defined as <db>/<schema>/tablename.
+ * If noOfSeparators is not equal to 2,
+ * then it is not a valid table name.
+ */
+ Uint32 noOfSeps = 0;
+ if(strlen(tableName) < 5)
+ return GrepError::REP_NOT_PROPER_TABLE;
+ for(Uint32 i =0; i < strlen(tableName); i++)
+ if(tableName[i]==table_name_separator)
+ noOfSeps++;
+ if(noOfSeps!=2)
+ return GrepError::REP_NOT_PROPER_TABLE;
+ for(Uint32 i=0; i<m_selectedTables.size(); i++) {
+ if(strcmp(tableName, m_selectedTables[i]->tableName)==0) {
+ delete m_selectedTables[i];
+ m_selectedTables.erase(i);
+ return GrepError::NO_ERROR;
+ }
+ }
+ return GrepError::REP_TABLE_NOT_FOUND;
+}
+
+void
+Channel::printTables()
+{
+ if(m_selectedTables.size() == 0)
+ ndbout_c("| ALL TABLES "
+ " |");
+ else {
+ for(Uint32 i=0; i<m_selectedTables.size(); i++)
+ ndbout_c("| %-69s |", m_selectedTables[i]->tableName);
+ }
+}
+
+Vector<struct table *> *
+Channel::getSelectedTables()
+{
+ if(m_selectedTables.size() == 0) return 0;
+ return &m_selectedTables;
+}
+
+/*****************************************************************************
+ * PRINT
+ *****************************************************************************/
+
+void
+Channel::print(Position pos)
+{
+ switch(pos){
+ case PS: ndbout << "PS Rep"; break;
+ case SSReq: ndbout << "Tra-Req"; break;
+ case SS: ndbout << "SS Rep"; break;
+ case AppReq: ndbout << "App-Req"; break;
+ case App: ndbout << "Applied"; break;
+ case DelReq: ndbout << "Del-Req"; break;
+ default: REPABORT("Unknown replication position");
+ }
+}
+
+void
+Channel::print()
+{
+ for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
+ print(i);
+ }
+}
+
+void
+Channel::print(Position pos, Uint32 nodeGrp)
+{
+ print(pos);
+ if (state[nodeGrp][pos].first() == 1 && state[nodeGrp][pos].last() == 0) {
+ ndbout << " EMPTY";
+ } else {
+ ndbout << " [" << state[nodeGrp][pos].first() << "-"
+ << state[nodeGrp][pos].last() << "]";
+ }
+}
+
+static const char*
+channelline =
+"+-------------------------------------------------------------------------+\n"
+;
+
+void
+Channel::getEpochState(Position p,
+ Uint32 nodeGrp,
+ Uint32 * first,
+ Uint32 * last) {
+ if(state[nodeGrp][p].isEmpty()) {
+ *first = 1;
+ *last = 0;
+ return;
+ }
+ *first = state[nodeGrp][p].first();
+ *last = state[nodeGrp][p].last();
+}
+
+
+void
+Channel::print(Uint32 nodeGrp)
+{
+ ndbout << channelline;
+ ndbout_c("| | Meta scan |"
+ " Data scan |");
+ ndbout.print("| ");
+ if (m_metaScanEpochs.isEmpty()) {
+ ndbout.print("| ");
+ } else {
+ ndbout.print("| %10u-%-10u ",
+ m_metaScanEpochs.first(), m_metaScanEpochs.last());
+ }
+ if (m_dataScanEpochs.isEmpty()) {
+ ndbout_c("| |");
+ } else {
+ ndbout_c("| %10u-%-10u |",
+ m_dataScanEpochs.first(), m_dataScanEpochs.last());
+ }
+
+ /* --- */
+
+ ndbout << channelline;
+ ndbout_c("| Source Rep Server | Being Transfered |"
+ " Destination Rep Server |");
+ if (state[nodeGrp][PS].isEmpty()) {
+ ndbout.print("| ");
+ } else {
+ ndbout.print("| %10u-%-10u ",
+ state[nodeGrp][PS].first(), state[nodeGrp][PS].last());
+ }
+ if (state[nodeGrp][SSReq].isEmpty()) {
+ ndbout.print("| ");
+ } else {
+ ndbout.print("| %10u-%-10u ",
+ state[nodeGrp][SSReq].first(), state[nodeGrp][SSReq].last());
+ }
+ if (state[nodeGrp][SS].isEmpty()) {
+ ndbout_c("| |");
+ } else {
+ ndbout_c("| %10u-%-10u |",
+ state[nodeGrp][SS].first(), state[nodeGrp][SS].last());
+ }
+
+ /* --- */
+
+ ndbout << channelline;
+ ndbout_c("| Being Applied | Applied |"
+ " Being Deleted |");
+ if (state[nodeGrp][AppReq].isEmpty()) {
+ ndbout.print("| ");
+ } else {
+ ndbout.print("| %10u-%-10u ", state[nodeGrp][AppReq].first(),
+ state[nodeGrp][AppReq].last());
+ }
+ if (state[nodeGrp][App].isEmpty()) {
+ ndbout.print("| ");
+ } else {
+ ndbout.print("| %10u-%-10u ",
+ state[nodeGrp][App].first(), state[nodeGrp][App].last());
+ }
+ if (state[nodeGrp][DelReq].isEmpty()) {
+ ndbout_c("| |");
+ } else {
+ ndbout_c("| %10u-%-10u |",
+ state[nodeGrp][DelReq].first(), state[nodeGrp][DelReq].last());
+ }
+}
+
+/*****************************************************************************
+ * Private Methods
+ *****************************************************************************/
+
+void
+Channel::invariant()
+{
+ for (Uint32 j=0; j<MAX_NO_OF_NODE_GROUPS; j++)
+ {
+ if (!intervalDisjoint(state[j][SSReq], state[j][SS]))
+ REPABORT("Invariant 1 violated");
+ if (!intervalDisjoint(state[j][AppReq], state[j][App]))
+ REPABORT("Invariant 2 violated");
+ }
+}
diff --git a/ndb/src/rep/state/Channel.hpp b/ndb/src/old_files/rep/state/Channel.hpp
index cdf4eecca63..cdf4eecca63 100644
--- a/ndb/src/rep/state/Channel.hpp
+++ b/ndb/src/old_files/rep/state/Channel.hpp
diff --git a/ndb/src/rep/state/Interval.cpp b/ndb/src/old_files/rep/state/Interval.cpp
index 8266f19c58d..8266f19c58d 100644
--- a/ndb/src/rep/state/Interval.cpp
+++ b/ndb/src/old_files/rep/state/Interval.cpp
diff --git a/ndb/src/rep/state/Interval.hpp b/ndb/src/old_files/rep/state/Interval.hpp
index 935adaf26b1..935adaf26b1 100644
--- a/ndb/src/rep/state/Interval.hpp
+++ b/ndb/src/old_files/rep/state/Interval.hpp
diff --git a/ndb/src/rep/state/Makefile b/ndb/src/old_files/rep/state/Makefile
index 3eed69a97dd..3eed69a97dd 100644
--- a/ndb/src/rep/state/Makefile
+++ b/ndb/src/old_files/rep/state/Makefile
diff --git a/ndb/src/rep/state/RepState.cpp b/ndb/src/old_files/rep/state/RepState.cpp
index d8a50961a3c..d8a50961a3c 100644
--- a/ndb/src/rep/state/RepState.cpp
+++ b/ndb/src/old_files/rep/state/RepState.cpp
diff --git a/ndb/src/old_files/rep/state/RepState.hpp b/ndb/src/old_files/rep/state/RepState.hpp
new file mode 100644
index 00000000000..06bbca19f7e
--- /dev/null
+++ b/ndb/src/old_files/rep/state/RepState.hpp
@@ -0,0 +1,276 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef REP_STATE_HPP
+#define REP_STATE_HPP
+
+#include <GrepError.hpp>
+#include <signaldata/GrepImpl.hpp>
+#include <rep/repapi/repapi.h>
+#include <rep/ExtSender.hpp>
+#include <rep/adapters/AppNDB.hpp>
+#include <Properties.hpp>
+
+#include "Channel.hpp"
+#include "Interval.hpp"
+
+#define REQUESTOR_EXECUTES_NEEDED_FOR_UNKNOWN_CONNECTION 5
+
+class NdbApiSignal;
+
+
+/**
+ * @class RepState
+ * @brief The main information about the replication
+ */
+class RepState
+{
+public:
+ RepState();
+ ~RepState();
+ void init(ExtSender * extSender) { m_extSender = extSender; }
+
+ /***************************************************************************
+ * Callback functions
+ *
+ * These are used when RepState wants to do something
+ ***************************************************************************/
+
+ typedef void (FuncRequestCreateSubscriptionId)
+ (void * cbObj, NdbApiSignal* signal);
+
+ typedef void (FuncRequestCreateSubscription)
+ (void * cbObj, NdbApiSignal* signal, Uint32 subId,
+ Uint32 subKey ,
+ Vector <struct table *> * selectedTables);
+
+ typedef void (FuncRequestRemoveSubscription)
+ (void * cbObj, NdbApiSignal* signal, Uint32 subId, Uint32 subKey);
+
+ typedef void (FuncRequestTransfer)
+ (void * cbObj, NdbApiSignal* signal,
+ Uint32 nodeGrp, Uint32 first, Uint32 last);
+
+ typedef void (FuncRequestApply)
+ (void * cbObj, NdbApiSignal* signal,
+ Uint32 nodeGrp, Uint32 first, Uint32 last, Uint32 force);
+
+ typedef void (FuncRequestDeleteSS)
+ (void * cbObj, NdbApiSignal* signal,
+ Uint32 nodeGrp, Uint32 first, Uint32 last);
+
+ typedef void (FuncRequestDeletePS)
+ (void * cbObj, NdbApiSignal* signal,
+ Uint32 nodeGrp, Uint32 first, Uint32 last);
+
+ typedef void (FuncRequestStartMetaLog)
+ (void * cbObj, NdbApiSignal * signal, Uint32 subId, Uint32 subKey);
+
+ typedef void (FuncRequestStartDataLog)
+ (void * cbObj, NdbApiSignal * signal, Uint32 subId, Uint32 subKey);
+
+ typedef void (FuncRequestStartMetaScan)
+ (void * cbObj, NdbApiSignal * signal, Uint32 subId, Uint32 subKey);
+
+ typedef void (FuncRequestStartDataScan)
+ (void * cbObj, NdbApiSignal * signal, Uint32 subId, Uint32 subKey);
+
+ typedef void (FuncRequestEpochInfo)
+ (void * cbObj, NdbApiSignal * signal, Uint32 nodeGrp);
+
+ /***************************************************************************
+ *
+ ***************************************************************************/
+ void setSubscriptionRequests(FuncRequestCreateSubscriptionId f1,
+ FuncRequestCreateSubscription f2,
+ FuncRequestRemoveSubscription f3);
+ void setIntervalRequests(FuncRequestTransfer * f1,
+ FuncRequestApply * f2,
+ FuncRequestDeleteSS * f3,
+ FuncRequestDeletePS * f4);
+ void setStartRequests(FuncRequestStartMetaLog * f5,
+ FuncRequestStartDataLog * f6,
+ FuncRequestStartMetaScan * f7,
+ FuncRequestStartDataScan * f8,
+ FuncRequestEpochInfo * f9);
+
+ /***************************************************************************
+ * Enablings
+ ***************************************************************************/
+ bool isEnabled() { return m_channel.m_requestorEnabled; }
+ bool isTransferEnabled() { return m_channel.m_transferEnabled; }
+ bool isApplyEnabled() { return m_channel.m_applyEnabled; }
+ bool isDeleteEnabled() { return m_channel.m_deleteEnabled; }
+ bool isAutoStartEnabled() { return m_channel.m_autoStartEnabled; }
+
+ void enable() { m_channel.m_requestorEnabled = true; }
+ void enableTransfer() { m_channel.m_transferEnabled = true; }
+ void enableApply() { m_channel.m_applyEnabled = true; }
+ void enableDelete() { m_channel.m_deleteEnabled = true; }
+ void enableAutoStart() { m_channel.m_autoStartEnabled = true; }
+
+ void disable() { m_channel.m_requestorEnabled = false; }
+ void disableTransfer() { m_channel.m_transferEnabled = false; }
+ void disableApply() { m_channel.m_applyEnabled = false;}
+ void disableDelete() { m_channel.m_deleteEnabled = false; }
+ void disableAutoStart() { m_channel.m_autoStartEnabled = false; }
+
+ /***************************************************************************
+ * Node groups
+ ***************************************************************************/
+ void setNoOfNodeGroups(Uint32 n) { m_channel.setNoOfNodeGroups(n); }
+ Uint32 getNoOfNodeGroups() { return m_channel.getNoOfNodeGroups(); }
+
+ /***************************************************************************
+ * Event reporting to RepState
+ *
+ * These are used to update the state of the Requestor when something
+ * has happend.
+ ***************************************************************************/
+ void request(GrepReq::Request request);
+
+ //GrepError::Code createSubscription(Uint32 subId, Uint32 subKey);
+ GrepError::Code protectedExecute();
+ GrepError::Code protectedRequest(GrepReq::Request request, Uint32 arg);
+ GrepError::Code protectedRequest(GrepReq::Request request,
+ Uint32 arg1,
+ Uint32 arg2);
+ GrepError::Code protectedAddTable(const char * fullTableName);
+ GrepError::Code protectedRemoveTable(const char * fullTableName);
+ GrepError::Code add(Channel::Position s, Uint32 nodeGrp, const Interval i);
+ GrepError::Code clear(Channel::Position s, Uint32 nodeGrp, const Interval i);
+
+ void eventSubscriptionDeleted(Uint32 subId, Uint32 subKey);
+
+ void eventMetaLogStarted(NdbApiSignal*, Uint32 subId, Uint32 subKey);
+ void eventDataLogStarted(NdbApiSignal*, Uint32 subId, Uint32 subKey);
+ void eventMetaScanCompleted(NdbApiSignal*, Uint32 subId, Uint32 subKey,
+ Interval epochs);
+ void eventDataScanCompleted(NdbApiSignal*, Uint32 subId, Uint32 subKey,
+ Interval epochs);
+ void eventMetaScanFailed(Uint32 subId, Uint32 subKey, GrepError::Code error);
+ void eventDataScanFailed(Uint32 subId, Uint32 subKey, GrepError::Code error);
+
+ /**
+ * @fn sendInsertConf
+ * @param gci - the gci of the applied GCIBuffer.
+ * @param nodeGrp - the nodeGrp of the applied GCIBuffer.
+ */
+ void eventInsertConf(Uint32 gci, Uint32 nodeGrp);
+
+ /**
+ * @fn sendInsertRef
+ * @param gci - the gci of the applied GCIBuffer.
+ * @param nodeGrp - the nodeGrp of the applied GCIBuffer.
+ * @param tableId - the table of the applied GCIBuffer.
+ */
+ void eventInsertRef(Uint32 gci, Uint32 nodeGrp, Uint32 tableId,
+ GrepError::Code err);
+ void eventCreateTableRef(Uint32 gci,
+ Uint32 tableId,
+ const char * tableName,
+ GrepError::Code err) ;
+
+ void eventSubscriptionIdCreated(Uint32 subId, Uint32 subKey);
+ void eventSubscriptionIdCreateFailed(Uint32 subId, Uint32 subKey,
+ GrepError::Code error);
+
+ void eventSubscriptionCreated(Uint32 subId, Uint32 subKey);
+ void eventSubscriptionCreateFailed(Uint32 subId, Uint32 subKey,
+ GrepError::Code error);
+
+ void eventMetaLogStartFailed(Uint32 subId, Uint32 subKey,
+ GrepError::Code error);
+ void eventDataLogStartFailed(Uint32 subId, Uint32 subKey,
+ GrepError::Code error);
+
+ void eventNodeConnected(Uint32 nodeId);
+ void eventNodeDisconnected(Uint32 nodeId);
+ void eventNodeConnectable(Uint32 nodeId);
+
+ void printStatus();
+ Properties * getStatus();
+ Properties * query(QueryCounter counter, Uint32 replicationId);
+ Uint32 getSubId() { return m_channel.getSubId(); }
+ Uint32 getSubKey () { return m_channel.getSubKey(); }
+
+ void setApplier(class AppNDB * app) { m_applier = app; }
+ void setGCIContainer(class GCIContainer * c) { m_gciContainer = c; }
+
+ /* @todo should be private */
+ Channel m_channel;
+
+private:
+ /***************************************************************************
+ * PRIVATE ATTRIBUTES
+ ***************************************************************************/
+ ExtSender * m_extSender;
+ AppNDB * m_applier;
+ GCIContainer * m_gciContainer;
+
+ Uint32 m_subIdToRemove;
+ Uint32 m_subKeyToRemove;
+
+
+ enum Connected
+ {
+ UNKNOWN, ///<
+ CONNECTED, ///< Recently received info from (all needed) PS REP
+ DISCONNECTED, ///< Received disconnect info from (some needed) PS REP
+ CONNECTABLE ///< Received disconnect info from (some needed) PS REP
+ };
+ Connected m_connected;
+ Connected m_repConnected;
+ Uint32 m_connected_counter;
+
+ NdbMutex * m_mutex;
+
+ /** @todo Should be channel-specific */
+ Uint32 m_stopEpoch;
+
+ /***************************************************************************
+ * PRIVATE METHODS
+ ***************************************************************************/
+ GrepError::Code execute(NdbApiSignal*);
+ GrepError::Code request(GrepReq::Request req,
+ Uint32 arg1,
+ Uint32 arg2,
+ NdbApiSignal*);
+
+ FuncRequestCreateSubscriptionId * m_funcRequestCreateSubscriptionId;
+ FuncRequestCreateSubscription * m_funcRequestCreateSubscription;
+ FuncRequestRemoveSubscription * m_funcRequestRemoveSubscription;
+
+ FuncRequestTransfer * m_funcRequestTransfer;
+ FuncRequestApply * m_funcRequestApply;
+ FuncRequestDeleteSS * m_funcRequestDeleteSS;
+ FuncRequestDeletePS * m_funcRequestDeletePS;
+
+ FuncRequestStartMetaLog * m_funcRequestStartMetaLog;
+ FuncRequestStartDataLog * m_funcRequestStartDataLog;
+ FuncRequestStartMetaScan * m_funcRequestStartMetaScan;
+ FuncRequestStartDataScan * m_funcRequestStartDataScan;
+ FuncRequestEpochInfo * m_funcRequestEpochInfo;
+
+ void requestTransfer(NdbApiSignal * signal);
+ void requestApply(NdbApiSignal * signal);
+ void requestDelete(NdbApiSignal * signal);
+ void requestEpochInfo(NdbApiSignal * signal);
+ void getEpochState(Channel::Position pos, Properties * p);
+ friend void testRepState();
+};
+
+#endif
diff --git a/ndb/src/rep/state/RepStateEvent.cpp b/ndb/src/old_files/rep/state/RepStateEvent.cpp
index 9be304c8bfa..9be304c8bfa 100644
--- a/ndb/src/rep/state/RepStateEvent.cpp
+++ b/ndb/src/old_files/rep/state/RepStateEvent.cpp
diff --git a/ndb/src/rep/state/RepStateRequests.cpp b/ndb/src/old_files/rep/state/RepStateRequests.cpp
index 02677e141f6..02677e141f6 100644
--- a/ndb/src/rep/state/RepStateRequests.cpp
+++ b/ndb/src/old_files/rep/state/RepStateRequests.cpp
diff --git a/ndb/src/rep/state/testInterval/Makefile b/ndb/src/old_files/rep/state/testInterval/Makefile
index fbb0b48c280..fbb0b48c280 100644
--- a/ndb/src/rep/state/testInterval/Makefile
+++ b/ndb/src/old_files/rep/state/testInterval/Makefile
diff --git a/ndb/src/rep/state/testInterval/testInterval.cpp b/ndb/src/old_files/rep/state/testInterval/testInterval.cpp
index 463e4adffb7..463e4adffb7 100644
--- a/ndb/src/rep/state/testInterval/testInterval.cpp
+++ b/ndb/src/old_files/rep/state/testInterval/testInterval.cpp
diff --git a/ndb/src/rep/state/testRepState/Makefile b/ndb/src/old_files/rep/state/testRepState/Makefile
index 33c6076eff3..33c6076eff3 100644
--- a/ndb/src/rep/state/testRepState/Makefile
+++ b/ndb/src/old_files/rep/state/testRepState/Makefile
diff --git a/ndb/src/rep/state/testRepState/testRequestor.cpp b/ndb/src/old_files/rep/state/testRepState/testRequestor.cpp
index 8989f7098b8..8989f7098b8 100644
--- a/ndb/src/rep/state/testRepState/testRequestor.cpp
+++ b/ndb/src/old_files/rep/state/testRepState/testRequestor.cpp
diff --git a/ndb/src/rep/state/testRepState/testRequestor.hpp b/ndb/src/old_files/rep/state/testRepState/testRequestor.hpp
index 726b289114d..726b289114d 100644
--- a/ndb/src/rep/state/testRepState/testRequestor.hpp
+++ b/ndb/src/old_files/rep/state/testRepState/testRequestor.hpp
diff --git a/ndb/src/rep/storage/GCIBuffer.cpp b/ndb/src/old_files/rep/storage/GCIBuffer.cpp
index 013600b30a5..013600b30a5 100644
--- a/ndb/src/rep/storage/GCIBuffer.cpp
+++ b/ndb/src/old_files/rep/storage/GCIBuffer.cpp
diff --git a/ndb/src/rep/storage/GCIBuffer.hpp b/ndb/src/old_files/rep/storage/GCIBuffer.hpp
index 8a8473d1d49..8a8473d1d49 100644
--- a/ndb/src/rep/storage/GCIBuffer.hpp
+++ b/ndb/src/old_files/rep/storage/GCIBuffer.hpp
diff --git a/ndb/src/rep/storage/GCIContainer.cpp b/ndb/src/old_files/rep/storage/GCIContainer.cpp
index c161db0769b..c161db0769b 100644
--- a/ndb/src/rep/storage/GCIContainer.cpp
+++ b/ndb/src/old_files/rep/storage/GCIContainer.cpp
diff --git a/ndb/src/rep/storage/GCIContainer.hpp b/ndb/src/old_files/rep/storage/GCIContainer.hpp
index 48cbc66bfbd..48cbc66bfbd 100644
--- a/ndb/src/rep/storage/GCIContainer.hpp
+++ b/ndb/src/old_files/rep/storage/GCIContainer.hpp
diff --git a/ndb/src/rep/storage/GCIContainerPS.cpp b/ndb/src/old_files/rep/storage/GCIContainerPS.cpp
index 5adb53f965c..5adb53f965c 100644
--- a/ndb/src/rep/storage/GCIContainerPS.cpp
+++ b/ndb/src/old_files/rep/storage/GCIContainerPS.cpp
diff --git a/ndb/src/rep/storage/GCIContainerPS.hpp b/ndb/src/old_files/rep/storage/GCIContainerPS.hpp
index 7f5aaac4840..7f5aaac4840 100644
--- a/ndb/src/rep/storage/GCIContainerPS.hpp
+++ b/ndb/src/old_files/rep/storage/GCIContainerPS.hpp
diff --git a/ndb/src/rep/storage/GCIPage.cpp b/ndb/src/old_files/rep/storage/GCIPage.cpp
index 05ecde2fee1..05ecde2fee1 100644
--- a/ndb/src/rep/storage/GCIPage.cpp
+++ b/ndb/src/old_files/rep/storage/GCIPage.cpp
diff --git a/ndb/src/rep/storage/GCIPage.hpp b/ndb/src/old_files/rep/storage/GCIPage.hpp
index 50c5ab0cfba..50c5ab0cfba 100644
--- a/ndb/src/rep/storage/GCIPage.hpp
+++ b/ndb/src/old_files/rep/storage/GCIPage.hpp
diff --git a/ndb/src/rep/storage/LogRecord.hpp b/ndb/src/old_files/rep/storage/LogRecord.hpp
index a0bf3d52372..a0bf3d52372 100644
--- a/ndb/src/rep/storage/LogRecord.hpp
+++ b/ndb/src/old_files/rep/storage/LogRecord.hpp
diff --git a/ndb/src/rep/storage/Makefile b/ndb/src/old_files/rep/storage/Makefile
index 89b3af455e8..89b3af455e8 100644
--- a/ndb/src/rep/storage/Makefile
+++ b/ndb/src/old_files/rep/storage/Makefile
diff --git a/ndb/src/rep/storage/NodeConnectInfo.hpp b/ndb/src/old_files/rep/storage/NodeConnectInfo.hpp
index 403f92a5999..403f92a5999 100644
--- a/ndb/src/rep/storage/NodeConnectInfo.hpp
+++ b/ndb/src/old_files/rep/storage/NodeConnectInfo.hpp
diff --git a/ndb/src/rep/storage/NodeGroup.cpp b/ndb/src/old_files/rep/storage/NodeGroup.cpp
index 33451efb104..33451efb104 100644
--- a/ndb/src/rep/storage/NodeGroup.cpp
+++ b/ndb/src/old_files/rep/storage/NodeGroup.cpp
diff --git a/ndb/src/rep/storage/NodeGroup.hpp b/ndb/src/old_files/rep/storage/NodeGroup.hpp
index 1f515e02a23..1f515e02a23 100644
--- a/ndb/src/rep/storage/NodeGroup.hpp
+++ b/ndb/src/old_files/rep/storage/NodeGroup.hpp
diff --git a/ndb/src/rep/storage/NodeGroupInfo.cpp b/ndb/src/old_files/rep/storage/NodeGroupInfo.cpp
index 8c250268997..8c250268997 100644
--- a/ndb/src/rep/storage/NodeGroupInfo.cpp
+++ b/ndb/src/old_files/rep/storage/NodeGroupInfo.cpp
diff --git a/ndb/src/rep/storage/NodeGroupInfo.hpp b/ndb/src/old_files/rep/storage/NodeGroupInfo.hpp
index 3d0499d4425..3d0499d4425 100644
--- a/ndb/src/rep/storage/NodeGroupInfo.hpp
+++ b/ndb/src/old_files/rep/storage/NodeGroupInfo.hpp
diff --git a/ndb/src/rep/transfer/Makefile b/ndb/src/old_files/rep/transfer/Makefile
index 0d8851e287a..0d8851e287a 100644
--- a/ndb/src/rep/transfer/Makefile
+++ b/ndb/src/old_files/rep/transfer/Makefile
diff --git a/ndb/src/old_files/rep/transfer/TransPS.cpp b/ndb/src/old_files/rep/transfer/TransPS.cpp
new file mode 100644
index 00000000000..11fb0203cbc
--- /dev/null
+++ b/ndb/src/old_files/rep/transfer/TransPS.cpp
@@ -0,0 +1,553 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include "ConfigRetriever.hpp"
+#include <NdbSleep.h>
+
+#include <NdbApiSignal.hpp>
+#include <AttributeHeader.hpp>
+
+#include <signaldata/DictTabInfo.hpp>
+#include <signaldata/GetTabInfo.hpp>
+#include <signaldata/SumaImpl.hpp>
+#include <GrepError.hpp>
+#include <SimpleProperties.hpp>
+
+#include "TransPS.hpp"
+#include <rep/storage/NodeGroupInfo.hpp>
+
+/*****************************************************************************
+ * Constructor / Destructor / Init
+ *****************************************************************************/
+TransPS::TransPS(GCIContainerPS* gciContainer)
+{
+ m_repSender = new ExtSender();
+ m_gciContainerPS = gciContainer;
+}
+
+TransPS::~TransPS()
+{
+ delete m_repSender;
+}
+
+void
+TransPS::init(TransporterFacade * tf, const char * connectString)
+{
+ abort();
+#ifdef NOT_FUNCTIONAL
+ m_signalExecThread = NdbThread_Create(signalExecThread_C,
+ (void **)this,
+ 32768,
+ "TransPS_Service",
+ NDB_THREAD_PRIO_LOW);
+
+ ConfigRetriever configRetriever;
+ // configRetriever.setConnectString(connectString);
+ Properties* config = configRetriever.getConfig("REP", REP_VERSION_ID);
+ if (config == 0) {
+ ndbout << "TransPS: Configuration error: ";
+ const char* erString = configRetriever.getErrorString();
+ if (erString == 0) {
+ erString = "No error specified!";
+ }
+ ndbout << erString << endl;
+ exit(-1);
+ }
+
+ Properties * extConfig;
+ /**
+ * @todo Hardcoded primary system name
+ */
+ if (!config->getCopy("EXTERNAL SYSTEM_External", &extConfig)) {
+ ndbout << "External System \"External\" not found in configuration. "
+ << "Check config.ini." << endl;
+ config->print();
+ exit(-1);
+ }
+
+ m_ownNodeId = configRetriever.getOwnNodeId();
+ extConfig->put("LocalNodeId", m_ownNodeId);
+ extConfig->put("LocalNodeType", "REP");
+ Uint32 noOfConnections;
+ extConfig->get("NoOfConnections", &noOfConnections);
+ /* if (noOfConnections != 1) {
+ ndbout << "TransPS: There are " << noOfConnections << " connections "
+ << "defined in configuration"
+ << endl
+ << " There should be exactly one!" << endl;
+ exit(-1);
+ }
+ */
+ /******************************
+ * Set node id of external REP
+ ******************************/
+ const Properties * connection;
+ const char * extSystem;
+ Uint32 extRepNodeId, tmpOwnNodeId;
+
+ for(Uint32 i=0; i < noOfConnections; i++) {
+ extConfig->get("Connection", i, &connection);
+ if(connection == 0) REPABORT("No connection found");
+
+ if(connection->get("System1", &extSystem)) {
+ connection->get("NodeId1", &extRepNodeId);
+ connection->get("NodeId2", &tmpOwnNodeId);
+ } else {
+ connection->get("System2", &extSystem);
+ connection->get("NodeId1", &tmpOwnNodeId);
+ connection->get("NodeId2", &extRepNodeId);
+ }
+ if(m_ownNodeId == tmpOwnNodeId)
+ break;
+ }
+
+ if(extRepNodeId==0) REPABORT("External replication server not found");
+ if(extSystem==0) REPABORT("External system not found");
+
+ m_ownBlockNo = tf->open(this, execSignal, execNodeStatus);
+ assert(m_ownBlockNo > 0);
+
+ m_ownRef = numberToRef(m_ownBlockNo, m_ownNodeId);
+ assert(m_ownNodeId == tf->ownId());
+
+ ndbout_c("Phase 4 (TransPS): Connection %d to external REP node %d opened",
+ m_ownBlockNo, extRepNodeId);
+
+ m_repSender->setNodeId(extRepNodeId);
+ m_repSender->setOwnRef(m_ownRef);
+ m_repSender->setTransporterFacade(tf);
+#endif
+}
+
+/*****************************************************************************
+ * Signal Queue Executor
+ *****************************************************************************/
+
+class SigMatch
+{
+public:
+ int gsn;
+ void (TransPS::* function)(NdbApiSignal *signal);
+
+ SigMatch() { gsn = 0; function = NULL; };
+
+ SigMatch(int _gsn, void (TransPS::* _function)(NdbApiSignal *signal)) {
+ gsn = _gsn;
+ function = _function;
+ };
+
+ bool check(NdbApiSignal *signal) {
+ if(signal->readSignalNumber() == gsn) return true;
+ return false;
+ };
+};
+
+extern "C"
+void *
+signalExecThread_C(void *r)
+{
+ TransPS *repps = (TransPS*)r;
+
+ repps->signalExecThreadRun();
+
+ NdbThread_Exit(0);
+ /* NOTREACHED */
+ return 0;
+}
+
+void
+TransPS::signalExecThreadRun()
+{
+ Vector<SigMatch> sl;
+
+ /**
+ * Signals executed here
+ */
+ sl.push_back(SigMatch(GSN_REP_GET_GCI_REQ,
+ &TransPS::execREP_GET_GCI_REQ));
+ sl.push_back(SigMatch(GSN_REP_GET_GCIBUFFER_REQ,
+ &TransPS::execREP_GET_GCIBUFFER_REQ));
+ sl.push_back(SigMatch(GSN_REP_CLEAR_PS_GCIBUFFER_REQ,
+ &TransPS::execREP_CLEAR_PS_GCIBUFFER_REQ));
+
+ /**
+ * Signals to be forwarded to GREP::PSCoord
+ */
+ sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_REQ, &TransPS::sendSignalGrep));
+
+ /**
+ * Signals to be forwarded to GREP::PSCoord
+ */
+ sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_REQ, &TransPS::sendSignalGrep));
+ sl.push_back(SigMatch(GSN_GREP_SUB_START_REQ, &TransPS::sendSignalGrep));
+ sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_REQ, &TransPS::sendSignalGrep));
+ sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_REQ, &TransPS::sendSignalGrep));
+
+ while(1) {
+ SigMatch *handler = NULL;
+ NdbApiSignal *signal = NULL;
+ if(m_signalRecvQueue.waitFor(sl, handler, signal, DEFAULT_TIMEOUT)) {
+#if 0
+ ndbout_c("TransPS: Removed signal from queue (GSN: %d, QSize: %d)",
+ signal->readSignalNumber(), m_signalRecvQueue.size());
+#endif
+ if(handler->function != 0) {
+ (this->*handler->function)(signal);
+ delete signal;
+ signal = 0;
+ } else {
+ REPABORT("Illegal handler for signal");
+ }
+ }
+ }
+}
+
+void
+TransPS::sendSignalRep(NdbApiSignal * s)
+{
+ m_repSender->sendSignal(s);
+}
+
+void
+TransPS::sendSignalGrep(NdbApiSignal * s)
+{
+ m_grepSender->sendSignal(s);
+}
+
+void
+TransPS::sendFragmentedSignalRep(NdbApiSignal * s,
+ LinearSectionPtr ptr[3],
+ Uint32 sections)
+{
+ m_repSender->sendFragmentedSignal(s, ptr, sections);
+}
+
+void
+TransPS::sendFragmentedSignalGrep(NdbApiSignal * s,
+ LinearSectionPtr ptr[3],
+ Uint32 sections)
+{
+ m_grepSender->sendFragmentedSignal(s, ptr, sections);
+}
+
+
+void
+TransPS::execNodeStatus(void* obj, Uint16 nodeId, bool alive, bool nfCompleted)
+{
+// TransPS * thisObj = (TransPS*)obj;
+
+ RLOG(("Node changed state (NodeId %d, Alive %d, nfCompleted %d)",
+ nodeId, alive, nfCompleted));
+
+ if(!alive && !nfCompleted) { }
+
+ if(!alive && nfCompleted) { }
+}
+
+void
+TransPS::execSignal(void* executeObj, NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3]){
+
+ TransPS * executor = (TransPS *) executeObj;
+
+ const Uint32 gsn = signal->readSignalNumber();
+ const Uint32 len = signal->getLength();
+
+ NdbApiSignal * s = new NdbApiSignal(executor->m_ownRef);
+ switch(gsn){
+ case GSN_REP_GET_GCI_REQ:
+ case GSN_REP_GET_GCIBUFFER_REQ:
+ case GSN_REP_CLEAR_PS_GCIBUFFER_REQ:
+ s->set(0, SSREPBLOCKNO, gsn, len);
+ memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
+ executor->m_signalRecvQueue.receive(s);
+ break;
+ case GSN_GREP_SUB_CREATE_REQ:
+ {
+ if(signal->m_noOfSections > 0) {
+ memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
+ s->set(0, GREP, gsn,
+ len);
+ executor->sendFragmentedSignalGrep(s,ptr,1);
+ delete s;
+ } else {
+ s->set(0, GREP, gsn, len);
+ memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
+ executor->m_signalRecvQueue.receive(s);
+ }
+ }
+ break;
+ case GSN_GREP_SUB_START_REQ:
+ case GSN_GREP_SUB_SYNC_REQ:
+ case GSN_GREP_SUB_REMOVE_REQ:
+ case GSN_GREP_CREATE_SUBID_REQ:
+ s->set(0, GREP, gsn, len);
+ memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
+ executor->m_signalRecvQueue.receive(s);
+ break;
+ default:
+ REPABORT1("Illegal signal received in execSignal", gsn);
+ }
+#if 0
+ ndbout_c("TransPS: Inserted signal into queue (GSN: %d, Len: %d)",
+ signal->readSignalNumber(), len);
+#endif
+}
+
+/*****************************************************************************
+ * Signal Receivers
+ *****************************************************************************/
+
+void
+TransPS::execREP_GET_GCIBUFFER_REQ(NdbApiSignal* signal)
+{
+ RepGetGciBufferReq * req = (RepGetGciBufferReq*)signal->getDataPtr();
+ Uint32 firstGCI = req->firstGCI;
+ Uint32 lastGCI = req->lastGCI;
+ Uint32 nodeGrp = req->nodeGrp;
+
+ RLOG(("Received request for %d:[%d-%d]", nodeGrp, firstGCI, lastGCI));
+
+ NodeGroupInfo * tmp = m_gciContainerPS->getNodeGroupInfo();
+ Uint32 nodeId = tmp->getPrimaryNode(nodeGrp);
+ /**
+ * If there is no connected node in the nodegroup -> abort.
+ * @todo: Handle error when a nodegroup is "dead"
+ */
+ if(!nodeId) {
+ RLOG(("There are no connected nodes in node group %d", nodeGrp));
+ sendREP_GET_GCIBUFFER_REF(signal, firstGCI, lastGCI, nodeGrp,
+ GrepError::REP_NO_CONNECTED_NODES);
+ return;
+ }
+
+ transferPages(firstGCI, lastGCI, nodeId, nodeGrp, signal);
+
+ /**
+ * Done tfxing pages, sending GCIBuffer conf.
+ */
+ Uint32 first, last;
+ m_gciContainerPS->getAvailableGCIBuffers(nodeGrp, &first, &last);
+
+ RepGetGciBufferConf * conf = (RepGetGciBufferConf*)req;
+ conf->senderRef = m_ownRef;
+ conf->firstPSGCI = first; // Buffers found on REP PS (piggy-back info)
+ conf->lastPSGCI = last;
+ conf->firstSSGCI = firstGCI; // Now been transferred to REP SS
+ conf->lastSSGCI = lastGCI;
+ conf->nodeGrp = nodeGrp;
+ signal->set(0, SSREPBLOCKNO, GSN_REP_GET_GCIBUFFER_CONF,
+ RepGetGciBufferConf::SignalLength);
+ sendSignalRep(signal);
+
+ RLOG(("Sent %d:[%d-%d] (Stored PS:%d:[%d-%d])",
+ nodeGrp, firstGCI, lastGCI, nodeGrp, first, last));
+}
+
+void
+TransPS::transferPages(Uint32 firstGCI, Uint32 lastGCI,
+ Uint32 nodeId, Uint32 nodeGrp,
+ NdbApiSignal * signal)
+{
+ /**
+ * Transfer pages in GCI Buffer to SS
+ * When buffer is sent, send accounting information.
+ */
+ RepDataPage * pageData = (RepDataPage*)signal->getDataPtr();
+ LinearSectionPtr ptr[1];
+ GCIPage * page;
+ for(Uint32 i=firstGCI; i<=lastGCI; i++) {
+ Uint32 totalSizeSent = 0;
+ GCIBuffer * buffer = m_gciContainerPS->getGCIBuffer(i, nodeId);
+
+ if(buffer != 0) {
+ GCIBuffer::iterator it(buffer);
+ /**
+ * Send all pages to SS
+ */
+ for (page = it.first(); page != 0; page = it.next()) {
+ ptr[0].p = page->getStoragePtr();
+ ptr[0].sz = page->getStorageWordSize();
+ totalSizeSent += ptr[0].sz;
+ pageData->gci = i;
+ pageData->nodeGrp = nodeGrp;
+ signal->set(0, SSREPBLOCKNO, GSN_REP_DATA_PAGE,
+ RepDataPage::SignalLength);
+ sendFragmentedSignalRep(signal, ptr, 1);
+ }
+
+ /**
+ * Send accounting information to SS
+ */
+ RepGciBufferAccRep * rep = (RepGciBufferAccRep *)pageData;
+ rep->gci = i;
+ rep->nodeGrp = nodeGrp;
+ rep->totalSentBytes = (4 * totalSizeSent); //words to bytes
+ signal->set(0, SSREPBLOCKNO, GSN_REP_GCIBUFFER_ACC_REP,
+ RepGciBufferAccRep::SignalLength);
+ sendSignalRep(signal);
+
+ RLOG(("Sending %d:[%d] (%d bytes) to external REP (nodeId %d)",
+ nodeGrp, i, 4*totalSizeSent, nodeId));
+ }
+ }
+ page = 0;
+}
+
+void
+TransPS::execREP_GET_GCI_REQ(NdbApiSignal* signal)
+{
+ RepGetGciReq * req = (RepGetGciReq*)signal->getDataPtr();
+ Uint32 nodeGrp = req->nodeGrp;
+
+ Uint32 first, last;
+ m_gciContainerPS->getAvailableGCIBuffers(nodeGrp, &first, &last);
+
+ RepGetGciConf * conf = (RepGetGciConf*) req;
+ conf->firstPSGCI = first;
+ conf->lastPSGCI = last;
+ conf->senderRef = m_ownRef;
+ conf->nodeGrp = nodeGrp;
+ signal->set(0, SSREPBLOCKNO, GSN_REP_GET_GCI_CONF,
+ RepGetGciConf::SignalLength);
+ sendSignalRep(signal);
+}
+
+/**
+ * REP_CLEAR_PS_GCIBUFFER_REQ
+ * destroy the GCI buffer in the GCI Container
+ * and send a CONF to Grep::SSCoord
+ */
+void
+TransPS::execREP_CLEAR_PS_GCIBUFFER_REQ(NdbApiSignal * signal)
+{
+ RepClearPSGciBufferReq * const req =
+ (RepClearPSGciBufferReq*)signal->getDataPtr();
+ Uint32 firstGCI = req->firstGCI;
+ Uint32 lastGCI = req->lastGCI;
+ Uint32 nodeGrp = req->nodeGrp;
+
+ assert(firstGCI >= 0 && lastGCI > 0);
+ if(firstGCI<0 && lastGCI <= 0)
+ {
+ RLOG(("WARNING! Illegal delete request ignored"));
+ sendREP_CLEAR_PS_GCIBUFFER_REF(signal, firstGCI, lastGCI,
+ 0, nodeGrp,
+ GrepError::REP_DELETE_NEGATIVE_EPOCH);
+ }
+
+ if(firstGCI==0 && lastGCI==(Uint32)0xFFFF) {
+ m_gciContainerPS->getAvailableGCIBuffers(nodeGrp, &firstGCI, &lastGCI);
+ RLOG(("Deleting PS:[%d-%d]", firstGCI, lastGCI));
+ }
+
+ if(firstGCI == 0) {
+ Uint32 f, l;
+ m_gciContainerPS->getAvailableGCIBuffers(nodeGrp, &f, &l);
+
+ RLOG(("Deleting PS:[%d-%d]", f, l));
+
+ if(f>firstGCI)
+ firstGCI = f;
+ }
+
+ /**
+ * Delete buffer
+ * Abort if we try to destroy a buffer that does not exist
+ * Deleting buffer from every node in the nodegroup
+ */
+ for(Uint32 i=firstGCI; i<=lastGCI; i++) {
+ if(!m_gciContainerPS->destroyGCIBuffer(i, nodeGrp)) {
+ sendREP_CLEAR_PS_GCIBUFFER_REF(signal, firstGCI, lastGCI, i, nodeGrp,
+ GrepError::REP_DELETE_NONEXISTING_EPOCH);
+ return;
+ }
+
+ RLOG(("Deleted PS:%d:[%d]", nodeGrp, i));
+ }
+
+ /**
+ * Send reply to Grep::SSCoord
+ */
+ RepClearPSGciBufferConf * conf = (RepClearPSGciBufferConf*)req;
+ conf->firstGCI = firstGCI;
+ conf->lastGCI = lastGCI;
+ conf->nodeGrp = nodeGrp;
+ signal->set(0, SSREPBLOCKNO, GSN_REP_CLEAR_PS_GCIBUFFER_CONF,
+ RepClearPSGciBufferConf::SignalLength);
+ sendSignalRep(signal);
+}
+
+/*****************************************************************************
+ * Signal Senders
+ *****************************************************************************/
+
+void
+TransPS::sendREP_GET_GCI_REF(NdbApiSignal* signal,
+ Uint32 nodeGrp,
+ Uint32 firstPSGCI, Uint32 lastPSGCI,
+ GrepError::Code err)
+{
+ RepGetGciRef * ref = (RepGetGciRef *)signal->getDataPtrSend();
+ ref->firstPSGCI = firstPSGCI;
+ ref->lastPSGCI = lastPSGCI;
+ ref->firstSSGCI = 0;
+ ref->lastSSGCI = 0;
+ ref->nodeGrp = nodeGrp;
+ ref->err = err;
+ signal->set(0, SSREPBLOCKNO, GSN_REP_GET_GCI_REF,
+ RepGetGciRef::SignalLength);
+ sendSignalRep(signal);
+}
+
+void
+TransPS::sendREP_CLEAR_PS_GCIBUFFER_REF(NdbApiSignal* signal,
+ Uint32 firstGCI, Uint32 lastGCI,
+ Uint32 currentGCI,
+ Uint32 nodeGrp,
+ GrepError::Code err)
+{
+ RepClearPSGciBufferRef * ref =
+ (RepClearPSGciBufferRef *)signal->getDataPtrSend();
+ ref->firstGCI = firstGCI;
+ ref->lastGCI = lastGCI;
+ ref->currentGCI = currentGCI;
+ ref->nodeGrp = nodeGrp;
+ ref->err = err;
+ signal->set(0, SSREPBLOCKNO, GSN_REP_CLEAR_PS_GCIBUFFER_REF,
+ RepClearPSGciBufferRef::SignalLength);
+ sendSignalRep(signal);
+}
+
+void
+TransPS::sendREP_GET_GCIBUFFER_REF(NdbApiSignal* signal,
+ Uint32 firstGCI, Uint32 lastGCI,
+ Uint32 nodeGrp,
+ GrepError::Code err)
+{
+ RepGetGciBufferRef * ref =
+ (RepGetGciBufferRef *)signal->getDataPtrSend();
+ ref->firstPSGCI = firstGCI;
+ ref->lastPSGCI = lastGCI;
+ ref->firstSSGCI = 0;
+ ref->lastSSGCI = 0;
+ ref->nodeGrp = nodeGrp;
+ ref->err = err;
+ signal->set(0, SSREPBLOCKNO, GSN_REP_GET_GCIBUFFER_REF,
+ RepGetGciBufferRef::SignalLength);
+ sendSignalRep(signal);
+}
diff --git a/ndb/src/old_files/rep/transfer/TransPS.hpp b/ndb/src/old_files/rep/transfer/TransPS.hpp
new file mode 100644
index 00000000000..0464b9e47c0
--- /dev/null
+++ b/ndb/src/old_files/rep/transfer/TransPS.hpp
@@ -0,0 +1,136 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef TransPS_HPP
+#define TransPS_HPP
+
+#include <NdbTick.h>
+#include <NdbMain.h>
+#include <NdbOut.hpp>
+#include <NdbSleep.h>
+
+#include <TransporterDefinitions.hpp>
+#include <TransporterFacade.hpp>
+#include <ClusterMgr.hpp>
+
+#include <rep/storage/GCIContainerPS.hpp>
+
+#include <signaldata/RepImpl.hpp>
+
+#include <rep/SignalQueue.hpp>
+#include <rep/ExtSender.hpp>
+
+#include <rep/rep_version.hpp>
+
+extern "C" {
+static void * signalExecThread_C(void *);
+}
+
+/**
+ * @class TransPS
+ * @brief Responsible for REP-REP interface in Primary System role
+ */
+class TransPS {
+public:
+ /***************************************************************************
+ * Constructor / Destructor
+ ***************************************************************************/
+ TransPS(GCIContainerPS * gciContainer);
+ ~TransPS();
+
+ void init(TransporterFacade * tf, const char * connectString = NULL);
+
+ /***************************************************************************
+ * Public Methods
+ ***************************************************************************/
+ ExtSender * getRepSender() { return m_repSender; };
+ void setGrepSender(ExtSender * es) { m_grepSender = es; };
+
+private:
+ /***************************************************************************
+ * Private Methods
+ ***************************************************************************/
+ /**
+ * SignalQueue executor thread
+ */
+
+ friend void * signalExecThread_C(void *);
+
+ void signalExecThreadRun();
+
+ static void execSignal(void* signalSender, NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3]);
+
+ static void execNodeStatus(void* signalSender, NodeId,
+ bool alive, bool nfCompleted);
+
+ void sendSignalRep(NdbApiSignal * s);
+ void sendSignalGrep(NdbApiSignal * s);
+
+ void sendFragmentedSignalRep(NdbApiSignal * s, LinearSectionPtr ptr[3],
+ Uint32 sections );
+ void sendFragmentedSignalGrep(NdbApiSignal * s, LinearSectionPtr ptr[3],
+ Uint32 sections );
+
+ /***************************************************************************
+ * Signal executors
+ ***************************************************************************/
+ void execREP_CLEAR_PS_GCIBUFFER_REQ(NdbApiSignal*);
+ void execREP_GET_GCI_REQ(NdbApiSignal*);
+ void execREP_GET_GCIBUFFER_REQ(NdbApiSignal*);
+
+ /***************************************************************************
+ * Ref signal senders
+ ***************************************************************************/
+ void sendREP_GET_GCI_REF(NdbApiSignal* signal, Uint32 nodeGrp,
+ Uint32 firstPSGCI, Uint32 lastPSGCI,
+ GrepError::Code err);
+
+ void sendREP_CLEAR_PS_GCIBUFFER_REF(NdbApiSignal* signal,
+ Uint32 firstGCI, Uint32 lastGCI,
+ Uint32 currentGCI, Uint32 nodeGrp,
+ GrepError::Code err);
+
+ void sendREP_GET_GCIBUFFER_REF(NdbApiSignal* signal,
+ Uint32 firstGCI, Uint32 lastGCI,
+ Uint32 nodeGrp,
+ GrepError::Code err);
+
+ /***************************************************************************
+ * Other Methods
+ ***************************************************************************/
+ void transferPages(Uint32 firstGCI, Uint32 lastGCI, Uint32 id,
+ Uint32 nodeGrp, NdbApiSignal* signal);
+
+ /*************
+ * Variables
+ *************/
+ Uint32 m_ownNodeId; ///< NodeId of this node
+ Uint32 m_ownBlockNo; ///< BlockNo of this "block"
+ BlockReference m_ownRef; ///< Reference to this
+
+ BlockReference m_extRepRef; ///< Node ref of REP at SS
+
+ ExtSender * m_grepSender; ///< Responsible send to GREP
+ ExtSender * m_repSender; ///< Responsible send to REP
+
+ struct NdbThread * m_signalExecThread;
+ class SignalQueue m_signalRecvQueue;
+
+ GCIContainerPS * m_gciContainerPS; ///< Ref to gci container.
+};
+
+#endif
diff --git a/ndb/src/old_files/rep/transfer/TransSS.cpp b/ndb/src/old_files/rep/transfer/TransSS.cpp
new file mode 100644
index 00000000000..376c6375bc4
--- /dev/null
+++ b/ndb/src/old_files/rep/transfer/TransSS.cpp
@@ -0,0 +1,653 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include "ConfigRetriever.hpp"
+
+#include <NdbApiSignal.hpp>
+#include <AttributeHeader.hpp>
+
+#include <signaldata/RepImpl.hpp>
+#include <signaldata/DictTabInfo.hpp>
+#include <signaldata/GetTabInfo.hpp>
+#include <signaldata/SumaImpl.hpp>
+#include <signaldata/GrepImpl.hpp>
+
+#include <SimpleProperties.hpp>
+#include <rep/rep_version.hpp>
+
+#include "TransSS.hpp"
+
+//#define DEBUG_REP_GET_GCI_CONF
+
+/*****************************************************************************
+ * Constructor / Destructor / Init
+ *****************************************************************************/
+TransSS::TransSS(GCIContainer * gciContainer, RepState * repState)
+{
+ m_repSender = new ExtSender();
+ if (!m_repSender) REPABORT("Could not allocate new ExtSender");
+ m_gciContainer = gciContainer;
+ m_repState = repState;
+}
+
+TransSS::~TransSS()
+{
+ delete m_repSender;
+}
+
+void
+TransSS::init(const char * connectString)
+{
+ abort();
+#ifdef NOT_FUNCTIONAL
+ m_signalExecThread = NdbThread_Create(signalExecThread_C,
+ (void **)this,
+ 32768,
+ "TransSS_Service",
+ NDB_THREAD_PRIO_LOW);
+ ConfigRetriever configRetriever;
+ configRetriever.setConnectString(connectString);
+
+ Properties* config = configRetriever.getConfig("REP", REP_VERSION_ID);
+ if (config == 0) {
+ ndbout << "Configuration error: ";
+ const char* erString = configRetriever.getErrorString();
+ if (erString == 0) {
+ erString = "No error specified!";
+ }
+ ndbout << erString << endl;
+ exit(-1);
+ }
+ Properties * extConfig;
+
+ /**
+ * @todo Hardcoded standby system name
+ */
+ if (!config->getCopy("EXTERNAL SYSTEM_External", &extConfig)) {
+ ndbout << "External System \"External\" not found in configuration. "
+ << "Check config.ini." << endl;
+ config->print();
+ exit(-1);
+ }
+ m_ownNodeId = configRetriever.getOwnNodeId();
+ extConfig->put("LocalNodeId", m_ownNodeId);
+ extConfig->put("LocalNodeType", "REP");
+ Uint32 noOfConnections;
+ extConfig->get("NoOfConnections", &noOfConnections);
+ /* if (noOfConnections != 1) {
+ ndbout << "TransSS: There are " << noOfConnections << " connections "
+ << "defined in configuration"
+ << endl
+ << " There should be exactly one!" << endl;
+ exit(-1);
+ }*/
+
+ /******************************
+ * Set node id of external REP
+ ******************************/
+ const Properties * connection;
+ const char * extSystem;
+
+ Uint32 extRepNodeId, tmpOwnNodeId;
+
+ for(Uint32 i=0; i < noOfConnections; i++) {
+ extConfig->get("Connection", i, &connection);
+ if(connection == 0) REPABORT("Connection not found");
+
+ if(connection->get("System1", &extSystem)) {
+ connection->get("NodeId1", &extRepNodeId);
+ connection->get("NodeId2", &tmpOwnNodeId);
+ } else {
+ connection->get("System2", &extSystem);
+ connection->get("NodeId1", &tmpOwnNodeId);
+ connection->get("NodeId2", &extRepNodeId);
+ }
+ if(m_ownNodeId == tmpOwnNodeId)
+ break;
+ }
+
+ if(extRepNodeId==0) REPABORT("External replication server not found");
+ if(extSystem==0) REPABORT("External system not found");
+
+ m_transporterFacade = new TransporterFacade();
+ if (!m_transporterFacade->init(extConfig))
+ {
+ ndbout << "TransSS: Failed to initialize transporter facade" << endl;
+ exit(-1);
+ }
+
+ m_ownBlockNo = m_transporterFacade->open(this, execSignal, execNodeStatus);
+ assert(m_ownBlockNo > 0);
+ m_ownRef = numberToRef(m_ownBlockNo, m_ownNodeId);
+ assert(m_ownNodeId == m_transporterFacade->ownId());
+
+ ndbout_c("Phase 2 (TransSS): Connection %d to external REP node %d opened",
+ m_ownBlockNo, extRepNodeId);
+
+ m_repSender->setNodeId(extRepNodeId);
+ m_repSender->setOwnRef(m_ownRef);
+ m_repSender->setTransporterFacade(m_transporterFacade);
+#endif
+}
+
+/*****************************************************************************
+ * Signal Queue Executor
+ *****************************************************************************/
+
+class SigMatch
+{
+public:
+ int gsn;
+ void (TransSS::* function)(NdbApiSignal *signal);
+
+ SigMatch() { gsn = 0; function = NULL; };
+
+ SigMatch(int _gsn, void (TransSS::* _function)(NdbApiSignal *signal)) {
+ gsn = _gsn;
+ function = _function;
+ };
+
+ bool check(NdbApiSignal *signal) {
+ if(signal->readSignalNumber() == gsn)
+ return true;
+ return false;
+ };
+};
+
+extern "C"
+void *
+signalExecThread_C(void *r)
+{
+ TransSS *transss = (TransSS*)r;
+
+ transss->signalExecThreadRun();
+ NdbThread_Exit(0);
+ /* NOTREACHED */
+ return 0;
+}
+
+void
+TransSS::signalExecThreadRun()
+{
+ Vector<SigMatch> sl;
+ /**
+ * Signals to be forwarded to TransPS
+ */
+ sl.push_back(SigMatch(GSN_REP_GET_GCI_REQ,
+ &TransSS::sendSignalRep));
+ sl.push_back(SigMatch(GSN_REP_GET_GCIBUFFER_REQ,
+ &TransSS::sendSignalRep));
+ /**
+ * Signals to be executed
+ */
+ sl.push_back(SigMatch(GSN_REP_GCIBUFFER_ACC_REP,
+ &TransSS::execREP_GCIBUFFER_ACC_REP));
+ sl.push_back(SigMatch(GSN_REP_DISCONNECT_REP,
+ &TransSS::execREP_DISCONNECT_REP));
+ sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_CONF,
+ &TransSS::execGREP_SUB_REMOVE_CONF));
+ sl.push_back(SigMatch(GSN_REP_GET_GCIBUFFER_CONF,
+ &TransSS::execREP_GET_GCIBUFFER_CONF));
+
+ sl.push_back(SigMatch(GSN_REP_CLEAR_PS_GCIBUFFER_CONF,
+ &TransSS::execREP_CLEAR_PS_GCIBUFFER_CONF));
+ sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_CONF,
+ &TransSS::execGREP_SUB_SYNC_CONF));
+ sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_REF,
+ &TransSS::execGREP_SUB_SYNC_REF));
+ sl.push_back(SigMatch(GSN_REP_GET_GCIBUFFER_REF,
+ &TransSS::execREP_GET_GCIBUFFER_REF));
+
+ /**
+ * Signals to be executed : Subscriptions
+ */
+ sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_CONF,
+ &TransSS::execGREP_CREATE_SUBID_CONF));
+ sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_REF,
+ &TransSS::execGREP_CREATE_SUBID_REF));
+ sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_CONF,
+ &TransSS::execGREP_SUB_CREATE_CONF));
+ sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_REF,
+ &TransSS::execGREP_SUB_CREATE_REF));
+ sl.push_back(SigMatch(GSN_GREP_SUB_START_CONF,
+ &TransSS::execGREP_SUB_START_CONF));
+ sl.push_back(SigMatch(GSN_GREP_SUB_START_REF,
+ &TransSS::execGREP_SUB_START_REF));
+
+ /**
+ * Signals to be executed and forwarded
+ */
+ sl.push_back(SigMatch(GSN_REP_GET_GCI_CONF,
+ &TransSS::execREP_GET_GCI_CONF));
+
+ /**
+ * Signals to be forwarded
+ */
+ sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_REF,
+ &TransSS::execGREP_SUB_REMOVE_REF));
+ sl.push_back(SigMatch(GSN_REP_CLEAR_PS_GCIBUFFER_REF,
+ &TransSS::execREP_CLEAR_PS_GCIBUFFER_REF));
+ sl.push_back(SigMatch(GSN_REP_GET_GCI_REF,
+ &TransSS::execREP_GET_GCI_REF));
+
+ while(1) {
+ SigMatch *handler = NULL;
+ NdbApiSignal *signal = NULL;
+ if(m_signalRecvQueue.waitFor(sl, handler, signal, DEFAULT_TIMEOUT))
+ {
+#if 0
+ ndbout_c("TransSS: Removed signal from queue (GSN: %d, QSize: %d)",
+ signal->readSignalNumber(), m_signalRecvQueue.size());
+#endif
+ if(handler->function != 0)
+ {
+ (this->*handler->function)(signal);
+ delete signal;
+ signal = 0;
+ } else {
+ REPABORT("Illegal handler for signal");
+ }
+ }
+ }
+}
+
+void
+TransSS::sendSignalRep(NdbApiSignal * s)
+{
+ m_repSender->sendSignal(s);
+}
+
+void
+TransSS::execNodeStatus(void* obj, Uint16 nodeId,
+ bool alive, bool nfCompleted)
+{
+ TransSS * thisObj = (TransSS*)obj;
+
+ if (alive) {
+ thisObj->m_repState->eventNodeConnected(nodeId);
+
+ } else if (!nfCompleted) {
+ thisObj->m_repState->eventNodeDisconnected(nodeId);
+
+ } else if (nfCompleted) {
+ thisObj->m_repState->eventNodeConnectable(nodeId);
+
+ } else {
+ REPABORT("Illegal state for execNodeStatus");
+ }
+}
+
+void
+TransSS::execSignal(void* executorObj, NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3])
+{
+ TransSS * executor = (TransSS *) executorObj;
+
+ const Uint32 gsn = signal->readSignalNumber();
+ const Uint32 len = signal->getLength();
+
+ NdbApiSignal * s = new NdbApiSignal(executor->m_ownRef);
+ switch (gsn) {
+ case GSN_REP_GET_GCI_REQ:
+ case GSN_REP_GET_GCIBUFFER_REQ:
+ case GSN_REP_GET_GCIBUFFER_CONF:
+ case GSN_GREP_SUB_REMOVE_CONF:
+ case GSN_REP_DISCONNECT_REP:
+ case GSN_REP_GCIBUFFER_ACC_REP:
+ s->set(0, PSREPBLOCKNO, gsn, len);
+ memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
+ executor->m_signalRecvQueue.receive(s);
+ break;
+ case GSN_GREP_CREATE_SUBID_CONF:
+ case GSN_GREP_SUB_CREATE_CONF:
+ case GSN_GREP_SUB_START_CONF:
+ case GSN_GREP_SUB_SYNC_CONF:
+ case GSN_REP_GET_GCI_CONF:
+ case GSN_REP_CLEAR_PS_GCIBUFFER_CONF:
+ case GSN_GREP_CREATE_SUBID_REF:
+ case GSN_GREP_SUB_CREATE_REF:
+ case GSN_GREP_SUB_START_REF:
+ case GSN_GREP_SUB_SYNC_REF:
+ case GSN_GREP_SUB_REMOVE_REF:
+ case GSN_REP_GET_GCI_REF:
+ case GSN_REP_GET_GCIBUFFER_REF:
+ case GSN_REP_CLEAR_PS_GCIBUFFER_REF:
+ s->set(0, GREP, gsn, len);
+ memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
+ executor->m_signalRecvQueue.receive(s);
+ break;
+ case GSN_REP_DATA_PAGE:
+ executor->execREP_DATA_PAGE(signal, ptr);
+ delete s; s = 0;
+ break;
+ default:
+ REPABORT1("Illegal signal received in execSignal %d", gsn);
+ }
+
+#if 0
+ ndbout_c("TransSS: Inserted signal into queue (GSN: %d, Len: %d)",
+ signal->readSignalNumber(), len);
+#endif
+}
+
+/*****************************************************************************
+ * Signal Executors
+ *****************************************************************************/
+
+void
+TransSS::execREP_DATA_PAGE(NdbApiSignal * signal, LinearSectionPtr ptr[3])
+{
+ RepDataPage * const page = (RepDataPage*)signal->getDataPtr();
+ m_gciContainer->insertPage(page->gci, page->nodeGrp,
+ (char*)(ptr[0].p), 4 * ptr[0].sz);
+}
+
+/**
+ * Recd from TransPS
+ */
+void
+TransSS::execREP_GCIBUFFER_ACC_REP(NdbApiSignal * signal)
+{
+ RepGciBufferAccRep * const rep =
+ (RepGciBufferAccRep * )signal->getDataPtr();
+
+ Uint32 gci = rep->gci;
+ Uint32 nodeGrp = rep->nodeGrp;
+ Uint32 totalSize = rep->totalSentBytes;
+ GCIBuffer * buffer = m_gciContainer->getGCIBuffer(gci, nodeGrp);
+ Uint32 getReceivedBytes = 0;
+ if (buffer != 0)
+ getReceivedBytes = buffer->getReceivedBytes();
+
+ RLOG(("TransSS: Received %d:[%d] (%d of %d bytes)",
+ nodeGrp, gci, getReceivedBytes, totalSize));
+
+ if(getReceivedBytes != totalSize) {
+ REPABORT("Did not receive correct number of bytes");
+ }
+}
+
+/**
+ * Received from primary system
+ */
+void
+TransSS::execREP_GET_GCIBUFFER_CONF(NdbApiSignal * signal)
+{
+ RepGetGciBufferConf * conf = (RepGetGciBufferConf*)signal->getDataPtr();
+ conf->senderRef = m_ownRef;
+ Uint32 first = conf->firstSSGCI;
+ Uint32 last = conf->lastSSGCI;
+ for(Uint32 i = first; i <= last; i++) {
+ m_gciContainer->setCompleted(i, conf->nodeGrp);
+ }
+
+ /**
+ * Buffers @ PS
+ */
+ Interval ps(conf->firstPSGCI, conf->lastPSGCI);
+ m_repState->add(Channel::PS, conf->nodeGrp, ps);
+
+ /**
+ * Buffers @ SS
+ */
+ Uint32 ssfirst, sslast;
+ m_gciContainer->getAvailableGCIBuffers(conf->nodeGrp, &ssfirst, &sslast);
+ Interval ss(ssfirst, sslast);
+ m_repState->clear(Channel::SS, conf->nodeGrp, universeInterval);
+ m_repState->add(Channel::SS, conf->nodeGrp, ss);
+ m_repState->clear(Channel::SSReq, conf->nodeGrp, ss);
+
+ RLOG(("Transfered epochs (PS:%d[%d-%d], SS:%d[%d-%d])",
+ conf->nodeGrp, conf->firstPSGCI, conf->lastPSGCI,
+ conf->nodeGrp, conf->firstSSGCI, conf->lastSSGCI));
+}
+
+/**
+ * Received from primary system
+ */
+void
+TransSS::execGREP_SUB_REMOVE_CONF(NdbApiSignal * signal)
+{
+ GrepSubRemoveConf * conf = (GrepSubRemoveConf* )signal->getDataPtr();
+ Uint32 subId = conf->subscriptionId;
+ Uint32 subKey = conf->subscriptionKey;
+
+ /**
+ * @todo Fix this sending
+ */
+#if 0
+ signal->theData[0] = EventReport::GrepSubscriptionInfo;
+ signal->theData[1] = GrepEvent::GrepSS_SubRemoveConf;
+ signal->theData[2] = subId;
+ signal->theData[3] = subKey;
+ sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 4, JBB);
+#endif
+
+ m_repState->eventSubscriptionDeleted(subId, subKey);
+ RLOG(("Subscription deleted (SubId: %d, SubKey: %d)", subId, subKey));
+}
+
+void
+TransSS::execGREP_SUB_REMOVE_REF(NdbApiSignal * signal)
+{
+ GrepSubRemoveRef * ref = (GrepSubRemoveRef* )signal->getDataPtr();
+ Uint32 subId = ref->subscriptionId;
+ Uint32 subKey = ref->subscriptionKey;
+
+ /** @todo: Add repevent for this */
+ RLOG(("TransSS: Warning: Grep sub remove ref (SubId: %d, SubKey: %d)",
+ subId, subKey));
+}
+
+/**
+ * Received from primary system
+ */
+void
+TransSS::execREP_GET_GCI_CONF(NdbApiSignal * signal)
+{
+ RepGetGciConf * conf = (RepGetGciConf*)signal->getDataPtr();
+ Uint32 nodeGrp = conf->nodeGrp;
+ Interval i(conf->firstPSGCI, conf->lastPSGCI);
+ m_repState->add(Channel::PS, nodeGrp, i);
+
+ Uint32 first, last;
+ m_gciContainer->getAvailableGCIBuffers(nodeGrp, &first, &last);
+ Interval j(first, last);
+ m_repState->clear(Channel::SS, nodeGrp, universeInterval);
+ m_repState->add(Channel::SS, nodeGrp, j);
+
+#ifdef DEBUG_REP_GET_GCI_CONF
+ RLOG(("TransSS: Requestor info received "
+ "(PS: %d:[%d-%d], SS: %d:[%d-%d])",
+ conf->nodeGrp, conf->firstPSGCI, conf->lastPSGCI,
+ conf->nodeGrp, conf->firstSSGCI, conf->lastSSGCI));
+#endif
+}
+
+void
+TransSS::execREP_GET_GCI_REF(NdbApiSignal * signal)
+{
+ RepGetGciRef * ref = (RepGetGciRef*)signal->getDataPtr();
+ Uint32 nodeGrp = ref->nodeGrp;
+
+ RLOG(("WARNING! Requestor info request failed (Nodegrp: %d)", nodeGrp));
+}
+
+/**
+ * Recd from GrepPS
+ * This signal means that a DB node has disconnected.
+ * @todo Do we need to know that a DB node disconnected?
+ *
+ * A node has disconnected (REP or PS DB)
+ * @todo let the requestor respond to this event
+ * in a proper way.
+ */
+void
+TransSS::execREP_DISCONNECT_REP(NdbApiSignal * signal)
+{
+ RepDisconnectRep * const rep =
+ (RepDisconnectRep*)signal->getDataPtr();
+
+ //Uint32 nodeId = rep->nodeId;
+ Uint32 nodeType = rep->nodeType;
+
+ if((RepDisconnectRep::NodeType)nodeType == RepDisconnectRep::REP)
+ {
+ m_repState->disable();
+ }
+}
+
+/**
+ * The buffer is now deleted on REP PS. We can now clear it from PS.
+ */
+void
+TransSS::execREP_CLEAR_PS_GCIBUFFER_CONF(NdbApiSignal * signal)
+{
+ RepClearPSGciBufferConf * const conf =
+ (RepClearPSGciBufferConf*)signal->getDataPtr();
+ Uint32 firstGCI = conf->firstGCI;
+ Uint32 lastGCI = conf->lastGCI;
+ Uint32 nodeGrp = conf->nodeGrp;
+ Interval i(firstGCI, lastGCI);
+ m_repState->clear(Channel::PS, nodeGrp, i);
+ m_repState->clear(Channel::DelReq, nodeGrp, i);
+
+ RLOG(("Deleted PS:%d:[%d-%d]", nodeGrp, firstGCI, lastGCI));
+}
+
+/**
+ * Something went wrong when deleting buffer on REP PS
+ */
+void
+TransSS::execREP_CLEAR_PS_GCIBUFFER_REF(NdbApiSignal * signal)
+{
+ RepClearPSGciBufferRef * const ref =
+ (RepClearPSGciBufferRef*)signal->getDataPtr();
+ Uint32 firstGCI = ref->firstGCI;
+ Uint32 lastGCI = ref->lastGCI;
+ Uint32 nodeGrp = ref->nodeGrp;
+
+ RLOG(("WARNING! Could not delete PS:%d:[%d-%d]", nodeGrp, firstGCI, lastGCI));
+}
+
+/*****************************************************************************
+ * Signal Executors : SCAN
+ *****************************************************************************/
+
+/**
+ * Scan has started on PS side... (says PS REP)
+ */
+void
+TransSS::execGREP_SUB_SYNC_CONF(NdbApiSignal* signal)
+{
+ GrepSubSyncConf * const conf = (GrepSubSyncConf * ) signal->getDataPtr();
+ Uint32 subId = conf->subscriptionId;
+ Uint32 subKey = conf->subscriptionKey;
+ Interval epochs(conf->firstGCI, conf->lastGCI);
+ SubscriptionData::Part part = (SubscriptionData::Part) conf->part;
+
+ switch(part) {
+ case SubscriptionData::MetaData:
+ RLOG(("Metascan completed. Subcription %d-%d, Epochs [%d-%d]",
+ subId, subKey, epochs.first(), epochs.last()));
+ m_repState->eventMetaScanCompleted(signal, subId, subKey, epochs);
+#if 0
+ signal->theData[0] = EventReport::GrepSubscriptionInfo;
+ signal->theData[1] = GrepEvent::GrepSS_SubSyncMetaConf;
+ signal->theData[2] = subId;
+ signal->theData[3] = subKey;
+ signal->theData[4] = gci;
+ sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 5, JBB);
+#endif
+ break;
+ case SubscriptionData::TableData:
+ RLOG(("Datascan completed. Subcription %d-%d, Epochs [%d-%d]",
+ subId, subKey, epochs.first(), epochs.last()));
+ m_repState->eventDataScanCompleted(signal, subId, subKey, epochs);
+#if 0
+ signal->theData[0] = EventReport::GrepSubscriptionInfo;
+ signal->theData[1] = GrepEvent::GrepSS_SubSyncDataConf;
+ signal->theData[2] = subId;
+ signal->theData[3] = subKey;
+ signal->theData[4] = gci;
+ sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 5, JBB);
+#endif
+ break;
+ default:
+ REPABORT3("Wrong subscription part", part, subId, subKey);
+ }
+}
+
+void
+TransSS::execGREP_SUB_SYNC_REF(NdbApiSignal* signal)
+{
+ GrepSubSyncRef * const ref = (GrepSubSyncRef * ) signal->getDataPtr();
+ Uint32 subId = ref->subscriptionId;
+ Uint32 subKey = ref->subscriptionKey;
+ SubscriptionData::Part part = (SubscriptionData::Part) ref->part;
+ GrepError::Code error = (GrepError::Code) ref->err;
+
+ switch(part) {
+ case SubscriptionData::MetaData:
+ m_repState->eventMetaScanFailed(subId, subKey, error);
+#if 0
+ signal->theData[0] = EventReport::GrepSubscriptionAlert;
+ signal->theData[1] = GrepEvent::GrepSS_SubSyncMetaRef;
+ signal->theData[2] = subId;
+ signal->theData[3] = subKey;
+ // signal->theData[4] = gci;
+ sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 5, JBB);
+#endif
+ break;
+ case SubscriptionData::TableData:
+ m_repState->eventDataScanFailed(subId, subKey, error);
+#if 0
+ signal->theData[0] = EventReport::GrepSubscriptionAlert;
+ signal->theData[1] = GrepEvent::GrepSS_SubSyncDataRef;
+ signal->theData[2] = subId;
+ signal->theData[3] = subKey;
+ //signal->theData[4] = m_lastScanGCI;
+ sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 5, JBB);
+#endif
+ break;
+ default:
+ REPABORT3("Wrong subscription part", part, subId, subKey);
+ }
+}
+
+/**
+ * Something went wrong says REP PS
+ */
+void
+TransSS::execREP_GET_GCIBUFFER_REF(NdbApiSignal* signal)
+{
+ RepGetGciBufferRef * const ref = (RepGetGciBufferRef*)signal->getDataPtr();
+ /*
+ Uint32 senderData = ref->senderData;
+ Uint32 senderRef = ref->senderRef;
+ Uint32 firstPSGCI = ref->firstPSGCI;
+ Uint32 lastPSGCI = ref->lastPSGCI;
+ Uint32 firstSSGCI = ref->firstSSGCI;
+ Uint32 lastSSGCI = ref->lastSSGCI;
+ Uint32 currentGCIBuffer = ref->currentGCIBuffer;
+ Uint32 nodeGrp = ref->nodeGrp;
+ */
+ GrepError::Code err = ref->err;
+
+ RLOG(("WARNING! Request to get buffer failed. Error %d:%s",
+ err, GrepError::getErrorDesc(err)));
+}
diff --git a/ndb/src/old_files/rep/transfer/TransSS.hpp b/ndb/src/old_files/rep/transfer/TransSS.hpp
new file mode 100644
index 00000000000..3340038c8d1
--- /dev/null
+++ b/ndb/src/old_files/rep/transfer/TransSS.hpp
@@ -0,0 +1,145 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef TransSS_HPP
+#define TransSS_HPP
+
+#include <NdbTick.h>
+#include <NdbMain.h>
+#include <NdbOut.hpp>
+#include <NdbSleep.h>
+
+#include <TransporterDefinitions.hpp>
+#include <TransporterFacade.hpp>
+#include <ClusterMgr.hpp>
+#include <API.hpp>
+
+#include <rep/storage/GCIContainer.hpp>
+
+#include <rep/SignalQueue.hpp>
+#include <rep/ExtSender.hpp>
+
+#include <rep/state/RepState.hpp>
+
+extern "C" {
+static void * signalExecThread_C(void *);
+}
+
+/**
+ * @class TransSS
+ * @brief Responsible for REP-REP interface in Standby System role
+ */
+class TransSS {
+public:
+ /***************************************************************************
+ * Constructor / Destructor / Init
+ ***************************************************************************/
+ TransSS(GCIContainer * gciContainer, RepState * repState);
+ ~TransSS();
+ void init(const char * connectString = NULL);
+
+ /***************************************************************************
+ * Public Methods
+ ***************************************************************************/
+ ExtSender * getRepSender() { return m_repSender; };
+ TransporterFacade * getTransporterFacade() { return m_transporterFacade; };
+
+private:
+ /***************************************************************************
+ * Private Methods
+ ***************************************************************************/
+ friend void * signalExecThread_C(void *);
+ void signalExecThreadRun(); ///< SignalQueue executor thread
+
+ static void execSignal(void* executorObj, NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3]);
+ static void execNodeStatus(void* executorObj, NodeId, bool alive,
+ bool nfCompleted);
+
+ void sendSignalRep(NdbApiSignal * s);
+
+ /***************************************************************************
+ * Signal receivers
+ ***************************************************************************/
+ void execREP_GET_GCI_REQ(NdbApiSignal*);
+ void execREP_GET_GCI_CONF(NdbApiSignal*);
+ void execREP_GET_GCI_REF(NdbApiSignal*);
+
+ void execREP_GET_GCIBUFFER_REQ(NdbApiSignal*);
+ void execREP_GET_GCIBUFFER_CONF(NdbApiSignal*);
+ void execREP_GET_GCIBUFFER_REF(NdbApiSignal*);
+
+ void execGREP_SUB_REMOVE_CONF(NdbApiSignal *);
+ void execGREP_SUB_REMOVE_REF(NdbApiSignal *);
+
+ void execREP_INSERT_GCIBUFFER_REQ(NdbApiSignal*);
+ void execREP_INSERT_GCIBUFFER_CONF(NdbApiSignal*);
+ void execREP_INSERT_GCIBUFFER_REF(NdbApiSignal*);
+
+ void execREP_DATA_PAGE(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
+
+ void execREP_GCIBUFFER_ACC_REP(NdbApiSignal*);
+ void execREP_DISCONNECT_REP(NdbApiSignal*);
+
+
+ void execREP_CLEAR_PS_GCIBUFFER_CONF(NdbApiSignal*);
+ void execREP_CLEAR_PS_GCIBUFFER_REF(NdbApiSignal*);
+
+ void execGREP_SUB_SYNC_CONF(NdbApiSignal*);
+ void execGREP_SUB_SYNC_REF(NdbApiSignal*);
+
+ /***************************************************************************
+ * Signal receivers : Subscriptions
+ ***************************************************************************/
+ void execGREP_CREATE_SUBID_CONF(NdbApiSignal*);
+ void execGREP_CREATE_SUBID_REF(NdbApiSignal*);
+ void execGREP_SUB_CREATE_CONF(NdbApiSignal*);
+ void execGREP_SUB_CREATE_REF(NdbApiSignal*);
+ void execGREP_SUB_START_CONF(NdbApiSignal*);
+ void execGREP_SUB_START_REF(NdbApiSignal*);
+
+ /***************************************************************************
+ * Ref signal senders
+ ***************************************************************************/
+
+ void sendREP_GET_GCI_REF(NdbApiSignal* signal, Uint32 nodeGrp,
+ Uint32 firstSSGCI, Uint32 lastSSGCI,
+ GrepError::Code err);
+
+ void sendREP_GET_GCIBUFFER_REF(NdbApiSignal* signal,
+ Uint32 firstGCI, Uint32 lastGCI,
+ Uint32 nodeGrp, GrepError::Code err);
+
+ /***************************************************************************
+ * Private Variables
+ ***************************************************************************/
+ RepState * m_repState;
+
+ struct NdbThread * m_signalExecThread; ///< Signal Queue executor
+ class SignalQueue m_signalRecvQueue;
+
+ ExtSender * m_repSender; ///< Obj responsible send to REP
+
+ Uint32 m_ownNodeId; ///< NodeId of this node
+ Uint32 m_ownBlockNo; ///< BlockNo of this "block"
+ BlockReference m_ownRef; ///< Reference to this
+
+ GCIContainer * m_gciContainer; ///< Ref to gci container.
+
+ TransporterFacade * m_transporterFacade;
+};
+
+#endif
diff --git a/ndb/src/rep/transfer/TransSSSubscriptions.cpp b/ndb/src/old_files/rep/transfer/TransSSSubscriptions.cpp
index 582ba8040a6..582ba8040a6 100644
--- a/ndb/src/rep/transfer/TransSSSubscriptions.cpp
+++ b/ndb/src/old_files/rep/transfer/TransSSSubscriptions.cpp
diff --git a/ndb/src/rep/SignalQueue.hpp b/ndb/src/rep/SignalQueue.hpp
deleted file mode 100644
index 5ebc78a3a37..00000000000
--- a/ndb/src/rep/SignalQueue.hpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef __SIGNALQUEUE_HPP_INCLUDED__
-#define __SIGNALQUEUE_HPP_INCLUDED__
-
-#include <NdbApiSignal.hpp>
-#include <NdbMutex.h>
-#include <NdbCondition.h>
-#include <Vector.hpp>
-
-/* XXX Look for an already existing definition */
-#define DEFAULT_TIMEOUT 10000
-
-/**
- * @class SignalQueue
- * @brief
- */
-class SignalQueue {
-public:
- typedef void (* SignalHandler)(void *obj, int gsn, NdbApiSignal *signal);
-
- SignalQueue();
- ~SignalQueue();
-
- /**
- * Static wrapper making it possible to call receive without knowing the
- * type of the receiver
- */
- static void receive(void *me, NdbApiSignal *signal);
-
- /**
- * Enqueues a signal, and notifies any thread waiting for signals.
- */
- void receive(NdbApiSignal *signal);
-
- NdbApiSignal *waitFor(int gsn,
- NodeId nodeid = 0,
- Uint32 timeout = DEFAULT_TIMEOUT);
- template<class T> bool waitFor(Vector<T> &t,
- T *&handler,
- NdbApiSignal *&signal,
- Uint32 timeout = DEFAULT_TIMEOUT);
-
- /**
- * size()
- */
-
- Uint32 size() {return m_queueSize;};
-
-private:
- NdbMutex *m_mutex; /* Locks all data in SignalQueue */
- NdbCondition *m_cond; /* Notifies about new signal in the queue */
-
- /**
- * Returns the last recently received signal.
- * Must be called with m_mutex locked.
- *
- * The caller takes responsibility for deleting the returned object.
- *
- * @returns NULL if failed, or a received signal
- */
- NdbApiSignal *pop();
-
- class QueueEntry {
- public:
- NdbApiSignal *signal;
- QueueEntry *next;
- };
- QueueEntry *m_signalQueueHead; /** Head of the queue.
- * New entries added on the tail
- */
- Uint32 m_queueSize;
-};
-
-template<class T> bool
-SignalQueue::waitFor(Vector<T> &t,
- T *&handler,
- NdbApiSignal *&signal,
- Uint32 timeout) {
- Guard g(m_mutex);
-
- if(m_signalQueueHead == NULL)
- NdbCondition_WaitTimeout(m_cond, m_mutex, timeout);
-
- if(m_signalQueueHead == NULL)
- return false;
-
- for(size_t i = 0; i < t.size(); i++) {
- if(t[i].check(m_signalQueueHead->signal)) {
- handler = &t[i];
- signal = pop();
- return true;
- }
- }
-
- ndbout_c("SignalQueue: Queued signal without true check function (GSN: %d)",
- m_signalQueueHead->signal->theVerId_signalNumber);
- abort();
-
- return false;
-}
-
-#endif /* !__SIGNALQUEUE_HPP_INCLUDED__ */
diff --git a/ndb/src/rep/adapters/AppNDB.cpp b/ndb/src/rep/adapters/AppNDB.cpp
deleted file mode 100644
index abb146d921f..00000000000
--- a/ndb/src/rep/adapters/AppNDB.cpp
+++ /dev/null
@@ -1,581 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "AppNDB.hpp"
-#include <ConfigRetriever.hpp>
-#include <AttributeHeader.hpp>
-#include <NdbOperation.hpp>
-#include <NdbDictionaryImpl.hpp>
-
-#include <signaldata/RepImpl.hpp>
-#include <TransporterFacade.hpp>
-#include <trigger_definitions.h>
-#include <rep/storage/GCIPage.hpp>
-#include <rep/storage/GCIBuffer.hpp>
-#include <rep/rep_version.hpp>
-
-/*****************************************************************************
- * Constructor / Destructor / Init
- *****************************************************************************/
-
-AppNDB::~AppNDB()
-{
- delete m_tableInfoPs;
- delete m_ndb;
- m_tableInfoPs = 0;
-}
-
-AppNDB::AppNDB(GCIContainer * gciContainer, RepState * repState)
-{
- m_gciContainer = gciContainer;
- m_repState = repState;
- m_cond = NdbCondition_Create();
- m_started = true;
-}
-
-void
-AppNDB::init(const char* connectString) {
-
- // NdbThread_SetConcurrencyLevel(1+ 2);
- Ndb::useFullyQualifiedNames(false);
-
- m_ndb = new Ndb("");
- m_ndb->setConnectString(connectString);
- /**
- * @todo Set proper max no of transactions?? needed?? Default 12??
- */
- m_ndb->init(2048);
- m_dict = m_ndb->getDictionary();
-
- m_ownNodeId = m_ndb->getNodeId();
-
- ndbout << "-- NDB Cluster -- REP node " << m_ownNodeId << " -- Version "
- << REP_VERSION_ID << " --" << endl;
- ndbout_c("Connecting to NDB Cluster...");
- if (m_ndb->waitUntilReady() != 0){
- REPABORT("NDB Cluster not ready for connections");
- }
- ndbout_c("Phase 1 (AppNDB): Connection 1 to NDB Cluster opened (Applier)");
-
- m_tableInfoPs = new TableInfoPs();
-
- m_applierThread = NdbThread_Create(runAppNDB_C,
- (void**)this,
- 32768,
- "AppNDBThread",
- NDB_THREAD_PRIO_LOW);
-}
-
-
-/*****************************************************************************
- * Threads
- *****************************************************************************/
-
-extern "C"
-void*
-runAppNDB_C(void * me)
-{
- ((AppNDB *) me)->threadMainAppNDB();
- NdbThread_Exit(0);
- return me;
-}
-
-void
-AppNDB::threadMainAppNDB() {
- MetaRecord * mr;
- LogRecord * lr;
- GCIBuffer::iterator * itBuffer;
- GCIPage::iterator * itPage;
- GCIBuffer * buffer;
- GCIPage * page;
- Uint32 gci=0;
-
- bool force;
- while(true){
-
- m_gciBufferList.lock();
- if(m_gciBufferList.size()==0)
- NdbCondition_Wait(m_cond, m_gciBufferList.getMutex());
- m_gciBufferList.unlock();
-
- /**
- * Do nothing if we are not started!
- */
- if(!m_started)
- continue;
-
- if(m_gciBufferList.size()>0) {
- m_gciBufferList.lock();
- buffer = m_gciBufferList[0];
- assert(buffer!=0);
- if(buffer==0) {
- m_gciBufferList.unlock();
-// stopApplier(GrepError::REP_APPLY_NULL_GCIBUFFER);
- return;
- }
- m_gciBufferList.unlock();
-
- RLOG(("Applying %d:[%d]", buffer->getId(), buffer->getGCI()));
- gci = buffer->getGCI();
- /**
- * Do stuff with buffer
- */
-
- force = buffer->m_force;
- itBuffer = new GCIBuffer::iterator(buffer);
- page = itBuffer->first();
-
- Record * record;
- while(page!=0 && m_started) {
-
- itPage = new GCIPage::iterator(page);
- record = itPage->first();
-
- while(record!=0 && m_started) {
- switch(Record::RecordType(record->recordType)) {
- case Record::META:
- mr = (MetaRecord*)record;
- if(applyMetaRecord(mr, gci) < 0){
- /**
- * If we fail with a meta record then
- * we should fail the replication!
- */
- //stopApplier(GrepError::REP_APPLY_METARECORD_FAILED);
- }
- break;
- case Record::LOG:
- lr = (LogRecord*)record;
- if(applyLogRecord(lr, force, gci) < 0) {
- /**
- * If we fail to apply a log record AND
- * we have sent a ref to repstate event,
- * then we should not try to apply another one!
- */
-// stopApplier(GrepError::REP_APPLY_LOGRECORD_FAILED);
- }
- break;
- default:
- REPABORT("Illegal record type");
- };
- record = itPage->next();
- }
- delete itPage;
- itPage = 0;
- page = itBuffer->next();
- }
-
- m_gciBufferList.erase(0, true);
- /**
- * "callback" to RepState to send REP_INSERT_GCIBUFFER_CONF
- */
- m_repState->eventInsertConf(buffer->getGCI(), buffer->getId());
- delete itBuffer;
- itBuffer = 0;
- mr = 0;
- lr = 0;
- page = 0;
- buffer = 0;
- }
- }
-
-
-}
-
-void AppNDB::startApplier(){
- m_started = true;
-}
-
-
-void AppNDB::stopApplier(GrepError::Code err){
- m_started = false;
- m_repState->eventInsertRef(0,0,0, err);
-}
-
-
-GrepError::Code
-AppNDB::applyBuffer(Uint32 nodeGrp, Uint32 epoch, Uint32 force)
-{
- m_gciBufferList.lock();
-
- GCIBuffer * buffer = m_gciContainer->getGCIBuffer(epoch, nodeGrp);
- if (buffer == NULL) {
- RLOG(("WARNING! Request to apply NULL buffer %d[%d]. Force %d",
- nodeGrp, epoch, force));
- return GrepError::NO_ERROR;
- }
- if (!buffer->isComplete()) {
- RLOG(("WARNING! Request to apply non-complete buffer %d[%d]. Force %d",
- nodeGrp, epoch, force));
- return GrepError::REP_APPLY_NONCOMPLETE_GCIBUFFER;
- }
- buffer->m_force = force;
-
- assert(buffer!=0);
- m_gciBufferList.push_back(buffer, false);
- NdbCondition_Broadcast(m_cond);
- m_gciBufferList.unlock();
- return GrepError::NO_ERROR;
-}
-
-int
-AppNDB::applyLogRecord(LogRecord* lr, bool force, Uint32 gci)
-{
-#if 0
- RLOG(("Applying log record (force %d, Op %d, GCI %d)",
- force, lr->operation, gci));
-#endif
-
- int retries =0;
- retry:
- if(retries == 10) {
- m_repState->eventInsertRef(gci, 0, lr->tableId,
- GrepError::REP_APPLIER_EXECUTE_TRANSACTION);
- return -1;
- }
- NdbConnection * trans = m_ndb->startTransaction();
- if (trans == NULL) {
- /**
- * Transaction could not be started
- * @todo Handle the error by:
- * 1. Return error code
- * 2. Print log message
- * 3. On higher level indicate that DB has been tainted
- */
- ndbout_c("AppNDB: Send the following error msg to NDB Cluster support");
- reportNdbError("Cannot start transaction!", trans->getNdbError());
- m_repState->eventInsertRef(gci, 0, 0,
- GrepError::REP_APPLIER_START_TRANSACTION);
- REPABORT("Can not start transaction");
- }
-
- /**
- * Resolve table name based on table id
- */
- const Uint32 tableId = lr->tableId;
- const char * tableName = m_tableInfoPs->getTableName(tableId);
-
- /**
- * Close trans and return if it is systab_0.
- */
- if (tableId == 0) {
- RLOG(("WARNING! System table log record received"));
- m_ndb->closeTransaction(trans);
- return -1;
- }
-
- if (tableName==0) {
- /**
- * Table probably does not exist
- * (Under normal operation this should not happen
- * since log records should not appear unless the
- * table has been created.)
- *
- * @todo Perhaps the table is not cached due to a restart,
- * so let's check in the dictionary if it exists.
- */
- m_ndb->closeTransaction(trans);
- m_repState->eventInsertRef(gci, 0, tableId,
- GrepError::REP_APPLIER_NO_TABLE);
- return -1;
- }
-
- const NdbDictionary::Table * table = m_dict->getTable(tableName);
-
- NdbOperation * op = trans->getNdbOperation(tableName);
- if (op == NULL) {
- ndbout_c("AppNDB: Send the following error msg to NDB Cluster support");
- reportNdbError("Cannot get NdbOperation record",
- trans->getNdbError());
- m_repState->eventInsertRef(gci,0,tableId,
- GrepError::REP_APPLIER_NO_OPERATION);
- REPABORT("Can not get NdbOperation record");
- }
-
- int check=0;
- switch(lr->operation) {
- case TriggerEvent::TE_INSERT: // INSERT
- check = op->insertTuple();
- break;
- case TriggerEvent::TE_DELETE: // DELETE
- check = op->deleteTuple();
- break;
- case TriggerEvent::TE_UPDATE: // UPDATE
- if (force) {
- check = op->writeTuple();
- } else {
- check = op->updateTuple();
- }
- break;
- case TriggerEvent::TE_CUSTOM: //SCAN
- check = op->writeTuple();
- break;
- default:
- m_ndb->closeTransaction(trans);
- return -1;
- };
-
- if (check<0) {
- ndbout_c("AppNDB: Something is weird");
- }
-
- /**
- * @todo index inside LogRecord struct somewhat prettier
- * Now it 4 (sizeof(Uint32)), and 9 the position inside the struct
- * where the data starts.
- */
- AttributeHeader * ah=(AttributeHeader *)((char *)lr + sizeof(Uint32) * 9);
- AttributeHeader *end = (AttributeHeader *)(ah + lr->attributeHeaderWSize);
- Uint32 * dataPtr = (Uint32 *)(end);
-
- /**
- * @note attributeheader for operaration insert includes a duplicate
- * p.k. The quick fix for this problem/bug is to skip the first set of
- * of p.k, and start from the other set of P.Ks. Data is duplicated for
- * the p.k.
- */
- if (lr->operation == 0) {
- for(int i = 0; i< table->getNoOfPrimaryKeys(); i++) {
- ah+=ah->getHeaderSize();
- dataPtr = dataPtr + ah->getDataSize();
- }
- }
-
- while (ah < end) {
- const NdbDictionary::Column * column =
- table->getColumn(ah->getAttributeId());
- /**
- * @todo: Here is a limitation. I don't care if it is a tuplekey
- * that is autogenerated or an ordinary pk. I just whack it in.
- * However, this must be examined.
- */
- if(column->getPrimaryKey()) {
- if(op->equal(ah->getAttributeId(), (const char *)dataPtr) < 0) {
- ndbout_c("AppNDB: Equal failed id %d op %d name %s, gci %d force %d",
- ah->getAttributeId(),
- lr->operation,
- column->getName(), gci, force);
- reportNdbError("Equal!", trans->getNdbError());
- }
-
- } else {
- if(op->setValue(ah->getAttributeId(), (const char *)dataPtr) < 0)
- ndbout_c("AppNDB: setvalue failed id %d op %d name %s, gci %d force %d",
- ah->getAttributeId(),
- lr->operation,
- column->getName(), gci, force);
- }
-
- dataPtr = dataPtr + ah->getDataSize();
- ah = ah + ah->getHeaderSize() ;
- }
-
- if(trans->execute(Commit) != 0) {
- /**
- * Transaction commit failure
- */
- const NdbError err = trans->getNdbError();
- m_ndb->closeTransaction(trans);
- switch(err.status){
- case NdbError::Success:
- {
- m_repState->eventInsertRef(gci, 0, tableId,
- GrepError::REP_APPLIER_EXECUTE_TRANSACTION);
- return -1;
- }
- break;
- case NdbError::TemporaryError:
- {
- NdbSleep_MilliSleep(50);
- retries++;
- goto retry;
- }
- break;
- case NdbError::UnknownResult:
- {
- ndbout_c("AppNDB: Send the following error msg to NDB Cluster support");
- reportNdbError("Execute transaction failed!",
- trans->getNdbError());
- m_repState->eventInsertRef(gci, 0, tableId,
- GrepError::REP_APPLIER_EXECUTE_TRANSACTION);
- return -1;
- }
- break;
- case NdbError::PermanentError:
- {
- if(err.code == 626) {
- if(force && lr->operation == TriggerEvent::TE_DELETE) /**delete*/ {
- /**tuple was not found. Ignore this, since
- * we are trying to apply a "delete a tuple"-log record before
- * having applied the scan data.
- */
- return -1;
- }
- }
-
- ndbout_c("AppNDB: Send the following error msg to NDB Cluster support"); reportNdbError("Execute transaction failed!",
- trans->getNdbError());
- ndbout_c("\n\nAppNDB: RepNode will now crash.");
- m_ndb->closeTransaction(trans);
- m_repState->eventInsertRef(gci, 0, tableId,
- GrepError::REP_APPLIER_EXECUTE_TRANSACTION);
- return -1;
- }
- break;
- }
- }
-
- /**
- * No errors. Close transaction and continue in applierThread.
- */
- m_ndb->closeTransaction(trans);
- return 1;
-}
-
-
-int
-AppNDB::applyMetaRecord(MetaRecord* mr, Uint32 gci)
-{
- /**
- * Validate table id
- */
- Uint32 tableId = mr->tableId;
- if (tableId==0) {
- RLOG(("WARNING! Meta record contained record with tableId 0"));
- return 0;
- }
-
- /**
- * Prepare meta record
- */
- NdbDictionary::Table * table = prepareMetaRecord(mr);
- if(table == 0) {
- RLOG(("WARNING! Prepare table meta record failed for table %d", tableId));
- m_dict->getNdbError();
- m_repState->eventInsertRef(gci,0,tableId,
- GrepError::REP_APPLIER_PREPARE_TABLE);
- return -1;
- }
-
- /**
- * Table does not exist in TableInfoPs -> add it
- */
- if(m_tableInfoPs->getTableName(tableId)==0) {
- RLOG(("Table %d:%s added to m_tableInfoPs", tableId, table->getName()));
- m_tableInfoPs->insert(tableId,table->getName());
- }
-
- /**
- * Validate that table does not exist in Dict
- */
-
- const NdbDictionary::Table * tmpTable = m_dict->getTable(table->getName());
- if(tmpTable !=0) {
- /**
- * Oops, a table with the same name exists
- */
- if(tmpTable->getObjectVersion()!=table->getObjectVersion()) {
- char buf[100];
- sprintf(buf,"WARNING! Another version of table %d:%s already exists."
- "Currently, we dont support versions, so will abort now!",
- tableId, table->getName());
-
- REPABORT(buf);
-
- }
- RLOG(("WARNING! An identical table %d:%s already exists.",
- tableId, table->getName()));
- return -1;
- }
-
-
- /**
- * @todo WARNING! Should scan table MR for columns that are not supported
- */
- /*
- NdbDictionary::Column * column;
-
- for(int i=0; i<table->getNoOfColumns(); i++) {
- column = table->getColumn(i);
- if(column->getAutoIncrement()) {
- reportWarning(table->getName(), column->getName(),
- "Uses AUTOINCREMENT of PK");
- }
- }
- */
-
-
- /**
- * Create table
- */
- if(m_dict->createTable(*table)<0) {
- ndbout_c("AppNDB: Send the following error msg to NDB Cluster support");
- reportNdbError("Create table failed!", m_dict->getNdbError());
- m_repState->eventCreateTableRef(gci,
- tableId,
- table->getName(),
- GrepError::REP_APPLIER_CREATE_TABLE);
- return -1;
- }
-
- RLOG(("Table %d:%s created", tableId, table->getName()));
- return 0;
-}
-
-NdbDictionary::Table*
-AppNDB::prepareMetaRecord(MetaRecord* mr) {
- NdbTableImpl * tmp = 0;
- NdbDictionary::Table * table =0;
- Uint32 * data =(Uint32*)( ((char*)mr + sizeof(Uint32)*6));
- int res = NdbDictInterface::parseTableInfo(&tmp, data, mr->dataLen);
- if(res == 0) {
- table = tmp;
- return table;
- } else{
- return 0;
- }
-}
-
-void
-AppNDB::reportNdbError(const char * msg, const NdbError & err) {
- ndbout_c("%s : Error code %d , error message %s",
- msg, err.code,
- (err.message ? err.message : ""));
-}
-
-void
-AppNDB::reportWarning(const char * tableName, const char * message) {
- ndbout_c("WARNING: Table %s, %s", tableName, message);
-}
-
-void
-AppNDB::reportWarning(const char * tableName, const char * columnName,
- const char * message) {
- ndbout_c("WARNING: Table %s, column %s, %s", tableName, columnName,message);
-}
-
-int
-AppNDB::dropTable(Uint32 tableId)
-{
- char * tableName = m_tableInfoPs->getTableName(tableId);
- if(tableName == 0) return -1;
- ndbout_c("AppNDB: Dropping table ");
- if(m_dict->dropTable(tableName) != 0) {
- reportNdbError("Failed dropping table",m_dict->getNdbError());
- return -1;
- }
- m_tableInfoPs->del(tableId);
- return 1;
-}
diff --git a/ndb/src/rep/adapters/ExtNDB.cpp b/ndb/src/rep/adapters/ExtNDB.cpp
deleted file mode 100644
index eb541cdced9..00000000000
--- a/ndb/src/rep/adapters/ExtNDB.cpp
+++ /dev/null
@@ -1,551 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "ExtNDB.hpp"
-#include "ConfigRetriever.hpp"
-#include <NdbSleep.h>
-
-#include <NdbApiSignal.hpp>
-
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include <signaldata/SumaImpl.hpp>
-#include <AttributeHeader.hpp>
-#include <rep/rep_version.hpp>
-#include <ndb_limits.h>
-
-/*****************************************************************************
- * Constructor / Destructor / Init
- *****************************************************************************/
-ExtNDB::ExtNDB(GCIContainerPS * gciContainer, ExtAPI * extAPI)
-{
- m_grepSender = new ExtSender();
- if (!m_grepSender) REPABORT("Could not allocate object");
- m_gciContainerPS = gciContainer;
-
- m_nodeGroupInfo = new NodeGroupInfo();
- m_gciContainerPS->setNodeGroupInfo(m_nodeGroupInfo);
-
- m_doneSetGrepSender = false;
- m_subId = 0;
- m_subKey = 0;
- m_firstGCI = 0;
- m_dataLogStarted = false;
-
- m_extAPI = extAPI;
- if (!m_extAPI) REPABORT("Could not allocate object");
-}
-
-ExtNDB::~ExtNDB()
-{
- delete m_grepSender;
- delete m_nodeGroupInfo;
-}
-
-void
-ExtNDB::signalErrorHandler(NdbApiSignal * signal, Uint32 nodeId)
-{
- //const Uint32 gsn = signal->readSignalNumber();
- //const Uint32 len = signal->getLength();
- RLOG(("Send signal failed. Signal %p", signal));
-}
-
-bool
-ExtNDB::init(const char * connectString)
-{
- m_signalExecThread = NdbThread_Create(signalExecThread_C,
- (void **)this,
- 32768,
- "ExtNDB_Service",
- NDB_THREAD_PRIO_LOW);
-
- ConfigRetriever configRetriever;
- configRetriever.setConnectString(connectString);
-
- Properties* config = configRetriever.getConfig("REP", REP_VERSION_ID);
- if (config == 0) {
- ndbout << "ExtNDB: Configuration error: ";
- const char* erString = configRetriever.getErrorString();
- if (erString == 0) {
- erString = "No error specified!";
- }
- ndbout << erString << endl;
- return false;
- }
- m_ownNodeId = configRetriever.getOwnNodeId();
- config->put("LocalNodeId", m_ownNodeId);
- config->put("LocalNodeType", "REP");
-
- /**
- * Check which GREPs to connect to (in configuration)
- *
- * @note SYSTEM LIMITATION: Only connects to one GREP
- */
- Uint32 noOfConnections=0;
- NodeId grepNodeId=0;
- const Properties * connection;
-
- config->get("NoOfConnections", &noOfConnections);
- for (Uint32 i=0; i<noOfConnections; i++) {
- Uint32 nodeId1, nodeId2;
- config->get("Connection", i, &connection);
- connection->get("NodeId1", &nodeId1);
- connection->get("NodeId2", &nodeId2);
- if (!connection->contains("System1") &&
- !connection->contains("System2") &&
- (nodeId1 == m_ownNodeId || nodeId2 == m_ownNodeId)) {
- /**
- * Found connection
- */
- if (nodeId1 == m_ownNodeId) {
- grepNodeId = nodeId2;
- } else {
- grepNodeId = nodeId1;
- }
- }
- }
-
- m_transporterFacade = TransporterFacade::instance();
-
- assert(m_transporterFacade != 0);
-
- m_ownBlockNo = m_transporterFacade->open(this, execSignal, execNodeStatus);
- assert(m_ownBlockNo > 0);
- m_ownRef = numberToRef(m_ownBlockNo, m_ownNodeId);
- ndbout_c("EXTNDB blockno %d ownref %d ", m_ownBlockNo, m_ownRef);
- assert(m_ownNodeId == m_transporterFacade->ownId());
-
- m_grepSender->setOwnRef(m_ownRef);
- m_grepSender->setTransporterFacade(m_transporterFacade);
-
- if(!m_grepSender->connected(50000)){
- ndbout_c("ExtNDB: Failed to connect to DB nodes!");
- ndbout_c("ExtNDB: Tried to create transporter as (node %d, block %d).",
- m_ownNodeId, m_ownBlockNo);
- ndbout_c("ExtNDB: Check that DB nodes are started.");
- return false;
- }
- ndbout_c("Phase 3 (ExtNDB): Connection %d to NDB Cluster opened (Extractor)",
- m_ownBlockNo);
-
- for (Uint32 i=1; i<MAX_NDB_NODES; i++) {
- if (m_transporterFacade->getIsNodeDefined(i) &&
- m_transporterFacade->getIsNodeSendable(i))
- {
- Uint32 nodeGrp = m_transporterFacade->getNodeGrp(i);
- m_nodeGroupInfo->addNodeToNodeGrp(i, true, nodeGrp);
- Uint32 nodeId = m_nodeGroupInfo->getFirstConnectedNode(nodeGrp);
- m_grepSender->setNodeId(nodeId);
- if(m_nodeGroupInfo->getPrimaryNode(nodeGrp) == 0) {
- m_nodeGroupInfo->setPrimaryNode(nodeGrp, nodeId);
- }
- m_doneSetGrepSender = true;
-#if 0
- RLOG(("Added node %d to node group %d", i, nodeGrp));
-#endif
- }
- }
-
- return true;
-}
-
-/*****************************************************************************
- * Signal Queue Executor
- *****************************************************************************/
-
-class SigMatch
-{
-public:
- int gsn;
- void (ExtNDB::* function)(NdbApiSignal *signal);
-
- SigMatch() { gsn = 0; function = NULL; };
-
- SigMatch(int _gsn, void (ExtNDB::* _function)(NdbApiSignal *signal)) {
- gsn = _gsn;
- function = _function;
- };
-
- bool check(NdbApiSignal *signal) {
- if(signal->readSignalNumber() == gsn)
- return true;
- return false;
- };
-};
-
-void *
-ExtNDB::signalExecThread_C(void *r)
-{
- ExtNDB *grepps = (ExtNDB*)r;
-
- grepps->signalExecThreadRun();
-
- NdbThread_Exit(0);
- /* NOTREACHED */
- return 0;
-}
-
-void
-ExtNDB::signalExecThreadRun()
-{
- Vector<SigMatch> sl;
-
- /**
- * Signals to be executed
- */
- sl.push_back(SigMatch(GSN_SUB_GCP_COMPLETE_REP,
- &ExtNDB::execSUB_GCP_COMPLETE_REP));
-
- /**
- * Is also forwarded to SSCoord
- */
- sl.push_back(SigMatch(GSN_GREP_SUB_START_CONF,
- &ExtNDB::execGREP_SUB_START_CONF));
- sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_CONF,
- &ExtNDB::execGREP_SUB_CREATE_CONF));
- sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_CONF,
- &ExtNDB::execGREP_SUB_REMOVE_CONF));
- /**
- * Signals to be forwarded
- */
- sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_CONF,
- &ExtNDB::execGREP_CREATE_SUBID_CONF));
-
- sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_CONF, &ExtNDB::sendSignalRep));
-
- sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_REF, &ExtNDB::sendSignalRep));
- sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_REF, &ExtNDB::sendSignalRep));
- sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_REF, &ExtNDB::sendSignalRep));
-
- sl.push_back(SigMatch(GSN_GREP_SUB_START_REF, &ExtNDB::sendSignalRep));
- sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_REF, &ExtNDB::sendSignalRep));
-
- while(1) {
- SigMatch *handler = NULL;
- NdbApiSignal *signal = NULL;
- if(m_signalRecvQueue.waitFor(sl, handler, signal)) {
-#if 0
- RLOG(("Removed signal from queue (GSN: %d, QSize: %d)",
- signal->readSignalNumber(), m_signalRecvQueue.size()));
-#endif
- if(handler->function != 0) {
- (this->*handler->function)(signal);
- delete signal; signal = 0;
- } else {
- REPABORT("Illegal handler for signal");
- }
- }
- }
-}
-
-void
-ExtNDB::sendSignalRep(NdbApiSignal * s)
-{
- if(m_repSender->sendSignal(s) == -1)
- {
- signalErrorHandler(s, 0);
- }
-}
-
-void
-ExtNDB::execSignal(void* executorObj, NdbApiSignal* signal,
- class LinearSectionPtr ptr[3])
-{
- ExtNDB * executor = (ExtNDB*)executorObj;
-
- const Uint32 gsn = signal->readSignalNumber();
- const Uint32 len = signal->getLength();
-
- NdbApiSignal * s = new NdbApiSignal(executor->m_ownRef);
- switch(gsn){
- case GSN_SUB_GCP_COMPLETE_REP:
- case GSN_GREP_CREATE_SUBID_CONF:
- case GSN_GREP_SUB_CREATE_CONF:
- case GSN_GREP_SUB_START_CONF:
- case GSN_GREP_SUB_SYNC_CONF:
- case GSN_GREP_SUB_REMOVE_CONF:
- case GSN_GREP_CREATE_SUBID_REF:
- case GSN_GREP_SUB_CREATE_REF:
- case GSN_GREP_SUB_START_REF:
- case GSN_GREP_SUB_SYNC_REF:
- case GSN_GREP_SUB_REMOVE_REF:
- s->set(0, SSREPBLOCKNO, gsn, len);
- memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
- executor->m_signalRecvQueue.receive(s);
- break;
- case GSN_SUB_TABLE_DATA:
- executor->execSUB_TABLE_DATA(signal, ptr);
- delete s; s=0;
- break;
- case GSN_SUB_META_DATA:
- executor->execSUB_META_DATA(signal, ptr);
- delete s; s=0;
- break;
- default:
- REPABORT1("Illegal signal received in execSignal", gsn);
- }
- s=0;
-#if 0
- ndbout_c("ExtNDB: Inserted signal into queue (GSN: %d, Len: %d)",
- signal->readSignalNumber(), len);
-#endif
-}
-
-void
-ExtNDB::execNodeStatus(void* obj, Uint16 nodeId, bool alive, bool nfCompleted)
-{
- ExtNDB * thisObj = (ExtNDB*)obj;
-
- RLOG(("Changed node status (Id %d, Alive %d, nfCompleted %d)",
- nodeId, alive, nfCompleted));
-
- if(alive) {
- /**
- * Connected
- */
- Uint32 nodeGrp = thisObj->m_transporterFacade->getNodeGrp(nodeId);
- RLOG(("DB node %d of node group %d connected", nodeId, nodeGrp));
-
- thisObj->m_nodeGroupInfo->addNodeToNodeGrp(nodeId, true, nodeGrp);
- Uint32 firstNode = thisObj->m_nodeGroupInfo->getPrimaryNode(nodeGrp);
-
- if(firstNode == 0)
- thisObj->m_nodeGroupInfo->setPrimaryNode(nodeGrp, nodeId);
-
- if (!thisObj->m_doneSetGrepSender) {
- thisObj->m_grepSender->setNodeId(firstNode);
- thisObj->m_doneSetGrepSender = true;
- }
-
- RLOG(("Connect: First connected node in nodegroup: %d",
- thisObj->m_nodeGroupInfo->getPrimaryNode(nodeGrp)));
-
- } else if (!nfCompleted) {
-
- /**
- * Set node as "disconnected" in m_nodeGroupInfo until
- * node comes up again.
- */
- Uint32 nodeGrp = thisObj->m_transporterFacade->getNodeGrp(nodeId);
- RLOG(("DB node %d of node group %d disconnected",
- nodeId, nodeGrp));
- thisObj->m_nodeGroupInfo->setConnectStatus(nodeId, false);
- /**
- * The node that crashed was also the primary node, the we must change
- * primary node
- */
- if(nodeId == thisObj->m_nodeGroupInfo->getPrimaryNode(nodeGrp)) {
- Uint32 node = thisObj->m_nodeGroupInfo->getFirstConnectedNode(nodeGrp);
- if(node > 0) {
- thisObj->m_grepSender->setNodeId(node);
- thisObj->m_nodeGroupInfo->setPrimaryNode(nodeGrp, node);
- }
- else {
- thisObj->sendDisconnectRep(nodeGrp);
- }
- }
- RLOG(("Disconnect: First connected node in nodegroup: %d",
- thisObj->m_nodeGroupInfo->getPrimaryNode(nodeGrp)));
-
- } else if(nfCompleted) {
- } else {
- REPABORT("Function execNodeStatus with wrong parameters");
- }
-}
-
-/*****************************************************************************
- * Signal Receivers for LOG and SCAN
- *****************************************************************************/
-
-/**
- * Receive datalog/datascan from GREP/SUMA
- */
-void
-ExtNDB::execSUB_TABLE_DATA(NdbApiSignal * signal, LinearSectionPtr ptr[3])
-{
- SubTableData * const data = (SubTableData*)signal->getDataPtr();
- Uint32 tableId = data->tableId;
- Uint32 operation = data->operation;
- Uint32 gci = data->gci;
- Uint32 nodeId = refToNode(signal->theSendersBlockRef);
-
- if((SubTableData::LogType)data->logType == SubTableData::SCAN)
- {
- Uint32 nodeGrp = m_nodeGroupInfo->findNodeGroup(nodeId);
-
- NodeGroupInfo::iterator * it;
- it = new NodeGroupInfo::iterator(nodeGrp, m_nodeGroupInfo);
- for(NodeConnectInfo * nci=it->first(); it->exists();nci=it->next()) {
- m_gciContainerPS->insertLogRecord(nci->nodeId, tableId,
- operation, ptr, gci);
- }
- delete it; it = 0;
- } else {
- m_gciContainerPS->insertLogRecord(nodeId, tableId, operation, ptr, gci);
- }
-}
-
-/**
- * Receive metalog/metascan from GREP/SUMA
- */
-void
-ExtNDB::execSUB_META_DATA(NdbApiSignal * signal, LinearSectionPtr ptr[3])
-{
- Uint32 nodeId = refToNode(signal->theSendersBlockRef);
- SubMetaData * const data = (SubMetaData*)signal->getDataPtr();
- Uint32 tableId = data->tableId;
- Uint32 gci = data->gci;
-
- Uint32 nodeGrp = m_nodeGroupInfo->findNodeGroup(nodeId);
-
- NodeGroupInfo::iterator * it;
- it = new NodeGroupInfo::iterator(nodeGrp, m_nodeGroupInfo);
- for(NodeConnectInfo * nci=it->first(); it->exists();nci=it->next()) {
- m_gciContainerPS->insertMetaRecord(nci->nodeId, tableId, ptr, gci);
- RLOG(("Received meta record in %d[%d]", nci->nodeId, gci));
- }
-
- delete it; it = 0;
-}
-
-
-/*****************************************************************************
- * Signal Receivers (Signals that are actually just forwarded to SS REP)
- *****************************************************************************/
-
-void
-ExtNDB::execGREP_CREATE_SUBID_CONF(NdbApiSignal * signal)
-{
- CreateSubscriptionIdConf const * conf =
- (CreateSubscriptionIdConf *)signal->getDataPtr();
- Uint32 subId = conf->subscriptionId;
- Uint32 subKey = conf->subscriptionKey;
- ndbout_c("GREP_CREATE_SUBID_CONF m_extAPI=%p\n", m_extAPI);
- m_extAPI->eventSubscriptionIdCreated(subId, subKey);
-}
-
-/*****************************************************************************
- * Signal Receivers
- *****************************************************************************/
-
-/**
- * Receive information about completed GCI from GREP/SUMA
- *
- * GCI completed, i.e. no more unsent log records exists in SUMA
- * @todo use node id to identify buffers?
- */
-void
-ExtNDB::execSUB_GCP_COMPLETE_REP(NdbApiSignal * signal)
-{
- SubGcpCompleteRep * const rep = (SubGcpCompleteRep*)signal->getDataPtr();
- const Uint32 gci = rep->gci;
- Uint32 nodeId = refToNode(rep->senderRef);
-
- RLOG(("Epoch %d completed at node %d", gci, nodeId));
- m_gciContainerPS->setCompleted(gci, nodeId);
-
- if(m_firstGCI == gci && !m_dataLogStarted) {
- sendGREP_SUB_START_CONF(signal, m_firstGCI);
- m_dataLogStarted = true;
- }
-}
-
-/**
- * Send info that scan is competed to SS REP
- *
- * @todo Use node id to identify buffers?
- */
-void
-ExtNDB::sendGREP_SUB_START_CONF(NdbApiSignal * signal, Uint32 gci)
-{
- RLOG(("Datalog started (Epoch %d)", gci));
- GrepSubStartConf * conf = (GrepSubStartConf *)signal->getDataPtrSend();
- conf->firstGCI = gci;
- conf->subscriptionId = m_subId;
- conf->subscriptionKey = m_subKey;
- conf->part = SubscriptionData::TableData;
- signal->m_noOfSections = 0;
- signal->set(0, SSREPBLOCKNO, GSN_GREP_SUB_START_CONF,
- GrepSubStartConf::SignalLength);
- sendSignalRep(signal);
-}
-
-/**
- * Scan is completed... says SUMA/GREP
- *
- * @todo Use node id to identify buffers?
- */
-void
-ExtNDB::execGREP_SUB_START_CONF(NdbApiSignal * signal)
-{
- GrepSubStartConf * const conf = (GrepSubStartConf *)signal->getDataPtr();
- Uint32 part = conf->part;
- //Uint32 nodeId = refToNode(conf->senderRef);
- m_firstGCI = conf->firstGCI;
-
- if (part == SubscriptionData::TableData) {
- RLOG(("Datalog started (Epoch %d)", m_firstGCI));
- return;
- }
- RLOG(("Metalog started (Epoch %d)", m_firstGCI));
-
- signal->set(0, SSREPBLOCKNO, GSN_GREP_SUB_START_CONF,
- GrepSubStartConf::SignalLength);
- sendSignalRep(signal);
-}
-
-/**
- * Receive no of node groups that PS has and pass signal on to SS
- */
-void
-ExtNDB::execGREP_SUB_CREATE_CONF(NdbApiSignal * signal)
-{
- GrepSubCreateConf * conf = (GrepSubCreateConf *)signal->getDataPtrSend();
- m_subId = conf->subscriptionId;
- m_subKey = conf->subscriptionKey;
-
- conf->noOfNodeGroups = m_nodeGroupInfo->getNoOfNodeGroups();
- sendSignalRep(signal);
-}
-
-/**
- * Receive conf that subscription has been remove in GREP/SUMA
- *
- * Pass signal on to TransPS
- */
-void
-ExtNDB::execGREP_SUB_REMOVE_CONF(NdbApiSignal * signal)
-{
- m_gciContainerPS->reset();
- sendSignalRep(signal);
-}
-
-/**
- * If all PS nodes has disconnected, then remove all epochs
- * for this subscription.
- */
-void
-ExtNDB::sendDisconnectRep(Uint32 nodeId)
-{
- NdbApiSignal * signal = new NdbApiSignal(m_ownRef);
- signal->set(0, SSREPBLOCKNO, GSN_REP_DISCONNECT_REP,
- RepDisconnectRep::SignalLength);
- RepDisconnectRep * rep = (RepDisconnectRep*) signal->getDataPtrSend();
- rep->nodeId = nodeId;
- rep->subId = m_subId;
- rep->subKey = m_subKey;
- sendSignalRep(signal);
-}
diff --git a/ndb/src/rep/adapters/ExtNDB.hpp b/ndb/src/rep/adapters/ExtNDB.hpp
deleted file mode 100644
index bcbf51393aa..00000000000
--- a/ndb/src/rep/adapters/ExtNDB.hpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef EXTNDB_HPP
-#define EXTNDB_HPP
-
-#include <ndb_global.h>
-
-#include <TransporterDefinitions.hpp>
-#include <TransporterFacade.hpp>
-#include <ClusterMgr.hpp>
-#include <API.hpp>
-#include <Vector.hpp>
-
-#include <signaldata/RepImpl.hpp>
-#include <signaldata/GrepImpl.hpp>
-
-#include <rep/SignalQueue.hpp>
-#include <rep/ExtSender.hpp>
-
-#include <rep/storage/GCIContainerPS.hpp>
-#include "ExtAPI.hpp"
-
-/**
- * @class ExtNDB
- * @brief Class responsible for connection to primary system GREP
- */
-class ExtNDB
-{
-public:
- /***************************************************************************
- * Constructor / Destructor
- ***************************************************************************/
- ExtNDB(GCIContainerPS * gciContainer, ExtAPI * extAPI);
- ~ExtNDB();
- bool init(const char * connectString = NULL);
-
- /***************************************************************************
- * Public Methods
- ***************************************************************************/
- void setGrepSender(ExtSender * es) { m_grepSender = es; };
- ExtSender * getGrepSender() { return m_grepSender; };
- void setRepSender(ExtSender * es) {
- m_extAPI->setRepSender(es); m_repSender = es; };
- void signalErrorHandler(NdbApiSignal * s, Uint32 nodeId);
-
-private:
- static void execSignal(void* signalSender, NdbApiSignal* signal,
- class LinearSectionPtr ptr[3]);
-
- static void execNodeStatus(void* signalSender, NodeId,
- bool alive, bool nfCompleted);
-
- void signalExecThreadRun();
- static void * signalExecThread_C(void *);
-
- void sendSignalRep(NdbApiSignal *);
- void sendDisconnectRep(Uint32 nodeId);
-
- /***************************************************************************
- * Signal Executors
- ***************************************************************************/
- void execSUB_GCP_COMPLETE_REP(NdbApiSignal*);
- void execGREP_SUB_CREATE_CONF(NdbApiSignal * signal);
- void execGREP_SUB_REMOVE_CONF(NdbApiSignal * signal);
- void execGREP_SUB_START_CONF(NdbApiSignal * signal);
- void sendGREP_SUB_START_CONF(NdbApiSignal * signal, Uint32 gci);
- void execSUB_TABLE_DATA(NdbApiSignal * signal,LinearSectionPtr ptr[3]);
- void execSUB_META_DATA(NdbApiSignal * signal,LinearSectionPtr ptr[3]);
-
- // Signals that are actually just fowarded to REP
- void execGREP_CREATE_SUBID_CONF(NdbApiSignal *);
-
- /***************************************************************************
- * Private Variables
- ***************************************************************************/
- struct NdbThread * m_signalExecThread;
- class SignalQueue m_signalRecvQueue;
-
- Uint32 m_ownNodeId; ///< NodeId of this node
- Uint32 m_ownBlockNo; ///< BlockNo of this "block"
- BlockReference m_ownRef; ///< Reference to this
-
- ExtSender * m_grepSender; ///< Responsible send to GREP
- ExtSender * m_repSender; ///< Responsible send to SS REP
-
- NodeGroupInfo * m_nodeGroupInfo;
- GCIContainerPS * m_gciContainerPS; ///< Interface to GCICotainer
- ///< seen by PS
- TransporterFacade * m_transporterFacade;
-
- bool m_doneSetGrepSender; ///< Only done once
- bool m_dataLogStarted;
- Uint32 m_subId;
- Uint32 m_subKey;
- Uint32 m_firstGCI;
-
- ExtAPI * m_extAPI;
-};
-
-#endif
diff --git a/ndb/src/rep/state/Channel.cpp b/ndb/src/rep/state/Channel.cpp
deleted file mode 100644
index 1d573bad2f5..00000000000
--- a/ndb/src/rep/state/Channel.cpp
+++ /dev/null
@@ -1,487 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "Channel.hpp"
-
-Channel::Channel()
-{
- reset();
-}
-
-Channel::~Channel()
-{
- /**
- * Destroy list of selected tables
- */
- for(Uint32 i=0; i < m_selectedTables.size(); i++) {
- delete m_selectedTables[i];
- m_selectedTables[i] = 0;
- }
- m_selectedTables=0;
-}
-
-void
-Channel::reset()
-{
- for (Uint32 i=0; i<MAX_NO_OF_NODE_GROUPS; i++) {
- for (Uint32 j=0; j<NO_OF_POSITIONS; j++) {
- state[i][j].set(1,0);
- }
- }
- m_noOfNodeGroups = 0;
- m_requestorEnabled = true;
- m_transferEnabled = true;
- m_applyEnabled = true;
- m_deleteEnabled = true;
- m_autoStartEnabled = false;
- m_stopEpochId = intervalMax;
- setSubKey(0);
- setSubId(0);
- m_stateSub = NO_SUBSCRIPTION_EXISTS;
- m_stateRep = CONSISTENT;
- m_metaScanEpochs = emptyInterval;
- m_dataScanEpochs = emptyInterval;
-}
-
-bool
-Channel::requestTransfer(Uint32 nodeGrp, Interval * i)
-{
- invariant();
- Interval tmp1, tmp2;
-
- // i = PS - SSReq - SS - App
- intervalLeftMinus(state[nodeGrp][PS], state[nodeGrp][SSReq], &tmp1);
- intervalLeftMinus(tmp1, state[nodeGrp][SS], &tmp2);
- intervalLeftMinus(tmp2, state[nodeGrp][App], i);
-
- i->onlyLeft(GREP_SYSTEM_TABLE_MAX_RANGE);
- i->onlyUpToValue(m_stopEpochId);
- if (i->isEmpty()) return false;
-
- add(SSReq, nodeGrp, *i);
- invariant();
- return true;
-}
-
-bool
-Channel::requestApply(Uint32 nodeGrp, Uint32 * epoch)
-{
- invariant();
- Interval tmp1, tmp2;
-
- // tmp2 = SS - AppReq - App
- intervalLeftMinus(state[nodeGrp][SS], state[nodeGrp][AppReq], &tmp1);
- intervalLeftMinus(tmp1, state[nodeGrp][App], &tmp2);
-
- tmp2.onlyUpToValue(m_stopEpochId);
- if (tmp2.isEmpty()) return false;
- tmp2.onlyLeft(1);
-
- // Check that all GCI Buffers for epoch exists in SS
- for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
- if (!state[nodeGrp][SS].inInterval(tmp2.first()))
- return false;
- }
-
- invariant();
- add(AppReq, nodeGrp, tmp2);
- invariant();
- *epoch = tmp2.first();
- return true;
-}
-
-bool
-Channel::requestDelete(Uint32 nodeGrp, Interval * i)
-{
- invariant();
- Interval tmp1;
-
- // i = (App cut PS) - DelReq
- intervalCut(state[nodeGrp][App], state[nodeGrp][PS], &tmp1);
- intervalLeftMinus(tmp1, state[nodeGrp][DelReq], i);
-
- if (i->isEmpty()) return false;
- i->onlyLeft(GREP_SYSTEM_TABLE_MAX_RANGE);
-
- invariant();
- add(DelReq, nodeGrp, *i);
- invariant();
- return true;
-}
-
-void
-Channel::add(Position pos, Uint32 nodeGrp, const Interval i)
-{
- Interval r;
- intervalAdd(state[nodeGrp][pos], i, &r);
- state[nodeGrp][pos].set(r);
-}
-
-void
-Channel::clear(Position p, Uint32 nodeGrp, const Interval i)
-{
- Interval r;
- intervalLeftMinus(state[nodeGrp][p], i, &r);
- state[nodeGrp][p].set(r);
-}
-
-bool
-Channel::isSynchable(Uint32 nodeGrp)
-{
- return true;
- /*
- @todo This should be implemented...
-
- Interval tmp1, tmp2;
- intervalAdd(state[nodeGrp][PS], state[nodeGrp][SSReq], &tmp1);
- intervalAdd(tmp1, state[nodeGrp][SSReq], &tmp2);
- intervalAdd(tmp2, state[nodeGrp][SS], &tmp1);
- intervalAdd(tmp1, state[nodeGrp][AppReq], &tmp2);
- intervalAdd(tmp2, state[nodeGrp][App], &tmp1);
- if (intervalInclude(state[nodeGrp][PS], tmp1.right()))
- return true;
- else
- return false;
- */
-}
-
-/**
- * Return the cut of all App:s.
- */
-void
-Channel::getFullyAppliedEpochs(Interval * interval)
-{
- if (m_noOfNodeGroups < 1) {
- *interval = emptyInterval;
- return;
- }
-
- *interval = universeInterval;
- for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
- if (state[i][App].isEmpty()) {
- *interval = emptyInterval;
- return;
- }
-
- if (interval->first() < state[i][App].first()) {
- interval->setFirst(state[i][App].first());
- }
- if (state[i][App].last() < interval->last()) {
- interval->setLast(state[i][App].last());
- }
- }
- interval->normalize();
- return;
-}
-
-/**
- * Return true if it is ok to remove the subscription and then stop channel
- */
-bool
-Channel::isStoppable()
-{
- /**
- * Check that AppReq are empty for all nodegrps
- */
- for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
- if (!state[i][AppReq].isEmpty()) {
- RLOG(("Stop disallowed. AppReq is non-empty"));
- return false;
- }
- }
-
- /**
- * If stop immediately, then it is ok to stop now
- */
- if (m_stopEpochId == 0) {
- RLOG(("Stop allowed. AppReq empty and immediate stop requested"));
- return true;
- }
-
- /**
- * If stop on a certain epoch, then
- * check that stopEpochId is equal to the last applied epoch
- */
- Interval interval;
- getFullyAppliedEpochs(&interval);
- if (m_stopEpochId > interval.last()) {
- RLOG(("Stop disallowed. AppReq empty. Stop %d, LastApplied %d",
- m_stopEpochId, interval.last()));
- return false;
- }
-
- return true;
-}
-
-GrepError::Code
-Channel::setStopEpochId(Uint32 n)
-{
- /**
- * If n equal to zero, use next possible epoch (max(App, AppReq))
- */
- if (n == 0) {
- for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
- n = (state[i][App].last() > n) ? state[i][App].last() : n;
- n = (state[i][AppReq].last() > n) ? state[i][AppReq].last() : n;
- }
- }
-
- /**
- * If n >= max(App, AppReq) then set value, else return error code
- */
- for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
- if (n < state[i][App].last()) return GrepError::ILLEGAL_STOP_EPOCH_ID;
- if (n < state[i][AppReq].last()) return GrepError::ILLEGAL_STOP_EPOCH_ID;
- }
-
- m_stopEpochId = n;
- return GrepError::NO_ERROR;
-};
-
-bool
-Channel::shouldStop()
-{
- /**
- * If (m_stopEpochId == App) then channel should stop
- */
- for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
- if(m_stopEpochId != state[i][App].last()) return false;
- }
- return true;
-}
-
-/*****************************************************************************
- * SELECTIVE TABLE INTERFACE
- *****************************************************************************/
-
-GrepError::Code
-Channel::addTable(const char * tableName)
-{
- if(strlen(tableName)>MAX_TAB_NAME_SIZE)
- return GrepError::REP_NOT_PROPER_TABLE;
- /**
- * No of separators are the number of '/' found in tableName
- * since a table is defined as <db>/<schema>/tablename.
- * if noOfSeparators is not equal to 2, then it is not a valid
- * table name.
- */
- Uint32 noOfSeps = 0;
- if(strlen(tableName) < 5)
- return GrepError::REP_NOT_PROPER_TABLE;
- for(Uint32 i =0; i < strlen(tableName); i++)
- if(tableName[i]=='/')
- noOfSeps++;
- if(noOfSeps!=2)
- return GrepError::REP_NOT_PROPER_TABLE;
- table * t= new table(tableName);
- for(Uint32 i=0; i<m_selectedTables.size(); i++) {
- if(strcmp(tableName, m_selectedTables[i]->tableName)==0)
- return GrepError::REP_TABLE_ALREADY_SELECTED;
- }
- m_selectedTables.push_back(t);
- return GrepError::NO_ERROR;
-}
-
-GrepError::Code
-Channel::removeTable(const char * tableName)
-{
- if(strlen(tableName)>MAX_TAB_NAME_SIZE)
- return GrepError::REP_NOT_PROPER_TABLE;
- /**
- * No of separators are the number of '/' found in tableName
- * since a table is defined as <db>/<schema>/tablename.
- * If noOfSeparators is not equal to 2,
- * then it is not a valid table name.
- */
- Uint32 noOfSeps = 0;
- if(strlen(tableName) < 5)
- return GrepError::REP_NOT_PROPER_TABLE;
- for(Uint32 i =0; i < strlen(tableName); i++)
- if(tableName[i]=='/')
- noOfSeps++;
- if(noOfSeps!=2)
- return GrepError::REP_NOT_PROPER_TABLE;
- for(Uint32 i=0; i<m_selectedTables.size(); i++) {
- if(strcmp(tableName, m_selectedTables[i]->tableName)==0) {
- delete m_selectedTables[i];
- m_selectedTables.erase(i);
- return GrepError::NO_ERROR;
- }
- }
- return GrepError::REP_TABLE_NOT_FOUND;
-}
-
-void
-Channel::printTables()
-{
- if(m_selectedTables.size() == 0)
- ndbout_c("| ALL TABLES "
- " |");
- else {
- for(Uint32 i=0; i<m_selectedTables.size(); i++)
- ndbout_c("| %-69s |", m_selectedTables[i]->tableName);
- }
-}
-
-Vector<struct table *> *
-Channel::getSelectedTables()
-{
- if(m_selectedTables.size() == 0) return 0;
- return &m_selectedTables;
-}
-
-/*****************************************************************************
- * PRINT
- *****************************************************************************/
-
-void
-Channel::print(Position pos)
-{
- switch(pos){
- case PS: ndbout << "PS Rep"; break;
- case SSReq: ndbout << "Tra-Req"; break;
- case SS: ndbout << "SS Rep"; break;
- case AppReq: ndbout << "App-Req"; break;
- case App: ndbout << "Applied"; break;
- case DelReq: ndbout << "Del-Req"; break;
- default: REPABORT("Unknown replication position");
- }
-}
-
-void
-Channel::print()
-{
- for (Uint32 i=0; i<m_noOfNodeGroups; i++) {
- print(i);
- }
-}
-
-void
-Channel::print(Position pos, Uint32 nodeGrp)
-{
- print(pos);
- if (state[nodeGrp][pos].first() == 1 && state[nodeGrp][pos].last() == 0) {
- ndbout << " EMPTY";
- } else {
- ndbout << " [" << state[nodeGrp][pos].first() << "-"
- << state[nodeGrp][pos].last() << "]";
- }
-}
-
-static const char*
-channelline =
-"+-------------------------------------------------------------------------+\n"
-;
-
-void
-Channel::getEpochState(Position p,
- Uint32 nodeGrp,
- Uint32 * first,
- Uint32 * last) {
- if(state[nodeGrp][p].isEmpty()) {
- *first = 1;
- *last = 0;
- return;
- }
- *first = state[nodeGrp][p].first();
- *last = state[nodeGrp][p].last();
-}
-
-
-void
-Channel::print(Uint32 nodeGrp)
-{
- ndbout << channelline;
- ndbout_c("| | Meta scan |"
- " Data scan |");
- ndbout.print("| ");
- if (m_metaScanEpochs.isEmpty()) {
- ndbout.print("| ");
- } else {
- ndbout.print("| %10u-%-10u ",
- m_metaScanEpochs.first(), m_metaScanEpochs.last());
- }
- if (m_dataScanEpochs.isEmpty()) {
- ndbout_c("| |");
- } else {
- ndbout_c("| %10u-%-10u |",
- m_dataScanEpochs.first(), m_dataScanEpochs.last());
- }
-
- /* --- */
-
- ndbout << channelline;
- ndbout_c("| Source Rep Server | Being Transfered |"
- " Destination Rep Server |");
- if (state[nodeGrp][PS].isEmpty()) {
- ndbout.print("| ");
- } else {
- ndbout.print("| %10u-%-10u ",
- state[nodeGrp][PS].first(), state[nodeGrp][PS].last());
- }
- if (state[nodeGrp][SSReq].isEmpty()) {
- ndbout.print("| ");
- } else {
- ndbout.print("| %10u-%-10u ",
- state[nodeGrp][SSReq].first(), state[nodeGrp][SSReq].last());
- }
- if (state[nodeGrp][SS].isEmpty()) {
- ndbout_c("| |");
- } else {
- ndbout_c("| %10u-%-10u |",
- state[nodeGrp][SS].first(), state[nodeGrp][SS].last());
- }
-
- /* --- */
-
- ndbout << channelline;
- ndbout_c("| Being Applied | Applied |"
- " Being Deleted |");
- if (state[nodeGrp][AppReq].isEmpty()) {
- ndbout.print("| ");
- } else {
- ndbout.print("| %10u-%-10u ", state[nodeGrp][AppReq].first(),
- state[nodeGrp][AppReq].last());
- }
- if (state[nodeGrp][App].isEmpty()) {
- ndbout.print("| ");
- } else {
- ndbout.print("| %10u-%-10u ",
- state[nodeGrp][App].first(), state[nodeGrp][App].last());
- }
- if (state[nodeGrp][DelReq].isEmpty()) {
- ndbout_c("| |");
- } else {
- ndbout_c("| %10u-%-10u |",
- state[nodeGrp][DelReq].first(), state[nodeGrp][DelReq].last());
- }
-}
-
-/*****************************************************************************
- * Private Methods
- *****************************************************************************/
-
-void
-Channel::invariant()
-{
- for (Uint32 j=0; j<MAX_NO_OF_NODE_GROUPS; j++)
- {
- if (!intervalDisjoint(state[j][SSReq], state[j][SS]))
- REPABORT("Invariant 1 violated");
- if (!intervalDisjoint(state[j][AppReq], state[j][App]))
- REPABORT("Invariant 2 violated");
- }
-}
diff --git a/ndb/src/rep/state/RepState.hpp b/ndb/src/rep/state/RepState.hpp
deleted file mode 100644
index e88151d5609..00000000000
--- a/ndb/src/rep/state/RepState.hpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef REP_STATE_HPP
-#define REP_STATE_HPP
-
-#include <GrepError.hpp>
-#include <signaldata/GrepImpl.hpp>
-#include <rep/repapi/repapi.h>
-#include <rep/ExtSender.hpp>
-#include <rep/adapters/AppNDB.hpp>
-
-#include "Channel.hpp"
-#include "Interval.hpp"
-
-#define REQUESTOR_EXECUTES_NEEDED_FOR_UNKNOWN_CONNECTION 5
-
-class NdbApiSignal;
-
-
-/**
- * @class RepState
- * @brief The main information about the replication
- */
-class RepState
-{
-public:
- RepState();
- ~RepState();
- void init(ExtSender * extSender) { m_extSender = extSender; }
-
- /***************************************************************************
- * Callback functions
- *
- * These are used when RepState wants to do something
- ***************************************************************************/
-
- typedef void (FuncRequestCreateSubscriptionId)
- (void * cbObj, NdbApiSignal* signal);
-
- typedef void (FuncRequestCreateSubscription)
- (void * cbObj, NdbApiSignal* signal, Uint32 subId,
- Uint32 subKey ,
- Vector <struct table *> * selectedTables);
-
- typedef void (FuncRequestRemoveSubscription)
- (void * cbObj, NdbApiSignal* signal, Uint32 subId, Uint32 subKey);
-
- typedef void (FuncRequestTransfer)
- (void * cbObj, NdbApiSignal* signal,
- Uint32 nodeGrp, Uint32 first, Uint32 last);
-
- typedef void (FuncRequestApply)
- (void * cbObj, NdbApiSignal* signal,
- Uint32 nodeGrp, Uint32 first, Uint32 last, Uint32 force);
-
- typedef void (FuncRequestDeleteSS)
- (void * cbObj, NdbApiSignal* signal,
- Uint32 nodeGrp, Uint32 first, Uint32 last);
-
- typedef void (FuncRequestDeletePS)
- (void * cbObj, NdbApiSignal* signal,
- Uint32 nodeGrp, Uint32 first, Uint32 last);
-
- typedef void (FuncRequestStartMetaLog)
- (void * cbObj, NdbApiSignal * signal, Uint32 subId, Uint32 subKey);
-
- typedef void (FuncRequestStartDataLog)
- (void * cbObj, NdbApiSignal * signal, Uint32 subId, Uint32 subKey);
-
- typedef void (FuncRequestStartMetaScan)
- (void * cbObj, NdbApiSignal * signal, Uint32 subId, Uint32 subKey);
-
- typedef void (FuncRequestStartDataScan)
- (void * cbObj, NdbApiSignal * signal, Uint32 subId, Uint32 subKey);
-
- typedef void (FuncRequestEpochInfo)
- (void * cbObj, NdbApiSignal * signal, Uint32 nodeGrp);
-
- /***************************************************************************
- *
- ***************************************************************************/
- void setSubscriptionRequests(FuncRequestCreateSubscriptionId f1,
- FuncRequestCreateSubscription f2,
- FuncRequestRemoveSubscription f3);
- void setIntervalRequests(FuncRequestTransfer * f1,
- FuncRequestApply * f2,
- FuncRequestDeleteSS * f3,
- FuncRequestDeletePS * f4);
- void setStartRequests(FuncRequestStartMetaLog * f5,
- FuncRequestStartDataLog * f6,
- FuncRequestStartMetaScan * f7,
- FuncRequestStartDataScan * f8,
- FuncRequestEpochInfo * f9);
-
- /***************************************************************************
- * Enablings
- ***************************************************************************/
- bool isEnabled() { return m_channel.m_requestorEnabled; }
- bool isTransferEnabled() { return m_channel.m_transferEnabled; }
- bool isApplyEnabled() { return m_channel.m_applyEnabled; }
- bool isDeleteEnabled() { return m_channel.m_deleteEnabled; }
- bool isAutoStartEnabled() { return m_channel.m_autoStartEnabled; }
-
- void enable() { m_channel.m_requestorEnabled = true; }
- void enableTransfer() { m_channel.m_transferEnabled = true; }
- void enableApply() { m_channel.m_applyEnabled = true; }
- void enableDelete() { m_channel.m_deleteEnabled = true; }
- void enableAutoStart() { m_channel.m_autoStartEnabled = true; }
-
- void disable() { m_channel.m_requestorEnabled = false; }
- void disableTransfer() { m_channel.m_transferEnabled = false; }
- void disableApply() { m_channel.m_applyEnabled = false;}
- void disableDelete() { m_channel.m_deleteEnabled = false; }
- void disableAutoStart() { m_channel.m_autoStartEnabled = false; }
-
- /***************************************************************************
- * Node groups
- ***************************************************************************/
- void setNoOfNodeGroups(Uint32 n) { m_channel.setNoOfNodeGroups(n); }
- Uint32 getNoOfNodeGroups() { return m_channel.getNoOfNodeGroups(); }
-
- /***************************************************************************
- * Event reporting to RepState
- *
- * These are used to update the state of the Requestor when something
- * has happend.
- ***************************************************************************/
- void request(GrepReq::Request request);
-
- //GrepError::Code createSubscription(Uint32 subId, Uint32 subKey);
- GrepError::Code protectedExecute();
- GrepError::Code protectedRequest(GrepReq::Request request, Uint32 arg);
- GrepError::Code protectedRequest(GrepReq::Request request,
- Uint32 arg1,
- Uint32 arg2);
- GrepError::Code protectedAddTable(const char * fullTableName);
- GrepError::Code protectedRemoveTable(const char * fullTableName);
- GrepError::Code add(Channel::Position s, Uint32 nodeGrp, const Interval i);
- GrepError::Code clear(Channel::Position s, Uint32 nodeGrp, const Interval i);
-
- void eventSubscriptionDeleted(Uint32 subId, Uint32 subKey);
-
- void eventMetaLogStarted(NdbApiSignal*, Uint32 subId, Uint32 subKey);
- void eventDataLogStarted(NdbApiSignal*, Uint32 subId, Uint32 subKey);
- void eventMetaScanCompleted(NdbApiSignal*, Uint32 subId, Uint32 subKey,
- Interval epochs);
- void eventDataScanCompleted(NdbApiSignal*, Uint32 subId, Uint32 subKey,
- Interval epochs);
- void eventMetaScanFailed(Uint32 subId, Uint32 subKey, GrepError::Code error);
- void eventDataScanFailed(Uint32 subId, Uint32 subKey, GrepError::Code error);
-
- /**
- * @fn sendInsertConf
- * @param gci - the gci of the applied GCIBuffer.
- * @param nodeGrp - the nodeGrp of the applied GCIBuffer.
- */
- void eventInsertConf(Uint32 gci, Uint32 nodeGrp);
-
- /**
- * @fn sendInsertRef
- * @param gci - the gci of the applied GCIBuffer.
- * @param nodeGrp - the nodeGrp of the applied GCIBuffer.
- * @param tableId - the table of the applied GCIBuffer.
- */
- void eventInsertRef(Uint32 gci, Uint32 nodeGrp, Uint32 tableId,
- GrepError::Code err);
- void eventCreateTableRef(Uint32 gci,
- Uint32 tableId,
- const char * tableName,
- GrepError::Code err) ;
-
- void eventSubscriptionIdCreated(Uint32 subId, Uint32 subKey);
- void eventSubscriptionIdCreateFailed(Uint32 subId, Uint32 subKey,
- GrepError::Code error);
-
- void eventSubscriptionCreated(Uint32 subId, Uint32 subKey);
- void eventSubscriptionCreateFailed(Uint32 subId, Uint32 subKey,
- GrepError::Code error);
-
- void eventMetaLogStartFailed(Uint32 subId, Uint32 subKey,
- GrepError::Code error);
- void eventDataLogStartFailed(Uint32 subId, Uint32 subKey,
- GrepError::Code error);
-
- void eventNodeConnected(Uint32 nodeId);
- void eventNodeDisconnected(Uint32 nodeId);
- void eventNodeConnectable(Uint32 nodeId);
-
- void printStatus();
- Properties * getStatus();
- Properties * query(QueryCounter counter, Uint32 replicationId);
- Uint32 getSubId() { return m_channel.getSubId(); }
- Uint32 getSubKey () { return m_channel.getSubKey(); }
-
- void setApplier(class AppNDB * app) { m_applier = app; }
- void setGCIContainer(class GCIContainer * c) { m_gciContainer = c; }
-
- /* @todo should be private */
- Channel m_channel;
-
-private:
- /***************************************************************************
- * PRIVATE ATTRIBUTES
- ***************************************************************************/
- ExtSender * m_extSender;
- AppNDB * m_applier;
- GCIContainer * m_gciContainer;
-
- Uint32 m_subIdToRemove;
- Uint32 m_subKeyToRemove;
-
-
- enum Connected
- {
- UNKNOWN, ///<
- CONNECTED, ///< Recently received info from (all needed) PS REP
- DISCONNECTED, ///< Received disconnect info from (some needed) PS REP
- CONNECTABLE ///< Received disconnect info from (some needed) PS REP
- };
- Connected m_connected;
- Connected m_repConnected;
- Uint32 m_connected_counter;
-
- NdbMutex * m_mutex;
-
- /** @todo Should be channel-specific */
- Uint32 m_stopEpoch;
-
- /***************************************************************************
- * PRIVATE METHODS
- ***************************************************************************/
- GrepError::Code execute(NdbApiSignal*);
- GrepError::Code request(GrepReq::Request req,
- Uint32 arg1,
- Uint32 arg2,
- NdbApiSignal*);
-
- FuncRequestCreateSubscriptionId * m_funcRequestCreateSubscriptionId;
- FuncRequestCreateSubscription * m_funcRequestCreateSubscription;
- FuncRequestRemoveSubscription * m_funcRequestRemoveSubscription;
-
- FuncRequestTransfer * m_funcRequestTransfer;
- FuncRequestApply * m_funcRequestApply;
- FuncRequestDeleteSS * m_funcRequestDeleteSS;
- FuncRequestDeletePS * m_funcRequestDeletePS;
-
- FuncRequestStartMetaLog * m_funcRequestStartMetaLog;
- FuncRequestStartDataLog * m_funcRequestStartDataLog;
- FuncRequestStartMetaScan * m_funcRequestStartMetaScan;
- FuncRequestStartDataScan * m_funcRequestStartDataScan;
- FuncRequestEpochInfo * m_funcRequestEpochInfo;
-
- void requestTransfer(NdbApiSignal * signal);
- void requestApply(NdbApiSignal * signal);
- void requestDelete(NdbApiSignal * signal);
- void requestEpochInfo(NdbApiSignal * signal);
- void getEpochState(Channel::Position pos, Properties * p);
- friend void testRepState();
-};
-
-#endif
diff --git a/ndb/src/rep/transfer/TransPS.cpp b/ndb/src/rep/transfer/TransPS.cpp
deleted file mode 100644
index 1f65e95850d..00000000000
--- a/ndb/src/rep/transfer/TransPS.cpp
+++ /dev/null
@@ -1,549 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include "ConfigRetriever.hpp"
-#include <NdbSleep.h>
-
-#include <NdbApiSignal.hpp>
-#include <AttributeHeader.hpp>
-
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include <signaldata/SumaImpl.hpp>
-#include <GrepError.hpp>
-#include <SimpleProperties.hpp>
-
-#include "TransPS.hpp"
-#include <rep/storage/NodeGroupInfo.hpp>
-
-/*****************************************************************************
- * Constructor / Destructor / Init
- *****************************************************************************/
-TransPS::TransPS(GCIContainerPS* gciContainer)
-{
- m_repSender = new ExtSender();
- m_gciContainerPS = gciContainer;
-}
-
-TransPS::~TransPS()
-{
- delete m_repSender;
-}
-
-void
-TransPS::init(TransporterFacade * tf, const char * connectString)
-{
- m_signalExecThread = NdbThread_Create(signalExecThread_C,
- (void **)this,
- 32768,
- "TransPS_Service",
- NDB_THREAD_PRIO_LOW);
-
- ConfigRetriever configRetriever;
- // configRetriever.setConnectString(connectString);
- Properties* config = configRetriever.getConfig("REP", REP_VERSION_ID);
- if (config == 0) {
- ndbout << "TransPS: Configuration error: ";
- const char* erString = configRetriever.getErrorString();
- if (erString == 0) {
- erString = "No error specified!";
- }
- ndbout << erString << endl;
- exit(-1);
- }
-
- Properties * extConfig;
- /**
- * @todo Hardcoded primary system name
- */
- if (!config->getCopy("EXTERNAL SYSTEM_External", &extConfig)) {
- ndbout << "External System \"External\" not found in configuration. "
- << "Check config.ini." << endl;
- config->print();
- exit(-1);
- }
-
- m_ownNodeId = configRetriever.getOwnNodeId();
- extConfig->put("LocalNodeId", m_ownNodeId);
- extConfig->put("LocalNodeType", "REP");
- Uint32 noOfConnections;
- extConfig->get("NoOfConnections", &noOfConnections);
- /* if (noOfConnections != 1) {
- ndbout << "TransPS: There are " << noOfConnections << " connections "
- << "defined in configuration"
- << endl
- << " There should be exactly one!" << endl;
- exit(-1);
- }
- */
- /******************************
- * Set node id of external REP
- ******************************/
- const Properties * connection;
- const char * extSystem;
- Uint32 extRepNodeId, tmpOwnNodeId;
-
- for(Uint32 i=0; i < noOfConnections; i++) {
- extConfig->get("Connection", i, &connection);
- if(connection == 0) REPABORT("No connection found");
-
- if(connection->get("System1", &extSystem)) {
- connection->get("NodeId1", &extRepNodeId);
- connection->get("NodeId2", &tmpOwnNodeId);
- } else {
- connection->get("System2", &extSystem);
- connection->get("NodeId1", &tmpOwnNodeId);
- connection->get("NodeId2", &extRepNodeId);
- }
- if(m_ownNodeId == tmpOwnNodeId)
- break;
- }
-
- if(extRepNodeId==0) REPABORT("External replication server not found");
- if(extSystem==0) REPABORT("External system not found");
-
- m_ownBlockNo = tf->open(this, execSignal, execNodeStatus);
- assert(m_ownBlockNo > 0);
-
- m_ownRef = numberToRef(m_ownBlockNo, m_ownNodeId);
- assert(m_ownNodeId == tf->ownId());
-
- ndbout_c("Phase 4 (TransPS): Connection %d to external REP node %d opened",
- m_ownBlockNo, extRepNodeId);
-
- m_repSender->setNodeId(extRepNodeId);
- m_repSender->setOwnRef(m_ownRef);
- m_repSender->setTransporterFacade(tf);
-}
-
-/*****************************************************************************
- * Signal Queue Executor
- *****************************************************************************/
-
-class SigMatch
-{
-public:
- int gsn;
- void (TransPS::* function)(NdbApiSignal *signal);
-
- SigMatch() { gsn = 0; function = NULL; };
-
- SigMatch(int _gsn, void (TransPS::* _function)(NdbApiSignal *signal)) {
- gsn = _gsn;
- function = _function;
- };
-
- bool check(NdbApiSignal *signal) {
- if(signal->readSignalNumber() == gsn) return true;
- return false;
- };
-};
-
-void *
-TransPS::signalExecThread_C(void *r)
-{
- TransPS *repps = (TransPS*)r;
-
- repps->signalExecThreadRun();
-
- NdbThread_Exit(0);
- /* NOTREACHED */
- return 0;
-}
-
-void
-TransPS::signalExecThreadRun()
-{
- Vector<SigMatch> sl;
-
- /**
- * Signals executed here
- */
- sl.push_back(SigMatch(GSN_REP_GET_GCI_REQ,
- &TransPS::execREP_GET_GCI_REQ));
- sl.push_back(SigMatch(GSN_REP_GET_GCIBUFFER_REQ,
- &TransPS::execREP_GET_GCIBUFFER_REQ));
- sl.push_back(SigMatch(GSN_REP_CLEAR_PS_GCIBUFFER_REQ,
- &TransPS::execREP_CLEAR_PS_GCIBUFFER_REQ));
-
- /**
- * Signals to be forwarded to GREP::PSCoord
- */
- sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_REQ, &TransPS::sendSignalGrep));
-
- /**
- * Signals to be forwarded to GREP::PSCoord
- */
- sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_REQ, &TransPS::sendSignalGrep));
- sl.push_back(SigMatch(GSN_GREP_SUB_START_REQ, &TransPS::sendSignalGrep));
- sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_REQ, &TransPS::sendSignalGrep));
- sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_REQ, &TransPS::sendSignalGrep));
-
- while(1) {
- SigMatch *handler = NULL;
- NdbApiSignal *signal = NULL;
- if(m_signalRecvQueue.waitFor(sl, handler, signal)) {
-#if 0
- ndbout_c("TransPS: Removed signal from queue (GSN: %d, QSize: %d)",
- signal->readSignalNumber(), m_signalRecvQueue.size());
-#endif
- if(handler->function != 0) {
- (this->*handler->function)(signal);
- delete signal;
- signal = 0;
- } else {
- REPABORT("Illegal handler for signal");
- }
- }
- }
-}
-
-void
-TransPS::sendSignalRep(NdbApiSignal * s)
-{
- m_repSender->sendSignal(s);
-}
-
-void
-TransPS::sendSignalGrep(NdbApiSignal * s)
-{
- m_grepSender->sendSignal(s);
-}
-
-void
-TransPS::sendFragmentedSignalRep(NdbApiSignal * s,
- LinearSectionPtr ptr[3],
- Uint32 sections)
-{
- m_repSender->sendFragmentedSignal(s, ptr, sections);
-}
-
-void
-TransPS::sendFragmentedSignalGrep(NdbApiSignal * s,
- LinearSectionPtr ptr[3],
- Uint32 sections)
-{
- m_grepSender->sendFragmentedSignal(s, ptr, sections);
-}
-
-
-void
-TransPS::execNodeStatus(void* obj, Uint16 nodeId, bool alive, bool nfCompleted)
-{
-// TransPS * thisObj = (TransPS*)obj;
-
- RLOG(("Node changed state (NodeId %d, Alive %d, nfCompleted %d)",
- nodeId, alive, nfCompleted));
-
- if(!alive && !nfCompleted) { }
-
- if(!alive && nfCompleted) { }
-}
-
-void
-TransPS::execSignal(void* executeObj, NdbApiSignal* signal,
- class LinearSectionPtr ptr[3]){
-
- TransPS * executor = (TransPS *) executeObj;
-
- const Uint32 gsn = signal->readSignalNumber();
- const Uint32 len = signal->getLength();
-
- NdbApiSignal * s = new NdbApiSignal(executor->m_ownRef);
- switch(gsn){
- case GSN_REP_GET_GCI_REQ:
- case GSN_REP_GET_GCIBUFFER_REQ:
- case GSN_REP_CLEAR_PS_GCIBUFFER_REQ:
- s->set(0, SSREPBLOCKNO, gsn, len);
- memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
- executor->m_signalRecvQueue.receive(s);
- break;
- case GSN_GREP_SUB_CREATE_REQ:
- {
- if(signal->m_noOfSections > 0) {
- memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
- s->set(0, GREP, gsn,
- len);
- executor->sendFragmentedSignalGrep(s,ptr,1);
- delete s;
- } else {
- s->set(0, GREP, gsn, len);
- memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
- executor->m_signalRecvQueue.receive(s);
- }
- }
- break;
- case GSN_GREP_SUB_START_REQ:
- case GSN_GREP_SUB_SYNC_REQ:
- case GSN_GREP_SUB_REMOVE_REQ:
- case GSN_GREP_CREATE_SUBID_REQ:
- s->set(0, GREP, gsn, len);
- memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
- executor->m_signalRecvQueue.receive(s);
- break;
- default:
- REPABORT1("Illegal signal received in execSignal", gsn);
- }
-#if 0
- ndbout_c("TransPS: Inserted signal into queue (GSN: %d, Len: %d)",
- signal->readSignalNumber(), len);
-#endif
-}
-
-/*****************************************************************************
- * Signal Receivers
- *****************************************************************************/
-
-void
-TransPS::execREP_GET_GCIBUFFER_REQ(NdbApiSignal* signal)
-{
- RepGetGciBufferReq * req = (RepGetGciBufferReq*)signal->getDataPtr();
- Uint32 firstGCI = req->firstGCI;
- Uint32 lastGCI = req->lastGCI;
- Uint32 nodeGrp = req->nodeGrp;
-
- RLOG(("Received request for %d:[%d-%d]", nodeGrp, firstGCI, lastGCI));
-
- NodeGroupInfo * tmp = m_gciContainerPS->getNodeGroupInfo();
- Uint32 nodeId = tmp->getPrimaryNode(nodeGrp);
- /**
- * If there is no connected node in the nodegroup -> abort.
- * @todo: Handle error when a nodegroup is "dead"
- */
- if(!nodeId) {
- RLOG(("There are no connected nodes in node group %d", nodeGrp));
- sendREP_GET_GCIBUFFER_REF(signal, firstGCI, lastGCI, nodeGrp,
- GrepError::REP_NO_CONNECTED_NODES);
- return;
- }
-
- transferPages(firstGCI, lastGCI, nodeId, nodeGrp, signal);
-
- /**
- * Done tfxing pages, sending GCIBuffer conf.
- */
- Uint32 first, last;
- m_gciContainerPS->getAvailableGCIBuffers(nodeGrp, &first, &last);
-
- RepGetGciBufferConf * conf = (RepGetGciBufferConf*)req;
- conf->senderRef = m_ownRef;
- conf->firstPSGCI = first; // Buffers found on REP PS (piggy-back info)
- conf->lastPSGCI = last;
- conf->firstSSGCI = firstGCI; // Now been transferred to REP SS
- conf->lastSSGCI = lastGCI;
- conf->nodeGrp = nodeGrp;
- signal->set(0, SSREPBLOCKNO, GSN_REP_GET_GCIBUFFER_CONF,
- RepGetGciBufferConf::SignalLength);
- sendSignalRep(signal);
-
- RLOG(("Sent %d:[%d-%d] (Stored PS:%d:[%d-%d])",
- nodeGrp, firstGCI, lastGCI, nodeGrp, first, last));
-}
-
-void
-TransPS::transferPages(Uint32 firstGCI, Uint32 lastGCI,
- Uint32 nodeId, Uint32 nodeGrp,
- NdbApiSignal * signal)
-{
- /**
- * Transfer pages in GCI Buffer to SS
- * When buffer is sent, send accounting information.
- */
- RepDataPage * pageData = (RepDataPage*)signal->getDataPtr();
- LinearSectionPtr ptr[1];
- GCIPage * page;
- for(Uint32 i=firstGCI; i<=lastGCI; i++) {
- Uint32 totalSizeSent = 0;
- GCIBuffer * buffer = m_gciContainerPS->getGCIBuffer(i, nodeId);
-
- if(buffer != 0) {
- GCIBuffer::iterator it(buffer);
- /**
- * Send all pages to SS
- */
- for (page = it.first(); page != 0; page = it.next()) {
- ptr[0].p = page->getStoragePtr();
- ptr[0].sz = page->getStorageWordSize();
- totalSizeSent += ptr[0].sz;
- pageData->gci = i;
- pageData->nodeGrp = nodeGrp;
- signal->set(0, SSREPBLOCKNO, GSN_REP_DATA_PAGE,
- RepDataPage::SignalLength);
- sendFragmentedSignalRep(signal, ptr, 1);
- }
-
- /**
- * Send accounting information to SS
- */
- RepGciBufferAccRep * rep = (RepGciBufferAccRep *)pageData;
- rep->gci = i;
- rep->nodeGrp = nodeGrp;
- rep->totalSentBytes = (4 * totalSizeSent); //words to bytes
- signal->set(0, SSREPBLOCKNO, GSN_REP_GCIBUFFER_ACC_REP,
- RepGciBufferAccRep::SignalLength);
- sendSignalRep(signal);
-
- RLOG(("Sending %d:[%d] (%d bytes) to external REP (nodeId %d)",
- nodeGrp, i, 4*totalSizeSent, nodeId));
- }
- }
- page = 0;
-}
-
-void
-TransPS::execREP_GET_GCI_REQ(NdbApiSignal* signal)
-{
- RepGetGciReq * req = (RepGetGciReq*)signal->getDataPtr();
- Uint32 nodeGrp = req->nodeGrp;
-
- Uint32 first, last;
- m_gciContainerPS->getAvailableGCIBuffers(nodeGrp, &first, &last);
-
- RepGetGciConf * conf = (RepGetGciConf*) req;
- conf->firstPSGCI = first;
- conf->lastPSGCI = last;
- conf->senderRef = m_ownRef;
- conf->nodeGrp = nodeGrp;
- signal->set(0, SSREPBLOCKNO, GSN_REP_GET_GCI_CONF,
- RepGetGciConf::SignalLength);
- sendSignalRep(signal);
-}
-
-/**
- * REP_CLEAR_PS_GCIBUFFER_REQ
- * destroy the GCI buffer in the GCI Container
- * and send a CONF to Grep::SSCoord
- */
-void
-TransPS::execREP_CLEAR_PS_GCIBUFFER_REQ(NdbApiSignal * signal)
-{
- RepClearPSGciBufferReq * const req =
- (RepClearPSGciBufferReq*)signal->getDataPtr();
- Uint32 firstGCI = req->firstGCI;
- Uint32 lastGCI = req->lastGCI;
- Uint32 nodeGrp = req->nodeGrp;
-
- assert(firstGCI >= 0 && lastGCI > 0);
- if(firstGCI<0 && lastGCI <= 0)
- {
- RLOG(("WARNING! Illegal delete request ignored"));
- sendREP_CLEAR_PS_GCIBUFFER_REF(signal, firstGCI, lastGCI,
- 0, nodeGrp,
- GrepError::REP_DELETE_NEGATIVE_EPOCH);
- }
-
- if(firstGCI==0 && lastGCI==(Uint32)0xFFFF) {
- m_gciContainerPS->getAvailableGCIBuffers(nodeGrp, &firstGCI, &lastGCI);
- RLOG(("Deleting PS:[%d-%d]", firstGCI, lastGCI));
- }
-
- if(firstGCI == 0) {
- Uint32 f, l;
- m_gciContainerPS->getAvailableGCIBuffers(nodeGrp, &f, &l);
-
- RLOG(("Deleting PS:[%d-%d]", f, l));
-
- if(f>firstGCI)
- firstGCI = f;
- }
-
- /**
- * Delete buffer
- * Abort if we try to destroy a buffer that does not exist
- * Deleting buffer from every node in the nodegroup
- */
- for(Uint32 i=firstGCI; i<=lastGCI; i++) {
- if(!m_gciContainerPS->destroyGCIBuffer(i, nodeGrp)) {
- sendREP_CLEAR_PS_GCIBUFFER_REF(signal, firstGCI, lastGCI, i, nodeGrp,
- GrepError::REP_DELETE_NONEXISTING_EPOCH);
- return;
- }
-
- RLOG(("Deleted PS:%d:[%d]", nodeGrp, i));
- }
-
- /**
- * Send reply to Grep::SSCoord
- */
- RepClearPSGciBufferConf * conf = (RepClearPSGciBufferConf*)req;
- conf->firstGCI = firstGCI;
- conf->lastGCI = lastGCI;
- conf->nodeGrp = nodeGrp;
- signal->set(0, SSREPBLOCKNO, GSN_REP_CLEAR_PS_GCIBUFFER_CONF,
- RepClearPSGciBufferConf::SignalLength);
- sendSignalRep(signal);
-}
-
-/*****************************************************************************
- * Signal Senders
- *****************************************************************************/
-
-void
-TransPS::sendREP_GET_GCI_REF(NdbApiSignal* signal,
- Uint32 nodeGrp,
- Uint32 firstPSGCI, Uint32 lastPSGCI,
- GrepError::Code err)
-{
- RepGetGciRef * ref = (RepGetGciRef *)signal->getDataPtrSend();
- ref->firstPSGCI = firstPSGCI;
- ref->lastPSGCI = lastPSGCI;
- ref->firstSSGCI = 0;
- ref->lastSSGCI = 0;
- ref->nodeGrp = nodeGrp;
- ref->err = err;
- signal->set(0, SSREPBLOCKNO, GSN_REP_GET_GCI_REF,
- RepGetGciRef::SignalLength);
- sendSignalRep(signal);
-}
-
-void
-TransPS::sendREP_CLEAR_PS_GCIBUFFER_REF(NdbApiSignal* signal,
- Uint32 firstGCI, Uint32 lastGCI,
- Uint32 currentGCI,
- Uint32 nodeGrp,
- GrepError::Code err)
-{
- RepClearPSGciBufferRef * ref =
- (RepClearPSGciBufferRef *)signal->getDataPtrSend();
- ref->firstGCI = firstGCI;
- ref->lastGCI = lastGCI;
- ref->currentGCI = currentGCI;
- ref->nodeGrp = nodeGrp;
- ref->err = err;
- signal->set(0, SSREPBLOCKNO, GSN_REP_CLEAR_PS_GCIBUFFER_REF,
- RepClearPSGciBufferRef::SignalLength);
- sendSignalRep(signal);
-}
-
-void
-TransPS::sendREP_GET_GCIBUFFER_REF(NdbApiSignal* signal,
- Uint32 firstGCI, Uint32 lastGCI,
- Uint32 nodeGrp,
- GrepError::Code err)
-{
- RepGetGciBufferRef * ref =
- (RepGetGciBufferRef *)signal->getDataPtrSend();
- ref->firstPSGCI = firstGCI;
- ref->lastPSGCI = lastGCI;
- ref->firstSSGCI = 0;
- ref->lastSSGCI = 0;
- ref->nodeGrp = nodeGrp;
- ref->err = err;
- signal->set(0, SSREPBLOCKNO, GSN_REP_GET_GCIBUFFER_REF,
- RepGetGciBufferRef::SignalLength);
- sendSignalRep(signal);
-}
diff --git a/ndb/src/rep/transfer/TransPS.hpp b/ndb/src/rep/transfer/TransPS.hpp
deleted file mode 100644
index b47f1acfca2..00000000000
--- a/ndb/src/rep/transfer/TransPS.hpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef TransPS_HPP
-#define TransPS_HPP
-
-#include <NdbTick.h>
-#include <NdbMain.h>
-#include <NdbOut.hpp>
-#include <NdbSleep.h>
-
-#include <TransporterDefinitions.hpp>
-#include <TransporterFacade.hpp>
-#include <ClusterMgr.hpp>
-
-#include <rep/storage/GCIContainerPS.hpp>
-
-#include <signaldata/RepImpl.hpp>
-
-#include <rep/SignalQueue.hpp>
-#include <rep/ExtSender.hpp>
-
-#include <rep/rep_version.hpp>
-
-/**
- * @class TransPS
- * @brief Responsible for REP-REP interface in Primary System role
- */
-class TransPS {
-public:
- /***************************************************************************
- * Constructor / Destructor
- ***************************************************************************/
- TransPS(GCIContainerPS * gciContainer);
- ~TransPS();
-
- void init(TransporterFacade * tf, const char * connectString = NULL);
-
- /***************************************************************************
- * Public Methods
- ***************************************************************************/
- ExtSender * getRepSender() { return m_repSender; };
- void setGrepSender(ExtSender * es) { m_grepSender = es; };
-
-private:
- /***************************************************************************
- * Private Methods
- ***************************************************************************/
- /**
- * SignalQueue executor thread
- */
- void signalExecThreadRun();
- static void * signalExecThread_C(void *);
-
- static void execSignal(void* signalSender, NdbApiSignal* signal,
- class LinearSectionPtr ptr[3]);
-
- static void execNodeStatus(void* signalSender, NodeId,
- bool alive, bool nfCompleted);
-
- void sendSignalRep(NdbApiSignal * s);
- void sendSignalGrep(NdbApiSignal * s);
-
- void sendFragmentedSignalRep(NdbApiSignal * s, LinearSectionPtr ptr[3],
- Uint32 sections );
- void sendFragmentedSignalGrep(NdbApiSignal * s, LinearSectionPtr ptr[3],
- Uint32 sections );
-
- /***************************************************************************
- * Signal executors
- ***************************************************************************/
- void execREP_CLEAR_PS_GCIBUFFER_REQ(NdbApiSignal*);
- void execREP_GET_GCI_REQ(NdbApiSignal*);
- void execREP_GET_GCIBUFFER_REQ(NdbApiSignal*);
-
- /***************************************************************************
- * Ref signal senders
- ***************************************************************************/
- void sendREP_GET_GCI_REF(NdbApiSignal* signal, Uint32 nodeGrp,
- Uint32 firstPSGCI, Uint32 lastPSGCI,
- GrepError::Code err);
-
- void sendREP_CLEAR_PS_GCIBUFFER_REF(NdbApiSignal* signal,
- Uint32 firstGCI, Uint32 lastGCI,
- Uint32 currentGCI, Uint32 nodeGrp,
- GrepError::Code err);
-
- void sendREP_GET_GCIBUFFER_REF(NdbApiSignal* signal,
- Uint32 firstGCI, Uint32 lastGCI,
- Uint32 nodeGrp,
- GrepError::Code err);
-
- /***************************************************************************
- * Other Methods
- ***************************************************************************/
- void transferPages(Uint32 firstGCI, Uint32 lastGCI, Uint32 id,
- Uint32 nodeGrp, NdbApiSignal* signal);
-
- /*************
- * Variables
- *************/
- Uint32 m_ownNodeId; ///< NodeId of this node
- Uint32 m_ownBlockNo; ///< BlockNo of this "block"
- BlockReference m_ownRef; ///< Reference to this
-
- BlockReference m_extRepRef; ///< Node ref of REP at SS
-
- ExtSender * m_grepSender; ///< Responsible send to GREP
- ExtSender * m_repSender; ///< Responsible send to REP
-
- struct NdbThread * m_signalExecThread;
- class SignalQueue m_signalRecvQueue;
-
- GCIContainerPS * m_gciContainerPS; ///< Ref to gci container.
-};
-
-#endif
diff --git a/ndb/src/rep/transfer/TransSS.cpp b/ndb/src/rep/transfer/TransSS.cpp
deleted file mode 100644
index 83f4b570330..00000000000
--- a/ndb/src/rep/transfer/TransSS.cpp
+++ /dev/null
@@ -1,649 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include "ConfigRetriever.hpp"
-
-#include <NdbApiSignal.hpp>
-#include <AttributeHeader.hpp>
-
-#include <signaldata/RepImpl.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include <signaldata/SumaImpl.hpp>
-#include <signaldata/GrepImpl.hpp>
-
-#include <SimpleProperties.hpp>
-#include <rep/rep_version.hpp>
-
-#include "TransSS.hpp"
-
-//#define DEBUG_REP_GET_GCI_CONF
-
-/*****************************************************************************
- * Constructor / Destructor / Init
- *****************************************************************************/
-TransSS::TransSS(GCIContainer * gciContainer, RepState * repState)
-{
- m_repSender = new ExtSender();
- if (!m_repSender) REPABORT("Could not allocate new ExtSender");
- m_gciContainer = gciContainer;
- m_repState = repState;
-}
-
-TransSS::~TransSS()
-{
- delete m_repSender;
-}
-
-void
-TransSS::init(const char * connectString)
-{
- m_signalExecThread = NdbThread_Create(signalExecThread_C,
- (void **)this,
- 32768,
- "TransSS_Service",
- NDB_THREAD_PRIO_LOW);
- ConfigRetriever configRetriever;
- configRetriever.setConnectString(connectString);
-
- Properties* config = configRetriever.getConfig("REP", REP_VERSION_ID);
- if (config == 0) {
- ndbout << "Configuration error: ";
- const char* erString = configRetriever.getErrorString();
- if (erString == 0) {
- erString = "No error specified!";
- }
- ndbout << erString << endl;
- exit(-1);
- }
- Properties * extConfig;
-
- /**
- * @todo Hardcoded standby system name
- */
- if (!config->getCopy("EXTERNAL SYSTEM_External", &extConfig)) {
- ndbout << "External System \"External\" not found in configuration. "
- << "Check config.ini." << endl;
- config->print();
- exit(-1);
- }
- m_ownNodeId = configRetriever.getOwnNodeId();
- extConfig->put("LocalNodeId", m_ownNodeId);
- extConfig->put("LocalNodeType", "REP");
- Uint32 noOfConnections;
- extConfig->get("NoOfConnections", &noOfConnections);
- /* if (noOfConnections != 1) {
- ndbout << "TransSS: There are " << noOfConnections << " connections "
- << "defined in configuration"
- << endl
- << " There should be exactly one!" << endl;
- exit(-1);
- }*/
-
- /******************************
- * Set node id of external REP
- ******************************/
- const Properties * connection;
- const char * extSystem;
-
- Uint32 extRepNodeId, tmpOwnNodeId;
-
- for(Uint32 i=0; i < noOfConnections; i++) {
- extConfig->get("Connection", i, &connection);
- if(connection == 0) REPABORT("Connection not found");
-
- if(connection->get("System1", &extSystem)) {
- connection->get("NodeId1", &extRepNodeId);
- connection->get("NodeId2", &tmpOwnNodeId);
- } else {
- connection->get("System2", &extSystem);
- connection->get("NodeId1", &tmpOwnNodeId);
- connection->get("NodeId2", &extRepNodeId);
- }
- if(m_ownNodeId == tmpOwnNodeId)
- break;
- }
-
- if(extRepNodeId==0) REPABORT("External replication server not found");
- if(extSystem==0) REPABORT("External system not found");
-
- m_transporterFacade = new TransporterFacade();
- if (!m_transporterFacade->init(extConfig))
- {
- ndbout << "TransSS: Failed to initialize transporter facade" << endl;
- exit(-1);
- }
-
- m_ownBlockNo = m_transporterFacade->open(this, execSignal, execNodeStatus);
- assert(m_ownBlockNo > 0);
- m_ownRef = numberToRef(m_ownBlockNo, m_ownNodeId);
- assert(m_ownNodeId == m_transporterFacade->ownId());
-
- ndbout_c("Phase 2 (TransSS): Connection %d to external REP node %d opened",
- m_ownBlockNo, extRepNodeId);
-
- m_repSender->setNodeId(extRepNodeId);
- m_repSender->setOwnRef(m_ownRef);
- m_repSender->setTransporterFacade(m_transporterFacade);
-}
-
-/*****************************************************************************
- * Signal Queue Executor
- *****************************************************************************/
-
-class SigMatch
-{
-public:
- int gsn;
- void (TransSS::* function)(NdbApiSignal *signal);
-
- SigMatch() { gsn = 0; function = NULL; };
-
- SigMatch(int _gsn, void (TransSS::* _function)(NdbApiSignal *signal)) {
- gsn = _gsn;
- function = _function;
- };
-
- bool check(NdbApiSignal *signal) {
- if(signal->readSignalNumber() == gsn)
- return true;
- return false;
- };
-};
-
-void *
-TransSS::signalExecThread_C(void *r)
-{
- TransSS *transss = (TransSS*)r;
-
- transss->signalExecThreadRun();
- NdbThread_Exit(0);
- /* NOTREACHED */
- return 0;
-}
-
-void
-TransSS::signalExecThreadRun()
-{
- Vector<SigMatch> sl;
- /**
- * Signals to be forwarded to TransPS
- */
- sl.push_back(SigMatch(GSN_REP_GET_GCI_REQ,
- &TransSS::sendSignalRep));
- sl.push_back(SigMatch(GSN_REP_GET_GCIBUFFER_REQ,
- &TransSS::sendSignalRep));
- /**
- * Signals to be executed
- */
- sl.push_back(SigMatch(GSN_REP_GCIBUFFER_ACC_REP,
- &TransSS::execREP_GCIBUFFER_ACC_REP));
- sl.push_back(SigMatch(GSN_REP_DISCONNECT_REP,
- &TransSS::execREP_DISCONNECT_REP));
- sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_CONF,
- &TransSS::execGREP_SUB_REMOVE_CONF));
- sl.push_back(SigMatch(GSN_REP_GET_GCIBUFFER_CONF,
- &TransSS::execREP_GET_GCIBUFFER_CONF));
-
- sl.push_back(SigMatch(GSN_REP_CLEAR_PS_GCIBUFFER_CONF,
- &TransSS::execREP_CLEAR_PS_GCIBUFFER_CONF));
- sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_CONF,
- &TransSS::execGREP_SUB_SYNC_CONF));
- sl.push_back(SigMatch(GSN_GREP_SUB_SYNC_REF,
- &TransSS::execGREP_SUB_SYNC_REF));
- sl.push_back(SigMatch(GSN_REP_GET_GCIBUFFER_REF,
- &TransSS::execREP_GET_GCIBUFFER_REF));
-
- /**
- * Signals to be executed : Subscriptions
- */
- sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_CONF,
- &TransSS::execGREP_CREATE_SUBID_CONF));
- sl.push_back(SigMatch(GSN_GREP_CREATE_SUBID_REF,
- &TransSS::execGREP_CREATE_SUBID_REF));
- sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_CONF,
- &TransSS::execGREP_SUB_CREATE_CONF));
- sl.push_back(SigMatch(GSN_GREP_SUB_CREATE_REF,
- &TransSS::execGREP_SUB_CREATE_REF));
- sl.push_back(SigMatch(GSN_GREP_SUB_START_CONF,
- &TransSS::execGREP_SUB_START_CONF));
- sl.push_back(SigMatch(GSN_GREP_SUB_START_REF,
- &TransSS::execGREP_SUB_START_REF));
-
- /**
- * Signals to be executed and forwarded
- */
- sl.push_back(SigMatch(GSN_REP_GET_GCI_CONF,
- &TransSS::execREP_GET_GCI_CONF));
-
- /**
- * Signals to be forwarded
- */
- sl.push_back(SigMatch(GSN_GREP_SUB_REMOVE_REF,
- &TransSS::execGREP_SUB_REMOVE_REF));
- sl.push_back(SigMatch(GSN_REP_CLEAR_PS_GCIBUFFER_REF,
- &TransSS::execREP_CLEAR_PS_GCIBUFFER_REF));
- sl.push_back(SigMatch(GSN_REP_GET_GCI_REF,
- &TransSS::execREP_GET_GCI_REF));
-
- while(1) {
- SigMatch *handler = NULL;
- NdbApiSignal *signal = NULL;
- if(m_signalRecvQueue.waitFor(sl, handler, signal))
- {
-#if 0
- ndbout_c("TransSS: Removed signal from queue (GSN: %d, QSize: %d)",
- signal->readSignalNumber(), m_signalRecvQueue.size());
-#endif
- if(handler->function != 0)
- {
- (this->*handler->function)(signal);
- delete signal;
- signal = 0;
- } else {
- REPABORT("Illegal handler for signal");
- }
- }
- }
-}
-
-void
-TransSS::sendSignalRep(NdbApiSignal * s)
-{
- m_repSender->sendSignal(s);
-}
-
-void
-TransSS::execNodeStatus(void* obj, Uint16 nodeId,
- bool alive, bool nfCompleted)
-{
- TransSS * thisObj = (TransSS*)obj;
-
- if (alive) {
- thisObj->m_repState->eventNodeConnected(nodeId);
-
- } else if (!nfCompleted) {
- thisObj->m_repState->eventNodeDisconnected(nodeId);
-
- } else if (nfCompleted) {
- thisObj->m_repState->eventNodeConnectable(nodeId);
-
- } else {
- REPABORT("Illegal state for execNodeStatus");
- }
-}
-
-void
-TransSS::execSignal(void* executorObj, NdbApiSignal* signal,
- class LinearSectionPtr ptr[3])
-{
- TransSS * executor = (TransSS *) executorObj;
-
- const Uint32 gsn = signal->readSignalNumber();
- const Uint32 len = signal->getLength();
-
- NdbApiSignal * s = new NdbApiSignal(executor->m_ownRef);
- switch (gsn) {
- case GSN_REP_GET_GCI_REQ:
- case GSN_REP_GET_GCIBUFFER_REQ:
- case GSN_REP_GET_GCIBUFFER_CONF:
- case GSN_GREP_SUB_REMOVE_CONF:
- case GSN_REP_DISCONNECT_REP:
- case GSN_REP_GCIBUFFER_ACC_REP:
- s->set(0, PSREPBLOCKNO, gsn, len);
- memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
- executor->m_signalRecvQueue.receive(s);
- break;
- case GSN_GREP_CREATE_SUBID_CONF:
- case GSN_GREP_SUB_CREATE_CONF:
- case GSN_GREP_SUB_START_CONF:
- case GSN_GREP_SUB_SYNC_CONF:
- case GSN_REP_GET_GCI_CONF:
- case GSN_REP_CLEAR_PS_GCIBUFFER_CONF:
- case GSN_GREP_CREATE_SUBID_REF:
- case GSN_GREP_SUB_CREATE_REF:
- case GSN_GREP_SUB_START_REF:
- case GSN_GREP_SUB_SYNC_REF:
- case GSN_GREP_SUB_REMOVE_REF:
- case GSN_REP_GET_GCI_REF:
- case GSN_REP_GET_GCIBUFFER_REF:
- case GSN_REP_CLEAR_PS_GCIBUFFER_REF:
- s->set(0, GREP, gsn, len);
- memcpy(s->getDataPtrSend(), signal->getDataPtr(), 4 * len);
- executor->m_signalRecvQueue.receive(s);
- break;
- case GSN_REP_DATA_PAGE:
- executor->execREP_DATA_PAGE(signal, ptr);
- delete s; s = 0;
- break;
- default:
- REPABORT1("Illegal signal received in execSignal %d", gsn);
- }
-
-#if 0
- ndbout_c("TransSS: Inserted signal into queue (GSN: %d, Len: %d)",
- signal->readSignalNumber(), len);
-#endif
-}
-
-/*****************************************************************************
- * Signal Executors
- *****************************************************************************/
-
-void
-TransSS::execREP_DATA_PAGE(NdbApiSignal * signal, LinearSectionPtr ptr[3])
-{
- RepDataPage * const page = (RepDataPage*)signal->getDataPtr();
- m_gciContainer->insertPage(page->gci, page->nodeGrp,
- (char*)(ptr[0].p), 4 * ptr[0].sz);
-}
-
-/**
- * Recd from TransPS
- */
-void
-TransSS::execREP_GCIBUFFER_ACC_REP(NdbApiSignal * signal)
-{
- RepGciBufferAccRep * const rep =
- (RepGciBufferAccRep * )signal->getDataPtr();
-
- Uint32 gci = rep->gci;
- Uint32 nodeGrp = rep->nodeGrp;
- Uint32 totalSize = rep->totalSentBytes;
- GCIBuffer * buffer = m_gciContainer->getGCIBuffer(gci, nodeGrp);
- Uint32 getReceivedBytes = 0;
- if (buffer != 0)
- getReceivedBytes = buffer->getReceivedBytes();
-
- RLOG(("TransSS: Received %d:[%d] (%d of %d bytes)",
- nodeGrp, gci, getReceivedBytes, totalSize));
-
- if(getReceivedBytes != totalSize) {
- REPABORT("Did not receive correct number of bytes");
- }
-}
-
-/**
- * Received from primary system
- */
-void
-TransSS::execREP_GET_GCIBUFFER_CONF(NdbApiSignal * signal)
-{
- RepGetGciBufferConf * conf = (RepGetGciBufferConf*)signal->getDataPtr();
- conf->senderRef = m_ownRef;
- Uint32 first = conf->firstSSGCI;
- Uint32 last = conf->lastSSGCI;
- for(Uint32 i = first; i <= last; i++) {
- m_gciContainer->setCompleted(i, conf->nodeGrp);
- }
-
- /**
- * Buffers @ PS
- */
- Interval ps(conf->firstPSGCI, conf->lastPSGCI);
- m_repState->add(Channel::PS, conf->nodeGrp, ps);
-
- /**
- * Buffers @ SS
- */
- Uint32 ssfirst, sslast;
- m_gciContainer->getAvailableGCIBuffers(conf->nodeGrp, &ssfirst, &sslast);
- Interval ss(ssfirst, sslast);
- m_repState->clear(Channel::SS, conf->nodeGrp, universeInterval);
- m_repState->add(Channel::SS, conf->nodeGrp, ss);
- m_repState->clear(Channel::SSReq, conf->nodeGrp, ss);
-
- RLOG(("Transfered epochs (PS:%d[%d-%d], SS:%d[%d-%d])",
- conf->nodeGrp, conf->firstPSGCI, conf->lastPSGCI,
- conf->nodeGrp, conf->firstSSGCI, conf->lastSSGCI));
-}
-
-/**
- * Received from primary system
- */
-void
-TransSS::execGREP_SUB_REMOVE_CONF(NdbApiSignal * signal)
-{
- GrepSubRemoveConf * conf = (GrepSubRemoveConf* )signal->getDataPtr();
- Uint32 subId = conf->subscriptionId;
- Uint32 subKey = conf->subscriptionKey;
-
- /**
- * @todo Fix this sending
- */
-#if 0
- signal->theData[0] = EventReport::GrepSubscriptionInfo;
- signal->theData[1] = GrepEvent::GrepSS_SubRemoveConf;
- signal->theData[2] = subId;
- signal->theData[3] = subKey;
- sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 4, JBB);
-#endif
-
- m_repState->eventSubscriptionDeleted(subId, subKey);
- RLOG(("Subscription deleted (SubId: %d, SubKey: %d)", subId, subKey));
-}
-
-void
-TransSS::execGREP_SUB_REMOVE_REF(NdbApiSignal * signal)
-{
- GrepSubRemoveRef * ref = (GrepSubRemoveRef* )signal->getDataPtr();
- Uint32 subId = ref->subscriptionId;
- Uint32 subKey = ref->subscriptionKey;
-
- /** @todo: Add repevent for this */
- RLOG(("TransSS: Warning: Grep sub remove ref (SubId: %d, SubKey: %d)",
- subId, subKey));
-}
-
-/**
- * Received from primary system
- */
-void
-TransSS::execREP_GET_GCI_CONF(NdbApiSignal * signal)
-{
- RepGetGciConf * conf = (RepGetGciConf*)signal->getDataPtr();
- Uint32 nodeGrp = conf->nodeGrp;
- Interval i(conf->firstPSGCI, conf->lastPSGCI);
- m_repState->add(Channel::PS, nodeGrp, i);
-
- Uint32 first, last;
- m_gciContainer->getAvailableGCIBuffers(nodeGrp, &first, &last);
- Interval j(first, last);
- m_repState->clear(Channel::SS, nodeGrp, universeInterval);
- m_repState->add(Channel::SS, nodeGrp, j);
-
-#ifdef DEBUG_REP_GET_GCI_CONF
- RLOG(("TransSS: Requestor info received "
- "(PS: %d:[%d-%d], SS: %d:[%d-%d])",
- conf->nodeGrp, conf->firstPSGCI, conf->lastPSGCI,
- conf->nodeGrp, conf->firstSSGCI, conf->lastSSGCI));
-#endif
-}
-
-void
-TransSS::execREP_GET_GCI_REF(NdbApiSignal * signal)
-{
- RepGetGciRef * ref = (RepGetGciRef*)signal->getDataPtr();
- Uint32 nodeGrp = ref->nodeGrp;
-
- RLOG(("WARNING! Requestor info request failed (Nodegrp: %d)", nodeGrp));
-}
-
-/**
- * Recd from GrepPS
- * This signal means that a DB node has disconnected.
- * @todo Do we need to know that a DB node disconnected?
- *
- * A node has disconnected (REP or PS DB)
- * @todo let the requestor respond to this event
- * in a proper way.
- */
-void
-TransSS::execREP_DISCONNECT_REP(NdbApiSignal * signal)
-{
- RepDisconnectRep * const rep =
- (RepDisconnectRep*)signal->getDataPtr();
-
- //Uint32 nodeId = rep->nodeId;
- Uint32 nodeType = rep->nodeType;
-
- if((RepDisconnectRep::NodeType)nodeType == RepDisconnectRep::REP)
- {
- m_repState->disable();
- }
-}
-
-/**
- * The buffer is now deleted on REP PS. We can now clear it from PS.
- */
-void
-TransSS::execREP_CLEAR_PS_GCIBUFFER_CONF(NdbApiSignal * signal)
-{
- RepClearPSGciBufferConf * const conf =
- (RepClearPSGciBufferConf*)signal->getDataPtr();
- Uint32 firstGCI = conf->firstGCI;
- Uint32 lastGCI = conf->lastGCI;
- Uint32 nodeGrp = conf->nodeGrp;
- Interval i(firstGCI, lastGCI);
- m_repState->clear(Channel::PS, nodeGrp, i);
- m_repState->clear(Channel::DelReq, nodeGrp, i);
-
- RLOG(("Deleted PS:%d:[%d-%d]", nodeGrp, firstGCI, lastGCI));
-}
-
-/**
- * Something went wrong when deleting buffer on REP PS
- */
-void
-TransSS::execREP_CLEAR_PS_GCIBUFFER_REF(NdbApiSignal * signal)
-{
- RepClearPSGciBufferRef * const ref =
- (RepClearPSGciBufferRef*)signal->getDataPtr();
- Uint32 firstGCI = ref->firstGCI;
- Uint32 lastGCI = ref->lastGCI;
- Uint32 nodeGrp = ref->nodeGrp;
-
- RLOG(("WARNING! Could not delete PS:%d:[%d-%d]", nodeGrp, firstGCI, lastGCI));
-}
-
-/*****************************************************************************
- * Signal Executors : SCAN
- *****************************************************************************/
-
-/**
- * Scan has started on PS side... (says PS REP)
- */
-void
-TransSS::execGREP_SUB_SYNC_CONF(NdbApiSignal* signal)
-{
- GrepSubSyncConf * const conf = (GrepSubSyncConf * ) signal->getDataPtr();
- Uint32 subId = conf->subscriptionId;
- Uint32 subKey = conf->subscriptionKey;
- Interval epochs(conf->firstGCI, conf->lastGCI);
- SubscriptionData::Part part = (SubscriptionData::Part) conf->part;
-
- switch(part) {
- case SubscriptionData::MetaData:
- RLOG(("Metascan completed. Subcription %d-%d, Epochs [%d-%d]",
- subId, subKey, epochs.first(), epochs.last()));
- m_repState->eventMetaScanCompleted(signal, subId, subKey, epochs);
-#if 0
- signal->theData[0] = EventReport::GrepSubscriptionInfo;
- signal->theData[1] = GrepEvent::GrepSS_SubSyncMetaConf;
- signal->theData[2] = subId;
- signal->theData[3] = subKey;
- signal->theData[4] = gci;
- sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 5, JBB);
-#endif
- break;
- case SubscriptionData::TableData:
- RLOG(("Datascan completed. Subcription %d-%d, Epochs [%d-%d]",
- subId, subKey, epochs.first(), epochs.last()));
- m_repState->eventDataScanCompleted(signal, subId, subKey, epochs);
-#if 0
- signal->theData[0] = EventReport::GrepSubscriptionInfo;
- signal->theData[1] = GrepEvent::GrepSS_SubSyncDataConf;
- signal->theData[2] = subId;
- signal->theData[3] = subKey;
- signal->theData[4] = gci;
- sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 5, JBB);
-#endif
- break;
- default:
- REPABORT3("Wrong subscription part", part, subId, subKey);
- }
-}
-
-void
-TransSS::execGREP_SUB_SYNC_REF(NdbApiSignal* signal)
-{
- GrepSubSyncRef * const ref = (GrepSubSyncRef * ) signal->getDataPtr();
- Uint32 subId = ref->subscriptionId;
- Uint32 subKey = ref->subscriptionKey;
- SubscriptionData::Part part = (SubscriptionData::Part) ref->part;
- GrepError::Code error = (GrepError::Code) ref->err;
-
- switch(part) {
- case SubscriptionData::MetaData:
- m_repState->eventMetaScanFailed(subId, subKey, error);
-#if 0
- signal->theData[0] = EventReport::GrepSubscriptionAlert;
- signal->theData[1] = GrepEvent::GrepSS_SubSyncMetaRef;
- signal->theData[2] = subId;
- signal->theData[3] = subKey;
- // signal->theData[4] = gci;
- sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 5, JBB);
-#endif
- break;
- case SubscriptionData::TableData:
- m_repState->eventDataScanFailed(subId, subKey, error);
-#if 0
- signal->theData[0] = EventReport::GrepSubscriptionAlert;
- signal->theData[1] = GrepEvent::GrepSS_SubSyncDataRef;
- signal->theData[2] = subId;
- signal->theData[3] = subKey;
- //signal->theData[4] = m_lastScanGCI;
- sendSignal(CMVMI_REF,GSN_EVENT_REP,signal, 5, JBB);
-#endif
- break;
- default:
- REPABORT3("Wrong subscription part", part, subId, subKey);
- }
-}
-
-/**
- * Something went wrong says REP PS
- */
-void
-TransSS::execREP_GET_GCIBUFFER_REF(NdbApiSignal* signal)
-{
- RepGetGciBufferRef * const ref = (RepGetGciBufferRef*)signal->getDataPtr();
- /*
- Uint32 senderData = ref->senderData;
- Uint32 senderRef = ref->senderRef;
- Uint32 firstPSGCI = ref->firstPSGCI;
- Uint32 lastPSGCI = ref->lastPSGCI;
- Uint32 firstSSGCI = ref->firstSSGCI;
- Uint32 lastSSGCI = ref->lastSSGCI;
- Uint32 currentGCIBuffer = ref->currentGCIBuffer;
- Uint32 nodeGrp = ref->nodeGrp;
- */
- GrepError::Code err = ref->err;
-
- RLOG(("WARNING! Request to get buffer failed. Error %d:%s",
- err, GrepError::getErrorDesc(err)));
-}
diff --git a/ndb/src/rep/transfer/TransSS.hpp b/ndb/src/rep/transfer/TransSS.hpp
deleted file mode 100644
index 6f2089e46ac..00000000000
--- a/ndb/src/rep/transfer/TransSS.hpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef TransSS_HPP
-#define TransSS_HPP
-
-#include <NdbTick.h>
-#include <NdbMain.h>
-#include <NdbOut.hpp>
-#include <NdbSleep.h>
-
-#include <TransporterDefinitions.hpp>
-#include <TransporterFacade.hpp>
-#include <ClusterMgr.hpp>
-#include <API.hpp>
-
-#include <rep/storage/GCIContainer.hpp>
-
-#include <rep/SignalQueue.hpp>
-#include <rep/ExtSender.hpp>
-
-#include <rep/state/RepState.hpp>
-
-/**
- * @class TransSS
- * @brief Responsible for REP-REP interface in Standby System role
- */
-class TransSS {
-public:
- /***************************************************************************
- * Constructor / Destructor / Init
- ***************************************************************************/
- TransSS(GCIContainer * gciContainer, RepState * repState);
- ~TransSS();
- void init(const char * connectString = NULL);
-
- /***************************************************************************
- * Public Methods
- ***************************************************************************/
- ExtSender * getRepSender() { return m_repSender; };
- TransporterFacade * getTransporterFacade() { return m_transporterFacade; };
-
-private:
- /***************************************************************************
- * Private Methods
- ***************************************************************************/
- void signalExecThreadRun(); ///< SignalQueue executor thread
- static void * signalExecThread_C(void *);
-
- static void execSignal(void* executorObj, NdbApiSignal* signal,
- class LinearSectionPtr ptr[3]);
- static void execNodeStatus(void* executorObj, NodeId, bool alive,
- bool nfCompleted);
-
- void sendSignalRep(NdbApiSignal * s);
-
- /***************************************************************************
- * Signal receivers
- ***************************************************************************/
- void execREP_GET_GCI_REQ(NdbApiSignal*);
- void execREP_GET_GCI_CONF(NdbApiSignal*);
- void execREP_GET_GCI_REF(NdbApiSignal*);
-
- void execREP_GET_GCIBUFFER_REQ(NdbApiSignal*);
- void execREP_GET_GCIBUFFER_CONF(NdbApiSignal*);
- void execREP_GET_GCIBUFFER_REF(NdbApiSignal*);
-
- void execGREP_SUB_REMOVE_CONF(NdbApiSignal *);
- void execGREP_SUB_REMOVE_REF(NdbApiSignal *);
-
- void execREP_INSERT_GCIBUFFER_REQ(NdbApiSignal*);
- void execREP_INSERT_GCIBUFFER_CONF(NdbApiSignal*);
- void execREP_INSERT_GCIBUFFER_REF(NdbApiSignal*);
-
- void execREP_DATA_PAGE(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
- void execREP_GCIBUFFER_ACC_REP(NdbApiSignal*);
- void execREP_DISCONNECT_REP(NdbApiSignal*);
-
-
- void execREP_CLEAR_PS_GCIBUFFER_CONF(NdbApiSignal*);
- void execREP_CLEAR_PS_GCIBUFFER_REF(NdbApiSignal*);
-
- void execGREP_SUB_SYNC_CONF(NdbApiSignal*);
- void execGREP_SUB_SYNC_REF(NdbApiSignal*);
-
- /***************************************************************************
- * Signal receivers : Subscriptions
- ***************************************************************************/
- void execGREP_CREATE_SUBID_CONF(NdbApiSignal*);
- void execGREP_CREATE_SUBID_REF(NdbApiSignal*);
- void execGREP_SUB_CREATE_CONF(NdbApiSignal*);
- void execGREP_SUB_CREATE_REF(NdbApiSignal*);
- void execGREP_SUB_START_CONF(NdbApiSignal*);
- void execGREP_SUB_START_REF(NdbApiSignal*);
-
- /***************************************************************************
- * Ref signal senders
- ***************************************************************************/
-
- void sendREP_GET_GCI_REF(NdbApiSignal* signal, Uint32 nodeGrp,
- Uint32 firstSSGCI, Uint32 lastSSGCI,
- GrepError::Code err);
-
- void sendREP_GET_GCIBUFFER_REF(NdbApiSignal* signal,
- Uint32 firstGCI, Uint32 lastGCI,
- Uint32 nodeGrp, GrepError::Code err);
-
- /***************************************************************************
- * Private Variables
- ***************************************************************************/
- RepState * m_repState;
-
- struct NdbThread * m_signalExecThread; ///< Signal Queue executor
- class SignalQueue m_signalRecvQueue;
-
- ExtSender * m_repSender; ///< Obj responsible send to REP
-
- Uint32 m_ownNodeId; ///< NodeId of this node
- Uint32 m_ownBlockNo; ///< BlockNo of this "block"
- BlockReference m_ownRef; ///< Reference to this
-
- GCIContainer * m_gciContainer; ///< Ref to gci container.
-
- TransporterFacade * m_transporterFacade;
-};
-
-#endif
diff --git a/ndb/src/scripts/Makefile b/ndb/src/scripts/Makefile
deleted file mode 100644
index bc8049ac34b..00000000000
--- a/ndb/src/scripts/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-include .defs.mk
-
-DIRS :=
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/test/Makefile b/ndb/test/Makefile
deleted file mode 100644
index 19472917560..00000000000
--- a/ndb/test/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-include .defs.mk
-
-DIRS := src tools ndbapi run-test
-
-EXTRA_DIRS = newtonapi
-
-ifeq ($(NDB_ARCH), x86_64)
-EXTRA_DIRS =
-endif
-
-DIRS += $(EXTRA_DIRS)
-
-ifneq ($(NDB_ODBC),N)
-DIRS += odbc
-endif
-
-include $(NDB_TOP)/Epilogue.mk
-
-_bins_ndbapi : _libs_src
diff --git a/ndb/test/Makefile.am b/ndb/test/Makefile.am
new file mode 100644
index 00000000000..2e0f30df9d4
--- /dev/null
+++ b/ndb/test/Makefile.am
@@ -0,0 +1,6 @@
+SUBDIRS = src tools ndbapi run-test
+
+EXTRA_DIST = include
+
+dist-hook:
+ -rm -rf `find $(distdir) -type d -name SCCS`
diff --git a/ndb/test/include/NDBT_Table.hpp b/ndb/test/include/NDBT_Table.hpp
index 950c1f15ff7..eee76773106 100644
--- a/ndb/test/include/NDBT_Table.hpp
+++ b/ndb/test/include/NDBT_Table.hpp
@@ -25,66 +25,6 @@
class NDBT_Attribute : public NdbDictionary::Column {
friend class NdbOut& operator <<(class NdbOut&, const NDBT_Attribute &);
public:
- NDBT_Attribute(const char* anAttrName,
- AttrType type,
- int sz = 4,
- KeyType key = NoKey,
- bool nullable = false,
- StorageAttributeType indexOnly = NormalStorageAttribute,
- StorageMode _sm = MMBased) :
- NdbDictionary::Column(anAttrName)
- {
- assert(anAttrName != 0);
-
- setNullable(nullable);
- setIndexOnlyStorage(indexOnly == IndexStorageAttribute);
- setPrimaryKey(key != NoKey);
- setTupleKey(key == TupleId);
- setLength(1);
- switch(type){
- case ::Signed:
- if(sz == 8)
- setType(NdbDictionary::Column::Bigint);
- else if (sz == 4)
- setType(NdbDictionary::Column::Int);
- else {
- setType(NdbDictionary::Column::Int);
- setLength(sz);
- }
- break;
-
- case ::UnSigned:
- if(sz == 8)
- setType(NdbDictionary::Column::Bigunsigned);
- else if (sz == 4)
- setType(NdbDictionary::Column::Unsigned);
- else {
- setType(NdbDictionary::Column::Unsigned);
- setLength(sz);
- }
- break;
-
- case ::Float:
- if(sz == 8)
- setType(NdbDictionary::Column::Double);
- else if (sz == 4)
- setType(NdbDictionary::Column::Float);
- else{
- setType(NdbDictionary::Column::Float);
- setLength(sz);
- }
- break;
-
- case ::String:
- setType(NdbDictionary::Column::Char);
- setLength(sz);
- break;
-
- case ::NoAttrTypeDef:
- break;
- }
- }
-
NDBT_Attribute(const char* _name,
Column::Type _type,
int _length = 1,
@@ -132,4 +72,13 @@ NDBT_Table::discoverTableFromDb(Ndb* ndb, const char * name){
return ndb->getDictionary()->getTable(name);
}
+
+/**
+ * Print meta information about index
+ * (information on how it is strored, what the attributes look like etc.)
+ */
+class NdbOut& operator <<(class NdbOut&, const NdbDictionary::Index &);
+
+
+
#endif
diff --git a/ndb/test/include/NdbConfig.hpp b/ndb/test/include/NdbConfig.hpp
index f13872f4d64..19439fafbb2 100644
--- a/ndb/test/include/NdbConfig.hpp
+++ b/ndb/test/include/NdbConfig.hpp
@@ -17,29 +17,22 @@
#ifndef NDBT_CONFIG_HPP
#define NDBT_CONFIG_HPP
+#include <ndb_types.h>
#include <mgmapi.h>
#include <Vector.hpp>
#include <NdbRestarter.hpp>
-#include <Properties.hpp>
+#include <mgmapi_config_parameters.h>
-class NdbConfig : public NdbRestarter{
+class NdbConfig : public NdbRestarter {
public:
NdbConfig(int own_id, const char* addr = 0)
: NdbRestarter(addr),
ownNodeId(own_id) {};
- bool getProperty(unsigned int node_id, const char* type,
- const char * name, Uint32 * value) const;
- bool getProperty(unsigned int node_id, const char* type,
- const char * name, const char ** value) const;
-
- bool getHostName(unsigned int node_id,
- const char ** hostname) const;
-protected:
- bool getPropsForNode(unsigned int node_id,
- const char* type,
- const Properties ** props) const;
+ bool getProperty(unsigned nodeid, unsigned type, unsigned key, Uint32 * val);
+ bool getHostName(unsigned int node_id, const char ** hostname);
+ //protected:
int ownNodeId;
};
diff --git a/ndb/test/include/NdbRestarter.hpp b/ndb/test/include/NdbRestarter.hpp
index cfd5409bb69..b4c29a87eff 100644
--- a/ndb/test/include/NdbRestarter.hpp
+++ b/ndb/test/include/NdbRestarter.hpp
@@ -89,7 +89,9 @@ protected:
const char* host;
int port;
NdbMgmHandle handle;
-
+ ndb_mgm_configuration * m_config;
+protected:
+ ndb_mgm_configuration * getConfig();
};
#endif
diff --git a/ndb/test/include/NdbSchemaCon.hpp b/ndb/test/include/NdbSchemaCon.hpp
new file mode 100644
index 00000000000..313daf0094b
--- /dev/null
+++ b/ndb/test/include/NdbSchemaCon.hpp
@@ -0,0 +1,147 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef NdbSchemaCon_H
+#define NdbSchemaCon_H
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+
+#include <ndb_types.h>
+#include "NdbError.hpp"
+#include <NdbSchemaOp.hpp>
+
+class NdbSchemaOp;
+class Ndb;
+class NdbApiSignal;
+
+/**
+ * @class NdbSchemaCon
+ * @brief Represents a schema transaction.
+ *
+ * When creating a new table,
+ * the first step is to get a NdbSchemaCon object to represent
+ * the schema transaction.
+ * This is done by calling Ndb::startSchemaTransaction.
+ *
+ * The next step is to get a NdbSchemaOp object by calling
+ * NdbSchemaCon::getNdbSchemaOp.
+ * The NdbSchemaOp object then has methods to define the table and
+ * its attributes.
+ *
+ * Finally, the NdbSchemaCon::execute method inserts the table
+ * into the database.
+ *
+ * @note Currently only one table can be added per transaction.
+ * @note Depricated, use NdbDictionary
+ */
+class NdbSchemaCon
+{
+friend class Ndb;
+friend class NdbSchemaOp;
+
+public:
+
+ static
+ NdbSchemaCon* startSchemaTrans(Ndb* pNdb){
+ return new NdbSchemaCon(pNdb);
+ }
+
+ static
+ void closeSchemaTrans(NdbSchemaCon* pSchCon){
+ delete pSchCon;
+ }
+
+
+ /**
+ * Execute a schema transaction.
+ *
+ * @return 0 if successful otherwise -1.
+ */
+ int execute();
+
+ /**
+ * Get a schemaoperation.
+ *
+ * @note Currently, only one operation per transaction is allowed.
+ *
+ * @return Pointer to a NdbSchemaOp or NULL if unsuccessful.
+ */
+ NdbSchemaOp* getNdbSchemaOp();
+
+ /**
+ * Get the latest error
+ *
+ * @return Error object.
+ */
+ const NdbError & getNdbError() const;
+
+private:
+
+/******************************************************************************
+ * These are the create and delete methods of this class.
+ *****************************************************************************/
+
+ NdbSchemaCon(Ndb* aNdb);
+ ~NdbSchemaCon();
+
+/******************************************************************************
+ * These are the private methods of this class.
+ *****************************************************************************/
+
+ void release(); // Release all schemaop in schemaCon
+
+ /***************************************************************************
+ * These methods are service methods to other classes in the NDBAPI.
+ ***************************************************************************/
+
+ int checkMagicNumber(); // Verify correct object
+ int receiveDICTTABCONF(NdbApiSignal* aSignal);
+ int receiveDICTTABREF(NdbApiSignal* aSignal);
+
+
+ int receiveCREATE_INDX_CONF(NdbApiSignal*);
+ int receiveCREATE_INDX_REF(NdbApiSignal*);
+ int receiveDROP_INDX_CONF(NdbApiSignal*);
+ int receiveDROP_INDX_REF(NdbApiSignal*);
+
+
+/*****************************************************************************
+ * These are the private variables of this class.
+ *****************************************************************************/
+
+
+ NdbError theError; // Errorcode
+ Ndb* theNdb; // Pointer to Ndb object
+
+ NdbSchemaOp* theFirstSchemaOpInList; // First operation in operation list.
+ int theMagicNumber; // Magic number
+};
+
+inline
+int
+NdbSchemaCon::checkMagicNumber()
+{
+ if (theMagicNumber != 0x75318642)
+ return -1;
+ return 0;
+}//NdbSchemaCon::checkMagicNumber()
+
+
+
+#endif
+#endif
+
+
diff --git a/ndb/test/include/NdbSchemaOp.hpp b/ndb/test/include/NdbSchemaOp.hpp
new file mode 100644
index 00000000000..43f76c8c253
--- /dev/null
+++ b/ndb/test/include/NdbSchemaOp.hpp
@@ -0,0 +1,587 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef NdbSchemaOp_H
+#define NdbSchemaOp_H
+
+#include <NdbDictionary.hpp>
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+
+ /**
+ * Type of attribute
+ *
+ * NOTE! AttrType is deprecated, use NdbDictionary::Column::Type instead!
+ */
+ enum AttrType {
+ Signed, ///< Attributes of this type can be read with:
+ ///< NdbRecAttr::int64_value,
+ ///< NdbRecAttr::int32_value,
+ ///< NdbRecAttr::short_value,
+ ///< NdbRecAttr::char_value
+ UnSigned, ///< Attributes of this type can be read with:
+ ///< NdbRecAttr::u_64_value,
+ ///< NdbRecAttr::u_32_value,
+ ///< NdbRecAttr::u_short_value,
+ ///< NdbRecAttr::u_char_value
+ Float, ///< Attributes of this type can be read with:
+ ///< NdbRecAttr::float_value and
+ ///< NdbRecAttr::double_value
+ String, ///< Attributes of this type can be read with:
+ ///< NdbRecAttr::aRef,
+ ///< NdbRecAttr::getAttributeObject
+ NoAttrTypeDef ///< Used for debugging only
+ };
+
+
+ /**
+ * @deprecated
+ */
+ enum NullAttributeType {
+ NoNullTypeDefined = -1,
+ NotNullAttribute,
+ NullAttribute,
+ AttributeDefined
+ };
+ /**
+ * Indicates whether the attribute is part of a primary key or not
+ */
+ enum KeyType {
+ Undefined = -1, ///< Used for debugging only
+ NoKey, ///< Attribute is not part of primary key
+ ///< or tuple identity
+ TupleKey, ///< Attribute is part of primary key
+ TupleId ///< Attribute is part of tuple identity
+ ///< (This type of attribute is created
+ ///< internally, and should not be
+ ///< manually created.)
+ };
+ /**
+ * Indicate whether the attribute should be stored on disk or not
+ */
+ enum StorageMode {
+ MMBased = 0, ///< Main memory
+ DiskBased = 1, ///< Disk (Not yet supported.)
+ NoStorageTypeDef ///< Used for debugging only
+ };
+
+ /**
+ * Where attribute is stored.
+ *
+ * This is used to indicate whether a primary key
+ * should only be stored in the index storage and not in the data storage
+ * or if it should be stored in both places.
+ * The first alternative makes the attribute take less space,
+ * but makes it impossible to scan using attribute.
+ *
+ * @note Use NormalStorageAttribute for most cases.
+ * (IndexStorageAttribute should only be used on primary key
+ * attributes and only if you do not want to scan using the attribute.)
+ */
+ enum StorageAttributeType {
+ NoStorageAttributeTypeDefined = -1, ///< <i>Missing explanation</i>
+ IndexStorageAttribute, ///< Attribute is only stored in
+ ///< index storage (ACC)
+ NormalStorageAttribute ///< Attribute values are stored
+ ///< both in the index (ACC) and
+ ///< in the data storage (TUP)
+ };
+
+
+ /**
+ * Type of fragmentation used for a table
+ */
+ enum FragmentType {
+ Default = 0, ///< (All is default!)
+ Single = 1, ///< Only one fragment
+ All = 2, ///< Default value. One fragment per node group
+ DistributionGroup = 3, ///< Distribution Group used for fragmentation.
+ ///< One fragment per node group
+ DistributionKey = 4, ///< Distribution Key used for fragmentation.
+ ///< One fragment per node group.
+ AllLarge = 5, ///< Sixten fragments per node group.
+ DGroupLarge = 6, ///< Distribution Group used for fragmentation.
+ ///< Sixten fragments per node group
+ DKeyLarge = 7 ///< Distribution Key used for fragmentation.
+ ///< Sixten fragments per node group
+ };
+
+ /**
+ * Type of table or index.
+ */
+ enum TableType {
+ UndefTableType = 0,
+ SystemTable = 1, ///< Internal.Table cannot be updated by user
+ UserTable = 2, ///< Normal application table
+ UniqueHashIndex = 3, ///< Unique un-ordered hash index
+ HashIndex = 4, ///< Non-unique un-ordered hash index
+ UniqueOrderedIndex = 5, ///< Unique ordered index
+ OrderedIndex = 6 ///< Non-unique ordered index
+ };
+
+
+class NdbSchemaCon;
+class Ndb;
+
+
+/**
+ * @class NdbSchemaOp
+ * @brief Represents various operations for use in schema transactions
+ *
+ * This class is used for schema operations, e.g. creating tables and
+ * attributes.
+ *
+ * The NdbSchemaOp object is created using NdbSchemaCon::getNdbSchemaOp.
+ *
+ * @note This class is depricated and is now replaced with the class
+ * NdbDictionary.
+ */
+class NdbSchemaOp
+{
+ friend class Ndb;
+ friend class NdbSchemaCon;
+
+public:
+
+
+ /**
+ * Create a new table in the database.
+ *
+ * @note The NdbSchemaCon should be closed with
+ * Ndb::closeSchemaTransaction, even if this method fails.
+ *
+ * @param aTableName Table name. Should not be NULL.
+ * @param aTableSize (Performance parameter.)
+ * Initial size of the data part of the table
+ * expressed in kByte.
+ * The database handles
+ * bad parameter setting but at a certain
+ * loss in performance.
+ * The size given here is
+ * the initial size allocated for the table
+ * storage (the data part).
+ * When calculating the data storage one should
+ * add the size of all attributes (each attribute
+ * consumes at least 4 bytes) and also an overhead
+ * of 12 byte.
+ * Variable size attributes (not supported yet)
+ * will have a size of 12 bytes plus the actual
+ * data storage parts where there is an
+ * additional overhead based on the size of the
+ * variable part.
+ * <br>
+ * An example table with 5 attributes:
+ * one 64 bit attribute, one 32 bit attribute,
+ * two 16 bit attributes and one array of 64 8 bits.
+ * This table will consume
+ * 12 (overhead) + 8 + 4 + 2*4 (4 is minimum) + 64 =
+ * 96 bytes per record.
+ * Additionally an overhead of about 2 % as page
+ * headers and waste should be allocated.
+ * Thus, 1 million records should consume 96 MBytes
+ * plus the overhead 2 MByte and rounded up to
+ * 100 000 kBytes.
+ * <br><em>
+ * This parameter is currently not used.
+ * </em>
+ * @param aTupleKey Indicates if the table has a primary key or not.
+ * <br>
+ * <b>TupleKey</b> means that a <em>primary key</em>
+ * consisting of one to four attributes
+ * (at most one of variable size)
+ * uniquely identifies each record in the created
+ * table.
+ * <br>
+ * <b>TupleId</b> means that a <em>tuple identity</em>
+ * is used. The tuple identity is
+ * a unique key indentifying each record of the
+ * created table.
+ * The tuple identity is a (non-stored)
+ * 64 bit attribute named <b>NDB$TID</b>.
+ * <br>
+ * When inserting a record (tuple), the method
+ * NdbOperation::setTupleId
+ * will generate a unique tuple identity
+ * and return it to the user.
+ * <br>
+ * When reading, updating or deleting a record
+ * in a table with <b>TupleId</b>,
+ * NdbOperation::equal("NDB$TID", value_Uint64)
+ * can be used to identify the record.
+ * <br>
+ * Legal values: TupleKey or TupleId.
+ * @param aNrOfPages (Performance parameter.)
+ * Specifies the initial size of the index storage.
+ * When calculating the index storage,
+ * each key has approximately 14 byte of
+ * overhead plus the size of the key.
+ * Each key attribute takes up at least 4 bytes
+ * of storage.
+ * Thus a mixed key consisting of a
+ * 64 bit attribute, a 32 bit attribute
+ * and a 16 bit attribute will
+ * consume approx. 30 bytes per key.
+ * Thus, the if initial size is to be 1 million rows,
+ * then aNrOfPages should be set to
+ * 30 M / 8k = 2670 pages.
+ * <br><em>
+ * This parameter is currently not used.
+ * </em>
+ * @param aFragmentType Type of fragmentation.<br>
+ * <b>All</b> (default) means that the
+ * table fragments are automatically
+ * distributed on all nodes in the system.<br>
+ * <b>DistributionGroup</b> and
+ * <b>DistributionKey</b> are
+ * also supported. For further details about
+ * these types see the documentation of
+ * Ndb::startTransaction.
+ * @param aKValue (Hash parameter.)
+ * Only allowed value is 6.
+ * Later implementations might add flexibility
+ * in this parameter.
+ * @param aMinLoadFactor (Hash parameter.)
+ * This value specifies the load factor when
+ * starting to shrink the hash table.
+ * It must be smaller than aMaxLoadFactor.
+ * Both these factors are given in percentage.
+ * @param aMaxLoadFactor (Hash parameter.)
+ * This value specifies the load factor when
+ * starting to split the containers in the local
+ * hash tables. 100 is the maximum which will
+ * optimize memory usage (this is the figure
+ * used for the above calculations).
+ * A lower figure will store less information in
+ * each container and thus
+ * find the key faster but consume more memory.
+ * @param aMemoryType Currently only 1 is allowed which specifies
+ * storage of table in main memory.
+ * Later 2 will be added where the table is stored
+ * completely on disk
+ * and 3 where the index is in main memory but
+ * data is on disk.
+ * If 1 is chosen an individual attribute can
+ * still be specified as a disk attribute.
+ * @param aStoredTable If set to false it indicates that the table is
+ * a temporary table and should not be logged
+ * to disk.
+ * In case of a system restart the table will still
+ * be defined and exist but will be empty.
+ * Thus no checkpointing and
+ * no logging is performed on the table.
+ * The default value is true and indicates a
+ * normal table with full checkpointing and
+ * logging activated.
+ * @return Returns 0 when successful and returns -1 otherwise.
+ */
+ int createTable( const char* aTableName,
+ Uint32 aTableSize = 8,
+ KeyType aTupleKey = TupleKey,
+ int aNrOfPages = 2,
+ FragmentType aFragmentType = All,
+ int aKValue = 6,
+ int aMinLoadFactor = 78,
+ int aMaxLoadFactor = 80,
+ int aMemoryType = 1,
+ bool aStoredTable = true);
+
+ /**
+ * This is the old function declaration, don't use.
+ *
+ * @deprecated do not use!
+ */
+ inline int createTable( const char* aTableName,
+ Uint32 aTableSize,
+ KeyType aTupleKey,
+ int aNrOfPages,
+ FragmentType aFragmentType,
+ int aKValue,
+ int aMinLoadFactor,
+ int aMaxLoadFactor,
+ int aMemoryType,
+ int aStoredTable){
+ return createTable(aTableName,
+ aTableSize,
+ aTupleKey,
+ aNrOfPages,
+ aFragmentType,
+ aKValue,
+ aMinLoadFactor,
+ aMaxLoadFactor,
+ aMemoryType,
+ (aStoredTable == 1 ? true : false));
+ }
+
+ /**
+ * Add a new attribute to a database table.
+ *
+ * Attributes can only be added to a table in the same transaction
+ * as the transaction creating the table.
+ *
+ * @note The NdbSchemaCon transaction should be closed with
+ * Ndb::closeSchemaTransaction, even if this method fails.
+ *
+ * Example creating an unsigned int attribute belonging to the primary key
+ * of the table it is created in:
+ * @code
+ * MySchemaOp->createAttribute("Attr1", // Attribute name
+ * TupleKey, // Belongs to primary key
+ * 32, // 32 bits
+ * 1, // Not an array attribute
+ * UnSigned, // Unsigned type
+ * );
+ * @endcode
+ *
+ * Example creating a string attribute belonging to the primary key
+ * of the table it is created in:
+ * @code
+ * MySchemaOp->createAttribute("Attr1", // Attribute name
+ * TupleKey, // Belongs to primary key
+ * 8, // Each character is 8 bits
+ * 12, // Max 12 chars in string
+ * String, // Attribute if of type string
+ * );
+ * @endcode
+ *
+ * A <em>distribution key</em> is a set of attributes which are used
+ * to distribute the tuples onto the NDB nodes.
+ * A <em>distribution group</em> is a part (currently 16 bits)
+ * of an attribute used to distribute the tuples onto the NDB nodes.
+ * The distribution key uses the NDB Cluster hashing function,
+ * while the distribution group uses a simpler function.
+ *
+ * @param aAttrName Attribute name. Should not be NULL.
+ * @param aTupleKey This parameter specifies whether the
+ * attribute is part of the primary key or not.
+ * Floats are not allowed in the primary key.
+ * <br>
+ * Legal values: NoKey, TupleKey
+ * @param aAttrSize Specifies the size of the elements of the
+ * attribute. (An attribute can consist
+ * of an array of elements.)
+ * <br>
+ * Legal values: 8, 16, 32, 64 and 128 bits.
+ * @param aArraySize Size of array.
+ * <br>
+ * Legal values:
+ * 0 = variable-sized array,
+ * 1 = no array, and
+ * 2- = fixed size array.
+ * <br>
+ * <em>
+ * Variable-sized array attributes are
+ * not yet supported.
+ * </em>
+ * <br>
+ * There is no upper limit of the array size
+ * for a single attribute.
+ * @param aAttrType The attribute type.
+ * This is only of interest if calculations are
+ * made within NDB.
+ * <br>
+ * Legal values: UnSigned, Signed, Float, String
+ * @param aStorageMode Main memory based or disk based attribute.<br>
+ * Legal values: MMBased, DiskBased
+ * <br>
+ * <em>
+ * Disk-based attributes are not yet supported.
+ * </em>
+ * @param nullable Set to true if NULL is a correct value for
+ * the attribute.
+ * <br>
+ * Legal values: true, false
+ * @param aStType Stored in both index and data storage or
+ * only store in index data storage.
+ * <br>
+ * This parameter is only of interest for tuple
+ * key attributes.
+ * All tuple key attributes values are always stored
+ * in the index storage part.
+ * If this parameter is set to
+ * IndexStorageAttribute, then the attribute values
+ * will <em>only</em> be stored in the index
+ * storage part and <em>not</em> in the data
+ * storage part.
+ * <br>
+ * If there will be no scans using the primary
+ * key attribute and if the size of the attribute
+ * is large, then this might be of interest.
+ * A typical example is a table where
+ * http-addresses are used as primary key.
+ * <br>
+ * Legal values: NormalStorageAttribute,
+ * IndexStorageAttribute
+ * @param aDistributionKey Sometimes it is preferable to use a subset
+ * of the primary key as the distribution key.
+ * An example is TPC-C where it might be
+ * good to use the warehouse id and district id
+ * as the distribution key.
+ * <br>
+ * Locally in the fragments the full primary key
+ * will still be used with the hashing algorithm.
+ * Set to 1 if this attribute is part of the
+ * distribution key.
+ * All distribution key attributes must be
+ * defined before
+ * any other attributes are defined.
+ * @param aDistributionGroup In other applications it is desirable to use
+ * only a part of an attribute to create the
+ * distribution key.
+ * This is applicable for some telecom
+ * applications.
+ * <br>
+ * In these situations one must provide how many
+ * bits of the attribute that is to
+ * be used as the distribution hash value.
+ * <br>
+ * This provides some control to the
+ * application of the distribution.
+ * It still needs to be part of a primary key
+ * the attribute and must be defined as the
+ * first attribute.
+ * @param aDistributionGroupNoOfBits
+ * Number of bits to use of the
+ * distribution group attribute in the
+ * distribution hash value.
+ * <br>
+ * Currently, only 16 bits is supported. It will
+ * always be the last 16 bits in the attribute
+ * which is used for the distribution group.
+ * @param aAutoIncrement Set to autoincrement attribute.
+ * @param aDefaultValue Set a default value of attribute.
+ *
+ * @return Returns 0 when successful and returns -1 otherwise.
+ ****************************************************************************/
+ int createAttribute(const char* aAttrName,
+ KeyType aTupleKey = NoKey,
+ int aAttrSize = 32,
+ int aArraySize = 1,
+ AttrType aAttrType = UnSigned,
+ StorageMode aStorageMode = MMBased,
+ bool nullable = false,
+ StorageAttributeType aStType= NormalStorageAttribute,
+ int aDistributionKey = 0,
+ int aDistributionGroup = 0,
+ int aDistributionGroupNoOfBits = 16,
+ bool aAutoIncrement = false,
+ const char* aDefaultValue = 0);
+
+ /**
+ * @deprecated do not use!
+ */
+ int createAttribute(const char* aAttrName,
+ KeyType aTupleKey,
+ int aAttrSize,
+ int aArraySize,
+ AttrType aAttrType,
+ StorageMode aStorageMode,
+ NullAttributeType aNullAttr,
+ StorageAttributeType aStType = NormalStorageAttribute,
+ int aDistributionKey = 0,
+ int aDistributionGroup = 0,
+ int aDistributionGroupNoOfBits = 16){
+ return createAttribute(aAttrName,
+ aTupleKey,
+ aAttrSize,
+ aArraySize,
+ aAttrType,
+ aStorageMode,
+ aNullAttr == NullAttribute,
+ aStType,
+ aDistributionKey,
+ aDistributionGroup,
+ aDistributionGroupNoOfBits);
+ }
+
+ const NdbError & getNdbError() const;
+
+protected:
+
+/*****************************************************************************
+ * These are the methods used to create and delete the NdbOperation objects.
+ ****************************************************************************/
+ NdbSchemaOp(Ndb* aNdb);
+
+ ~NdbSchemaOp();
+
+/******************************************************************************
+ * These methods are service routines used by the other NDBAPI classes.
+ *****************************************************************************/
+
+ void release(); // Release all memory connected
+ // to the operations object.
+
+/****************************************************************************
+ * The methods below is the execution part of the NdbSchemaOp class.
+ *****************************************************************************/
+
+ int sendRec();
+ int sendSignals(Uint32 aNodeId, bool HaveMutex);
+
+ int init(NdbSchemaCon* aSchemaCon);
+
+ /**************************************************************************
+ * These are the private variables that are defined in the operation
+ * objects.
+ **************************************************************************/
+ Ndb* theNdb; // Point back to the Ndb object.
+ NdbSchemaCon* theSchemaCon; // Point back to the connection object.
+
+
+ class NdbDictionary::Table * m_currentTable;
+};
+
+
+/**
+ * Get old attribute type from new type
+ *
+ * NOTE! attrType is deprecated, use getType instead!
+ *
+ * @return Type of attribute: { Signed, UnSigned, Float,a String }
+ */
+inline
+AttrType
+convertColumnTypeToAttrType(NdbDictionary::Column::Type _type)
+{
+
+ switch(_type){
+ case NdbDictionary::Column::Bigint:
+ case NdbDictionary::Column::Int:
+ return Signed;
+ case NdbDictionary::Column::Bigunsigned:
+ case NdbDictionary::Column::Unsigned:
+ return UnSigned;
+ case NdbDictionary::Column::Float:
+ case NdbDictionary::Column::Decimal:
+ case NdbDictionary::Column::Double:
+ return Float;
+ case NdbDictionary::Column::Char:
+ case NdbDictionary::Column::Varchar:
+ case NdbDictionary::Column::Binary:
+ case NdbDictionary::Column::Varbinary:
+ return String;
+ case NdbDictionary::Column::Datetime:
+ case NdbDictionary::Column::Timespec:
+ case NdbDictionary::Column::Undefined:
+ default:
+ return NoAttrTypeDef;
+ }
+}
+#endif
+
+#endif
+
+
diff --git a/ndb/test/ndbapi/telco/InsertRecs.cpp b/ndb/test/ndbapi/InsertRecs.cpp
index f42786d666d..f42786d666d 100644
--- a/ndb/test/ndbapi/telco/InsertRecs.cpp
+++ b/ndb/test/ndbapi/InsertRecs.cpp
diff --git a/ndb/test/ndbapi/Makefile b/ndb/test/ndbapi/Makefile
deleted file mode 100644
index 91f0c84c18e..00000000000
--- a/ndb/test/ndbapi/Makefile
+++ /dev/null
@@ -1,50 +0,0 @@
-include .defs.mk
-
-
-ifeq ($(NDB_OS), OSE)
-DIRS = basic flexBench flexAsynch
-else
-DIRS = lmc-bench bank ronja
-BIN_DIRS = \
- flexAsynch \
- flexBench \
- flexHammer \
- flexScan \
- flexTT \
- create_tab \
- create_all_tabs \
- drop_all_tabs \
- bulk_copy \
- restarter2 restarter \
- restarts testScan testNdbApi \
- testScanInterpreter testIndex \
- testInterpreter \
- testOIBasic \
- testBackup \
- testBasic \
- basicAsynch \
- testNodeRestart \
- testOperations testTransactions \
- testSystemRestart \
- testTimeout \
- testMgm \
- testRestartGci \
- testDataBuffers \
- testDict \
- acid \
- interpreterInTup \
- telco \
- indexTest \
- test_event \
- indexTest2 \
- testGrep
-
-ifeq ($(NDB_OS), SOLARIS)
-ifeq ($(NDB_COMPILER), FORTE6)
- DIRS += flexTimedAsynch
-endif
-endif
-endif
-
-include ${NDB_TOP}/Epilogue.mk
-
diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am
new file mode 100644
index 00000000000..52058c306fb
--- /dev/null
+++ b/ndb/test/ndbapi/Makefile.am
@@ -0,0 +1,81 @@
+
+SUBDIRS = bank
+
+ndbtest_PROGRAMS = \
+flexBench \
+drop_all_tabs \
+create_all_tabs \
+create_tab \
+flexAsynch \
+flexBench \
+flexHammer \
+flexScan \
+flexTT \
+testBackup \
+testBasic \
+testBasicAsynch \
+testBlobs \
+testDataBuffers \
+testDict \
+testIndex \
+testMgm \
+testNdbApi \
+testNodeRestart \
+testOIBasic \
+testOperations \
+testRestartGci \
+testScan \
+testScanInterpreter \
+testSystemRestart \
+testTimeout \
+testTransactions \
+test_event
+
+#flexTimedAsynch
+#testBlobs
+#flex_bench_mysql
+
+create_all_tabs_SOURCES = create_all_tabs.cpp
+create_tab_SOURCES = create_tab.cpp
+drop_all_tabs_SOURCES = drop_all_tabs.cpp
+flexAsynch_SOURCES = flexAsynch.cpp
+flexBench_SOURCES = flexBench.cpp
+flexHammer_SOURCES = flexHammer.cpp
+flexScan_SOURCES = flexScan.cpp
+flexTT_SOURCES = flexTT.cpp
+#flexTimedAsynch_SOURCES = flexTimedAsynch.cpp
+#flex_bench_mysql_SOURCES = flex_bench_mysql.cpp
+testBackup_SOURCES = testBackup.cpp
+testBasic_SOURCES = testBasic.cpp
+testBasicAsynch_SOURCES = testBasicAsynch.cpp
+testBlobs_SOURCES = testBlobs.cpp
+testDataBuffers_SOURCES = testDataBuffers.cpp
+testDict_SOURCES = testDict.cpp
+testIndex_SOURCES = testIndex.cpp
+testMgm_SOURCES = testMgm.cpp
+testNdbApi_SOURCES = testNdbApi.cpp
+testNodeRestart_SOURCES = testNodeRestart.cpp
+testOIBasic_SOURCES = testOIBasic.cpp
+testOperations_SOURCES = testOperations.cpp
+testRestartGci_SOURCES = testRestartGci.cpp
+testScan_SOURCES = testScan.cpp
+testScanInterpreter_SOURCES = testScanInterpreter.cpp
+testSystemRestart_SOURCES = testSystemRestart.cpp
+testTimeout_SOURCES = testTimeout.cpp
+testTransactions_SOURCES = testTransactions.cpp
+test_event_SOURCES = test_event.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am
+
+##testDict_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
+##testIndex_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
+##testSystemRestart_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
+##testTransactions_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
+testBackup_LDADD = $(LDADD) bank/libbank.a
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
+
diff --git a/ndb/test/ndbapi/Makefile_old b/ndb/test/ndbapi/Makefile_old
new file mode 100644
index 00000000000..34761e1eb9c
--- /dev/null
+++ b/ndb/test/ndbapi/Makefile_old
@@ -0,0 +1,51 @@
+include .defs.mk
+
+
+ifeq ($(NDB_OS), OSE)
+DIRS = basic flexBench flexAsynch
+else
+DIRS = lmc-bench bank ronja
+BIN_DIRS = \
+ flexAsynch \
+ flexBench \
+ flexHammer \
+ flexScan \
+ flexTT \
+ create_tab \
+ create_all_tabs \
+ drop_all_tabs \
+ bulk_copy \
+ restarter2 restarter \
+ restarts testScan testNdbApi \
+ testScanInterpreter testIndex \
+ testInterpreter \
+ testOIBasic \
+ testBackup \
+ testBasic \
+ basicAsynch \
+ testNodeRestart \
+ testOperations testTransactions \
+ testSystemRestart \
+ testTimeout \
+ testMgm \
+ testRestartGci \
+ testDataBuffers \
+ testDict \
+ acid \
+ interpreterInTup \
+ telco \
+ indexTest \
+ test_event \
+ indexTest2 \
+ testGrep \
+ testBlobs
+
+ifeq ($(NDB_OS), SOLARIS)
+ifeq ($(NDB_COMPILER), FORTE6)
+ DIRS += flexTimedAsynch
+endif
+endif
+endif
+
+include ${NDB_TOP}/Epilogue.mk
+
diff --git a/ndb/test/ndbapi/testScanInterpreter/ScanFilter.hpp b/ndb/test/ndbapi/ScanFilter.hpp
index 09786756798..09786756798 100644
--- a/ndb/test/ndbapi/testScanInterpreter/ScanFilter.hpp
+++ b/ndb/test/ndbapi/ScanFilter.hpp
diff --git a/ndb/test/ndbapi/testScan/ScanFunctions.hpp b/ndb/test/ndbapi/ScanFunctions.hpp
index 36d01909861..36d01909861 100644
--- a/ndb/test/ndbapi/testScan/ScanFunctions.hpp
+++ b/ndb/test/ndbapi/ScanFunctions.hpp
diff --git a/ndb/test/ndbapi/testScanInterpreter/ScanInterpretTest.hpp b/ndb/test/ndbapi/ScanInterpretTest.hpp
index 3862de34111..3862de34111 100644
--- a/ndb/test/ndbapi/testScanInterpreter/ScanInterpretTest.hpp
+++ b/ndb/test/ndbapi/ScanInterpretTest.hpp
diff --git a/ndb/test/ndbapi/acid2/TraceNdbApi.cpp b/ndb/test/ndbapi/TraceNdbApi.cpp
index bd43b15f2e6..bd43b15f2e6 100644
--- a/ndb/test/ndbapi/acid2/TraceNdbApi.cpp
+++ b/ndb/test/ndbapi/TraceNdbApi.cpp
diff --git a/ndb/test/ndbapi/acid2/VerifyNdbApi.cpp b/ndb/test/ndbapi/VerifyNdbApi.cpp
index 79645827e2c..79645827e2c 100644
--- a/ndb/test/ndbapi/acid2/VerifyNdbApi.cpp
+++ b/ndb/test/ndbapi/VerifyNdbApi.cpp
diff --git a/ndb/test/ndbapi/acid.cpp b/ndb/test/ndbapi/acid.cpp
new file mode 100644
index 00000000000..157b3c7b3ef
--- /dev/null
+++ b/ndb/test/ndbapi/acid.cpp
@@ -0,0 +1,558 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <NdbSchemaCon.hpp>
+#include <NdbMutex.h>
+#include <NdbOut.hpp>
+#include <NdbSleep.h>
+#include <NdbThread.h>
+#include <NdbTick.h>
+#include <NdbMain.h>
+#include <NdbTest.hpp>
+#include <random.h>
+
+//#define TRACE
+#define DEBUG
+//#define RELEASE
+#define NODE_REC // epaulsa: introduces pointer checks to help 'acid' keep core
+// during node recovery
+
+#ifdef TRACE
+
+#define VerifyMethodInt(c, m) (ReportMethodInt(c->m, c, #c, #m, __FILE__, __LINE__))
+#define VerifyMethodPtr(v, c, m) (v=ReportMethodPtr(c->m, c, #v, #c, #m, __FILE__, __LINE__))
+#define VerifyMethodVoid(c, m) (c->m, ReportMethodVoid(c, #c, #m, __FILE__, __LINE__))
+
+int ReportMethodInt(int iRes, NdbConnection* pNdbConnection, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
+{
+ ndbout << szFile << "(" << iLine << ") : ";
+ ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
+ ndbout << pNdbConnection->getNdbError();
+ NdbOperation* pNdbOperation = pNdbConnection->getNdbErrorOperation();
+ if(pNdbOperation) {
+ ndbout << " : " << pNdbOperation->getNdbError();
+ }
+ ndbout << " : " << pNdbConnection->getNdbErrorLine();
+ ndbout << endl;
+ return iRes;
+}
+
+template <class C>
+int ReportMethodInt(int iRes, C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
+{
+ ndbout << szFile << "(" << iLine << ") : ";
+ ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
+ ndbout << pC->getNdbError();
+ ndbout << endl;
+ return iRes;
+}
+
+template <class R, class C>
+R* ReportMethodPtr(R* pR, C* pC, const char* szVariable, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
+{
+ ndbout << szFile << "(" << iLine << ") : ";
+ ndbout << szVariable << " = " << szClass << "->" << szMethod << " return " << (long)(void*)pR << " : ";
+ ndbout << pC->getNdbError();
+ ndbout << endl;
+ return pR;
+}
+
+template <class C>
+void ReportMethodVoid(C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
+{
+ ndbout << szFile << "(" << iLine << ") : ";
+ ndbout << szClass << "->" << szMethod << " : ";
+ ndbout << pC->getNdbError();
+ ndbout << endl;
+}
+#endif /* TRACE */
+
+
+#ifdef DEBUG
+
+#define VerifyMethodInt(c, m) (ReportMethodInt(c->m, c, #c, #m, __FILE__, __LINE__))
+#define VerifyMethodPtr(v, c, m) (v=ReportMethodPtr(c->m, c, #v, #c, #m, __FILE__, __LINE__))
+#define VerifyMethodVoid(c, m) (c->m, ReportMethodVoid(c, #c, #m, __FILE__, __LINE__))
+
+int ReportMethodInt(int iRes, NdbConnection* pNdbConnection, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
+{
+ if(iRes<0) {
+ ndbout << szFile << "(" << iLine << ") : ";
+ ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
+ ndbout << pNdbConnection->getNdbError();
+ NdbOperation* pNdbOperation = pNdbConnection->getNdbErrorOperation();
+ if(pNdbOperation) {
+ ndbout << " : " << pNdbOperation->getNdbError();
+ }
+ ndbout << " : " << pNdbConnection->getNdbErrorLine();
+ ndbout << " : ";
+ ndbout << endl;
+ }
+ return iRes;
+}
+
+template <class C>
+int ReportMethodInt(int iRes, C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
+{
+ if(iRes<0) {
+ ndbout << szFile << "(" << iLine << ") : ";
+ ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
+ ndbout << pC->getNdbError();
+ ndbout << endl;
+ }
+ return iRes;
+}
+
+template <class R, class C>
+R* ReportMethodPtr(R* pR, C* pC, const char* szVariable, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
+{
+ if(!pR) {
+ ndbout << szFile << "(" << iLine << ") : ";
+ ndbout << szVariable << " = " << szClass << "->" << szMethod << " return " << " : ";
+ ndbout << pC->getNdbError();
+ ndbout << endl;
+ }
+ return pR;
+}
+
+template <class C>
+void ReportMethodVoid(C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
+{
+ if(pC->getNdbError().code) {
+ ndbout << szFile << "(" << iLine << ") : ";
+ ndbout << szClass << "->" << szMethod << " : ";
+ ndbout << pC->getNdbError();
+ ndbout << endl;
+ }
+}
+
+
+#endif /* DEBUG */
+
+
+#ifdef RELEASE
+
+#define VerifyMethodInt(c, m) (c->m)
+#define VerifyMethodPtr(v, c, m) (v=(c->m))
+#define VerifyMethodVoid(c, m) (c->m)
+
+int ReportMethodInt(int iRes, NdbConnection* pNdbConnection, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
+{
+ if(iRes<0) {
+ ndbout << szFile << "(" << iLine << ") : ";
+ ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
+ ndbout << pNdbConnection->getNdbError();
+ NdbOperation* pNdbOperation = pNdbConnection->getNdbErrorOperation();
+ if(pNdbOperation) {
+ ndbout << " : " << pNdbOperation->getNdbError();
+ }
+ ndbout << " : " << pNdbConnection->getNdbErrorLine();
+ ndbout << endl;
+ }
+ return iRes;
+}
+
+#endif /* RELEASE */
+
+// epaulsa =>
+#ifndef NODE_REC
+#define CHK_TR(p)
+#else
+#define CHK_TR(p) if(!p){ \
+ ndbout <<"startTransaction failed, returning now." << endl ; \
+ delete pNdb ; \
+ pNdb = NULL ; \
+ return 0 ; \
+ }
+#endif // NODE_REC
+// <= epaulsa
+
+const char* c_szWarehouse = "WAREHOUSE";
+const char* c_szWarehouseNumber = "W_ID";
+const char* c_szWarehouseSum = "W_SUM";
+const char* c_szWarehouseCount = "W_CNT";
+const char* c_szDistrict = "DISTRICT";
+const char* c_szDistrictWarehouseNumber = "D_W_ID";
+const char* c_szDistrictNumber = "D_ID";
+const char* c_szDistrictSum = "D_SUM";
+const char* c_szDistrictCount = "D_CNT";
+
+Uint32 g_nWarehouseCount = 10;
+Uint32 g_nDistrictPerWarehouse = 10;
+Uint32 g_nThreadCount = 1;
+NdbMutex* g_pNdbMutex = 0;
+
+extern "C" void* NdbThreadFuncInsert(void* pArg)
+{
+ myRandom48Init((long int)NdbTick_CurrentMillisecond());
+ unsigned nSucc = 0;
+ unsigned nFail = 0;
+ Ndb* pNdb = NULL ;
+ pNdb = new Ndb("TEST_DB");
+ VerifyMethodInt(pNdb, init());
+ VerifyMethodInt(pNdb, waitUntilReady());
+
+ while(NdbMutex_Trylock(g_pNdbMutex)) {
+ Uint32 nWarehouse = myRandom48(g_nWarehouseCount);
+ NdbConnection* pNdbConnection = NULL ;
+ VerifyMethodPtr(pNdbConnection, pNdb, startTransaction());
+ CHK_TR(pNdbConnection);
+ NdbOperation* pNdbOperationW = NULL ;
+ VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse));
+ VerifyMethodInt(pNdbOperationW, insertTuple());
+ VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse));
+ VerifyMethodInt(pNdbOperationW, setValue(c_szWarehouseCount, Uint32(1)));
+ Uint32 nWarehouseSum = 0;
+ for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
+ NdbOperation* pNdbOperationD = NULL ;
+ VerifyMethodPtr(pNdbOperationD, pNdbConnection, getNdbOperation(c_szDistrict));
+ VerifyMethodInt(pNdbOperationD, insertTuple());
+ VerifyMethodInt(pNdbOperationD, equal(c_szDistrictWarehouseNumber, nWarehouse));
+ VerifyMethodInt(pNdbOperationD, equal(c_szDistrictNumber, nDistrict));
+ VerifyMethodInt(pNdbOperationD, setValue(c_szDistrictCount, Uint32(1)));
+ Uint32 nDistrictSum = myRandom48(100);
+ nWarehouseSum += nDistrictSum;
+ VerifyMethodInt(pNdbOperationD, setValue(c_szDistrictSum, nDistrictSum));
+ }
+ VerifyMethodInt(pNdbOperationW, setValue(c_szWarehouseSum, nWarehouseSum));
+ int iExec = pNdbConnection->execute(Commit);
+ int iError = pNdbConnection->getNdbError().code;
+
+ if(iExec<0 && iError!=0 && iError!=266 && iError!=630) {
+ ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__);
+ }
+ if(iExec==0) {
+ ++nSucc;
+ } else {
+ ++nFail;
+ }
+ VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
+ }
+ ndbout << "insert: " << nSucc << " succeeded, " << nFail << " failed " << endl;
+ NdbMutex_Unlock(g_pNdbMutex);
+ delete pNdb;
+ pNdb = NULL ;
+ return NULL;
+}
+
+
+extern "C" void* NdbThreadFuncUpdate(void* pArg)
+{
+ myRandom48Init((long int)NdbTick_CurrentMillisecond());
+ unsigned nSucc = 0;
+ unsigned nFail = 0;
+ Ndb* pNdb = NULL ;
+ pNdb = new Ndb("TEST_DB");
+ VerifyMethodInt(pNdb, init());
+ VerifyMethodInt(pNdb, waitUntilReady());
+
+ while(NdbMutex_Trylock(g_pNdbMutex)) {
+ Uint32 nWarehouse = myRandom48(g_nWarehouseCount);
+ NdbConnection* pNdbConnection = NULL ;
+ VerifyMethodPtr(pNdbConnection, pNdb, startTransaction());
+ CHK_TR(pNdbConnection) ; // epaulsa
+ NdbOperation* pNdbOperationW = NULL ;
+ VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse));
+ VerifyMethodInt(pNdbOperationW, interpretedUpdateTuple());
+ VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse));
+ VerifyMethodInt(pNdbOperationW, incValue(c_szWarehouseCount, Uint32(1)));
+ Uint32 nWarehouseSum = 0;
+ for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
+ NdbOperation* pNdbOperationD = NULL ;
+ VerifyMethodPtr(pNdbOperationD, pNdbConnection, getNdbOperation(c_szDistrict));
+ VerifyMethodInt(pNdbOperationD, interpretedUpdateTuple());
+ VerifyMethodInt(pNdbOperationD, equal(c_szDistrictWarehouseNumber, nWarehouse));
+ VerifyMethodInt(pNdbOperationD, equal(c_szDistrictNumber, nDistrict));
+ VerifyMethodInt(pNdbOperationD, incValue(c_szDistrictCount, Uint32(1)));
+ Uint32 nDistrictSum = myRandom48(100);
+ nWarehouseSum += nDistrictSum;
+ VerifyMethodInt(pNdbOperationD, setValue(c_szDistrictSum, nDistrictSum));
+ }
+ VerifyMethodInt(pNdbOperationW, setValue(c_szWarehouseSum, nWarehouseSum));
+ int iExec = pNdbConnection->execute(Commit);
+ int iError = pNdbConnection->getNdbError().code;
+
+ if(iExec<0 && iError!=0 && iError!=266 && iError!=626) {
+ ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__);
+ }
+ if(iExec==0) {
+ ++nSucc;
+ } else {
+ ++nFail;
+ }
+ VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
+ }
+ ndbout << "update: " << nSucc << " succeeded, " << nFail << " failed " << endl;
+ NdbMutex_Unlock(g_pNdbMutex);
+ delete pNdb;
+ pNdb = NULL ;
+ return NULL;
+}
+
+
+extern "C" void* NdbThreadFuncDelete(void* pArg)
+{
+ myRandom48Init((long int)NdbTick_CurrentMillisecond());
+ unsigned nSucc = 0;
+ unsigned nFail = 0;
+ Ndb* pNdb = NULL ;
+ pNdb = new Ndb("TEST_DB");
+ VerifyMethodInt(pNdb, init());
+ VerifyMethodInt(pNdb, waitUntilReady());
+
+ while(NdbMutex_Trylock(g_pNdbMutex)) {
+ Uint32 nWarehouse = myRandom48(g_nWarehouseCount);
+ NdbConnection* pNdbConnection = NULL ;
+ VerifyMethodPtr(pNdbConnection, pNdb, startTransaction());
+ CHK_TR(pNdbConnection) ; // epaulsa
+ NdbOperation* pNdbOperationW = NULL ;
+ VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse));
+ VerifyMethodInt(pNdbOperationW, deleteTuple());
+ VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse));
+ for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
+ NdbOperation* pNdbOperationD = NULL ;
+ VerifyMethodPtr(pNdbOperationD, pNdbConnection, getNdbOperation(c_szDistrict));
+ VerifyMethodInt(pNdbOperationD, deleteTuple());
+ VerifyMethodInt(pNdbOperationD, equal(c_szDistrictWarehouseNumber, nWarehouse));
+ VerifyMethodInt(pNdbOperationD, equal(c_szDistrictNumber, nDistrict));
+ }
+ int iExec = pNdbConnection->execute(Commit);
+ int iError = pNdbConnection->getNdbError().code;
+
+ if(iExec<0 && iError!=0 && iError!=266 && iError!=626) {
+ ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__);
+ }
+ if(iExec==0) {
+ ++nSucc;
+ } else {
+ ++nFail;
+ }
+ VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
+ }
+ ndbout << "delete: " << nSucc << " succeeded, " << nFail << " failed " << endl;
+ NdbMutex_Unlock(g_pNdbMutex);
+ delete pNdb;
+ pNdb = NULL ;
+ return NULL;
+}
+
+
+extern "C" void* NdbThreadFuncRead(void* pArg)
+{
+ myRandom48Init((long int)NdbTick_CurrentMillisecond());
+ unsigned nSucc = 0;
+ unsigned nFail = 0;
+ NdbRecAttr** ppNdbRecAttrDSum = new NdbRecAttr*[g_nDistrictPerWarehouse];
+ NdbRecAttr** ppNdbRecAttrDCnt = new NdbRecAttr*[g_nDistrictPerWarehouse];
+ Ndb* pNdb = NULL ;
+ pNdb = new Ndb("TEST_DB");
+ VerifyMethodInt(pNdb, init());
+ VerifyMethodInt(pNdb, waitUntilReady());
+
+ while(NdbMutex_Trylock(g_pNdbMutex)) {
+ Uint32 nWarehouse = myRandom48(g_nWarehouseCount);
+ NdbConnection* pNdbConnection = NULL ;
+ VerifyMethodPtr(pNdbConnection, pNdb, startTransaction());
+ CHK_TR(pNdbConnection) ; // epaulsa
+ NdbOperation* pNdbOperationW = NULL ;
+ VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse));
+ VerifyMethodInt(pNdbOperationW, readTuple());
+ VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse));
+ NdbRecAttr* pNdbRecAttrWSum;
+ VerifyMethodPtr(pNdbRecAttrWSum, pNdbOperationW, getValue(c_szWarehouseSum, 0));
+ NdbRecAttr* pNdbRecAttrWCnt;
+ VerifyMethodPtr(pNdbRecAttrWCnt, pNdbOperationW, getValue(c_szWarehouseCount, 0));
+ for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
+ NdbOperation* pNdbOperationD = NULL ;
+ VerifyMethodPtr(pNdbOperationD, pNdbConnection, getNdbOperation(c_szDistrict));
+ VerifyMethodInt(pNdbOperationD, readTuple());
+ VerifyMethodInt(pNdbOperationD, equal(c_szDistrictWarehouseNumber, nWarehouse));
+ VerifyMethodInt(pNdbOperationD, equal(c_szDistrictNumber, nDistrict));
+ VerifyMethodPtr(ppNdbRecAttrDSum[nDistrict], pNdbOperationD, getValue(c_szDistrictSum, 0));
+ VerifyMethodPtr(ppNdbRecAttrDCnt[nDistrict], pNdbOperationD, getValue(c_szDistrictCount, 0));
+ }
+ int iExec = pNdbConnection->execute(Commit);
+ int iError = pNdbConnection->getNdbError().code;
+
+ if(iExec<0 && iError!=0 && iError!=266 && iError!=626) {
+ ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__);
+ }
+ if(iExec==0) {
+ Uint32 nSum = 0;
+ Uint32 nCnt = 0;
+ for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
+ nSum += ppNdbRecAttrDSum[nDistrict]->u_32_value();
+ nCnt += ppNdbRecAttrDCnt[nDistrict]->u_32_value();
+ }
+ if(nSum!=pNdbRecAttrWSum->u_32_value()
+ || nCnt!=g_nDistrictPerWarehouse*pNdbRecAttrWCnt->u_32_value()) {
+ ndbout << "INCONSISTENT!" << endl;
+ ndbout << "iExec==" << iExec << endl;
+ ndbout << "iError==" << iError << endl;
+ ndbout << endl;
+ ndbout << c_szWarehouseSum << "==" << pNdbRecAttrWSum->u_32_value() << ", ";
+ ndbout << c_szWarehouseCount << "==" << pNdbRecAttrWCnt->u_32_value() << endl;
+ ndbout << "nSum==" << nSum << ", nCnt=" << nCnt << endl;
+ for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
+ ndbout << c_szDistrictSum << "[" << nDistrict << "]==" << ppNdbRecAttrDSum[nDistrict]->u_32_value() << ", ";
+ ndbout << c_szDistrictCount << "[" << nDistrict << "]==" << ppNdbRecAttrDCnt[nDistrict]->u_32_value() << endl;
+ }
+ VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
+ delete pNdb; pNdb = NULL ;
+ delete[] ppNdbRecAttrDSum; ppNdbRecAttrDSum = NULL ;
+ delete[] ppNdbRecAttrDCnt; ppNdbRecAttrDCnt = NULL ;
+ NDBT_ProgramExit(NDBT_FAILED);
+ }
+ ++nSucc;
+ } else {
+ ++nFail;
+ }
+ VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
+ }
+ ndbout << "read: " << nSucc << " succeeded, " << nFail << " failed " << endl;
+ NdbMutex_Unlock(g_pNdbMutex);
+ delete pNdb; pNdb = NULL ;
+ delete[] ppNdbRecAttrDSum; ppNdbRecAttrDSum = NULL ;
+ delete[] ppNdbRecAttrDCnt; ppNdbRecAttrDCnt = NULL ;
+ return NULL;
+}
+
+
+NDB_COMMAND(acid, "acid", "acid", "acid", 65535)
+{
+ long nSeconds = 60;
+ int rc = NDBT_OK;
+
+ for(int i=1; i<argc; ++i) {
+ if(argv[i][0]=='-' || argv[i][0]=='/') {
+ switch(argv[i][1]) {
+ case 'w': g_nWarehouseCount=atol(argv[i]+2); break;
+ case 'd': g_nDistrictPerWarehouse=atol(argv[i]+2); break;
+ case 's': nSeconds=atol(argv[i]+2); break;
+ case 't': g_nThreadCount=atol(argv[i]+2); break;
+ default: ndbout << "invalid option" << endl; return 1;
+ }
+ } else {
+ ndbout << "invalid operand" << endl;
+ return 1;
+ }
+ }
+ ndbout << argv[0];
+ ndbout << " -w" << g_nWarehouseCount;
+ ndbout << " -d" << g_nDistrictPerWarehouse;
+ ndbout << " -s" << (int)nSeconds;
+ ndbout << " -t" << g_nThreadCount;
+ ndbout << endl;
+
+ Ndb* pNdb = NULL ;
+ pNdb = new Ndb("TEST_DB");
+ VerifyMethodInt(pNdb, init());
+ VerifyMethodInt(pNdb, waitUntilReady());
+
+ NdbSchemaCon* pNdbSchemaCon= NdbSchemaCon::startSchemaTrans(pNdb);
+ if(!pNdbSchemaCon){
+ ndbout <<"startSchemaTransaction failed, exiting now" << endl ;
+ delete pNdb ;
+ NDBT_ProgramExit(NDBT_FAILED) ;
+ }
+ NdbSchemaOp* pNdbSchemaOp = NULL ;
+ VerifyMethodPtr(pNdbSchemaOp, pNdbSchemaCon, getNdbSchemaOp());
+#if defined NDB_OSE || defined NDB_SOFTOSE
+ VerifyMethodInt(pNdbSchemaOp, createTable(
+ c_szWarehouse,
+ (4+4+4+12)*1.02*g_nWarehouseCount/1024+1,
+ TupleKey,
+ (4+14)*g_nWarehouseCount/8/1024+1,
+ All,
+ 6,
+ 78,
+ 80,
+ 1,
+ false));
+#else
+ VerifyMethodInt(pNdbSchemaOp, createTable(
+ c_szWarehouse,
+ (4+4+4+12)*1.02*g_nWarehouseCount/1024+1,
+ TupleKey,
+ (4+14)*g_nWarehouseCount/8/1024+1));
+#endif
+ VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szWarehouseNumber, TupleKey, 32, 1, UnSigned, MMBased, false));
+ VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szWarehouseSum, NoKey, 32, 1, UnSigned, MMBased, false));
+ VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szWarehouseCount, NoKey, 32, 1, UnSigned, MMBased, false));
+ VerifyMethodInt(pNdbSchemaCon, execute());
+ NdbSchemaCon::closeSchemaTrans(pNdbSchemaCon);
+
+ pNdbSchemaCon= NdbSchemaCon::startSchemaTrans(pNdb);
+ VerifyMethodPtr(pNdbSchemaOp, pNdbSchemaCon, getNdbSchemaOp());
+#if defined NDB_OSE || defined NDB_SOFTOSE
+ VerifyMethodInt(pNdbSchemaOp, createTable(
+ c_szDistrict,
+ (4+4+4+4+12)*1.02*g_nWarehouseCount*g_nDistrictPerWarehouse/1024+1,
+ TupleKey,
+ (4+4+14)*g_nWarehouseCount*g_nDistrictPerWarehouse/8/1024+1,
+ All,
+ 6,
+ 78,
+ 80,
+ 1,
+ false));
+#else
+ VerifyMethodInt(pNdbSchemaOp, createTable(
+ c_szDistrict,
+ (4+4+4+4+12)*1.02*g_nWarehouseCount*g_nDistrictPerWarehouse/1024+1,
+ TupleKey,
+ (4+4+14)*g_nWarehouseCount*g_nDistrictPerWarehouse/8/1024+1));
+
+#endif
+ VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szDistrictWarehouseNumber, TupleKey, 32, 1, UnSigned, MMBased, false));
+ VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szDistrictNumber, TupleKey, 32, 1, UnSigned, MMBased, false));
+ VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szDistrictSum, NoKey, 32, 1, UnSigned, MMBased, false));
+ VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szDistrictCount, NoKey, 32, 1, UnSigned, MMBased, false));
+ VerifyMethodInt(pNdbSchemaCon, execute());
+ NdbSchemaCon::closeSchemaTrans(pNdbSchemaCon);
+ g_pNdbMutex = NdbMutex_Create();
+ NdbMutex_Lock(g_pNdbMutex);
+
+ NdbThread** ppNdbThread = new NdbThread*[g_nThreadCount*4];
+ for(Uint32 nThread=0; nThread<g_nThreadCount; ++nThread) {
+ ppNdbThread[nThread*4+0] = NdbThread_Create(NdbThreadFuncInsert, 0, 65535, "insert",
+ NDB_THREAD_PRIO_LOW);
+ ppNdbThread[nThread*4+1] = NdbThread_Create(NdbThreadFuncUpdate, 0, 65535, "update",
+ NDB_THREAD_PRIO_LOW);
+ ppNdbThread[nThread*4+2] = NdbThread_Create(NdbThreadFuncDelete, 0, 65535, "delete",
+ NDB_THREAD_PRIO_LOW);
+ ppNdbThread[nThread*4+3] = NdbThread_Create(NdbThreadFuncRead, 0, 65535, "read",
+ NDB_THREAD_PRIO_LOW);
+ }
+
+ NdbSleep_SecSleep(nSeconds);
+ NdbMutex_Unlock(g_pNdbMutex);
+
+ void* pStatus;
+ for(Uint32 nThread=0; nThread<g_nThreadCount; ++nThread) {
+ NdbThread_WaitFor(ppNdbThread[nThread*4+0], &pStatus);
+ NdbThread_WaitFor(ppNdbThread[nThread*4+1], &pStatus);
+ NdbThread_WaitFor(ppNdbThread[nThread*4+2], &pStatus);
+ NdbThread_WaitFor(ppNdbThread[nThread*4+3], &pStatus);
+ }
+
+ NdbMutex_Destroy(g_pNdbMutex);
+ delete[] ppNdbThread;
+ delete pNdb;
+ return NDBT_ProgramExit(rc);
+}
+
diff --git a/ndb/test/ndbapi/acid/acid.cpp b/ndb/test/ndbapi/acid/acid.cpp
deleted file mode 100644
index 49961531a1c..00000000000
--- a/ndb/test/ndbapi/acid/acid.cpp
+++ /dev/null
@@ -1,561 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NdbApi.hpp>
-#include <NdbMutex.h>
-#include <NdbOut.hpp>
-#include <NdbSleep.h>
-#include <NdbThread.h>
-#include <NdbTick.h>
-#include <NdbMain.h>
-#include <NdbTest.hpp>
-#include <random.h>
-
-//#define TRACE
-#define DEBUG
-//#define RELEASE
-#define NODE_REC // epaulsa: introduces pointer checks to help 'acid' keep core
-// during node recovery
-
-#ifdef TRACE
-
-#define VerifyMethodInt(c, m) (ReportMethodInt(c->m, c, #c, #m, __FILE__, __LINE__))
-#define VerifyMethodPtr(v, c, m) (v=ReportMethodPtr(c->m, c, #v, #c, #m, __FILE__, __LINE__))
-#define VerifyMethodVoid(c, m) (c->m, ReportMethodVoid(c, #c, #m, __FILE__, __LINE__))
-
-int ReportMethodInt(int iRes, NdbConnection* pNdbConnection, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
-{
- ndbout << szFile << "(" << iLine << ") : ";
- ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
- ndbout << pNdbConnection->getNdbError();
- NdbOperation* pNdbOperation = pNdbConnection->getNdbErrorOperation();
- if(pNdbOperation) {
- ndbout << " : " << pNdbOperation->getNdbError();
- }
- ndbout << " : " << pNdbConnection->getNdbErrorLine();
- ndbout << endl;
- return iRes;
-}
-
-template <class C>
-int ReportMethodInt(int iRes, C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
-{
- ndbout << szFile << "(" << iLine << ") : ";
- ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
- ndbout << pC->getNdbError();
- ndbout << endl;
- return iRes;
-}
-
-template <class R, class C>
-R* ReportMethodPtr(R* pR, C* pC, const char* szVariable, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
-{
- ndbout << szFile << "(" << iLine << ") : ";
- ndbout << szVariable << " = " << szClass << "->" << szMethod << " return " << (long)(void*)pR << " : ";
- ndbout << pC->getNdbError();
- ndbout << endl;
- return pR;
-}
-
-template <class C>
-void ReportMethodVoid(C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
-{
- ndbout << szFile << "(" << iLine << ") : ";
- ndbout << szClass << "->" << szMethod << " : ";
- ndbout << pC->getNdbError();
- ndbout << endl;
-}
-#endif /* TRACE */
-
-
-#ifdef DEBUG
-
-#define VerifyMethodInt(c, m) (ReportMethodInt(c->m, c, #c, #m, __FILE__, __LINE__))
-#define VerifyMethodPtr(v, c, m) (v=ReportMethodPtr(c->m, c, #v, #c, #m, __FILE__, __LINE__))
-#define VerifyMethodVoid(c, m) (c->m, ReportMethodVoid(c, #c, #m, __FILE__, __LINE__))
-
-int ReportMethodInt(int iRes, NdbConnection* pNdbConnection, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
-{
- if(iRes<0) {
- ndbout << szFile << "(" << iLine << ") : ";
- ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
- ndbout << pNdbConnection->getNdbError();
- NdbOperation* pNdbOperation = pNdbConnection->getNdbErrorOperation();
- if(pNdbOperation) {
- ndbout << " : " << pNdbOperation->getNdbError();
- }
- ndbout << " : " << pNdbConnection->getNdbErrorLine();
- ndbout << " : ";
- ndbout << endl;
- }
- return iRes;
-}
-
-template <class C>
-int ReportMethodInt(int iRes, C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
-{
- if(iRes<0) {
- ndbout << szFile << "(" << iLine << ") : ";
- ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
- ndbout << pC->getNdbError();
- ndbout << endl;
- }
- return iRes;
-}
-
-template <class R, class C>
-R* ReportMethodPtr(R* pR, C* pC, const char* szVariable, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
-{
- if(!pR) {
- ndbout << szFile << "(" << iLine << ") : ";
- ndbout << szVariable << " = " << szClass << "->" << szMethod << " return " << " : ";
- ndbout << pC->getNdbError();
- ndbout << endl;
- }
- return pR;
-}
-
-template <class C>
-void ReportMethodVoid(C* pC, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
-{
- if(pC->getNdbError().code) {
- ndbout << szFile << "(" << iLine << ") : ";
- ndbout << szClass << "->" << szMethod << " : ";
- ndbout << pC->getNdbError();
- ndbout << endl;
- }
-}
-
-
-#endif /* DEBUG */
-
-
-#ifdef RELEASE
-
-#define VerifyMethodInt(c, m) (c->m)
-#define VerifyMethodPtr(v, c, m) (v=(c->m))
-#define VerifyMethodVoid(c, m) (c->m)
-
-int ReportMethodInt(int iRes, NdbConnection* pNdbConnection, const char* szClass, const char* szMethod, const char* szFile, const int iLine)
-{
- if(iRes<0) {
- ndbout << szFile << "(" << iLine << ") : ";
- ndbout << szClass << "->" << szMethod << " return " << iRes << " : ";
- ndbout << pNdbConnection->getNdbError();
- NdbOperation* pNdbOperation = pNdbConnection->getNdbErrorOperation();
- if(pNdbOperation) {
- ndbout << " : " << pNdbOperation->getNdbError();
- }
- ndbout << " : " << pNdbConnection->getNdbErrorLine();
- ndbout << endl;
- }
- return iRes;
-}
-
-#endif /* RELEASE */
-
-// epaulsa =>
-#ifndef NODE_REC
-#define CHK_TR(p)
-#else
-#define CHK_TR(p) if(!p){ \
- ndbout <<"startTransaction failed, returning now." << endl ; \
- delete pNdb ; \
- pNdb = NULL ; \
- return 0 ; \
- }
-#endif // NODE_REC
-// <= epaulsa
-
-const char* c_szWarehouse = "WAREHOUSE";
-const char* c_szWarehouseNumber = "W_ID";
-const char* c_szWarehouseSum = "W_SUM";
-const char* c_szWarehouseCount = "W_CNT";
-const char* c_szDistrict = "DISTRICT";
-const char* c_szDistrictWarehouseNumber = "D_W_ID";
-const char* c_szDistrictNumber = "D_ID";
-const char* c_szDistrictSum = "D_SUM";
-const char* c_szDistrictCount = "D_CNT";
-
-Uint32 g_nWarehouseCount = 10;
-Uint32 g_nDistrictPerWarehouse = 10;
-Uint32 g_nThreadCount = 1;
-NdbMutex* g_pNdbMutex = 0;
-
-extern "C" void* NdbThreadFuncInsert(void* pArg)
-{
- myRandom48Init((long int)NdbTick_CurrentMillisecond());
- unsigned nSucc = 0;
- unsigned nFail = 0;
- Ndb* pNdb = NULL ;
- pNdb = new Ndb("TEST_DB");
- VerifyMethodInt(pNdb, init());
- VerifyMethodInt(pNdb, waitUntilReady());
-
- while(NdbMutex_Trylock(g_pNdbMutex)) {
- Uint32 nWarehouse = myRandom48(g_nWarehouseCount);
- NdbConnection* pNdbConnection = NULL ;
- VerifyMethodPtr(pNdbConnection, pNdb, startTransaction());
- CHK_TR(pNdbConnection);
- NdbOperation* pNdbOperationW = NULL ;
- VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse));
- VerifyMethodInt(pNdbOperationW, insertTuple());
- VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse));
- VerifyMethodInt(pNdbOperationW, setValue(c_szWarehouseCount, Uint32(1)));
- Uint32 nWarehouseSum = 0;
- for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
- NdbOperation* pNdbOperationD = NULL ;
- VerifyMethodPtr(pNdbOperationD, pNdbConnection, getNdbOperation(c_szDistrict));
- VerifyMethodInt(pNdbOperationD, insertTuple());
- VerifyMethodInt(pNdbOperationD, equal(c_szDistrictWarehouseNumber, nWarehouse));
- VerifyMethodInt(pNdbOperationD, equal(c_szDistrictNumber, nDistrict));
- VerifyMethodInt(pNdbOperationD, setValue(c_szDistrictCount, Uint32(1)));
- Uint32 nDistrictSum = myRandom48(100);
- nWarehouseSum += nDistrictSum;
- VerifyMethodInt(pNdbOperationD, setValue(c_szDistrictSum, nDistrictSum));
- }
- VerifyMethodInt(pNdbOperationW, setValue(c_szWarehouseSum, nWarehouseSum));
- int iExec = pNdbConnection->execute(Commit);
- int iError = pNdbConnection->getNdbError().code;
- CommitStatusType cs = pNdbConnection->commitStatus();
-
- if(iExec<0 && iError!=0 && iError!=266 && iError!=630) {
- ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__);
- }
- if(iExec==0) {
- ++nSucc;
- } else {
- ++nFail;
- }
- VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
- }
- ndbout << "insert: " << nSucc << " succeeded, " << nFail << " failed " << endl;
- NdbMutex_Unlock(g_pNdbMutex);
- delete pNdb;
- pNdb = NULL ;
- return NULL;
-}
-
-
-extern "C" void* NdbThreadFuncUpdate(void* pArg)
-{
- myRandom48Init((long int)NdbTick_CurrentMillisecond());
- unsigned nSucc = 0;
- unsigned nFail = 0;
- Ndb* pNdb = NULL ;
- pNdb = new Ndb("TEST_DB");
- VerifyMethodInt(pNdb, init());
- VerifyMethodInt(pNdb, waitUntilReady());
-
- while(NdbMutex_Trylock(g_pNdbMutex)) {
- Uint32 nWarehouse = myRandom48(g_nWarehouseCount);
- NdbConnection* pNdbConnection = NULL ;
- VerifyMethodPtr(pNdbConnection, pNdb, startTransaction());
- CHK_TR(pNdbConnection) ; // epaulsa
- NdbOperation* pNdbOperationW = NULL ;
- VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse));
- VerifyMethodInt(pNdbOperationW, interpretedUpdateTuple());
- VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse));
- VerifyMethodInt(pNdbOperationW, incValue(c_szWarehouseCount, Uint32(1)));
- Uint32 nWarehouseSum = 0;
- for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
- NdbOperation* pNdbOperationD = NULL ;
- VerifyMethodPtr(pNdbOperationD, pNdbConnection, getNdbOperation(c_szDistrict));
- VerifyMethodInt(pNdbOperationD, interpretedUpdateTuple());
- VerifyMethodInt(pNdbOperationD, equal(c_szDistrictWarehouseNumber, nWarehouse));
- VerifyMethodInt(pNdbOperationD, equal(c_szDistrictNumber, nDistrict));
- VerifyMethodInt(pNdbOperationD, incValue(c_szDistrictCount, Uint32(1)));
- Uint32 nDistrictSum = myRandom48(100);
- nWarehouseSum += nDistrictSum;
- VerifyMethodInt(pNdbOperationD, setValue(c_szDistrictSum, nDistrictSum));
- }
- VerifyMethodInt(pNdbOperationW, setValue(c_szWarehouseSum, nWarehouseSum));
- int iExec = pNdbConnection->execute(Commit);
- int iError = pNdbConnection->getNdbError().code;
- CommitStatusType cs = pNdbConnection->commitStatus();
-
- if(iExec<0 && iError!=0 && iError!=266 && iError!=626) {
- ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__);
- }
- if(iExec==0) {
- ++nSucc;
- } else {
- ++nFail;
- }
- VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
- }
- ndbout << "update: " << nSucc << " succeeded, " << nFail << " failed " << endl;
- NdbMutex_Unlock(g_pNdbMutex);
- delete pNdb;
- pNdb = NULL ;
- return NULL;
-}
-
-
-extern "C" void* NdbThreadFuncDelete(void* pArg)
-{
- myRandom48Init((long int)NdbTick_CurrentMillisecond());
- unsigned nSucc = 0;
- unsigned nFail = 0;
- Ndb* pNdb = NULL ;
- pNdb = new Ndb("TEST_DB");
- VerifyMethodInt(pNdb, init());
- VerifyMethodInt(pNdb, waitUntilReady());
-
- while(NdbMutex_Trylock(g_pNdbMutex)) {
- Uint32 nWarehouse = myRandom48(g_nWarehouseCount);
- NdbConnection* pNdbConnection = NULL ;
- VerifyMethodPtr(pNdbConnection, pNdb, startTransaction());
- CHK_TR(pNdbConnection) ; // epaulsa
- NdbOperation* pNdbOperationW = NULL ;
- VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse));
- VerifyMethodInt(pNdbOperationW, deleteTuple());
- VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse));
- for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
- NdbOperation* pNdbOperationD = NULL ;
- VerifyMethodPtr(pNdbOperationD, pNdbConnection, getNdbOperation(c_szDistrict));
- VerifyMethodInt(pNdbOperationD, deleteTuple());
- VerifyMethodInt(pNdbOperationD, equal(c_szDistrictWarehouseNumber, nWarehouse));
- VerifyMethodInt(pNdbOperationD, equal(c_szDistrictNumber, nDistrict));
- }
- int iExec = pNdbConnection->execute(Commit);
- int iError = pNdbConnection->getNdbError().code;
- CommitStatusType cs = pNdbConnection->commitStatus();
-
- if(iExec<0 && iError!=0 && iError!=266 && iError!=626) {
- ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__);
- }
- if(iExec==0) {
- ++nSucc;
- } else {
- ++nFail;
- }
- VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
- }
- ndbout << "delete: " << nSucc << " succeeded, " << nFail << " failed " << endl;
- NdbMutex_Unlock(g_pNdbMutex);
- delete pNdb;
- pNdb = NULL ;
- return NULL;
-}
-
-
-extern "C" void* NdbThreadFuncRead(void* pArg)
-{
- myRandom48Init((long int)NdbTick_CurrentMillisecond());
- unsigned nSucc = 0;
- unsigned nFail = 0;
- NdbRecAttr** ppNdbRecAttrDSum = new NdbRecAttr*[g_nDistrictPerWarehouse];
- NdbRecAttr** ppNdbRecAttrDCnt = new NdbRecAttr*[g_nDistrictPerWarehouse];
- Ndb* pNdb = NULL ;
- pNdb = new Ndb("TEST_DB");
- VerifyMethodInt(pNdb, init());
- VerifyMethodInt(pNdb, waitUntilReady());
-
- while(NdbMutex_Trylock(g_pNdbMutex)) {
- Uint32 nWarehouse = myRandom48(g_nWarehouseCount);
- NdbConnection* pNdbConnection = NULL ;
- VerifyMethodPtr(pNdbConnection, pNdb, startTransaction());
- CHK_TR(pNdbConnection) ; // epaulsa
- NdbOperation* pNdbOperationW = NULL ;
- VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse));
- VerifyMethodInt(pNdbOperationW, readTuple());
- VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse));
- NdbRecAttr* pNdbRecAttrWSum;
- VerifyMethodPtr(pNdbRecAttrWSum, pNdbOperationW, getValue(c_szWarehouseSum, 0));
- NdbRecAttr* pNdbRecAttrWCnt;
- VerifyMethodPtr(pNdbRecAttrWCnt, pNdbOperationW, getValue(c_szWarehouseCount, 0));
- for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
- NdbOperation* pNdbOperationD = NULL ;
- VerifyMethodPtr(pNdbOperationD, pNdbConnection, getNdbOperation(c_szDistrict));
- VerifyMethodInt(pNdbOperationD, readTuple());
- VerifyMethodInt(pNdbOperationD, equal(c_szDistrictWarehouseNumber, nWarehouse));
- VerifyMethodInt(pNdbOperationD, equal(c_szDistrictNumber, nDistrict));
- VerifyMethodPtr(ppNdbRecAttrDSum[nDistrict], pNdbOperationD, getValue(c_szDistrictSum, 0));
- VerifyMethodPtr(ppNdbRecAttrDCnt[nDistrict], pNdbOperationD, getValue(c_szDistrictCount, 0));
- }
- int iExec = pNdbConnection->execute(Commit);
- int iError = pNdbConnection->getNdbError().code;
- CommitStatusType cs = pNdbConnection->commitStatus();
- if(iExec<0 && iError!=0 && iError!=266 && iError!=626) {
- ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__);
- }
- if(iExec==0) {
- Uint32 nSum = 0;
- Uint32 nCnt = 0;
- for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
- nSum += ppNdbRecAttrDSum[nDistrict]->u_32_value();
- nCnt += ppNdbRecAttrDCnt[nDistrict]->u_32_value();
- }
- if(nSum!=pNdbRecAttrWSum->u_32_value()
- || nCnt!=g_nDistrictPerWarehouse*pNdbRecAttrWCnt->u_32_value()) {
- ndbout << "INCONSISTENT!" << endl;
- ndbout << "iExec==" << iExec << endl;
- ndbout << "iError==" << iError << endl;
- ndbout << endl;
- ndbout << c_szWarehouseSum << "==" << pNdbRecAttrWSum->u_32_value() << ", ";
- ndbout << c_szWarehouseCount << "==" << pNdbRecAttrWCnt->u_32_value() << endl;
- ndbout << "nSum==" << nSum << ", nCnt=" << nCnt << endl;
- for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
- ndbout << c_szDistrictSum << "[" << nDistrict << "]==" << ppNdbRecAttrDSum[nDistrict]->u_32_value() << ", ";
- ndbout << c_szDistrictCount << "[" << nDistrict << "]==" << ppNdbRecAttrDCnt[nDistrict]->u_32_value() << endl;
- }
- VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
- delete pNdb; pNdb = NULL ;
- delete[] ppNdbRecAttrDSum; ppNdbRecAttrDSum = NULL ;
- delete[] ppNdbRecAttrDCnt; ppNdbRecAttrDCnt = NULL ;
- NDBT_ProgramExit(NDBT_FAILED);
- }
- ++nSucc;
- } else {
- ++nFail;
- }
- VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
- }
- ndbout << "read: " << nSucc << " succeeded, " << nFail << " failed " << endl;
- NdbMutex_Unlock(g_pNdbMutex);
- delete pNdb; pNdb = NULL ;
- delete[] ppNdbRecAttrDSum; ppNdbRecAttrDSum = NULL ;
- delete[] ppNdbRecAttrDCnt; ppNdbRecAttrDCnt = NULL ;
- return NULL;
-}
-
-
-NDB_COMMAND(acid, "acid", "acid", "acid", 65535)
-{
- long nSeconds = 60;
- int rc = NDBT_OK;
-
- for(int i=1; i<argc; ++i) {
- if(argv[i][0]=='-' || argv[i][0]=='/') {
- switch(argv[i][1]) {
- case 'w': g_nWarehouseCount=atol(argv[i]+2); break;
- case 'd': g_nDistrictPerWarehouse=atol(argv[i]+2); break;
- case 's': nSeconds=atol(argv[i]+2); break;
- case 't': g_nThreadCount=atol(argv[i]+2); break;
- default: ndbout << "invalid option" << endl; return 1;
- }
- } else {
- ndbout << "invalid operand" << endl;
- return 1;
- }
- }
- ndbout << argv[0];
- ndbout << " -w" << g_nWarehouseCount;
- ndbout << " -d" << g_nDistrictPerWarehouse;
- ndbout << " -s" << (int)nSeconds;
- ndbout << " -t" << g_nThreadCount;
- ndbout << endl;
-
- Ndb* pNdb = NULL ;
- pNdb = new Ndb("TEST_DB");
- VerifyMethodInt(pNdb, init());
- VerifyMethodInt(pNdb, waitUntilReady());
-
- NdbSchemaCon* pNdbSchemaCon = NULL ;
- VerifyMethodPtr(pNdbSchemaCon, pNdb, startSchemaTransaction());
- if(!pNdbSchemaCon){
- ndbout <<"startSchemaTransaction failed, exiting now" << endl ;
- delete pNdb ;
- NDBT_ProgramExit(NDBT_FAILED) ;
- }
- NdbSchemaOp* pNdbSchemaOp = NULL ;
- VerifyMethodPtr(pNdbSchemaOp, pNdbSchemaCon, getNdbSchemaOp());
-#if defined NDB_OSE || defined NDB_SOFTOSE
- VerifyMethodInt(pNdbSchemaOp, createTable(
- c_szWarehouse,
- (4+4+4+12)*1.02*g_nWarehouseCount/1024+1,
- TupleKey,
- (4+14)*g_nWarehouseCount/8/1024+1,
- All,
- 6,
- 78,
- 80,
- 1,
- false));
-#else
- VerifyMethodInt(pNdbSchemaOp, createTable(
- c_szWarehouse,
- (4+4+4+12)*1.02*g_nWarehouseCount/1024+1,
- TupleKey,
- (4+14)*g_nWarehouseCount/8/1024+1));
-#endif
- VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szWarehouseNumber, TupleKey, 32, 1, UnSigned, MMBased, false));
- VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szWarehouseSum, NoKey, 32, 1, UnSigned, MMBased, false));
- VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szWarehouseCount, NoKey, 32, 1, UnSigned, MMBased, false));
- VerifyMethodInt(pNdbSchemaCon, execute());
- VerifyMethodVoid(pNdb, closeSchemaTransaction(pNdbSchemaCon));
-
- VerifyMethodPtr(pNdbSchemaCon, pNdb, startSchemaTransaction());
- VerifyMethodPtr(pNdbSchemaOp, pNdbSchemaCon, getNdbSchemaOp());
-#if defined NDB_OSE || defined NDB_SOFTOSE
- VerifyMethodInt(pNdbSchemaOp, createTable(
- c_szDistrict,
- (4+4+4+4+12)*1.02*g_nWarehouseCount*g_nDistrictPerWarehouse/1024+1,
- TupleKey,
- (4+4+14)*g_nWarehouseCount*g_nDistrictPerWarehouse/8/1024+1,
- All,
- 6,
- 78,
- 80,
- 1,
- false));
-#else
- VerifyMethodInt(pNdbSchemaOp, createTable(
- c_szDistrict,
- (4+4+4+4+12)*1.02*g_nWarehouseCount*g_nDistrictPerWarehouse/1024+1,
- TupleKey,
- (4+4+14)*g_nWarehouseCount*g_nDistrictPerWarehouse/8/1024+1));
-
-#endif
- VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szDistrictWarehouseNumber, TupleKey, 32, 1, UnSigned, MMBased, false));
- VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szDistrictNumber, TupleKey, 32, 1, UnSigned, MMBased, false));
- VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szDistrictSum, NoKey, 32, 1, UnSigned, MMBased, false));
- VerifyMethodInt(pNdbSchemaOp, createAttribute(c_szDistrictCount, NoKey, 32, 1, UnSigned, MMBased, false));
- VerifyMethodInt(pNdbSchemaCon, execute());
- VerifyMethodVoid(pNdb, closeSchemaTransaction(pNdbSchemaCon));
- g_pNdbMutex = NdbMutex_Create();
- NdbMutex_Lock(g_pNdbMutex);
-
- NdbThread** ppNdbThread = new NdbThread*[g_nThreadCount*4];
- for(Uint32 nThread=0; nThread<g_nThreadCount; ++nThread) {
- ppNdbThread[nThread*4+0] = NdbThread_Create(NdbThreadFuncInsert, 0, 65535, "insert",
- NDB_THREAD_PRIO_LOW);
- ppNdbThread[nThread*4+1] = NdbThread_Create(NdbThreadFuncUpdate, 0, 65535, "update",
- NDB_THREAD_PRIO_LOW);
- ppNdbThread[nThread*4+2] = NdbThread_Create(NdbThreadFuncDelete, 0, 65535, "delete",
- NDB_THREAD_PRIO_LOW);
- ppNdbThread[nThread*4+3] = NdbThread_Create(NdbThreadFuncRead, 0, 65535, "read",
- NDB_THREAD_PRIO_LOW);
- }
-
- NdbSleep_SecSleep(nSeconds);
- NdbMutex_Unlock(g_pNdbMutex);
-
- void* pStatus;
- for(Uint32 nThread=0; nThread<g_nThreadCount; ++nThread) {
- NdbThread_WaitFor(ppNdbThread[nThread*4+0], &pStatus);
- NdbThread_WaitFor(ppNdbThread[nThread*4+1], &pStatus);
- NdbThread_WaitFor(ppNdbThread[nThread*4+2], &pStatus);
- NdbThread_WaitFor(ppNdbThread[nThread*4+3], &pStatus);
- }
-
- NdbMutex_Destroy(g_pNdbMutex);
- delete[] ppNdbThread;
- delete pNdb;
- return NDBT_ProgramExit(rc);
-}
-
diff --git a/ndb/test/ndbapi/acid2/acid2.cpp b/ndb/test/ndbapi/acid2.cpp
index 434a0450daa..434a0450daa 100644
--- a/ndb/test/ndbapi/acid2/acid2.cpp
+++ b/ndb/test/ndbapi/acid2.cpp
diff --git a/ndb/test/ndbapi/telco/adoInsertRecs.cpp b/ndb/test/ndbapi/adoInsertRecs.cpp
index 0bc67ef641b..0bc67ef641b 100644
--- a/ndb/test/ndbapi/telco/adoInsertRecs.cpp
+++ b/ndb/test/ndbapi/adoInsertRecs.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/generator/asyncGenerator.cpp b/ndb/test/ndbapi/asyncGenerator.cpp
index 84a93414712..84a93414712 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/generator/asyncGenerator.cpp
+++ b/ndb/test/ndbapi/asyncGenerator.cpp
diff --git a/ndb/test/ndbapi/bank/Bank.cpp b/ndb/test/ndbapi/bank/Bank.cpp
new file mode 100644
index 00000000000..14883205693
--- /dev/null
+++ b/ndb/test/ndbapi/bank/Bank.cpp
@@ -0,0 +1,2458 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Bank.hpp"
+#include <time.h>
+#include <NdbSleep.h>
+#include <UtilTransactions.hpp>
+
+Bank::Bank():
+ m_ndb("BANK"),
+ m_maxAccount(-1),
+ m_initialized(false)
+{
+
+}
+
+int Bank::init(){
+ if (m_initialized == true)
+ return NDBT_OK;
+
+ myRandom48Init(NdbTick_CurrentMillisecond());
+
+ m_ndb.init();
+ while (m_ndb.waitUntilReady(10) != 0)
+ ndbout << "Waiting for ndb to be ready" << endl;
+
+ if (getNumAccounts() != NDBT_OK)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+int Bank::performTransactions(int maxSleepBetweenTrans, int yield){
+
+ if (init() != NDBT_OK)
+ return NDBT_FAILED;
+ int transactions = 0;
+
+ while(1){
+
+ while(m_ndb.waitUntilReady(10) != 0)
+ ndbout << "Waiting for ndb to be ready" << endl;
+
+ while(performTransaction() != NDBT_FAILED){
+ transactions++;
+
+ if (maxSleepBetweenTrans > 0){
+ int val = myRandom48(maxSleepBetweenTrans);
+ NdbSleep_MilliSleep(val);
+ }
+
+ if((transactions % 100) == 0)
+ g_info << transactions << endl;
+
+ if (yield != 0 && transactions >= yield)
+ return NDBT_OK;
+ }
+ }
+ return NDBT_FAILED;
+
+}
+
+int Bank::performTransaction(){
+ int result = NDBT_OK;
+
+ if (m_maxAccount <= 0){
+ g_err << "No accounts in bank" << endl;
+ return NDBT_FAILED;
+ }
+
+ int fromAccount = myRandom48(m_maxAccount);
+ int toAccount = myRandom48(m_maxAccount);
+
+ if (fromAccount == toAccount){
+ // Increase toAccount with 1
+ toAccount = (toAccount+1)%m_maxAccount;
+ }
+
+ int maxAmount = getMaxAmount();
+
+ int amount = myRandom48(maxAmount);
+
+ retry_transaction:
+ int res = performTransaction(fromAccount, toAccount, amount);
+ if (res != 0){
+ switch (res){
+ case NDBT_FAILED:
+ g_err << "performTransaction returned NDBT_FAILED" << endl
+ << " fromAccount = " << fromAccount << endl
+ << " toAccount = " << toAccount << endl
+ << " amount = " << amount << endl;
+ result = NDBT_FAILED;
+ break;
+ case NOT_ENOUGH_FUNDS:
+ // ndbout << "performTransaction returned NOT_ENOUGH_FUNDS" << endl;
+ break;
+ case NDBT_TEMPORARY:
+ g_err << "TEMPORARY_ERRROR retrying" << endl;
+ goto retry_transaction;
+ break;
+ default:
+ g_info << "performTransaction returned "<<res << endl;
+ break;
+ }
+ }
+ return result;
+}
+
+/**
+ * Perform a transaction in the bank.
+ * Ie. transfer money from one account to another.
+ *
+ * @param
+ * @return 0 if successful or an error code
+ */
+int Bank::performTransaction(int fromAccountId,
+ int toAccountId,
+ int amount ){
+ /**
+ * 1. Start transaction
+ * 2. Check balance on from account, if there is
+ * not enough funds abort transaction
+ * 3. Update ACCOUNT set balance = balance - amount on
+ * from account
+ * 4. Insert withdrawal in TRANSACTION
+ * 5. Insert deposit in transaction
+ * 6. Update ACCOUNT set balance = balance + amount on
+ * to account
+ * 7. Commit transaction
+ */
+ // g_info << "performTransaction " << fromAccountId
+ // << ", "<<toAccountId<<", "<<amount << endl;
+
+ // Call the first implementation of this trans
+ // In the future we can have several different versions of this trans
+ // and call them randomly
+ return performTransactionImpl1(fromAccountId, toAccountId, amount);
+}
+
+
+int Bank::performTransactionImpl1(int fromAccountId,
+ int toAccountId,
+ int amount ){
+
+ int check;
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if( pTrans == NULL ) {
+ const NdbError err = m_ndb.getNdbError();
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ return NDBT_TEMPORARY;
+ }
+ ERR(err);
+ return NDBT_FAILED;
+ }
+
+ /**
+ * Check balance on from account
+ */
+ NdbOperation* pOp = pTrans->getNdbOperation("ACCOUNT");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->readTupleExclusive();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("ACCOUNT_ID", fromAccountId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* balanceFromRec = pOp->getValue("BALANCE");
+ if( balanceFromRec ==NULL ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* fromAccountTypeRec = pOp->getValue("ACCOUNT_TYPE");
+ if( fromAccountTypeRec == NULL ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ const NdbError err = pTrans->getNdbError();
+ m_ndb.closeTransaction(pTrans);
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ return NDBT_TEMPORARY;
+ }
+ ERR(err);
+ return NDBT_FAILED;
+ }
+
+ Uint32 balanceFrom = balanceFromRec->u_32_value();
+ // ndbout << "balanceFrom: " << balanceFrom << endl;
+
+ if (((Int64)balanceFrom - amount) < 0){
+ m_ndb.closeTransaction(pTrans);
+ //ndbout << "Not enough funds" << endl;
+ return NOT_ENOUGH_FUNDS;
+ }
+
+ Uint32 fromAccountType = fromAccountTypeRec->u_32_value();
+
+ /**
+ * Read balance on to account
+ */
+ NdbOperation* pOp6 = pTrans->getNdbOperation("ACCOUNT");
+ if (pOp6 == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp6->readTupleExclusive();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp6->equal("ACCOUNT_ID", toAccountId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* balanceToRec = pOp6->getValue("BALANCE");
+ if( balanceToRec == NULL ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* toAccountTypeRec = pOp6->getValue("ACCOUNT_TYPE");
+ if( toAccountTypeRec == NULL ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ const NdbError err = pTrans->getNdbError();
+ m_ndb.closeTransaction(pTrans);
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ return NDBT_TEMPORARY;
+ }
+ ERR(err);
+ return NDBT_FAILED;
+ }
+
+ Uint32 balanceTo = balanceToRec->u_32_value();
+ // ndbout << "balanceTo: " << balanceTo << endl;
+ Uint32 toAccountType = toAccountTypeRec->u_32_value();
+
+ // Ok, all clear to do the transaction
+ Uint64 transId;
+ if (getNextTransactionId(transId) != NDBT_OK){
+ return NDBT_FAILED;
+ }
+
+ Uint64 currTime;
+ if (getCurrTime(currTime) != NDBT_OK){
+ return NDBT_FAILED;
+ }
+
+ /**
+ * Update balance on from account
+ */
+ NdbOperation* pOp2 = pTrans->getNdbOperation("ACCOUNT");
+ if (pOp2 == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp2->updateTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp2->equal("ACCOUNT_ID", fromAccountId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp2->setValue("BALANCE", balanceFrom - amount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ /**
+ * Update balance on to account
+ */
+ NdbOperation* pOp3 = pTrans->getNdbOperation("ACCOUNT");
+ if (pOp3 == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->updateTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->equal("ACCOUNT_ID", toAccountId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->setValue("BALANCE", balanceTo + amount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ /**
+ * Insert withdrawal transaction
+ */
+ NdbOperation* pOp4 = pTrans->getNdbOperation("TRANSACTION");
+ if (pOp4 == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp4->insertTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp4->equal("TRANSACTION_ID", transId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp4->equal("ACCOUNT", fromAccountId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp4->setValue("ACCOUNT_TYPE", fromAccountType);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp4->setValue("OTHER_ACCOUNT", toAccountId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp4->setValue("TRANSACTION_TYPE", WithDrawal);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp4->setValue("TIME", currTime);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp4->setValue("AMOUNT", amount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ /**
+ * Insert deposit transaction
+ */
+ NdbOperation* pOp5 = pTrans->getNdbOperation("TRANSACTION");
+ if (pOp5 == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp5->insertTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp5->equal("TRANSACTION_ID", transId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp5->equal("ACCOUNT", toAccountId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp5->setValue("ACCOUNT_TYPE", toAccountType);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp5->setValue("OTHER_ACCOUNT", fromAccountId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp5->setValue("TRANSACTION_TYPE", Deposit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp5->setValue("TIME", currTime);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp5->setValue("AMOUNT", amount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ const NdbError err = pTrans->getNdbError();
+ m_ndb.closeTransaction(pTrans);
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ return NDBT_TEMPORARY;
+ }
+ ERR(err);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_OK;
+}
+
+
+
+
+int Bank::performMakeGLs(int yield){
+ int result;
+ if (init() != NDBT_OK)
+ return NDBT_FAILED;
+
+ int counter, maxCounter;
+ int yieldCounter = 0;
+
+ while (1){
+ // Counters to keep tracck of how many
+ // GLs should be made before performing a validation
+ counter = 0;
+ maxCounter = 50 + myRandom48(100);
+
+ while(m_ndb.waitUntilReady(10) != 0)
+ ndbout << "Waiting for ndb to be ready" << endl;
+
+ /**
+ * Validate GLs and Transactions for previous days
+ *
+ */
+ result = performValidateGLs();
+ if (result != NDBT_OK){
+ if (result == VERIFICATION_FAILED){
+ g_err << "performValidateGLs verification failed" << endl;
+ return NDBT_FAILED;
+ }
+ g_info << "performValidateGLs failed" << endl;
+ continue;
+ }
+
+ result = performValidatePurged();
+ if (result != NDBT_OK){
+ if (result == VERIFICATION_FAILED){
+ g_err << "performValidatePurged verification failed" << endl;
+ return NDBT_FAILED;
+ }
+ g_info << "performValidatePurged failed" << endl;
+ continue;
+ }
+
+ while (1){
+
+ yieldCounter++;
+ if (yield != 0 && yieldCounter >= yield)
+ return NDBT_OK;
+
+ /**
+ * Find last GL time.
+ * ( GL record with highest time value)
+ */
+ Uint64 lastGLTime;
+ if (findLastGL(lastGLTime) != NDBT_OK){
+ g_info << "findLastGL failed" << endl;
+ // Break out of inner while loop
+ break;
+ }
+
+ lastGLTime++;
+
+ /**
+ * If last GL time + 1 is smaller than current time
+ * perform a GL for that time
+ */
+ Uint64 currTime;
+ if (getCurrTime(currTime) != NDBT_OK){
+ g_info << "getCurrTime failed" << endl;
+ // Break out of inner while loop
+ break;
+ }
+ if (lastGLTime < currTime){
+ counter++;
+ if (performMakeGL(lastGLTime) != NDBT_OK){
+ g_info << "performMakeGL failed" << endl;
+ // Break out of inner while loop
+ break;
+ }
+
+ if (counter > maxCounter){
+ // Break out of inner while loop and
+ // validatePreviousGLs
+ g_info << "counter("<<counter<<") > maxCounter("<<maxCounter<<")" << endl;
+ break;
+ }
+
+ } else {
+ ;//ndbout << "It's not time to make GL yet" << endl;
+
+ // ndbout << "Sleeping 1 second" << endl;
+ NdbSleep_SecSleep(1);
+
+ }
+
+ Uint32 age = 3;
+ if (purgeOldGLTransactions(currTime, age) != NDBT_OK){
+ g_info << "purgeOldGLTransactions failed" << endl;
+ // Break out of inner while loop
+ break;
+ }
+
+ }
+ }
+
+ return NDBT_FAILED;
+
+}
+
+int Bank::performValidateAllGLs(){
+ int result;
+ if (init() != NDBT_OK)
+ return NDBT_FAILED;
+
+ while (1){
+
+ while(m_ndb.waitUntilReady(10) != 0)
+ ndbout << "Waiting for ndb to be ready" << endl;
+
+ /**
+ * Validate GLs and Transactions for previous days
+ * Set age so that ALL GL's are validated
+ */
+ int age = 100000;
+ result = performValidateGLs(age);
+ if (result != NDBT_OK){
+ if (result == VERIFICATION_FAILED){
+ g_err << "performValidateGLs verification failed" << endl;
+ return NDBT_FAILED;
+ }
+ g_err << "performValidateGLs failed" << endl;
+ return NDBT_FAILED;
+ }
+
+ /**
+ *
+ *
+ */
+ result = performValidatePurged();
+ if (result != NDBT_OK){
+ if (result == VERIFICATION_FAILED){
+ g_err << "performValidatePurged verification failed" << endl;
+ return NDBT_FAILED;
+ }
+ g_err << "performValidatePurged failed" << endl;
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+ }
+
+ return NDBT_FAILED;
+
+}
+
+int Bank::findLastGL(Uint64 &lastTime){
+
+ int check;
+ /**
+ * SELECT MAX(time) FROM GL
+ */
+ NdbConnection* pScanTrans = m_ndb.startTransaction();
+ if (pScanTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
+ if (pOp == NULL) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->openScanRead(64);
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* timeRec = pOp->getValue("TIME");
+ if( timeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pScanTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ eof = pScanTrans->nextScanResult();
+ lastTime = 0;
+
+ while(eof == 0){
+ rows++;
+ Uint64 t = timeRec->u_32_value();
+
+ if (t > lastTime)
+ lastTime = t;
+
+ eof = pScanTrans->nextScanResult();
+ }
+ if (eof == -1) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pScanTrans);
+
+ return NDBT_OK;
+}
+
+
+int Bank::performMakeGL(int time){
+ g_info << "performMakeGL: " << time << endl;
+ /**
+ * Create one GL record for each account type.
+ * All in the same transaction
+ */
+ // Start transaction
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL){
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+ for (int i = 0; i < getNumAccountTypes(); i++){
+
+ if (performMakeGLForAccountType(pTrans, time, i) != NDBT_OK){
+ g_err << "performMakeGLForAccountType returned NDBT_FAILED"<<endl;
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+ }
+ // Execute transaction
+ if( pTrans->execute(Commit) == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+ m_ndb.closeTransaction(pTrans);
+
+ return NDBT_OK;
+}
+
+int Bank::performMakeGLForAccountType(NdbConnection* pTrans,
+ Uint64 glTime,
+ Uint32 accountTypeId){
+ int check;
+
+ Uint32 balance = 0;
+ Uint32 withdrawalCount = 0;
+ Uint32 withdrawalSum = 0;
+ Uint32 depositSum = 0;
+ Uint32 depositCount = 0;
+ Uint32 countTransactions = 0;
+ Uint32 purged = 0;
+
+ // Insert record in GL so that we know
+ // that no one else is performing the same task
+ // Set purged = 0 to indicate that TRANSACTION
+ // records still exist
+ NdbOperation* pOp = pTrans->getNdbOperation("GL");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->insertTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("TIME", glTime);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->setValue("BALANCE", balance);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->setValue("DEPOSIT_COUNT", depositCount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->setValue("DEPOSIT_SUM", depositSum);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->setValue("WITHDRAWAL_COUNT", withdrawalCount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->setValue("WITHDRAWAL_SUM", withdrawalSum);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->setValue("PURGED", purged);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ ERR(pOp->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ // Read previous GL record to get old balance
+ NdbOperation* pOp2 = pTrans->getNdbOperation("GL");
+ if (pOp2 == NULL) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp2->readTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp2->equal("TIME", glTime-1);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp2->equal("ACCOUNT_TYPE", accountTypeId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* oldBalanceRec = pOp2->getValue("BALANCE");
+ if( oldBalanceRec == NULL ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ ERR(pOp2->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ Uint32 oldBalance = oldBalanceRec->u_32_value();
+ // ndbout << "oldBalance = "<<oldBalance<<endl;
+ balance = oldBalance;
+ // Start a scan transaction to search
+ // for TRANSACTION records with TIME = time
+ // and ACCOUNT_TYPE = accountTypeId
+ // Build sum of all found transactions
+
+ if (sumTransactionsForGL(glTime,
+ accountTypeId,
+ balance,
+ withdrawalCount,
+ withdrawalSum,
+ depositSum,
+ depositCount,
+ countTransactions,
+ pTrans) != NDBT_OK){
+ return NDBT_FAILED;
+ }
+ // ndbout << "sumTransactionsForGL completed" << endl;
+ // ndbout << "balance="<<balance<<endl
+ // << "withdrawalCount="<<withdrawalCount<<endl
+ // << "withdrawalSum="<<withdrawalSum<<endl
+ // << "depositCount="<<depositCount<<endl
+ // << "depositSum="<<depositSum<<endl;
+
+
+
+ NdbOperation* pOp3 = pTrans->getNdbOperation("GL");
+ if (pOp3 == NULL) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->updateTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->equal("TIME", glTime);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->equal("ACCOUNT_TYPE", accountTypeId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->setValue("BALANCE", balance);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->setValue("DEPOSIT_COUNT", depositCount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->setValue("DEPOSIT_SUM", depositSum);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->setValue("WITHDRAWAL_COUNT", withdrawalCount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->setValue("WITHDRAWAL_SUM", withdrawalSum);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->setValue("PURGED", purged);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ // Execute transaction
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+
+
+
+int Bank::sumTransactionsForGL(const Uint64 glTime,
+ const Uint32 accountType,
+ Uint32& balance,
+ Uint32& withdrawalCount,
+ Uint32& withdrawalSum,
+ Uint32& depositSum,
+ Uint32& depositCount,
+ Uint32& transactionsCount,
+ NdbConnection* pTrans){
+ int check;
+
+ // g_info << "sumTransactionsForGL: " << glTime << ", " << accountType << endl;
+
+ NdbConnection* pScanTrans = m_ndb.startTransaction();
+ if (pScanTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION");
+ if (pOp == NULL) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->openScanExclusive(64);
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
+ if( accountTypeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* timeRec = pOp->getValue("TIME");
+ if( timeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* transTypeRec = pOp->getValue("TRANSACTION_TYPE");
+ if( transTypeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* amountRec = pOp->getValue("AMOUNT");
+ if( amountRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pScanTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ int rowsFound = 0;
+ eof = pScanTrans->nextScanResult();
+
+ while(eof == 0){
+ rows++;
+ Uint32 a = accountTypeRec->u_32_value();
+ Uint64 t = timeRec->u_64_value();
+
+ if (a == accountType && t == glTime){
+ rowsFound++;
+ // One record found
+ int transType = transTypeRec->u_32_value();
+ int amount = amountRec->u_32_value();
+ if (transType == WithDrawal){
+ withdrawalCount++;
+ withdrawalSum += amount;
+ balance -= amount;
+ } else {
+ assert(transType == Deposit);
+ depositCount++;
+ depositSum += amount;
+ balance += amount;
+ }
+ }
+
+ eof = pScanTrans->nextScanResult();
+
+ if ((rows % 100) == 0){
+ // "refresh" ownner transaction every 100th row
+ if (pTrans->refresh() == -1) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+ }
+
+ }
+ if (eof == -1) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pScanTrans);
+ // ndbout << rows << " TRANSACTIONS have been read" << endl;
+ transactionsCount = rowsFound;
+
+ return NDBT_OK;
+
+}
+
+ int Bank::performValidateGLs(Uint64 age){
+
+ Uint64 currTime;
+ if (getCurrTime(currTime) != NDBT_OK){
+ return NDBT_FAILED;
+ }
+ Uint64 glTime = currTime - 1;
+ while((glTime > 0) && ((glTime + age) >= currTime)){
+
+ int result = performValidateGL(glTime);
+ if (result != NDBT_OK){
+ g_err << "performValidateGL failed" << endl;
+ return result;
+ }
+
+ glTime--;
+ }
+
+ return NDBT_OK;
+ }
+
+int Bank::performValidateGL(Uint64 glTime){
+
+ ndbout << "performValidateGL: " << glTime << endl;
+ /**
+ * Rules:
+ * - There should be zero or NoAccountTypes GL records for each glTime
+ * - If purged == 0, then the TRANSACTION table should be checked
+ * to see that there are:
+ * + DEPOSIT_COUNT deposit transactions with account_type == ACCOUNT_TYPE
+ * and TIME == glTime. The sum of these transactions should be
+ * DEPOSIT_SUM
+ * + WITHDRAWAL_COUNT withdrawal transactions with account_type ==
+ * ACCOUNT_TYPE and TIME == glTime. The sum of these transactions
+ * should be WITHDRAWAL_SUM
+ * + BALANCE should be equal to the sum of all transactions plus
+ * the balance of the previous GL record
+ * - If purged == 1 then there should be NO transactions with TIME == glTime
+ * and ACCOUNT_TYPE == account_type
+ *
+ */
+
+ int check;
+ /**
+ * SELECT * FROM GL WHERE account_type = @accountType and time = @time
+ */
+ NdbConnection* pScanTrans = m_ndb.startTransaction();
+ if (pScanTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
+ if (pOp == NULL) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->openScanRead(64);
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
+ if( accountTypeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* timeRec = pOp->getValue("TIME");
+ if( timeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* purgedRec = pOp->getValue("PURGED");
+ if( purgedRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
+ if( balanceRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* depositSumRec = pOp->getValue("DEPOSIT_SUM");
+ if( depositSumRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* depositCountRec = pOp->getValue("DEPOSIT_COUNT");
+ if( depositCountRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* withdrawalSumRec = pOp->getValue("WITHDRAWAL_SUM");
+ if( withdrawalSumRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+ NdbRecAttr* withdrawalCountRec = pOp->getValue("WITHDRAWAL_COUNT");
+ if( withdrawalCountRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pScanTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ int countGlRecords = 0;
+ int result = NDBT_OK;
+ eof = pScanTrans->nextScanResult();
+
+ while(eof == 0){
+ rows++;
+ Uint64 t = timeRec->u_64_value();
+
+ if (t == glTime){
+ countGlRecords++;
+ Uint32 a = accountTypeRec->u_32_value();
+ Uint32 purged = purgedRec->u_32_value();
+ Uint32 wsum = withdrawalSumRec->u_32_value();
+ Uint32 wcount = withdrawalCountRec->u_32_value();
+ Uint32 dsum = depositSumRec->u_32_value();
+ Uint32 dcount = depositCountRec->u_32_value();
+ Uint32 b = balanceRec->u_32_value();
+
+ Uint32 balance = 0;
+ Uint32 withdrawalSum = 0;
+ Uint32 withdrawalCount = 0;
+ Uint32 depositSum = 0;
+ Uint32 depositCount = 0;
+ Uint32 countTransactions = 0;
+ if (purged == 0){
+ // If purged == 0, then the TRANSACTION table should be checked
+ // to see that there are:
+ // + DEPOSIT_COUNT deposit transactions with account_type == ACCOUNT_TYPE
+ // and TIME == glTime. The sum of these transactions should be
+ // DEPOSIT_SUM
+ // + WITHDRAWAL_COUNT withdrawal transactions with account_type ==
+ // ACCOUNT_TYPE and TIME == glTime. The sum of these transactions
+ // should be WITHDRAWAL_SUM
+ // + BALANCE should be equal to the sum of all transactions plus
+ // the balance of the previous GL record
+ if (sumTransactionsForGL(t,
+ a,
+ balance,
+ withdrawalCount,
+ withdrawalSum,
+ depositSum,
+ depositCount,
+ countTransactions,
+ pScanTrans) != NDBT_OK){
+ result = NDBT_FAILED;
+ } else {
+ Uint32 prevBalance = 0;
+ if (getBalanceForGL(t-1, a, prevBalance) != NDBT_OK){
+ result = NDBT_FAILED;
+ } else
+ if (((prevBalance + balance) != b) ||
+ (wsum != withdrawalSum) ||
+ (wcount != withdrawalCount) ||
+ (dsum != depositSum) ||
+ (dcount != depositCount)){
+ g_err << "performValidateGL, sums and counts failed" << endl
+ << "balance : " << balance+prevBalance << "!="<<b<<endl
+ << "with sum : " << withdrawalSum << "!="<<wsum<<endl
+ << "with count: " << withdrawalCount << "!="<<wcount<<endl
+ << "dep sum : " << depositSum << "!="<<dsum<<endl
+ << "dep count : " << depositCount << "!="<<dcount<<endl;
+ result = VERIFICATION_FAILED;
+ }
+ }
+
+ } else {
+ assert(purged == 1);
+ // If purged == 1 then there should be NO transactions with
+ // TIME == glTime and ACCOUNT_TYPE == account_type
+
+ if (sumTransactionsForGL(t,
+ a,
+ balance,
+ withdrawalCount,
+ withdrawalSum,
+ depositSum,
+ depositCount,
+ countTransactions,
+ pScanTrans) != NDBT_OK){
+ result = NDBT_FAILED;
+ } else {
+ if (countTransactions != 0){
+ g_err << "performValidateGL, countTransactions("<<countTransactions<<") != 0" << endl;
+ result = VERIFICATION_FAILED;
+ }
+ }
+ }
+
+ }
+ eof = pScanTrans->nextScanResult();
+ }
+ if (eof == -1) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pScanTrans);
+
+ // - There should be zero or NoAccountTypes GL records for each glTime
+ if ((countGlRecords != 0) && (countGlRecords != getNumAccountTypes())){
+ g_err << "performValidateGL: " << endl
+ << "countGlRecords = " << countGlRecords << endl;
+ result = VERIFICATION_FAILED;
+ }
+
+ return result;
+
+
+ }
+
+int Bank::getBalanceForGL(const Uint64 glTime,
+ const Uint32 accountTypeId,
+ Uint32 &balance){
+ int check;
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pTrans->getNdbOperation("GL");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->readTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("TIME", glTime);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
+ if( balanceRec == NULL ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pTrans);
+
+ balance = balanceRec->u_32_value();
+
+ return NDBT_OK;
+}
+
+
+
+int Bank::getOldestPurgedGL(const Uint32 accountType,
+ Uint64 &oldest){
+ int check;
+ /**
+ * SELECT MAX(time) FROM GL WHERE account_type = @accountType and purged=1
+ */
+ NdbConnection* pScanTrans = m_ndb.startTransaction();
+ if (pScanTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
+ if (pOp == NULL) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->openScanRead(64);
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
+ if( accountTypeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* timeRec = pOp->getValue("TIME");
+ if( timeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* purgedRec = pOp->getValue("PURGED");
+ if( purgedRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pScanTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ eof = pScanTrans->nextScanResult();
+ oldest = 0;
+
+ while(eof == 0){
+ rows++;
+ Uint32 a = accountTypeRec->u_32_value();
+ Uint32 p = purgedRec->u_32_value();
+
+ if (a == accountType && p == 1){
+ // One record found
+ Uint64 t = timeRec->u_64_value();
+ if (t > oldest)
+ oldest = t;
+ }
+ eof = pScanTrans->nextScanResult();
+ }
+ if (eof == -1) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pScanTrans);
+
+ return NDBT_OK;
+}
+
+int Bank::getOldestNotPurgedGL(Uint64 &oldest,
+ Uint32 &accountTypeId,
+ bool &found){
+ int check;
+ /**
+ * SELECT time, accountTypeId FROM GL
+ * WHERE purged=0 order by time asc
+ */
+ NdbConnection* pScanTrans = m_ndb.startTransaction();
+ if (pScanTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
+ if (pOp == NULL) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->openScanRead(64);
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
+ if( accountTypeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* timeRec = pOp->getValue("TIME");
+ if( timeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* purgedRec = pOp->getValue("PURGED");
+ if( purgedRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pScanTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ eof = pScanTrans->nextScanResult();
+ oldest = (Uint64)-1;
+ found = false;
+
+ while(eof == 0){
+ rows++;
+ Uint32 p = purgedRec->u_32_value();
+ if (p == 0){
+ found = true;
+ // One record found
+ Uint32 a = accountTypeRec->u_32_value();
+ Uint64 t = timeRec->u_64_value();
+ if (t < oldest){
+ oldest = t;
+ accountTypeId = a;
+ }
+ }
+ eof = pScanTrans->nextScanResult();
+ }
+ if (eof == -1) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pScanTrans);
+
+ return NDBT_OK;
+}
+
+
+int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
+ const Uint64 oldest){
+ /**
+ * SELECT COUNT(transaction_id) FROM TRANSACTION
+ * WHERE account_type = @accountType and time <= @oldest
+ *
+ */
+
+ int check;
+ NdbConnection* pScanTrans = m_ndb.startTransaction();
+ if (pScanTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION");
+ if (pOp == NULL) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->openScanRead(64);
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
+ if( accountTypeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* timeRec = pOp->getValue("TIME");
+ if( timeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* transactionIdRec = pOp->getValue("TRANSACTION_ID");
+ if( transactionIdRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pScanTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ int found = 0;
+ eof = pScanTrans->nextScanResult();
+
+ while(eof == 0){
+ rows++;
+ Uint32 a = accountTypeRec->u_32_value();
+ Uint32 t = timeRec->u_32_value();
+
+ if (a == accountType && t <= oldest){
+ // One record found
+ Uint64 ti = transactionIdRec->u_64_value();
+ g_err << "checkNoTransactionsOlderThan found one record" << endl
+ << " t = " << t << endl
+ << " a = " << a << endl
+ << " ti = " << ti << endl;
+ found++;
+ }
+ eof = pScanTrans->nextScanResult();
+ }
+ if (eof == -1) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pScanTrans);
+
+ if (found == 0)
+ return NDBT_OK;
+ else
+ return VERIFICATION_FAILED;
+}
+
+
+ int Bank::performValidatePurged(){
+ /**
+ * Make sure there are no TRANSACTIONS older than the oldest
+ * purged GL record
+ *
+ */
+
+ for (int i = 0; i < getNumAccountTypes(); i++){
+ ndbout << "performValidatePurged: " << i << endl;
+ Uint64 oldestGlTime;
+ if (getOldestPurgedGL(i, oldestGlTime) != NDBT_OK){
+ g_err << "getOldestPurgedGL failed" << endl;
+ return NDBT_FAILED;
+ }
+ int result = checkNoTransactionsOlderThan(i, oldestGlTime);
+ if (result != NDBT_OK){
+ g_err << "checkNoTransactionsOlderThan failed" << endl;
+ return result;
+ }
+
+ }
+
+ return NDBT_OK;
+ }
+
+ int Bank::purgeOldGLTransactions(Uint64 currTime, Uint32 age){
+ /**
+ * For each GL record that are older than age and have purged == 0
+ * - delete all TRANSACTIONS belonging to the GL and set purged = 1
+ *
+ *
+ */
+ bool found;
+ int count = 0;
+
+ while(1){
+ count++;
+ if (count > 100)
+ return NDBT_OK;
+
+ // Search for the oldest GL record with purged == 0
+ Uint64 oldestGlTime;
+ Uint32 accountTypeId;
+ if (getOldestNotPurgedGL(oldestGlTime, accountTypeId, found) != NDBT_OK){
+ g_err << "getOldestNotPurgedGL failed" << endl;
+ return NDBT_FAILED;
+ }
+
+
+ if (found == false){
+ // ndbout << "not found" << endl;
+ return NDBT_OK;
+ }
+
+
+// ndbout << "purgeOldGLTransactions" << endl
+// << " oldestGlTime = " << oldestGlTime << endl
+// << " currTime = " << currTime << endl
+// << " age = " << age << endl;
+ // Check if this GL is old enough to be purged
+ if ((currTime < age) || (oldestGlTime > (currTime-age))){
+ // ndbout << "is not old enough" << endl;
+ return NDBT_OK;
+ }
+
+ if (purgeTransactions(oldestGlTime, accountTypeId) != NDBT_OK){
+ g_err << "purgeTransactions failed" << endl;
+ return NDBT_FAILED;
+ }
+ }
+ g_err << "abnormal return" << endl;
+ return NDBT_FAILED;
+ }
+
+
+int Bank::purgeTransactions(const Uint64 glTime,
+ const Uint32 accountTypeId)
+{
+ int check;
+ g_info << "purgeTransactions: " << glTime << ", "<<accountTypeId<<endl;
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL){
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ // Start by updating the GL record with purged = 1, use NoCommit
+ NdbOperation* pOp = pTrans->getNdbOperation("GL");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->updateTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("TIME", glTime);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ Uint32 purged = 1;
+ check = pOp->setValue("PURGED", purged);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ // Execute transaction
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ // Find all transactions and take over them for delete
+
+ if(findTransactionsToPurge(glTime,
+ accountTypeId,
+ pTrans) != NDBT_OK){
+ g_err << "findTransactionToPurge failed" << endl;
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+
+
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_OK;
+}
+
+
+int Bank::findTransactionsToPurge(const Uint64 glTime,
+ const Uint32 accountType,
+ NdbConnection* pTrans){
+ int check;
+
+ NdbConnection* pScanTrans = m_ndb.startTransaction();
+ if (pScanTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION");
+ if (pOp == NULL) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->openScanExclusive(64);
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* timeRec = pOp->getValue("TIME");
+ if( timeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
+ if( accountTypeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pScanTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ int rowsFound = 0;
+ eof = pScanTrans->nextScanResult();
+
+ while(eof == 0){
+ rows++;
+ Uint64 t = timeRec->u_64_value();
+ Uint32 a = accountTypeRec->u_32_value();
+
+ if (a == accountType && t == glTime){
+ rowsFound++;
+ // One record found
+ NdbOperation* pDelOp = pOp->takeOverForDelete(pTrans);
+ if (pDelOp == NULL){
+ ERR(m_ndb.getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ // Execute transaction
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+ }
+ eof = pScanTrans->nextScanResult();
+ }
+ if (eof == -1) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pScanTrans);
+ // ndbout << rowsFound << " TRANSACTIONS have been deleted" << endl;
+
+ return NDBT_OK;
+
+}
+
+
+ int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield){
+ if (init() != NDBT_OK)
+ return NDBT_FAILED;
+
+ int yieldCounter = 0;
+
+ while(1){
+
+ while(m_ndb.waitUntilReady(10) != 0)
+ ndbout << "Waiting for ndb to be ready" << endl;
+
+ while(1){
+
+ Uint64 currTime;
+ if (incCurrTime(currTime) != NDBT_OK)
+ break;
+
+ g_info << "Current time is " << currTime << endl;
+ if (maxSleepBetweenDays > 0){
+ int val = myRandom48(maxSleepBetweenDays);
+ NdbSleep_SecSleep(val);
+ }
+
+ yieldCounter++;
+ if (yield != 0 && yieldCounter >= yield)
+ return NDBT_OK;
+
+ }
+ }
+ return NDBT_FAILED;
+ }
+
+
+
+int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){
+
+ int check;
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL){
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->readTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* valueRec = pOp->getValue("VALUE");
+ if( valueRec ==NULL ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ value = valueRec->u_64_value();
+
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_OK;
+
+}
+
+int Bank::writeSystemValue(SystemValueId sysValId, Uint64 value){
+
+ int check;
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL){
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->insertTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->setValue("VALUE", value);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_OK;
+
+}
+
+int Bank::getNextTransactionId(Uint64 &value){
+ return increaseSystemValue2(LastTransactionId, value);
+}
+
+int Bank::incCurrTime(Uint64 &value){
+ return increaseSystemValue(CurrentTime, value);
+}
+
+
+int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
+ /**
+ * Increase value with one and return
+ * updated value
+ *
+ */
+
+ int check;
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL){
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->readTupleExclusive();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* valueRec = pOp->getValue("VALUE");
+ if( valueRec ==NULL ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ value = valueRec->u_64_value();
+ value++;
+
+ NdbOperation* pOp2 = pTrans->getNdbOperation("SYSTEM_VALUES");
+ if (pOp2 == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp2->updateTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp2->equal("SYSTEM_VALUES_ID", sysValId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp2->setValue("VALUE", value);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp3 = pTrans->getNdbOperation("SYSTEM_VALUES");
+ if (pOp3 == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->readTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp3->equal("SYSTEM_VALUES_ID", sysValId);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // Read new value
+ NdbRecAttr* valueNewRec = pOp3->getValue("VALUE");
+ if( valueNewRec ==NULL ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // Check that value updated equals the value we read after the update
+ if (valueNewRec->u_64_value() != value){
+ g_err << "getNextTransactionId: value was not updated" << endl;
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pTrans);
+
+
+ return 0;
+
+}
+
+int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){
+ /**
+ * Increase value with one and return
+ * updated value
+ * A more optimized version using interpreted update!
+ *
+ */
+
+ int check;
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL){
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpretedUpdateTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("SYSTEM_VALUES_ID", sysValId );
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint32 valToIncWith = 1;
+ check = pOp->incValue("VALUE", valToIncWith);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* valueRec = pOp->getValue("VALUE");
+ if( valueRec == NULL ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ value = valueRec->u_64_value();
+
+ m_ndb.closeTransaction(pTrans);
+
+ return 0;
+
+}
+
+
+
+int Bank::getCurrTime(Uint64 &time){
+ return readSystemValue(CurrentTime, time);
+}
+
+
+int Bank::performSumAccounts(int maxSleepBetweenSums, int yield){
+ if (init() != NDBT_OK)
+ return NDBT_FAILED;
+
+ int yieldCounter = 0;
+
+ while (1){
+
+ while (m_ndb.waitUntilReady(10) != 0)
+ ndbout << "Waiting for ndb to be ready" << endl;
+
+ Uint32 sumAccounts = 0;
+ Uint32 numAccounts = 0;
+ if (getSumAccounts(sumAccounts, numAccounts) != NDBT_OK){
+ g_err << "getSumAccounts FAILED" << endl;
+ } else {
+
+ g_info << "num="<<numAccounts<<", sum=" << sumAccounts << endl;
+
+ if (sumAccounts != (10000000 + (10000*(numAccounts-1)))){
+ g_err << "performSumAccounts FAILED" << endl
+ << " sumAccounts="<<sumAccounts<<endl
+ << " expected ="<<(10000000 + (10000*(numAccounts-1)))<<endl
+ << " numAccounts="<<numAccounts<<endl;
+ return NDBT_FAILED;
+ }
+
+ if (maxSleepBetweenSums > 0){
+ int val = myRandom48(maxSleepBetweenSums);
+ NdbSleep_MilliSleep(val);
+ }
+ }
+
+ yieldCounter++;
+ if (yield != 0 && yieldCounter >= yield)
+ return NDBT_OK;
+ }
+ return NDBT_FAILED;
+}
+
+
+int Bank::getSumAccounts(Uint32 &sumAccounts,
+ Uint32 &numAccounts){
+
+ // SELECT SUM(balance) FROM ACCOUNT
+
+ int check;
+ NdbConnection* pScanTrans = m_ndb.startTransaction();
+ if (pScanTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pScanTrans->getNdbOperation("ACCOUNT");
+ if (pOp == NULL) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->openScanExclusive(64);
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
+ if( balanceRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pScanTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ eof = pScanTrans->nextScanResult();
+
+ while(eof == 0){
+ Uint32 b = balanceRec->u_32_value();
+
+ sumAccounts += b;
+ numAccounts++;
+
+ // ndbout << numAccounts << ": balance =" << b
+ // << ", sum="<< sumAccounts << endl;
+
+ // Take over the operation so that the lock is kept in db
+ NdbOperation* pLockOp = pOp->takeOverForUpdate(pTrans);
+ if (pLockOp == NULL){
+ ERR(m_ndb.getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint32 illegalBalance = 99;
+ check = pLockOp->setValue("BALANCE", illegalBalance);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ // Execute transaction
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ eof = pScanTrans->nextScanResult();
+ }
+ if (eof == -1) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // TODO Forget about rolling back, just close pTrans!!
+
+ // Rollback transaction
+ check = pTrans->execute(Rollback);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pScanTrans);
+ m_ndb.closeTransaction(pTrans);
+
+
+ return NDBT_OK;
+
+}
diff --git a/ndb/test/ndbapi/bank/BankLoad.cpp b/ndb/test/ndbapi/bank/BankLoad.cpp
new file mode 100644
index 00000000000..76261b664a6
--- /dev/null
+++ b/ndb/test/ndbapi/bank/BankLoad.cpp
@@ -0,0 +1,582 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Bank.hpp"
+#include <UtilTransactions.hpp>
+
+/**
+ * Default account types
+ *
+ */
+struct AccountTypesStruct {
+ int id;
+ const char* descr;
+};
+const AccountTypesStruct accountTypes[] = {
+ { 0, "KASSA"},
+ { 1, "BANKOMAT"},
+ { 2, "POSTGIRO"},
+ { 3, "LÖNEKONTO"},
+ { 4, "SPARKONTO"}
+};
+
+const int
+accountTypesSize = sizeof(accountTypes)/sizeof(AccountTypesStruct);
+
+
+const char* tableNames[] = {
+ "GL",
+ "ACCOUNT",
+ "SYSTEM_VALUES",
+ "TRANSACTION",
+ "ACCOUNT_TYPE"
+};
+
+const int
+tableNamesSize = sizeof(tableNames)/sizeof(const char*);
+
+
+int Bank::getNumAccountTypes(){
+ return accountTypesSize;
+}
+
+int Bank::createAndLoadBank(bool ovrWrt){
+
+ m_ndb.init();
+ if (m_ndb.waitUntilReady() != 0)
+ return NDBT_FAILED;
+
+ const NdbDictionary::Table* pSysValTab =
+ m_ndb.getDictionary()->getTable("SYSTEM_VALUES");
+ if (pSysValTab != NULL){
+ // The table exists
+ if (ovrWrt == false){
+ ndbout << "Bank already exist and overwrite == false" << endl;
+ return NDBT_FAILED;
+ }
+ }
+
+ if (createTables() != NDBT_OK)
+ return NDBT_FAILED;
+
+ if (clearTables() != NDBT_OK)
+ return NDBT_FAILED;
+
+ if (loadAccountType() != NDBT_OK)
+ return NDBT_FAILED;
+
+ if (loadAccount(10) != NDBT_OK)
+ return NDBT_FAILED;
+
+ if (loadSystemValues() != NDBT_OK)
+ return NDBT_FAILED;
+
+ if (loadGl() != NDBT_OK)
+ return NDBT_FAILED;
+
+ return NDBT_OK;
+
+}
+
+int Bank::dropBank(){
+
+ m_ndb.init();
+ if (m_ndb.waitUntilReady() != 0)
+ return NDBT_FAILED;
+
+ if (dropTables() != NDBT_OK)
+ return NDBT_FAILED;
+
+ return NDBT_OK;
+
+}
+
+int Bank::createTables(){
+ for (int i = 0; i < tableNamesSize; i++){
+ if (createTable(tableNames[i]) != NDBT_OK)
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+
+int Bank::dropTables(){
+ for (int i = 0; i < tableNamesSize; i++){
+ if (dropTable(tableNames[i]) != NDBT_OK)
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int Bank::clearTables(){
+ for (int i = 0; i < tableNamesSize; i++){
+ if (clearTable(tableNames[i]) != NDBT_OK)
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int Bank::clearTable(const char* tabName){
+ UtilTransactions util(&m_ndb, tabName);
+ if(util.clearTable(&m_ndb, 64) != 0)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+int Bank::createTable(const char* tabName){
+ ndbout << "createTable " << tabName << endl;
+
+ const NdbDictionary::Table* pTab = NDBT_Tables::getTable(tabName);
+ if (pTab == NULL)
+ return NDBT_FAILED;
+
+ const NdbDictionary::Table* org =
+ m_ndb.getDictionary()->getTable(tabName);
+
+ if (org != 0 && pTab->equal(* org)){
+ return NDBT_OK;
+ }
+
+ if (org != 0){
+ ndbout << "Different table with same name exists" << endl;
+ return NDBT_FAILED;
+ }
+
+ if(m_ndb.getDictionary()->createTable(* pTab) == -1){
+ ndbout << "Failed to create table: " <<
+ m_ndb.getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+int Bank::dropTable(const char* tabName){
+ const NdbDictionary::Table* org =
+ m_ndb.getDictionary()->getTable(tabName);
+
+ if (org == NULL)
+ return NDBT_OK;
+
+ ndbout << "dropTable " <<tabName<<endl;
+ if (m_ndb.getDictionary()->dropTable(tabName) != 0){
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+
+
+
+
+
+
+
+/**
+ * Load SYSTEM_VALUES table
+ * This table keeps track of system wide settings
+ * For example:
+ * - next transaction id
+ *
+ */
+int Bank::loadSystemValues (){
+int result;
+
+/**
+ * Insert start value for next transaction id
+ *
+ */
+result = writeSystemValue(LastTransactionId, 0);
+
+/**
+ * Insert start value for current time
+ *
+ */
+result = writeSystemValue(CurrentTime, 1);
+
+return result;
+
+}
+
+
+/**
+ * Load GL table
+ *
+ * Insert GL records for time = 0 with balance 0
+ */
+int Bank::loadGl(){
+ g_info << "loadGl" << endl;
+ int check;
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL){
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ for (int i = 0; i < getNumAccountTypes(); i++){
+
+ NdbOperation* pOp = pTrans->getNdbOperation("GL");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->insertTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint64 time = 0;
+ check = pOp->equal("TIME", time);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("ACCOUNT_TYPE", i);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint32 balance = 0;
+ if (getBalanceForAccountType(i, balance) != NDBT_OK){
+ return NDBT_FAILED;
+ }
+
+ check = pOp->setValue("BALANCE", balance);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint32 depositCount = 0;
+ check = pOp->setValue("DEPOSIT_COUNT", depositCount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint32 depositSum = 0;
+ check = pOp->setValue("DEPOSIT_SUM", depositSum);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint32 withdrawalCount = 0;
+ check = pOp->setValue("WITHDRAWAL_COUNT", withdrawalCount);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint32 withdrawalSum = 0;
+ check = pOp->setValue("WITHDRAWAL_SUM", withdrawalSum);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ Uint32 purged = 1;
+ check = pOp->setValue("PURGED", purged);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ }
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_OK;
+};
+
+
+int Bank::getBalanceForAccountType(const Uint32 accountType,
+ Uint32& balance){
+ int check;
+ g_info << "getBalanceForAccountType: accountType="<<accountType<<endl;
+
+ NdbConnection* pScanTrans = m_ndb.startTransaction();
+ if (pScanTrans == NULL) {
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pScanTrans->getNdbOperation("ACCOUNT");
+ if (pOp == NULL) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->openScanRead(64);
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
+ if( accountTypeRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
+ if( balanceRec ==NULL ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pScanTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ eof = pScanTrans->nextScanResult();
+
+ while(eof == 0){
+ rows++;
+ Uint32 a = accountTypeRec->u_32_value();
+ Uint32 b = balanceRec->u_32_value();
+
+ if (a == accountType){
+ // One record found
+ balance += b;
+ }
+
+ eof = pScanTrans->nextScanResult();
+ }
+ if (eof == -1) {
+ ERR(pScanTrans->getNdbError());
+ m_ndb.closeTransaction(pScanTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pScanTrans);
+ // ndbout << rows << " rows have been read" << endl;
+
+ return NDBT_OK;
+
+}
+
+/**
+ * Load ACCOUNT_TYPE table
+ *
+ *
+ */
+int Bank::loadAccountType(){
+ g_info << "loadAccountType" << endl;
+ int check;
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL){
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ for (int i = 0; i < getNumAccountTypes(); i++){
+
+ NdbOperation* pOp = pTrans->getNdbOperation("ACCOUNT_TYPE");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->insertTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("ACCOUNT_TYPE_ID", accountTypes[i].id);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->setValue("DESCRIPTION", accountTypes[i].descr);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+ }
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_OK;
+};
+
+/**
+ * Load ACCOUNT table
+ *
+ *
+ *
+ */
+int Bank::loadAccount (int numAccounts){
+ g_info << "loadAccount" << endl;
+ int check;
+
+ NdbConnection* pTrans = m_ndb.startTransaction();
+ if (pTrans == NULL){
+ ERR(m_ndb.getNdbError());
+ return NDBT_FAILED;
+ }
+
+ for (int i = 0; i < numAccounts; i++){
+
+ NdbOperation* pOp = pTrans->getNdbOperation("ACCOUNT");
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->insertTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->equal("ACCOUNT_ID", i);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ int owner;
+ if (i == 0)
+ owner = 0;
+ else
+ owner = i + 3000;
+ check = pOp->setValue("OWNER", owner);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // Load balance so that the bank's account = 0 has 10 millions
+ // and all other accounts have 10000
+ // This set the total balance for the entire bank to
+ // 10000000 + (10000 * numAccounts-1)
+ // Since no money should dissapear from to the bank nor
+ // any money should be added this is a rule that can be checked when
+ // validating the db
+ int balance;
+ if (i == 0){
+ balance = 10000000;
+ } else {
+ balance = 10000;
+ }
+ check = pOp->setValue("BALANCE", balance);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // TODO - This is how to set a value in a 16, 1 attribute, not so nice?
+ // NOTE - its not even possible to set the value 0 in this column
+ // since that is equal to NULL when casting to char*
+ // check = pOp->setValue("ACCOUNT_TYPE", (const char*)(Uint16)(i/accountTypesSize), 2);
+ // NOTE attribute now changed to be a 32 bit
+
+
+ int accountType;
+ if (i == 0)
+ accountType = 0; // KASSA
+ else
+ accountType = ((i%accountTypesSize) == 0 ? 1 : (i%getNumAccountTypes()));
+ check = pOp->setValue("ACCOUNT_TYPE", accountType);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+ }
+ check = pTrans->execute(Commit);
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_OK;
+}
+
+
+int Bank::getNumAccounts(){
+ const NdbDictionary::Table* accountTab =
+ m_ndb.getDictionary()->getTable("ACCOUNT");
+ if (accountTab == NULL){
+ g_err << "Table ACCOUNT does not exist" << endl;
+ return NDBT_FAILED;
+ }
+ UtilTransactions util(*accountTab);
+ if(util.selectCount(&m_ndb, 64, &m_maxAccount) != 0)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+int Bank::getMaxAmount(){
+ return 10000;
+}
diff --git a/ndb/test/ndbapi/bank/Makefile.am b/ndb/test/ndbapi/bank/Makefile.am
new file mode 100644
index 00000000000..886d664aefb
--- /dev/null
+++ b/ndb/test/ndbapi/bank/Makefile.am
@@ -0,0 +1,22 @@
+
+ndbtest_PROGRAMS = testBank bankSumAccounts bankValidateAllGLs bankMakeGL bankTransactionMaker bankCreator bankTimer
+
+noinst_LIBRARIES = libbank.a
+
+libbank_a_SOURCES = Bank.cpp BankLoad.cpp Bank.hpp
+
+testBank_SOURCES = testBank.cpp
+bankSumAccounts_SOURCES = bankSumAccounts.cpp
+bankValidateAllGLs_SOURCES = bankValidateAllGLs.cpp
+bankMakeGL_SOURCES = bankMakeGL.cpp
+bankTransactionMaker_SOURCES = bankTransactionMaker.cpp
+bankCreator_SOURCES = bankCreator.cpp
+bankTimer_SOURCES = bankTimer.cpp
+
+LDADD_LOC = $(noinst_LIBRARIES)
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/test/ndbapi/bank/Makefile b/ndb/test/ndbapi/bank/Makefile_old
index f710f9e6612..f710f9e6612 100644
--- a/ndb/test/ndbapi/bank/Makefile
+++ b/ndb/test/ndbapi/bank/Makefile_old
diff --git a/ndb/test/ndbapi/bank/bankCreator.cpp b/ndb/test/ndbapi/bank/bankCreator.cpp
new file mode 100644
index 00000000000..5331ec6ba69
--- /dev/null
+++ b/ndb/test/ndbapi/bank/bankCreator.cpp
@@ -0,0 +1,54 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+#include <NdbOut.hpp>
+
+#include <NdbApi.hpp>
+#include <NdbMain.h>
+#include <NDBT.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+#include "Bank.hpp"
+
+
+int main(int argc, const char** argv){
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "This program will create and load the tables for bank\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ Bank bank;
+ int overWriteExisting = true;
+ if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK)
+ return NDBT_ProgramExit(NDBT_FAILED);
+ return NDBT_ProgramExit(NDBT_OK);
+
+}
+
+
+
diff --git a/ndb/test/ndbapi/bank/bankCreator/bankCreator.cpp b/ndb/test/ndbapi/bank/bankCreator/bankCreator.cpp
deleted file mode 100644
index d84818baf24..00000000000
--- a/ndb/test/ndbapi/bank/bankCreator/bankCreator.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include <ndb_global.h>
-#include <NdbOut.hpp>
-
-#include <NdbApi.hpp>
-#include <NdbMain.h>
-#include <NDBT.hpp>
-#include <NdbSleep.h>
-#include <getarg.h>
-#include "../Bank.hpp"
-
-
-int main(int argc, const char** argv){
- int _help = 0;
-
- struct getargs args[] = {
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "This program will create and load the tables for bank\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- Bank bank;
- int overWriteExisting = true;
- if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK)
- return NDBT_ProgramExit(NDBT_FAILED);
- return NDBT_ProgramExit(NDBT_OK);
-
-}
-
-
-
diff --git a/ndb/test/ndbapi/bank/bankMakeGL.cpp b/ndb/test/ndbapi/bank/bankMakeGL.cpp
new file mode 100644
index 00000000000..54bc559fbf9
--- /dev/null
+++ b/ndb/test/ndbapi/bank/bankMakeGL.cpp
@@ -0,0 +1,55 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+#include <NdbOut.hpp>
+
+#include <NdbApi.hpp>
+#include <NdbMain.h>
+#include <NDBT.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+#include "Bank.hpp"
+
+
+int main(int argc, const char** argv){
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "This program will make GL records in the bank\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ Bank bank;
+
+ if (bank.performMakeGLs() != 0)
+ return NDBT_ProgramExit(NDBT_FAILED);
+
+ return NDBT_ProgramExit(NDBT_OK);
+
+}
+
+
+
diff --git a/ndb/test/ndbapi/bank/bankMakeGL/bankMakeGL.cpp b/ndb/test/ndbapi/bank/bankMakeGL/bankMakeGL.cpp
deleted file mode 100644
index 55e9081a598..00000000000
--- a/ndb/test/ndbapi/bank/bankMakeGL/bankMakeGL.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include <ndb_global.h>
-#include <NdbOut.hpp>
-
-#include <NdbApi.hpp>
-#include <NdbMain.h>
-#include <NDBT.hpp>
-#include <NdbSleep.h>
-#include <getarg.h>
-#include "../Bank.hpp"
-
-
-int main(int argc, const char** argv){
- int _help = 0;
-
- struct getargs args[] = {
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "This program will make GL records in the bank\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- Bank bank;
-
- if (bank.performMakeGLs() != 0)
- return NDBT_ProgramExit(NDBT_FAILED);
-
- return NDBT_ProgramExit(NDBT_OK);
-
-}
-
-
-
diff --git a/ndb/test/ndbapi/bank/bankSumAccounts.cpp b/ndb/test/ndbapi/bank/bankSumAccounts.cpp
new file mode 100644
index 00000000000..c0a903f9034
--- /dev/null
+++ b/ndb/test/ndbapi/bank/bankSumAccounts.cpp
@@ -0,0 +1,55 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+#include <NdbOut.hpp>
+
+#include <NdbApi.hpp>
+#include <NdbMain.h>
+#include <NDBT.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+#include "Bank.hpp"
+
+
+int main(int argc, const char** argv){
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "This program will check the sum of all ACCOUNTS in the bank\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ Bank bank;
+
+ if (bank.performSumAccounts() != 0)
+ return NDBT_ProgramExit(NDBT_FAILED);
+
+ return NDBT_ProgramExit(NDBT_OK);
+
+}
+
+
+
diff --git a/ndb/test/ndbapi/bank/bankSumAccounts/bankSumAccounts.cpp b/ndb/test/ndbapi/bank/bankSumAccounts/bankSumAccounts.cpp
deleted file mode 100644
index ab3e862e8d2..00000000000
--- a/ndb/test/ndbapi/bank/bankSumAccounts/bankSumAccounts.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include <ndb_global.h>
-#include <NdbOut.hpp>
-
-#include <NdbApi.hpp>
-#include <NdbMain.h>
-#include <NDBT.hpp>
-#include <NdbSleep.h>
-#include <getarg.h>
-#include "../Bank.hpp"
-
-
-int main(int argc, const char** argv){
- int _help = 0;
-
- struct getargs args[] = {
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "This program will check the sum of all ACCOUNTS in the bank\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- Bank bank;
-
- if (bank.performSumAccounts() != 0)
- return NDBT_ProgramExit(NDBT_FAILED);
-
- return NDBT_ProgramExit(NDBT_OK);
-
-}
-
-
-
diff --git a/ndb/test/ndbapi/bank/bankTimer.cpp b/ndb/test/ndbapi/bank/bankTimer.cpp
new file mode 100644
index 00000000000..ba3165fccb4
--- /dev/null
+++ b/ndb/test/ndbapi/bank/bankTimer.cpp
@@ -0,0 +1,58 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+
+#include <NdbOut.hpp>
+
+#include <NdbApi.hpp>
+#include <NdbMain.h>
+#include <NDBT.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+#include "Bank.hpp"
+
+
+int main(int argc, const char** argv){
+ int _help = 0;
+ int _wait = 30;
+
+ struct getargs args[] = {
+ { "wait", 'w', arg_integer, &_wait, "Max time to wait between days", "secs" },
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "This program will increase time in the bank\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ Bank bank;
+
+ if (bank.performIncreaseTime(_wait) != 0)
+ return NDBT_ProgramExit(NDBT_FAILED);
+
+ return NDBT_ProgramExit(NDBT_OK);
+
+}
+
+
+
diff --git a/ndb/test/ndbapi/bank/bankTimer/bankTimer.cpp b/ndb/test/ndbapi/bank/bankTimer/bankTimer.cpp
deleted file mode 100644
index ba8de9e4af1..00000000000
--- a/ndb/test/ndbapi/bank/bankTimer/bankTimer.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include <ndb_global.h>
-
-#include <NdbOut.hpp>
-
-#include <NdbApi.hpp>
-#include <NdbMain.h>
-#include <NDBT.hpp>
-#include <NdbSleep.h>
-#include <getarg.h>
-#include "../Bank.hpp"
-
-
-int main(int argc, const char** argv){
- int _help = 0;
- int _wait = 30;
-
- struct getargs args[] = {
- { "wait", 'w', arg_integer, &_wait, "Max time to wait between days", "secs" },
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "This program will increase time in the bank\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- Bank bank;
-
- if (bank.performIncreaseTime(_wait) != 0)
- return NDBT_ProgramExit(NDBT_FAILED);
-
- return NDBT_ProgramExit(NDBT_OK);
-
-}
-
-
-
diff --git a/ndb/test/ndbapi/bank/bankTransactionMaker.cpp b/ndb/test/ndbapi/bank/bankTransactionMaker.cpp
new file mode 100644
index 00000000000..fe9b53e0c8d
--- /dev/null
+++ b/ndb/test/ndbapi/bank/bankTransactionMaker.cpp
@@ -0,0 +1,58 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+
+#include <NdbOut.hpp>
+
+#include <NdbApi.hpp>
+#include <NdbMain.h>
+#include <NDBT.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+#include "Bank.hpp"
+
+
+int main(int argc, const char** argv){
+ int _help = 0;
+ int _wait = 20;
+
+ struct getargs args[] = {
+ { "wait", 'w', arg_integer, &_wait, "Time to wait between transactions", "ms" },
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "This program will perform transactions in the bank\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ Bank bank;
+
+ if (bank.performTransactions(_wait) != 0)
+ return NDBT_ProgramExit(NDBT_FAILED);
+
+ return NDBT_ProgramExit(NDBT_OK);
+
+}
+
+
+
diff --git a/ndb/test/ndbapi/bank/bankTransactionMaker/bankTransactionMaker.cpp b/ndb/test/ndbapi/bank/bankTransactionMaker/bankTransactionMaker.cpp
deleted file mode 100644
index 0c7d5d72473..00000000000
--- a/ndb/test/ndbapi/bank/bankTransactionMaker/bankTransactionMaker.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include <ndb_global.h>
-
-#include <NdbOut.hpp>
-
-#include <NdbApi.hpp>
-#include <NdbMain.h>
-#include <NDBT.hpp>
-#include <NdbSleep.h>
-#include <getarg.h>
-#include "../Bank.hpp"
-
-
-int main(int argc, const char** argv){
- int _help = 0;
- int _wait = 20;
-
- struct getargs args[] = {
- { "wait", 'w', arg_integer, &_wait, "Time to wait between transactions", "ms" },
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "This program will perform transactions in the bank\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- Bank bank;
-
- if (bank.performTransactions(_wait) != 0)
- return NDBT_ProgramExit(NDBT_FAILED);
-
- return NDBT_ProgramExit(NDBT_OK);
-
-}
-
-
-
diff --git a/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp b/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp
new file mode 100644
index 00000000000..f9d974bb5f7
--- /dev/null
+++ b/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp
@@ -0,0 +1,56 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+
+#include <NdbOut.hpp>
+
+#include <NdbApi.hpp>
+#include <NdbMain.h>
+#include <NDBT.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+#include "Bank.hpp"
+
+
+int main(int argc, const char** argv){
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "This program will validate all GLs in the bank\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ Bank bank;
+
+ if (bank.performValidateAllGLs() != 0)
+ return NDBT_ProgramExit(NDBT_FAILED);
+
+ return NDBT_ProgramExit(NDBT_OK);
+
+}
+
+
+
diff --git a/ndb/test/ndbapi/bank/bankValidateAllGLs/bankValidateAllGLs.cpp b/ndb/test/ndbapi/bank/bankValidateAllGLs/bankValidateAllGLs.cpp
deleted file mode 100644
index 13136755de8..00000000000
--- a/ndb/test/ndbapi/bank/bankValidateAllGLs/bankValidateAllGLs.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include <ndb_global.h>
-
-#include <NdbOut.hpp>
-
-#include <NdbApi.hpp>
-#include <NdbMain.h>
-#include <NDBT.hpp>
-#include <NdbSleep.h>
-#include <getarg.h>
-#include "../Bank.hpp"
-
-
-int main(int argc, const char** argv){
- int _help = 0;
-
- struct getargs args[] = {
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "This program will validate all GLs in the bank\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- Bank bank;
-
- if (bank.performValidateAllGLs() != 0)
- return NDBT_ProgramExit(NDBT_FAILED);
-
- return NDBT_ProgramExit(NDBT_OK);
-
-}
-
-
-
diff --git a/ndb/test/ndbapi/bank/bankCreator/Makefile b/ndb/test/ndbapi/bank/old_dirs/bankCreator/Makefile
index d40103a8347..d40103a8347 100644
--- a/ndb/test/ndbapi/bank/bankCreator/Makefile
+++ b/ndb/test/ndbapi/bank/old_dirs/bankCreator/Makefile
diff --git a/ndb/test/ndbapi/bank/bankMakeGL/Makefile b/ndb/test/ndbapi/bank/old_dirs/bankMakeGL/Makefile
index 16a092e885c..16a092e885c 100644
--- a/ndb/test/ndbapi/bank/bankMakeGL/Makefile
+++ b/ndb/test/ndbapi/bank/old_dirs/bankMakeGL/Makefile
diff --git a/ndb/test/ndbapi/bank/bankSumAccounts/Makefile b/ndb/test/ndbapi/bank/old_dirs/bankSumAccounts/Makefile
index 34f1cc21bc6..34f1cc21bc6 100644
--- a/ndb/test/ndbapi/bank/bankSumAccounts/Makefile
+++ b/ndb/test/ndbapi/bank/old_dirs/bankSumAccounts/Makefile
diff --git a/ndb/test/ndbapi/bank/bankTimer/Makefile b/ndb/test/ndbapi/bank/old_dirs/bankTimer/Makefile
index a2fcf703723..a2fcf703723 100644
--- a/ndb/test/ndbapi/bank/bankTimer/Makefile
+++ b/ndb/test/ndbapi/bank/old_dirs/bankTimer/Makefile
diff --git a/ndb/test/ndbapi/bank/bankTransactionMaker/Makefile b/ndb/test/ndbapi/bank/old_dirs/bankTransactionMaker/Makefile
index 2e482898476..2e482898476 100644
--- a/ndb/test/ndbapi/bank/bankTransactionMaker/Makefile
+++ b/ndb/test/ndbapi/bank/old_dirs/bankTransactionMaker/Makefile
diff --git a/ndb/test/ndbapi/bank/bankValidateAllGLs/Makefile b/ndb/test/ndbapi/bank/old_dirs/bankValidateAllGLs/Makefile
index 660b73fb830..660b73fb830 100644
--- a/ndb/test/ndbapi/bank/bankValidateAllGLs/Makefile
+++ b/ndb/test/ndbapi/bank/old_dirs/bankValidateAllGLs/Makefile
diff --git a/ndb/test/ndbapi/bank/src/Makefile b/ndb/test/ndbapi/bank/old_dirs/src/Makefile
index e0ab8e0e536..e0ab8e0e536 100644
--- a/ndb/test/ndbapi/bank/src/Makefile
+++ b/ndb/test/ndbapi/bank/old_dirs/src/Makefile
diff --git a/ndb/test/ndbapi/bank/testBank/Makefile b/ndb/test/ndbapi/bank/old_dirs/testBank/Makefile
index 382aaadad7c..382aaadad7c 100644
--- a/ndb/test/ndbapi/bank/testBank/Makefile
+++ b/ndb/test/ndbapi/bank/old_dirs/testBank/Makefile
diff --git a/ndb/test/ndbapi/bank/src/Bank.cpp b/ndb/test/ndbapi/bank/src/Bank.cpp
deleted file mode 100644
index 11ebf087fd4..00000000000
--- a/ndb/test/ndbapi/bank/src/Bank.cpp
+++ /dev/null
@@ -1,2458 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "../Bank.hpp"
-#include <time.h>
-#include <NdbSleep.h>
-#include <UtilTransactions.hpp>
-
-Bank::Bank():
- m_ndb("BANK"),
- m_maxAccount(-1),
- m_initialized(false)
-{
-
-}
-
-int Bank::init(){
- if (m_initialized == true)
- return NDBT_OK;
-
- myRandom48Init(NdbTick_CurrentMillisecond());
-
- m_ndb.init();
- while (m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- if (getNumAccounts() != NDBT_OK)
- return NDBT_FAILED;
- return NDBT_OK;
-}
-
-int Bank::performTransactions(int maxSleepBetweenTrans, int yield){
-
- if (init() != NDBT_OK)
- return NDBT_FAILED;
- int transactions = 0;
-
- while(1){
-
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- while(performTransaction() != NDBT_FAILED){
- transactions++;
-
- if (maxSleepBetweenTrans > 0){
- int val = myRandom48(maxSleepBetweenTrans);
- NdbSleep_MilliSleep(val);
- }
-
- if((transactions % 100) == 0)
- g_info << transactions << endl;
-
- if (yield != 0 && transactions >= yield)
- return NDBT_OK;
- }
- }
- return NDBT_FAILED;
-
-}
-
-int Bank::performTransaction(){
- int result = NDBT_OK;
-
- if (m_maxAccount <= 0){
- g_err << "No accounts in bank" << endl;
- return NDBT_FAILED;
- }
-
- int fromAccount = myRandom48(m_maxAccount);
- int toAccount = myRandom48(m_maxAccount);
-
- if (fromAccount == toAccount){
- // Increase toAccount with 1
- toAccount = (toAccount+1)%m_maxAccount;
- }
-
- int maxAmount = getMaxAmount();
-
- int amount = myRandom48(maxAmount);
-
- retry_transaction:
- int res = performTransaction(fromAccount, toAccount, amount);
- if (res != 0){
- switch (res){
- case NDBT_FAILED:
- g_err << "performTransaction returned NDBT_FAILED" << endl
- << " fromAccount = " << fromAccount << endl
- << " toAccount = " << toAccount << endl
- << " amount = " << amount << endl;
- result = NDBT_FAILED;
- break;
- case NOT_ENOUGH_FUNDS:
- // ndbout << "performTransaction returned NOT_ENOUGH_FUNDS" << endl;
- break;
- case NDBT_TEMPORARY:
- g_err << "TEMPORARY_ERRROR retrying" << endl;
- goto retry_transaction;
- break;
- default:
- g_info << "performTransaction returned "<<res << endl;
- break;
- }
- }
- return result;
-}
-
-/**
- * Perform a transaction in the bank.
- * Ie. transfer money from one account to another.
- *
- * @param
- * @return 0 if successful or an error code
- */
-int Bank::performTransaction(int fromAccountId,
- int toAccountId,
- int amount ){
- /**
- * 1. Start transaction
- * 2. Check balance on from account, if there is
- * not enough funds abort transaction
- * 3. Update ACCOUNT set balance = balance - amount on
- * from account
- * 4. Insert withdrawal in TRANSACTION
- * 5. Insert deposit in transaction
- * 6. Update ACCOUNT set balance = balance + amount on
- * to account
- * 7. Commit transaction
- */
- // g_info << "performTransaction " << fromAccountId
- // << ", "<<toAccountId<<", "<<amount << endl;
-
- // Call the first implementation of this trans
- // In the future we can have several different versions of this trans
- // and call them randomly
- return performTransactionImpl1(fromAccountId, toAccountId, amount);
-}
-
-
-int Bank::performTransactionImpl1(int fromAccountId,
- int toAccountId,
- int amount ){
-
- int check;
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if( pTrans == NULL ) {
- const NdbError err = m_ndb.getNdbError();
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- return NDBT_TEMPORARY;
- }
- ERR(err);
- return NDBT_FAILED;
- }
-
- /**
- * Check balance on from account
- */
- NdbOperation* pOp = pTrans->getNdbOperation("ACCOUNT");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->readTupleExclusive();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->equal("ACCOUNT_ID", fromAccountId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* balanceFromRec = pOp->getValue("BALANCE");
- if( balanceFromRec ==NULL ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* fromAccountTypeRec = pOp->getValue("ACCOUNT_TYPE");
- if( fromAccountTypeRec == NULL ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(NoCommit);
- if( check == -1 ) {
- const NdbError err = pTrans->getNdbError();
- m_ndb.closeTransaction(pTrans);
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- return NDBT_TEMPORARY;
- }
- ERR(err);
- return NDBT_FAILED;
- }
-
- Uint32 balanceFrom = balanceFromRec->u_32_value();
- // ndbout << "balanceFrom: " << balanceFrom << endl;
-
- if (((Int64)balanceFrom - amount) < 0){
- m_ndb.closeTransaction(pTrans);
- //ndbout << "Not enough funds" << endl;
- return NOT_ENOUGH_FUNDS;
- }
-
- Uint32 fromAccountType = fromAccountTypeRec->u_32_value();
-
- /**
- * Read balance on to account
- */
- NdbOperation* pOp6 = pTrans->getNdbOperation("ACCOUNT");
- if (pOp6 == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp6->readTupleExclusive();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp6->equal("ACCOUNT_ID", toAccountId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* balanceToRec = pOp6->getValue("BALANCE");
- if( balanceToRec == NULL ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* toAccountTypeRec = pOp6->getValue("ACCOUNT_TYPE");
- if( toAccountTypeRec == NULL ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(NoCommit);
- if( check == -1 ) {
- const NdbError err = pTrans->getNdbError();
- m_ndb.closeTransaction(pTrans);
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- return NDBT_TEMPORARY;
- }
- ERR(err);
- return NDBT_FAILED;
- }
-
- Uint32 balanceTo = balanceToRec->u_32_value();
- // ndbout << "balanceTo: " << balanceTo << endl;
- Uint32 toAccountType = toAccountTypeRec->u_32_value();
-
- // Ok, all clear to do the transaction
- Uint64 transId;
- if (getNextTransactionId(transId) != NDBT_OK){
- return NDBT_FAILED;
- }
-
- Uint64 currTime;
- if (getCurrTime(currTime) != NDBT_OK){
- return NDBT_FAILED;
- }
-
- /**
- * Update balance on from account
- */
- NdbOperation* pOp2 = pTrans->getNdbOperation("ACCOUNT");
- if (pOp2 == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp2->updateTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp2->equal("ACCOUNT_ID", fromAccountId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp2->setValue("BALANCE", balanceFrom - amount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- /**
- * Update balance on to account
- */
- NdbOperation* pOp3 = pTrans->getNdbOperation("ACCOUNT");
- if (pOp3 == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp3->updateTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp3->equal("ACCOUNT_ID", toAccountId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp3->setValue("BALANCE", balanceTo + amount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- /**
- * Insert withdrawal transaction
- */
- NdbOperation* pOp4 = pTrans->getNdbOperation("TRANSACTION");
- if (pOp4 == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp4->insertTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp4->equal("TRANSACTION_ID", transId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp4->equal("ACCOUNT", fromAccountId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp4->setValue("ACCOUNT_TYPE", fromAccountType);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp4->setValue("OTHER_ACCOUNT", toAccountId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp4->setValue("TRANSACTION_TYPE", WithDrawal);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp4->setValue("TIME", currTime);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp4->setValue("AMOUNT", amount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- /**
- * Insert deposit transaction
- */
- NdbOperation* pOp5 = pTrans->getNdbOperation("TRANSACTION");
- if (pOp5 == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp5->insertTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp5->equal("TRANSACTION_ID", transId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp5->equal("ACCOUNT", toAccountId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp5->setValue("ACCOUNT_TYPE", toAccountType);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp5->setValue("OTHER_ACCOUNT", fromAccountId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp5->setValue("TRANSACTION_TYPE", Deposit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp5->setValue("TIME", currTime);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp5->setValue("AMOUNT", amount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- const NdbError err = pTrans->getNdbError();
- m_ndb.closeTransaction(pTrans);
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- return NDBT_TEMPORARY;
- }
- ERR(err);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pTrans);
- return NDBT_OK;
-}
-
-
-
-
-int Bank::performMakeGLs(int yield){
- int result;
- if (init() != NDBT_OK)
- return NDBT_FAILED;
-
- int counter, maxCounter;
- int yieldCounter = 0;
-
- while (1){
- // Counters to keep tracck of how many
- // GLs should be made before performing a validation
- counter = 0;
- maxCounter = 50 + myRandom48(100);
-
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- /**
- * Validate GLs and Transactions for previous days
- *
- */
- result = performValidateGLs();
- if (result != NDBT_OK){
- if (result == VERIFICATION_FAILED){
- g_err << "performValidateGLs verification failed" << endl;
- return NDBT_FAILED;
- }
- g_info << "performValidateGLs failed" << endl;
- continue;
- }
-
- result = performValidatePurged();
- if (result != NDBT_OK){
- if (result == VERIFICATION_FAILED){
- g_err << "performValidatePurged verification failed" << endl;
- return NDBT_FAILED;
- }
- g_info << "performValidatePurged failed" << endl;
- continue;
- }
-
- while (1){
-
- yieldCounter++;
- if (yield != 0 && yieldCounter >= yield)
- return NDBT_OK;
-
- /**
- * Find last GL time.
- * ( GL record with highest time value)
- */
- Uint64 lastGLTime;
- if (findLastGL(lastGLTime) != NDBT_OK){
- g_info << "findLastGL failed" << endl;
- // Break out of inner while loop
- break;
- }
-
- lastGLTime++;
-
- /**
- * If last GL time + 1 is smaller than current time
- * perform a GL for that time
- */
- Uint64 currTime;
- if (getCurrTime(currTime) != NDBT_OK){
- g_info << "getCurrTime failed" << endl;
- // Break out of inner while loop
- break;
- }
- if (lastGLTime < currTime){
- counter++;
- if (performMakeGL(lastGLTime) != NDBT_OK){
- g_info << "performMakeGL failed" << endl;
- // Break out of inner while loop
- break;
- }
-
- if (counter > maxCounter){
- // Break out of inner while loop and
- // validatePreviousGLs
- g_info << "counter("<<counter<<") > maxCounter("<<maxCounter<<")" << endl;
- break;
- }
-
- } else {
- ;//ndbout << "It's not time to make GL yet" << endl;
-
- // ndbout << "Sleeping 1 second" << endl;
- NdbSleep_SecSleep(1);
-
- }
-
- Uint32 age = 3;
- if (purgeOldGLTransactions(currTime, age) != NDBT_OK){
- g_info << "purgeOldGLTransactions failed" << endl;
- // Break out of inner while loop
- break;
- }
-
- }
- }
-
- return NDBT_FAILED;
-
-}
-
-int Bank::performValidateAllGLs(){
- int result;
- if (init() != NDBT_OK)
- return NDBT_FAILED;
-
- while (1){
-
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- /**
- * Validate GLs and Transactions for previous days
- * Set age so that ALL GL's are validated
- */
- int age = 100000;
- result = performValidateGLs(age);
- if (result != NDBT_OK){
- if (result == VERIFICATION_FAILED){
- g_err << "performValidateGLs verification failed" << endl;
- return NDBT_FAILED;
- }
- g_err << "performValidateGLs failed" << endl;
- return NDBT_FAILED;
- }
-
- /**
- *
- *
- */
- result = performValidatePurged();
- if (result != NDBT_OK){
- if (result == VERIFICATION_FAILED){
- g_err << "performValidatePurged verification failed" << endl;
- return NDBT_FAILED;
- }
- g_err << "performValidatePurged failed" << endl;
- return NDBT_FAILED;
- }
- return NDBT_OK;
- }
-
- return NDBT_FAILED;
-
-}
-
-int Bank::findLastGL(Uint64 &lastTime){
-
- int check;
- /**
- * SELECT MAX(time) FROM GL
- */
- NdbConnection* pScanTrans = m_ndb.startTransaction();
- if (pScanTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
- if (pOp == NULL) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanRead(64);
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* timeRec = pOp->getValue("TIME");
- if( timeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pScanTrans->executeScan();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- int rows = 0;
- eof = pScanTrans->nextScanResult();
- lastTime = 0;
-
- while(eof == 0){
- rows++;
- Uint64 t = timeRec->u_32_value();
-
- if (t > lastTime)
- lastTime = t;
-
- eof = pScanTrans->nextScanResult();
- }
- if (eof == -1) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pScanTrans);
-
- return NDBT_OK;
-}
-
-
-int Bank::performMakeGL(int time){
- g_info << "performMakeGL: " << time << endl;
- /**
- * Create one GL record for each account type.
- * All in the same transaction
- */
- // Start transaction
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL){
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
- for (int i = 0; i < getNumAccountTypes(); i++){
-
- if (performMakeGLForAccountType(pTrans, time, i) != NDBT_OK){
- g_err << "performMakeGLForAccountType returned NDBT_FAILED"<<endl;
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- }
- // Execute transaction
- if( pTrans->execute(Commit) == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- m_ndb.closeTransaction(pTrans);
-
- return NDBT_OK;
-}
-
-int Bank::performMakeGLForAccountType(NdbConnection* pTrans,
- Uint64 glTime,
- Uint32 accountTypeId){
- int check;
-
- Uint32 balance = 0;
- Uint32 withdrawalCount = 0;
- Uint32 withdrawalSum = 0;
- Uint32 depositSum = 0;
- Uint32 depositCount = 0;
- Uint32 countTransactions = 0;
- Uint32 purged = 0;
-
- // Insert record in GL so that we know
- // that no one else is performing the same task
- // Set purged = 0 to indicate that TRANSACTION
- // records still exist
- NdbOperation* pOp = pTrans->getNdbOperation("GL");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->insertTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->equal("TIME", glTime);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->setValue("BALANCE", balance);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->setValue("DEPOSIT_COUNT", depositCount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->setValue("DEPOSIT_SUM", depositSum);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->setValue("WITHDRAWAL_COUNT", withdrawalCount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->setValue("WITHDRAWAL_SUM", withdrawalSum);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->setValue("PURGED", purged);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(NoCommit);
- if( check == -1 ) {
- ERR(pOp->getNdbError());
- return NDBT_FAILED;
- }
-
- // Read previous GL record to get old balance
- NdbOperation* pOp2 = pTrans->getNdbOperation("GL");
- if (pOp2 == NULL) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp2->readTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp2->equal("TIME", glTime-1);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp2->equal("ACCOUNT_TYPE", accountTypeId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- NdbRecAttr* oldBalanceRec = pOp2->getValue("BALANCE");
- if( oldBalanceRec == NULL ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(NoCommit);
- if( check == -1 ) {
- ERR(pOp2->getNdbError());
- return NDBT_FAILED;
- }
-
- Uint32 oldBalance = oldBalanceRec->u_32_value();
- // ndbout << "oldBalance = "<<oldBalance<<endl;
- balance = oldBalance;
- // Start a scan transaction to search
- // for TRANSACTION records with TIME = time
- // and ACCOUNT_TYPE = accountTypeId
- // Build sum of all found transactions
-
- if (sumTransactionsForGL(glTime,
- accountTypeId,
- balance,
- withdrawalCount,
- withdrawalSum,
- depositSum,
- depositCount,
- countTransactions,
- pTrans) != NDBT_OK){
- return NDBT_FAILED;
- }
- // ndbout << "sumTransactionsForGL completed" << endl;
- // ndbout << "balance="<<balance<<endl
- // << "withdrawalCount="<<withdrawalCount<<endl
- // << "withdrawalSum="<<withdrawalSum<<endl
- // << "depositCount="<<depositCount<<endl
- // << "depositSum="<<depositSum<<endl;
-
-
-
- NdbOperation* pOp3 = pTrans->getNdbOperation("GL");
- if (pOp3 == NULL) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp3->updateTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp3->equal("TIME", glTime);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp3->equal("ACCOUNT_TYPE", accountTypeId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp3->setValue("BALANCE", balance);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp3->setValue("DEPOSIT_COUNT", depositCount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp3->setValue("DEPOSIT_SUM", depositSum);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp3->setValue("WITHDRAWAL_COUNT", withdrawalCount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp3->setValue("WITHDRAWAL_SUM", withdrawalSum);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp3->setValue("PURGED", purged);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- // Execute transaction
- check = pTrans->execute(NoCommit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- return NDBT_OK;
-}
-
-
-
-
-int Bank::sumTransactionsForGL(const Uint64 glTime,
- const Uint32 accountType,
- Uint32& balance,
- Uint32& withdrawalCount,
- Uint32& withdrawalSum,
- Uint32& depositSum,
- Uint32& depositCount,
- Uint32& transactionsCount,
- NdbConnection* pTrans){
- int check;
-
- // g_info << "sumTransactionsForGL: " << glTime << ", " << accountType << endl;
-
- NdbConnection* pScanTrans = m_ndb.startTransaction();
- if (pScanTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION");
- if (pOp == NULL) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanExclusive(64);
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
- if( accountTypeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* timeRec = pOp->getValue("TIME");
- if( timeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* transTypeRec = pOp->getValue("TRANSACTION_TYPE");
- if( transTypeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* amountRec = pOp->getValue("AMOUNT");
- if( amountRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pScanTrans->executeScan();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- int rows = 0;
- int rowsFound = 0;
- eof = pScanTrans->nextScanResult();
-
- while(eof == 0){
- rows++;
- Uint32 a = accountTypeRec->u_32_value();
- Uint64 t = timeRec->u_64_value();
-
- if (a == accountType && t == glTime){
- rowsFound++;
- // One record found
- int transType = transTypeRec->u_32_value();
- int amount = amountRec->u_32_value();
- if (transType == WithDrawal){
- withdrawalCount++;
- withdrawalSum += amount;
- balance -= amount;
- } else {
- assert(transType == Deposit);
- depositCount++;
- depositSum += amount;
- balance += amount;
- }
- }
-
- eof = pScanTrans->nextScanResult();
-
- if ((rows % 100) == 0){
- // "refresh" ownner transaction every 100th row
- if (pTrans->refresh() == -1) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
- }
-
- }
- if (eof == -1) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pScanTrans);
- // ndbout << rows << " TRANSACTIONS have been read" << endl;
- transactionsCount = rowsFound;
-
- return NDBT_OK;
-
-}
-
- int Bank::performValidateGLs(Uint64 age){
-
- Uint64 currTime;
- if (getCurrTime(currTime) != NDBT_OK){
- return NDBT_FAILED;
- }
- Uint64 glTime = currTime - 1;
- while((glTime > 0) && ((glTime + age) >= currTime)){
-
- int result = performValidateGL(glTime);
- if (result != NDBT_OK){
- g_err << "performValidateGL failed" << endl;
- return result;
- }
-
- glTime--;
- }
-
- return NDBT_OK;
- }
-
-int Bank::performValidateGL(Uint64 glTime){
-
- ndbout << "performValidateGL: " << glTime << endl;
- /**
- * Rules:
- * - There should be zero or NoAccountTypes GL records for each glTime
- * - If purged == 0, then the TRANSACTION table should be checked
- * to see that there are:
- * + DEPOSIT_COUNT deposit transactions with account_type == ACCOUNT_TYPE
- * and TIME == glTime. The sum of these transactions should be
- * DEPOSIT_SUM
- * + WITHDRAWAL_COUNT withdrawal transactions with account_type ==
- * ACCOUNT_TYPE and TIME == glTime. The sum of these transactions
- * should be WITHDRAWAL_SUM
- * + BALANCE should be equal to the sum of all transactions plus
- * the balance of the previous GL record
- * - If purged == 1 then there should be NO transactions with TIME == glTime
- * and ACCOUNT_TYPE == account_type
- *
- */
-
- int check;
- /**
- * SELECT * FROM GL WHERE account_type = @accountType and time = @time
- */
- NdbConnection* pScanTrans = m_ndb.startTransaction();
- if (pScanTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
- if (pOp == NULL) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanRead(64);
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
- if( accountTypeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* timeRec = pOp->getValue("TIME");
- if( timeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* purgedRec = pOp->getValue("PURGED");
- if( purgedRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
- if( balanceRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* depositSumRec = pOp->getValue("DEPOSIT_SUM");
- if( depositSumRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* depositCountRec = pOp->getValue("DEPOSIT_COUNT");
- if( depositCountRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* withdrawalSumRec = pOp->getValue("WITHDRAWAL_SUM");
- if( withdrawalSumRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
- NdbRecAttr* withdrawalCountRec = pOp->getValue("WITHDRAWAL_COUNT");
- if( withdrawalCountRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pScanTrans->executeScan();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- int rows = 0;
- int countGlRecords = 0;
- int result = NDBT_OK;
- eof = pScanTrans->nextScanResult();
-
- while(eof == 0){
- rows++;
- Uint64 t = timeRec->u_64_value();
-
- if (t == glTime){
- countGlRecords++;
- Uint32 a = accountTypeRec->u_32_value();
- Uint32 purged = purgedRec->u_32_value();
- Uint32 wsum = withdrawalSumRec->u_32_value();
- Uint32 wcount = withdrawalCountRec->u_32_value();
- Uint32 dsum = depositSumRec->u_32_value();
- Uint32 dcount = depositCountRec->u_32_value();
- Uint32 b = balanceRec->u_32_value();
-
- Uint32 balance = 0;
- Uint32 withdrawalSum = 0;
- Uint32 withdrawalCount = 0;
- Uint32 depositSum = 0;
- Uint32 depositCount = 0;
- Uint32 countTransactions = 0;
- if (purged == 0){
- // If purged == 0, then the TRANSACTION table should be checked
- // to see that there are:
- // + DEPOSIT_COUNT deposit transactions with account_type == ACCOUNT_TYPE
- // and TIME == glTime. The sum of these transactions should be
- // DEPOSIT_SUM
- // + WITHDRAWAL_COUNT withdrawal transactions with account_type ==
- // ACCOUNT_TYPE and TIME == glTime. The sum of these transactions
- // should be WITHDRAWAL_SUM
- // + BALANCE should be equal to the sum of all transactions plus
- // the balance of the previous GL record
- if (sumTransactionsForGL(t,
- a,
- balance,
- withdrawalCount,
- withdrawalSum,
- depositSum,
- depositCount,
- countTransactions,
- pScanTrans) != NDBT_OK){
- result = NDBT_FAILED;
- } else {
- Uint32 prevBalance = 0;
- if (getBalanceForGL(t-1, a, prevBalance) != NDBT_OK){
- result = NDBT_FAILED;
- } else
- if (((prevBalance + balance) != b) ||
- (wsum != withdrawalSum) ||
- (wcount != withdrawalCount) ||
- (dsum != depositSum) ||
- (dcount != depositCount)){
- g_err << "performValidateGL, sums and counts failed" << endl
- << "balance : " << balance+prevBalance << "!="<<b<<endl
- << "with sum : " << withdrawalSum << "!="<<wsum<<endl
- << "with count: " << withdrawalCount << "!="<<wcount<<endl
- << "dep sum : " << depositSum << "!="<<dsum<<endl
- << "dep count : " << depositCount << "!="<<dcount<<endl;
- result = VERIFICATION_FAILED;
- }
- }
-
- } else {
- assert(purged == 1);
- // If purged == 1 then there should be NO transactions with
- // TIME == glTime and ACCOUNT_TYPE == account_type
-
- if (sumTransactionsForGL(t,
- a,
- balance,
- withdrawalCount,
- withdrawalSum,
- depositSum,
- depositCount,
- countTransactions,
- pScanTrans) != NDBT_OK){
- result = NDBT_FAILED;
- } else {
- if (countTransactions != 0){
- g_err << "performValidateGL, countTransactions("<<countTransactions<<") != 0" << endl;
- result = VERIFICATION_FAILED;
- }
- }
- }
-
- }
- eof = pScanTrans->nextScanResult();
- }
- if (eof == -1) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pScanTrans);
-
- // - There should be zero or NoAccountTypes GL records for each glTime
- if ((countGlRecords != 0) && (countGlRecords != getNumAccountTypes())){
- g_err << "performValidateGL: " << endl
- << "countGlRecords = " << countGlRecords << endl;
- result = VERIFICATION_FAILED;
- }
-
- return result;
-
-
- }
-
-int Bank::getBalanceForGL(const Uint64 glTime,
- const Uint32 accountTypeId,
- Uint32 &balance){
- int check;
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pTrans->getNdbOperation("GL");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->readTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->equal("TIME", glTime);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
- if( balanceRec == NULL ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pTrans);
-
- balance = balanceRec->u_32_value();
-
- return NDBT_OK;
-}
-
-
-
-int Bank::getOldestPurgedGL(const Uint32 accountType,
- Uint64 &oldest){
- int check;
- /**
- * SELECT MAX(time) FROM GL WHERE account_type = @accountType and purged=1
- */
- NdbConnection* pScanTrans = m_ndb.startTransaction();
- if (pScanTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
- if (pOp == NULL) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanRead(64);
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
- if( accountTypeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* timeRec = pOp->getValue("TIME");
- if( timeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* purgedRec = pOp->getValue("PURGED");
- if( purgedRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pScanTrans->executeScan();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- int rows = 0;
- eof = pScanTrans->nextScanResult();
- oldest = 0;
-
- while(eof == 0){
- rows++;
- Uint32 a = accountTypeRec->u_32_value();
- Uint32 p = purgedRec->u_32_value();
-
- if (a == accountType && p == 1){
- // One record found
- Uint64 t = timeRec->u_64_value();
- if (t > oldest)
- oldest = t;
- }
- eof = pScanTrans->nextScanResult();
- }
- if (eof == -1) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pScanTrans);
-
- return NDBT_OK;
-}
-
-int Bank::getOldestNotPurgedGL(Uint64 &oldest,
- Uint32 &accountTypeId,
- bool &found){
- int check;
- /**
- * SELECT time, accountTypeId FROM GL
- * WHERE purged=0 order by time asc
- */
- NdbConnection* pScanTrans = m_ndb.startTransaction();
- if (pScanTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
- if (pOp == NULL) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanRead(64);
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
- if( accountTypeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* timeRec = pOp->getValue("TIME");
- if( timeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* purgedRec = pOp->getValue("PURGED");
- if( purgedRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pScanTrans->executeScan();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- int rows = 0;
- eof = pScanTrans->nextScanResult();
- oldest = (Uint64)-1;
- found = false;
-
- while(eof == 0){
- rows++;
- Uint32 p = purgedRec->u_32_value();
- if (p == 0){
- found = true;
- // One record found
- Uint32 a = accountTypeRec->u_32_value();
- Uint64 t = timeRec->u_64_value();
- if (t < oldest){
- oldest = t;
- accountTypeId = a;
- }
- }
- eof = pScanTrans->nextScanResult();
- }
- if (eof == -1) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pScanTrans);
-
- return NDBT_OK;
-}
-
-
-int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
- const Uint64 oldest){
- /**
- * SELECT COUNT(transaction_id) FROM TRANSACTION
- * WHERE account_type = @accountType and time <= @oldest
- *
- */
-
- int check;
- NdbConnection* pScanTrans = m_ndb.startTransaction();
- if (pScanTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION");
- if (pOp == NULL) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanRead(64);
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
- if( accountTypeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* timeRec = pOp->getValue("TIME");
- if( timeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* transactionIdRec = pOp->getValue("TRANSACTION_ID");
- if( transactionIdRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pScanTrans->executeScan();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- int rows = 0;
- int found = 0;
- eof = pScanTrans->nextScanResult();
-
- while(eof == 0){
- rows++;
- Uint32 a = accountTypeRec->u_32_value();
- Uint32 t = timeRec->u_32_value();
-
- if (a == accountType && t <= oldest){
- // One record found
- Uint64 ti = transactionIdRec->u_64_value();
- g_err << "checkNoTransactionsOlderThan found one record" << endl
- << " t = " << t << endl
- << " a = " << a << endl
- << " ti = " << ti << endl;
- found++;
- }
- eof = pScanTrans->nextScanResult();
- }
- if (eof == -1) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pScanTrans);
-
- if (found == 0)
- return NDBT_OK;
- else
- return VERIFICATION_FAILED;
-}
-
-
- int Bank::performValidatePurged(){
- /**
- * Make sure there are no TRANSACTIONS older than the oldest
- * purged GL record
- *
- */
-
- for (int i = 0; i < getNumAccountTypes(); i++){
- ndbout << "performValidatePurged: " << i << endl;
- Uint64 oldestGlTime;
- if (getOldestPurgedGL(i, oldestGlTime) != NDBT_OK){
- g_err << "getOldestPurgedGL failed" << endl;
- return NDBT_FAILED;
- }
- int result = checkNoTransactionsOlderThan(i, oldestGlTime);
- if (result != NDBT_OK){
- g_err << "checkNoTransactionsOlderThan failed" << endl;
- return result;
- }
-
- }
-
- return NDBT_OK;
- }
-
- int Bank::purgeOldGLTransactions(Uint64 currTime, Uint32 age){
- /**
- * For each GL record that are older than age and have purged == 0
- * - delete all TRANSACTIONS belonging to the GL and set purged = 1
- *
- *
- */
- bool found;
- int count = 0;
-
- while(1){
- count++;
- if (count > 100)
- return NDBT_OK;
-
- // Search for the oldest GL record with purged == 0
- Uint64 oldestGlTime;
- Uint32 accountTypeId;
- if (getOldestNotPurgedGL(oldestGlTime, accountTypeId, found) != NDBT_OK){
- g_err << "getOldestNotPurgedGL failed" << endl;
- return NDBT_FAILED;
- }
-
-
- if (found == false){
- // ndbout << "not found" << endl;
- return NDBT_OK;
- }
-
-
-// ndbout << "purgeOldGLTransactions" << endl
-// << " oldestGlTime = " << oldestGlTime << endl
-// << " currTime = " << currTime << endl
-// << " age = " << age << endl;
- // Check if this GL is old enough to be purged
- if ((currTime < age) || (oldestGlTime > (currTime-age))){
- // ndbout << "is not old enough" << endl;
- return NDBT_OK;
- }
-
- if (purgeTransactions(oldestGlTime, accountTypeId) != NDBT_OK){
- g_err << "purgeTransactions failed" << endl;
- return NDBT_FAILED;
- }
- }
- g_err << "abnormal return" << endl;
- return NDBT_FAILED;
- }
-
-
-int Bank::purgeTransactions(const Uint64 glTime,
- const Uint32 accountTypeId)
-{
- int check;
- g_info << "purgeTransactions: " << glTime << ", "<<accountTypeId<<endl;
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL){
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- // Start by updating the GL record with purged = 1, use NoCommit
- NdbOperation* pOp = pTrans->getNdbOperation("GL");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->updateTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->equal("TIME", glTime);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- Uint32 purged = 1;
- check = pOp->setValue("PURGED", purged);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- // Execute transaction
- check = pTrans->execute(NoCommit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- // Find all transactions and take over them for delete
-
- if(findTransactionsToPurge(glTime,
- accountTypeId,
- pTrans) != NDBT_OK){
- g_err << "findTransactionToPurge failed" << endl;
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
-
-
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pTrans);
- return NDBT_OK;
-}
-
-
-int Bank::findTransactionsToPurge(const Uint64 glTime,
- const Uint32 accountType,
- NdbConnection* pTrans){
- int check;
-
- NdbConnection* pScanTrans = m_ndb.startTransaction();
- if (pScanTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION");
- if (pOp == NULL) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanExclusive(64);
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* timeRec = pOp->getValue("TIME");
- if( timeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
- if( accountTypeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pScanTrans->executeScan();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- int rows = 0;
- int rowsFound = 0;
- eof = pScanTrans->nextScanResult();
-
- while(eof == 0){
- rows++;
- Uint64 t = timeRec->u_64_value();
- Uint32 a = accountTypeRec->u_32_value();
-
- if (a == accountType && t == glTime){
- rowsFound++;
- // One record found
- NdbOperation* pDelOp = pOp->takeOverForDelete(pTrans);
- if (pDelOp == NULL){
- ERR(m_ndb.getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- // Execute transaction
- check = pTrans->execute(NoCommit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
- }
- eof = pScanTrans->nextScanResult();
- }
- if (eof == -1) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pScanTrans);
- // ndbout << rowsFound << " TRANSACTIONS have been deleted" << endl;
-
- return NDBT_OK;
-
-}
-
-
- int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield){
- if (init() != NDBT_OK)
- return NDBT_FAILED;
-
- int yieldCounter = 0;
-
- while(1){
-
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- while(1){
-
- Uint64 currTime;
- if (incCurrTime(currTime) != NDBT_OK)
- break;
-
- g_info << "Current time is " << currTime << endl;
- if (maxSleepBetweenDays > 0){
- int val = myRandom48(maxSleepBetweenDays);
- NdbSleep_SecSleep(val);
- }
-
- yieldCounter++;
- if (yield != 0 && yieldCounter >= yield)
- return NDBT_OK;
-
- }
- }
- return NDBT_FAILED;
- }
-
-
-
-int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){
-
- int check;
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL){
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->readTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* valueRec = pOp->getValue("VALUE");
- if( valueRec ==NULL ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- value = valueRec->u_64_value();
-
- m_ndb.closeTransaction(pTrans);
- return NDBT_OK;
-
-}
-
-int Bank::writeSystemValue(SystemValueId sysValId, Uint64 value){
-
- int check;
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL){
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->insertTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->setValue("VALUE", value);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pTrans);
- return NDBT_OK;
-
-}
-
-int Bank::getNextTransactionId(Uint64 &value){
- return increaseSystemValue2(LastTransactionId, value);
-}
-
-int Bank::incCurrTime(Uint64 &value){
- return increaseSystemValue(CurrentTime, value);
-}
-
-
-int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
- /**
- * Increase value with one and return
- * updated value
- *
- */
-
- int check;
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL){
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->readTupleExclusive();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* valueRec = pOp->getValue("VALUE");
- if( valueRec ==NULL ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(NoCommit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- value = valueRec->u_64_value();
- value++;
-
- NdbOperation* pOp2 = pTrans->getNdbOperation("SYSTEM_VALUES");
- if (pOp2 == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp2->updateTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp2->equal("SYSTEM_VALUES_ID", sysValId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp2->setValue("VALUE", value);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp3 = pTrans->getNdbOperation("SYSTEM_VALUES");
- if (pOp3 == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp3->readTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp3->equal("SYSTEM_VALUES_ID", sysValId);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- // Read new value
- NdbRecAttr* valueNewRec = pOp3->getValue("VALUE");
- if( valueNewRec ==NULL ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- // Check that value updated equals the value we read after the update
- if (valueNewRec->u_64_value() != value){
- g_err << "getNextTransactionId: value was not updated" << endl;
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pTrans);
-
-
- return 0;
-
-}
-
-int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){
- /**
- * Increase value with one and return
- * updated value
- * A more optimized version using interpreted update!
- *
- */
-
- int check;
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL){
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpretedUpdateTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->equal("SYSTEM_VALUES_ID", sysValId );
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- Uint32 valToIncWith = 1;
- check = pOp->incValue("VALUE", valToIncWith);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* valueRec = pOp->getValue("VALUE");
- if( valueRec == NULL ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- value = valueRec->u_64_value();
-
- m_ndb.closeTransaction(pTrans);
-
- return 0;
-
-}
-
-
-
-int Bank::getCurrTime(Uint64 &time){
- return readSystemValue(CurrentTime, time);
-}
-
-
-int Bank::performSumAccounts(int maxSleepBetweenSums, int yield){
- if (init() != NDBT_OK)
- return NDBT_FAILED;
-
- int yieldCounter = 0;
-
- while (1){
-
- while (m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- Uint32 sumAccounts = 0;
- Uint32 numAccounts = 0;
- if (getSumAccounts(sumAccounts, numAccounts) != NDBT_OK){
- g_err << "getSumAccounts FAILED" << endl;
- } else {
-
- g_info << "num="<<numAccounts<<", sum=" << sumAccounts << endl;
-
- if (sumAccounts != (10000000 + (10000*(numAccounts-1)))){
- g_err << "performSumAccounts FAILED" << endl
- << " sumAccounts="<<sumAccounts<<endl
- << " expected ="<<(10000000 + (10000*(numAccounts-1)))<<endl
- << " numAccounts="<<numAccounts<<endl;
- return NDBT_FAILED;
- }
-
- if (maxSleepBetweenSums > 0){
- int val = myRandom48(maxSleepBetweenSums);
- NdbSleep_MilliSleep(val);
- }
- }
-
- yieldCounter++;
- if (yield != 0 && yieldCounter >= yield)
- return NDBT_OK;
- }
- return NDBT_FAILED;
-}
-
-
-int Bank::getSumAccounts(Uint32 &sumAccounts,
- Uint32 &numAccounts){
-
- // SELECT SUM(balance) FROM ACCOUNT
-
- int check;
- NdbConnection* pScanTrans = m_ndb.startTransaction();
- if (pScanTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pScanTrans->getNdbOperation("ACCOUNT");
- if (pOp == NULL) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanExclusive(64);
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
- if( balanceRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pScanTrans->executeScan();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL) {
- ERR(m_ndb.getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- eof = pScanTrans->nextScanResult();
-
- while(eof == 0){
- Uint32 b = balanceRec->u_32_value();
-
- sumAccounts += b;
- numAccounts++;
-
- // ndbout << numAccounts << ": balance =" << b
- // << ", sum="<< sumAccounts << endl;
-
- // Take over the operation so that the lock is kept in db
- NdbOperation* pLockOp = pOp->takeOverForUpdate(pTrans);
- if (pLockOp == NULL){
- ERR(m_ndb.getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- Uint32 illegalBalance = 99;
- check = pLockOp->setValue("BALANCE", illegalBalance);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- // Execute transaction
- check = pTrans->execute(NoCommit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- eof = pScanTrans->nextScanResult();
- }
- if (eof == -1) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- // TODO Forget about rolling back, just close pTrans!!
-
- // Rollback transaction
- check = pTrans->execute(Rollback);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pScanTrans);
- m_ndb.closeTransaction(pTrans);
-
-
- return NDBT_OK;
-
-}
diff --git a/ndb/test/ndbapi/bank/src/BankLoad.cpp b/ndb/test/ndbapi/bank/src/BankLoad.cpp
deleted file mode 100644
index 985a49d5f64..00000000000
--- a/ndb/test/ndbapi/bank/src/BankLoad.cpp
+++ /dev/null
@@ -1,582 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "../Bank.hpp"
-#include <UtilTransactions.hpp>
-
-/**
- * Default account types
- *
- */
-struct AccountTypesStruct {
- int id;
- const char* descr;
-};
-const AccountTypesStruct accountTypes[] = {
- { 0, "KASSA"},
- { 1, "BANKOMAT"},
- { 2, "POSTGIRO"},
- { 3, "LÖNEKONTO"},
- { 4, "SPARKONTO"}
-};
-
-const int
-accountTypesSize = sizeof(accountTypes)/sizeof(AccountTypesStruct);
-
-
-const char* tableNames[] = {
- "GL",
- "ACCOUNT",
- "SYSTEM_VALUES",
- "TRANSACTION",
- "ACCOUNT_TYPE"
-};
-
-const int
-tableNamesSize = sizeof(tableNames)/sizeof(const char*);
-
-
-int Bank::getNumAccountTypes(){
- return accountTypesSize;
-}
-
-int Bank::createAndLoadBank(bool ovrWrt){
-
- m_ndb.init();
- if (m_ndb.waitUntilReady() != 0)
- return NDBT_FAILED;
-
- const NdbDictionary::Table* pSysValTab =
- m_ndb.getDictionary()->getTable("SYSTEM_VALUES");
- if (pSysValTab != NULL){
- // The table exists
- if (ovrWrt == false){
- ndbout << "Bank already exist and overwrite == false" << endl;
- return NDBT_FAILED;
- }
- }
-
- if (createTables() != NDBT_OK)
- return NDBT_FAILED;
-
- if (clearTables() != NDBT_OK)
- return NDBT_FAILED;
-
- if (loadAccountType() != NDBT_OK)
- return NDBT_FAILED;
-
- if (loadAccount(10) != NDBT_OK)
- return NDBT_FAILED;
-
- if (loadSystemValues() != NDBT_OK)
- return NDBT_FAILED;
-
- if (loadGl() != NDBT_OK)
- return NDBT_FAILED;
-
- return NDBT_OK;
-
-}
-
-int Bank::dropBank(){
-
- m_ndb.init();
- if (m_ndb.waitUntilReady() != 0)
- return NDBT_FAILED;
-
- if (dropTables() != NDBT_OK)
- return NDBT_FAILED;
-
- return NDBT_OK;
-
-}
-
-int Bank::createTables(){
- for (int i = 0; i < tableNamesSize; i++){
- if (createTable(tableNames[i]) != NDBT_OK)
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-
-int Bank::dropTables(){
- for (int i = 0; i < tableNamesSize; i++){
- if (dropTable(tableNames[i]) != NDBT_OK)
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int Bank::clearTables(){
- for (int i = 0; i < tableNamesSize; i++){
- if (clearTable(tableNames[i]) != NDBT_OK)
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int Bank::clearTable(const char* tabName){
- UtilTransactions util(&m_ndb, tabName);
- if(util.clearTable(&m_ndb, 64) != 0)
- return NDBT_FAILED;
- return NDBT_OK;
-}
-
-int Bank::createTable(const char* tabName){
- ndbout << "createTable " << tabName << endl;
-
- const NdbDictionary::Table* pTab = NDBT_Tables::getTable(tabName);
- if (pTab == NULL)
- return NDBT_FAILED;
-
- const NdbDictionary::Table* org =
- m_ndb.getDictionary()->getTable(tabName);
-
- if (org != 0 && pTab->equal(* org)){
- return NDBT_OK;
- }
-
- if (org != 0){
- ndbout << "Different table with same name exists" << endl;
- return NDBT_FAILED;
- }
-
- if(m_ndb.getDictionary()->createTable(* pTab) == -1){
- ndbout << "Failed to create table: " <<
- m_ndb.getNdbError() << endl;
- return NDBT_FAILED;
- }
-
- return NDBT_OK;
-}
-
-int Bank::dropTable(const char* tabName){
- const NdbDictionary::Table* org =
- m_ndb.getDictionary()->getTable(tabName);
-
- if (org == NULL)
- return NDBT_OK;
-
- ndbout << "dropTable " <<tabName<<endl;
- if (m_ndb.getDictionary()->dropTable(tabName) != 0){
- return NDBT_FAILED;
- }
-
- return NDBT_OK;
-}
-
-
-
-
-
-
-
-
-/**
- * Load SYSTEM_VALUES table
- * This table keeps track of system wide settings
- * For example:
- * - next transaction id
- *
- */
-int Bank::loadSystemValues (){
-int result;
-
-/**
- * Insert start value for next transaction id
- *
- */
-result = writeSystemValue(LastTransactionId, 0);
-
-/**
- * Insert start value for current time
- *
- */
-result = writeSystemValue(CurrentTime, 1);
-
-return result;
-
-}
-
-
-/**
- * Load GL table
- *
- * Insert GL records for time = 0 with balance 0
- */
-int Bank::loadGl(){
- g_info << "loadGl" << endl;
- int check;
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL){
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- for (int i = 0; i < getNumAccountTypes(); i++){
-
- NdbOperation* pOp = pTrans->getNdbOperation("GL");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->insertTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- Uint64 time = 0;
- check = pOp->equal("TIME", time);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->equal("ACCOUNT_TYPE", i);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- Uint32 balance = 0;
- if (getBalanceForAccountType(i, balance) != NDBT_OK){
- return NDBT_FAILED;
- }
-
- check = pOp->setValue("BALANCE", balance);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- Uint32 depositCount = 0;
- check = pOp->setValue("DEPOSIT_COUNT", depositCount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- Uint32 depositSum = 0;
- check = pOp->setValue("DEPOSIT_SUM", depositSum);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- Uint32 withdrawalCount = 0;
- check = pOp->setValue("WITHDRAWAL_COUNT", withdrawalCount);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- Uint32 withdrawalSum = 0;
- check = pOp->setValue("WITHDRAWAL_SUM", withdrawalSum);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- Uint32 purged = 1;
- check = pOp->setValue("PURGED", purged);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- }
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pTrans);
- return NDBT_OK;
-};
-
-
-int Bank::getBalanceForAccountType(const Uint32 accountType,
- Uint32& balance){
- int check;
- g_info << "getBalanceForAccountType: accountType="<<accountType<<endl;
-
- NdbConnection* pScanTrans = m_ndb.startTransaction();
- if (pScanTrans == NULL) {
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pScanTrans->getNdbOperation("ACCOUNT");
- if (pOp == NULL) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanRead(64);
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
- if( accountTypeRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
- if( balanceRec ==NULL ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- check = pScanTrans->executeScan();
- if( check == -1 ) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- int rows = 0;
- eof = pScanTrans->nextScanResult();
-
- while(eof == 0){
- rows++;
- Uint32 a = accountTypeRec->u_32_value();
- Uint32 b = balanceRec->u_32_value();
-
- if (a == accountType){
- // One record found
- balance += b;
- }
-
- eof = pScanTrans->nextScanResult();
- }
- if (eof == -1) {
- ERR(pScanTrans->getNdbError());
- m_ndb.closeTransaction(pScanTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pScanTrans);
- // ndbout << rows << " rows have been read" << endl;
-
- return NDBT_OK;
-
-}
-
-/**
- * Load ACCOUNT_TYPE table
- *
- *
- */
-int Bank::loadAccountType(){
- g_info << "loadAccountType" << endl;
- int check;
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL){
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- for (int i = 0; i < getNumAccountTypes(); i++){
-
- NdbOperation* pOp = pTrans->getNdbOperation("ACCOUNT_TYPE");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->insertTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->equal("ACCOUNT_TYPE_ID", accountTypes[i].id);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->setValue("DESCRIPTION", accountTypes[i].descr);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- }
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pTrans);
- return NDBT_OK;
-};
-
-/**
- * Load ACCOUNT table
- *
- *
- *
- */
-int Bank::loadAccount (int numAccounts){
- g_info << "loadAccount" << endl;
- int check;
-
- NdbConnection* pTrans = m_ndb.startTransaction();
- if (pTrans == NULL){
- ERR(m_ndb.getNdbError());
- return NDBT_FAILED;
- }
-
- for (int i = 0; i < numAccounts; i++){
-
- NdbOperation* pOp = pTrans->getNdbOperation("ACCOUNT");
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->insertTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->equal("ACCOUNT_ID", i);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- int owner;
- if (i == 0)
- owner = 0;
- else
- owner = i + 3000;
- check = pOp->setValue("OWNER", owner);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- // Load balance so that the bank's account = 0 has 10 millions
- // and all other accounts have 10000
- // This set the total balance for the entire bank to
- // 10000000 + (10000 * numAccounts-1)
- // Since no money should dissapear from to the bank nor
- // any money should be added this is a rule that can be checked when
- // validating the db
- int balance;
- if (i == 0){
- balance = 10000000;
- } else {
- balance = 10000;
- }
- check = pOp->setValue("BALANCE", balance);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- // TODO - This is how to set a value in a 16, 1 attribute, not so nice?
- // NOTE - its not even possible to set the value 0 in this column
- // since that is equal to NULL when casting to char*
- // check = pOp->setValue("ACCOUNT_TYPE", (const char*)(Uint16)(i/accountTypesSize), 2);
- // NOTE attribute now changed to be a 32 bit
-
-
- int accountType;
- if (i == 0)
- accountType = 0; // KASSA
- else
- accountType = ((i%accountTypesSize) == 0 ? 1 : (i%getNumAccountTypes()));
- check = pOp->setValue("ACCOUNT_TYPE", accountType);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- }
- check = pTrans->execute(Commit);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- m_ndb.closeTransaction(pTrans);
- return NDBT_OK;
-}
-
-
-int Bank::getNumAccounts(){
- const NdbDictionary::Table* accountTab =
- m_ndb.getDictionary()->getTable("ACCOUNT");
- if (accountTab == NULL){
- g_err << "Table ACCOUNT does not exist" << endl;
- return NDBT_FAILED;
- }
- UtilTransactions util(*accountTab);
- if(util.selectCount(&m_ndb, 64, &m_maxAccount) != 0)
- return NDBT_FAILED;
- return NDBT_OK;
-}
-
-int Bank::getMaxAmount(){
- return 10000;
-}
diff --git a/ndb/test/ndbapi/bank/testBank.cpp b/ndb/test/ndbapi/bank/testBank.cpp
new file mode 100644
index 00000000000..77ac1172d7c
--- /dev/null
+++ b/ndb/test/ndbapi/bank/testBank.cpp
@@ -0,0 +1,150 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbRestarter.hpp>
+#include <NdbBackup.hpp>
+
+
+#define CHECK(b) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ continue; }
+
+
+#include "Bank.hpp"
+
+int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int overWriteExisting = true;
+ if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int wait = 30; // Max seconds between each "day"
+ int yield = 1; // Loops before bank returns
+
+ while (ctx->isTestStopped() == false) {
+ bank.performIncreaseTime(wait, yield);
+ }
+ return NDBT_OK;
+}
+
+int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int wait = 10; // Max ms between each transaction
+ int yield = 100; // Loops before bank returns
+
+ while (ctx->isTestStopped() == false) {
+ bank.performTransactions(wait, yield);
+ }
+ return NDBT_OK;
+}
+
+int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int yield = 20; // Loops before bank returns
+ int result = NDBT_OK;
+
+ while (ctx->isTestStopped() == false) {
+ if (bank.performMakeGLs(yield) != NDBT_OK){
+ ndbout << "bank.performMakeGLs FAILED" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+ return NDBT_OK;
+}
+
+int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int wait = 2000; // Max ms between each sum of accounts
+ int yield = 1; // Loops before bank returns
+ int result = NDBT_OK;
+
+ while (ctx->isTestStopped() == false) {
+ if (bank.performSumAccounts(wait, yield) != NDBT_OK){
+ ndbout << "bank.performSumAccounts FAILED" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+ return result ;
+}
+
+int runDropBank(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ if (bank.dropBank() != NDBT_OK)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+int runBankController(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int l = 0;
+ int result = NDBT_OK;
+
+ while (l < loops && result != NDBT_FAILED){
+
+ if (pNdb->waitUntilReady() != 0){
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ // Sleep for a while
+ NdbSleep_SecSleep(records);
+
+ l++;
+ }
+
+ if (pNdb->waitUntilReady() != 0){
+ result = NDBT_FAILED;
+ }
+
+ ctx->stopTest();
+
+ return result;
+}
+
+NDBT_TESTSUITE(testBank);
+TESTCASE("Bank",
+ "Run the bank\n"){
+ INITIALIZER(runCreateBank);
+ STEP(runBankTimer);
+ STEP(runBankTransactions);
+ STEP(runBankGL);
+ // TODO STEP(runBankSum);
+ STEP(runBankController);
+ FINALIZER(runDropBank);
+
+}
+NDBT_TESTSUITE_END(testBank);
+
+int main(int argc, const char** argv){
+ // Tables should not be auto created
+ testBank.setCreateTable(false);
+
+ return testBank.execute(argc, argv);
+}
+
+
diff --git a/ndb/test/ndbapi/bank/testBank/testBank.cpp b/ndb/test/ndbapi/bank/testBank/testBank.cpp
deleted file mode 100644
index 094ecaa499c..00000000000
--- a/ndb/test/ndbapi/bank/testBank/testBank.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NDBT.hpp>
-#include <NDBT_Test.hpp>
-#include <HugoTransactions.hpp>
-#include <UtilTransactions.hpp>
-#include <NdbRestarter.hpp>
-#include <NdbBackup.hpp>
-
-
-#define CHECK(b) if (!(b)) { \
- g_err << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- continue; }
-
-
-#include "../Bank.hpp"
-
-int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int overWriteExisting = true;
- if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK)
- return NDBT_FAILED;
- return NDBT_OK;
-}
-
-int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int wait = 30; // Max seconds between each "day"
- int yield = 1; // Loops before bank returns
-
- while (ctx->isTestStopped() == false) {
- bank.performIncreaseTime(wait, yield);
- }
- return NDBT_OK;
-}
-
-int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int wait = 10; // Max ms between each transaction
- int yield = 100; // Loops before bank returns
-
- while (ctx->isTestStopped() == false) {
- bank.performTransactions(wait, yield);
- }
- return NDBT_OK;
-}
-
-int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int yield = 20; // Loops before bank returns
- int result = NDBT_OK;
-
- while (ctx->isTestStopped() == false) {
- if (bank.performMakeGLs(yield) != NDBT_OK){
- ndbout << "bank.performMakeGLs FAILED" << endl;
- result = NDBT_FAILED;
- }
- }
- return NDBT_OK;
-}
-
-int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int wait = 2000; // Max ms between each sum of accounts
- int yield = 1; // Loops before bank returns
- int result = NDBT_OK;
-
- while (ctx->isTestStopped() == false) {
- if (bank.performSumAccounts(wait, yield) != NDBT_OK){
- ndbout << "bank.performSumAccounts FAILED" << endl;
- result = NDBT_FAILED;
- }
- }
- return result ;
-}
-
-int runDropBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- if (bank.dropBank() != NDBT_OK)
- return NDBT_FAILED;
- return NDBT_OK;
-}
-
-int runBankController(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int l = 0;
- int result = NDBT_OK;
-
- while (l < loops && result != NDBT_FAILED){
-
- if (pNdb->waitUntilReady() != 0){
- result = NDBT_FAILED;
- continue;
- }
-
- // Sleep for a while
- NdbSleep_SecSleep(records);
-
- l++;
- }
-
- if (pNdb->waitUntilReady() != 0){
- result = NDBT_FAILED;
- }
-
- ctx->stopTest();
-
- return result;
-}
-
-NDBT_TESTSUITE(testBank);
-TESTCASE("Bank",
- "Run the bank\n"){
- INITIALIZER(runCreateBank);
- STEP(runBankTimer);
- STEP(runBankTransactions);
- STEP(runBankGL);
- // TODO STEP(runBankSum);
- STEP(runBankController);
- FINALIZER(runDropBank);
-
-}
-NDBT_TESTSUITE_END(testBank);
-
-int main(int argc, const char** argv){
- // Tables should not be auto created
- testBank.setCreateTable(false);
-
- return testBank.execute(argc, argv);
-}
-
-
diff --git a/ndb/test/ndbapi/ronja/benchronja/benchronja.cpp b/ndb/test/ndbapi/benchronja.cpp
index ce0aee35e8f..ce0aee35e8f 100644
--- a/ndb/test/ndbapi/ronja/benchronja/benchronja.cpp
+++ b/ndb/test/ndbapi/benchronja.cpp
diff --git a/ndb/test/ndbapi/bulk_copy/bulk_copy.cpp b/ndb/test/ndbapi/bulk_copy.cpp
index 18881cae216..18881cae216 100644
--- a/ndb/test/ndbapi/bulk_copy/bulk_copy.cpp
+++ b/ndb/test/ndbapi/bulk_copy.cpp
diff --git a/ndb/test/ndbapi/vw_test/cdrserver.cpp b/ndb/test/ndbapi/cdrserver.cpp
index 8354d28f53f..8354d28f53f 100644
--- a/ndb/test/ndbapi/vw_test/cdrserver.cpp
+++ b/ndb/test/ndbapi/cdrserver.cpp
diff --git a/ndb/test/ndbapi/cello-sessionDb/celloDb.cpp b/ndb/test/ndbapi/celloDb.cpp
index ec61e783585..ec61e783585 100644
--- a/ndb/test/ndbapi/cello-sessionDb/celloDb.cpp
+++ b/ndb/test/ndbapi/celloDb.cpp
diff --git a/ndb/test/ndbapi/create_all_tabs/create_all_tabs.cpp b/ndb/test/ndbapi/create_all_tabs.cpp
index 55d04888144..55d04888144 100644
--- a/ndb/test/ndbapi/create_all_tabs/create_all_tabs.cpp
+++ b/ndb/test/ndbapi/create_all_tabs.cpp
diff --git a/ndb/test/ndbapi/create_tab/create_tab.cpp b/ndb/test/ndbapi/create_tab.cpp
index 8bb1e7a9572..8bb1e7a9572 100644
--- a/ndb/test/ndbapi/create_tab/create_tab.cpp
+++ b/ndb/test/ndbapi/create_tab.cpp
diff --git a/ndb/test/ndbapi/drop_all_tabs/drop_all_tabs.cpp b/ndb/test/ndbapi/drop_all_tabs.cpp
index 59c57396acd..59c57396acd 100644
--- a/ndb/test/ndbapi/drop_all_tabs/drop_all_tabs.cpp
+++ b/ndb/test/ndbapi/drop_all_tabs.cpp
diff --git a/ndb/test/ndbapi/flexAsynch.cpp b/ndb/test/ndbapi/flexAsynch.cpp
new file mode 100644
index 00000000000..396ac06c87a
--- /dev/null
+++ b/ndb/test/ndbapi/flexAsynch.cpp
@@ -0,0 +1,985 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+
+#include "NdbApi.hpp"
+#include <NdbSchemaCon.hpp>
+#include <NdbMain.h>
+#include <md5_hash.hpp>
+
+#include <NdbThread.h>
+#include <NdbSleep.h>
+#include <NdbTick.h>
+#include <NdbOut.hpp>
+#include <NdbTimer.hpp>
+#include <NDBT_Error.hpp>
+
+#include <NdbTest.hpp>
+
+#define MAX_PARTS 4
+#define MAX_SEEK 16
+#define MAXSTRLEN 16
+#define MAXATTR 64
+#define MAXTABLES 64
+#define MAXTHREADS 128
+#define MAXPAR 1024
+#define MAXATTRSIZE 1000
+#define PKSIZE 2
+
+enum StartType {
+ stIdle,
+ stInsert,
+ stRead,
+ stUpdate,
+ stDelete,
+ stStop
+} ;
+
+extern "C" { static void* threadLoop(void*); }
+static void setAttrNames(void);
+static void setTableNames(void);
+static int readArguments(int argc, const char** argv);
+static int createTables(Ndb*);
+static void defineOperation(NdbConnection* aTransObject, StartType aType,
+ Uint32 base, Uint32 aIndex);
+static void execute(StartType aType);
+static bool executeThread(StartType aType, Ndb* aNdbObject, unsigned int);
+static void executeCallback(int result, NdbConnection* NdbObject,
+ void* aObject);
+static bool error_handler(const NdbError & err);
+static Uint32 getKey(Uint32, Uint32) ;
+static void input_error();
+
+
+static int retry_opt = 3 ;
+static int failed = 0 ;
+
+ErrorData * flexAsynchErrorData;
+
+struct ThreadNdb
+{
+ int NoOfOps;
+ int ThreadNo;
+};
+
+static NdbThread* threadLife[MAXTHREADS];
+static int tNodeId;
+static int ThreadReady[MAXTHREADS];
+static StartType ThreadStart[MAXTHREADS];
+static char tableName[MAXTABLES][MAXSTRLEN+1];
+static char attrName[MAXATTR][MAXSTRLEN+1];
+
+// Program Parameters
+static bool tLocal = false;
+static int tLocalPart = 0;
+static int tSendForce = 0;
+static int tNoOfLoops = 1;
+static int tAttributeSize = 1;
+static unsigned int tNoOfThreads = 1;
+static unsigned int tNoOfParallelTrans = 32;
+static unsigned int tNoOfAttributes = 25;
+static unsigned int tNoOfTransactions = 500;
+static unsigned int tNoOfOpsPerTrans = 1;
+static unsigned int tLoadFactor = 80;
+static bool tempTable = false;
+static bool startTransGuess = true;
+
+//Program Flags
+static int theTestFlag = 0;
+static int theSimpleFlag = 0;
+static int theDirtyFlag = 0;
+static int theWriteFlag = 0;
+static int theStdTableNameFlag = 0;
+static int theTableCreateFlag = 0;
+
+#define START_REAL_TIME
+#define STOP_REAL_TIME
+#define START_TIMER { NdbTimer timer; timer.doStart();
+#define STOP_TIMER timer.doStop();
+#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
+
+static void
+resetThreads(){
+
+ for (int i = 0; i < tNoOfThreads ; i++) {
+ ThreadReady[i] = 0;
+ ThreadStart[i] = stIdle;
+ }//for
+}
+
+static void
+waitForThreads(void)
+{
+ int cont = 0;
+ do {
+ cont = 0;
+ NdbSleep_MilliSleep(20);
+ for (int i = 0; i < tNoOfThreads ; i++) {
+ if (ThreadReady[i] == 0) {
+ cont = 1;
+ }//if
+ }//for
+ } while (cont == 1);
+}
+
+static void
+tellThreads(StartType what)
+{
+ for (int i = 0; i < tNoOfThreads ; i++)
+ ThreadStart[i] = what;
+}
+
+NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
+{
+ ThreadNdb* pThreadData;
+ int tLoops=0;
+ int returnValue = NDBT_OK;
+
+ flexAsynchErrorData = new ErrorData;
+ flexAsynchErrorData->resetErrorCounters();
+
+ if (readArguments(argc, argv) != 0){
+ input_error();
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ pThreadData = new ThreadNdb[MAXTHREADS];
+
+ ndbout << endl << "FLEXASYNCH - Starting normal mode" << endl;
+ ndbout << "Perform benchmark of insert, update and delete transactions";
+ ndbout << endl;
+ ndbout << " " << tNoOfThreads << " number of concurrent threads " << endl;
+ ndbout << " " << tNoOfParallelTrans;
+ ndbout << " number of parallel operation per thread " << endl;
+ ndbout << " " << tNoOfTransactions << " transaction(s) per round " << endl;
+ ndbout << " " << tNoOfLoops << " iterations " << endl;
+ ndbout << " " << "Load Factor is " << tLoadFactor << "%" << endl;
+ ndbout << " " << tNoOfAttributes << " attributes per table " << endl;
+ ndbout << " " << tAttributeSize;
+ ndbout << " is the number of 32 bit words per attribute " << endl;
+ if (tempTable == true) {
+ ndbout << " Tables are without logging " << endl;
+ } else {
+ ndbout << " Tables are with logging " << endl;
+ }//if
+ if (startTransGuess == true) {
+ ndbout << " Transactions are executed with hint provided" << endl;
+ } else {
+ ndbout << " Transactions are executed with round robin scheme" << endl;
+ }//if
+ if (tSendForce == 0) {
+ ndbout << " No force send is used, adaptive algorithm used" << endl;
+ } else if (tSendForce == 1) {
+ ndbout << " Force send used" << endl;
+ } else {
+ ndbout << " No force send is used, adaptive algorithm disabled" << endl;
+ }//if
+
+ ndbout << endl;
+
+ NdbThread_SetConcurrencyLevel(2 + tNoOfThreads);
+
+ /* print Setting */
+ flexAsynchErrorData->printSettings(ndbout);
+
+ setAttrNames();
+ setTableNames();
+
+ Ndb * pNdb = new Ndb("TEST_DB");
+ pNdb->init();
+ tNodeId = pNdb->getNodeId();
+
+ ndbout << " NdbAPI node with id = " << pNdb->getNodeId() << endl;
+ ndbout << endl;
+
+ ndbout << "Waiting for ndb to become ready..." <<endl;
+ if (pNdb->waitUntilReady(10000) != 0){
+ ndbout << "NDB is not ready" << endl;
+ ndbout << "Benchmark failed!" << endl;
+ returnValue = NDBT_FAILED;
+ }
+
+ if(returnValue == NDBT_OK){
+ if (createTables(pNdb) != 0){
+ returnValue = NDBT_FAILED;
+ }
+ }
+
+ if(returnValue == NDBT_OK){
+ /****************************************************************
+ * Create NDB objects. *
+ ****************************************************************/
+ resetThreads();
+ for (int i = 0; i < tNoOfThreads ; i++) {
+ pThreadData[i].ThreadNo = i
+;
+ threadLife[i] = NdbThread_Create(threadLoop,
+ (void**)&pThreadData[i],
+ 32768,
+ "flexAsynchThread",
+ NDB_THREAD_PRIO_LOW);
+ }//for
+ ndbout << endl << "All NDB objects and table created" << endl << endl;
+ int noOfTransacts = tNoOfParallelTrans*tNoOfTransactions*tNoOfThreads;
+ /****************************************************************
+ * Execute program. *
+ ****************************************************************/
+
+ for(;;) {
+
+ int loopCount = tLoops + 1 ;
+ ndbout << endl << "Loop # " << loopCount << endl << endl ;
+
+ /****************************************************************
+ * Perform inserts. *
+ ****************************************************************/
+
+ failed = 0 ;
+
+ START_TIMER;
+ execute(stInsert);
+ STOP_TIMER;
+ PRINT_TIMER("insert", noOfTransacts, tNoOfOpsPerTrans);
+
+ if (0 < failed) {
+ int i = retry_opt ;
+ int ci = 1 ;
+ while (0 < failed && 0 < i){
+ ndbout << failed << " of the transactions returned errors!"
+ << endl << endl;
+ ndbout << "Attempting to redo the failed transactions now..."
+ << endl ;
+ ndbout << "Redo attempt " << ci <<" out of " << retry_opt
+ << endl << endl;
+ failed = 0 ;
+ START_TIMER;
+ execute(stInsert);
+ STOP_TIMER;
+ PRINT_TIMER("insert", noOfTransacts, tNoOfOpsPerTrans);
+ i-- ;
+ ci++;
+ }
+ if(0 == failed ){
+ ndbout << endl <<"Redo attempt succeeded" << endl << endl;
+ }else{
+ ndbout << endl <<"Redo attempt failed, moving on now..." << endl
+ << endl;
+ }//if
+ }//if
+
+ /****************************************************************
+ * Perform read. *
+ ****************************************************************/
+
+ failed = 0 ;
+
+ START_TIMER;
+ execute(stRead);
+ STOP_TIMER;
+ PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
+
+ if (0 < failed) {
+ int i = retry_opt ;
+ int cr = 1;
+ while (0 < failed && 0 < i){
+ ndbout << failed << " of the transactions returned errors!"<<endl ;
+ ndbout << endl;
+ ndbout <<"Attempting to redo the failed transactions now..." << endl;
+ ndbout << endl;
+ ndbout <<"Redo attempt " << cr <<" out of ";
+ ndbout << retry_opt << endl << endl;
+ failed = 0 ;
+ START_TIMER;
+ execute(stRead);
+ STOP_TIMER;
+ PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
+ i-- ;
+ cr++ ;
+ }//while
+ if(0 == failed ) {
+ ndbout << endl <<"Redo attempt succeeded" << endl << endl ;
+ }else{
+ ndbout << endl <<"Redo attempt failed, moving on now..." << endl << endl ;
+ }//if
+ }//if
+
+
+ /****************************************************************
+ * Perform update. *
+ ****************************************************************/
+
+ failed = 0 ;
+
+ START_TIMER;
+ execute(stUpdate);
+ STOP_TIMER;
+ PRINT_TIMER("update", noOfTransacts, tNoOfOpsPerTrans) ;
+
+ if (0 < failed) {
+ int i = retry_opt ;
+ int cu = 1 ;
+ while (0 < failed && 0 < i){
+ ndbout << failed << " of the transactions returned errors!"<<endl ;
+ ndbout << endl;
+ ndbout <<"Attempting to redo the failed transactions now..." << endl;
+ ndbout << endl <<"Redo attempt " << cu <<" out of ";
+ ndbout << retry_opt << endl << endl;
+ failed = 0 ;
+ START_TIMER;
+ execute(stUpdate);
+ STOP_TIMER;
+ PRINT_TIMER("update", noOfTransacts, tNoOfOpsPerTrans);
+ i-- ;
+ cu++ ;
+ }//while
+ if(0 == failed ){
+ ndbout << endl <<"Redo attempt succeeded" << endl << endl;
+ } else {
+ ndbout << endl;
+ ndbout <<"Redo attempt failed, moving on now..." << endl << endl;
+ }//if
+ }//if
+
+ /****************************************************************
+ * Perform read. *
+ ****************************************************************/
+
+ failed = 0 ;
+
+ START_TIMER;
+ execute(stRead);
+ STOP_TIMER;
+ PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
+
+ if (0 < failed) {
+ int i = retry_opt ;
+ int cr2 = 1 ;
+ while (0 < failed && 0 < i){
+ ndbout << failed << " of the transactions returned errors!"<<endl ;
+ ndbout << endl;
+ ndbout <<"Attempting to redo the failed transactions now..." << endl;
+ ndbout << endl <<"Redo attempt " << cr2 <<" out of ";
+ ndbout << retry_opt << endl << endl;
+ failed = 0 ;
+ START_TIMER;
+ execute(stRead);
+ STOP_TIMER;
+ PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
+ i-- ;
+ cr2++ ;
+ }//while
+ if(0 == failed ){
+ ndbout << endl <<"Redo attempt succeeded" << endl << endl;
+ }else{
+ ndbout << endl;
+ ndbout << "Redo attempt failed, moving on now..." << endl << endl;
+ }//if
+ }//if
+
+
+ /****************************************************************
+ * Perform delete. *
+ ****************************************************************/
+
+ failed = 0 ;
+
+ START_TIMER;
+ execute(stDelete);
+ STOP_TIMER;
+ PRINT_TIMER("delete", noOfTransacts, tNoOfOpsPerTrans);
+
+ if (0 < failed) {
+ int i = retry_opt ;
+ int cd = 1 ;
+ while (0 < failed && 0 < i){
+ ndbout << failed << " of the transactions returned errors!"<< endl ;
+ ndbout << endl;
+ ndbout <<"Attempting to redo the failed transactions now:" << endl ;
+ ndbout << endl <<"Redo attempt " << cd <<" out of ";
+ ndbout << retry_opt << endl << endl;
+ failed = 0 ;
+ START_TIMER;
+ execute(stDelete);
+ STOP_TIMER;
+ PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
+ i-- ;
+ cd++ ;
+ }//while
+ if(0 == failed ){
+ ndbout << endl <<"Redo attempt succeeded" << endl << endl ;
+ }else{
+ ndbout << endl;
+ ndbout << "Redo attempt failed, moving on now..." << endl << endl;
+ }//if
+ }//if
+
+ tLoops++;
+ ndbout << "--------------------------------------------------" << endl;
+
+ if(tNoOfLoops != 0){
+ if(tNoOfLoops <= tLoops)
+ break ;
+ }
+ }//for
+
+ execute(stStop);
+ void * tmp;
+ for(int i = 0; i<tNoOfThreads; i++){
+ NdbThread_WaitFor(threadLife[i], &tmp);
+ NdbThread_Destroy(&threadLife[i]);
+ }
+ }
+ delete [] pThreadData;
+ delete pNdb;
+
+ //printing errorCounters
+ flexAsynchErrorData->printErrorCounters(ndbout);
+
+ return NDBT_ProgramExit(returnValue);
+}//main()
+
+
+static void execute(StartType aType)
+{
+ resetThreads();
+ tellThreads(aType);
+ waitForThreads();
+}//execute()
+
+static void*
+threadLoop(void* ThreadData)
+{
+ Ndb* localNdb;
+ StartType tType;
+ ThreadNdb* tabThread = (ThreadNdb*)ThreadData;
+ int threadNo = tabThread->ThreadNo;
+ localNdb = new Ndb("TEST_DB");
+ localNdb->init(1024);
+ localNdb->waitUntilReady(10000);
+ unsigned int threadBase = (threadNo << 16) + tNodeId ;
+
+ for (;;){
+ while (ThreadStart[threadNo] == stIdle) {
+ NdbSleep_MilliSleep(10);
+ }//while
+
+ // Check if signal to exit is received
+ if (ThreadStart[threadNo] == stStop) {
+ break;
+ }//if
+
+ tType = ThreadStart[threadNo];
+ ThreadStart[threadNo] = stIdle;
+ if(!executeThread(tType, localNdb, threadBase)){
+ break;
+ }
+ ThreadReady[threadNo] = 1;
+ }//for
+
+ delete localNdb;
+ ThreadReady[threadNo] = 1;
+
+ NdbThread_Exit(0);
+ return NULL; // Just to keep compiler happy
+}//threadLoop()
+
+static
+bool
+executeThread(StartType aType, Ndb* aNdbObject, unsigned int threadBase) {
+ int i, j, k;
+ NdbConnection* tConArray[1024];
+ unsigned int tBase;
+ unsigned int tBase2;
+
+ for (i = 0; i < tNoOfTransactions; i++) {
+ if (tLocal == false) {
+ tBase = i * tNoOfParallelTrans * tNoOfOpsPerTrans;
+ } else {
+ tBase = i * tNoOfParallelTrans * MAX_SEEK;
+ }//if
+ START_REAL_TIME;
+ for (j = 0; j < tNoOfParallelTrans; j++) {
+ if (tLocal == false) {
+ tBase2 = tBase + (j * tNoOfOpsPerTrans);
+ } else {
+ tBase2 = tBase + (j * MAX_SEEK);
+ tBase2 = getKey(threadBase, tBase2);
+ }//if
+ if (startTransGuess == true) {
+ Uint64 Tkey64;
+ Uint32* Tkey32 = (Uint32*)&Tkey64;
+ Tkey32[0] = threadBase;
+ Tkey32[1] = tBase2;
+ tConArray[j] = aNdbObject->startTransaction((Uint32)0, //Priority
+ (const char*)&Tkey64, //Main PKey
+ (Uint32)4); //Key Length
+ } else {
+ tConArray[j] = aNdbObject->startTransaction();
+ }//if
+ if (tConArray[j] == NULL &&
+ !error_handler(aNdbObject->getNdbError()) ){
+ ndbout << endl << "Unable to recover! Quiting now" << endl ;
+ return false;
+ }//if
+
+ for (k = 0; k < tNoOfOpsPerTrans; k++) {
+ //-------------------------------------------------------
+ // Define the operation, but do not execute it yet.
+ //-------------------------------------------------------
+ defineOperation(tConArray[j], aType, threadBase, (tBase2 + k));
+ }//for
+
+ tConArray[j]->executeAsynchPrepare(Commit, &executeCallback, NULL);
+ }//for
+ STOP_REAL_TIME;
+ //-------------------------------------------------------
+ // Now we have defined a set of operations, it is now time
+ // to execute all of them.
+ //-------------------------------------------------------
+ int Tcomp = aNdbObject->sendPollNdb(3000, 0, 0);
+ while (Tcomp < tNoOfParallelTrans) {
+ int TlocalComp = aNdbObject->pollNdb(3000, 0);
+ Tcomp += TlocalComp;
+ }//while
+ for (j = 0 ; j < tNoOfParallelTrans ; j++) {
+ aNdbObject->closeTransaction(tConArray[j]);
+ }//for
+ }//for
+ return true;
+}//executeThread()
+
+static
+Uint32
+getKey(Uint32 aBase, Uint32 anIndex) {
+ Uint32 Tfound = anIndex;
+ Uint64 Tkey64;
+ Uint32* Tkey32 = (Uint32*)&Tkey64;
+ Tkey32[0] = aBase;
+ Uint32 hash;
+ for (Uint32 i = anIndex; i < (anIndex + MAX_SEEK); i++) {
+ Tkey32[1] = (Uint32)i;
+ hash = md5_hash((Uint64*)&Tkey64, (Uint32)2);
+ hash = (hash >> 6) & (MAX_PARTS - 1);
+ if (hash == tLocalPart) {
+ Tfound = i;
+ break;
+ }//if
+ }//for
+ return Tfound;
+}//getKey()
+
+static void
+executeCallback(int result, NdbConnection* NdbObject, void* aObject)
+{
+ if (result == -1) {
+
+ // Add complete error handling here
+
+ int retCode = flexAsynchErrorData->handleErrorCommon(NdbObject->getNdbError());
+ if (retCode == 1) {
+ if (NdbObject->getNdbError().code != 626 && NdbObject->getNdbError().code != 630){
+ ndbout_c("execute: %s", NdbObject->getNdbError().message);
+ ndbout_c("Error code = %d", NdbObject->getNdbError().code);}
+ } else if (retCode == 2) {
+ ndbout << "4115 should not happen in flexAsynch" << endl;
+ } else if (retCode == 3) {
+ /* What can we do here? */
+ ndbout_c("execute: %s", NdbObject->getNdbError().message);
+ }//if(retCode == 3)
+
+ // ndbout << "Error occured in poll:" << endl;
+ // ndbout << NdbObject->getNdbError() << endl;
+ failed++ ;
+ return;
+ }//if
+ return;
+}//executeCallback()
+
+
+
+static void
+defineOperation(NdbConnection* localNdbConnection, StartType aType,
+ Uint32 threadBase, Uint32 aIndex)
+{
+ NdbOperation* localNdbOperation;
+ unsigned int loopCountAttributes = tNoOfAttributes;
+ unsigned int countAttributes;
+ Uint32 attrValue[MAXATTRSIZE];
+
+ //-------------------------------------------------------
+ // Set-up the attribute values for this operation.
+ //-------------------------------------------------------
+ attrValue[0] = threadBase;
+ attrValue[1] = aIndex;
+ for (int k = 2; k < loopCountAttributes; k++) {
+ attrValue[k] = aIndex;
+ }//for
+ localNdbOperation = localNdbConnection->getNdbOperation(tableName[0]);
+ if (localNdbOperation == NULL) {
+ error_handler(localNdbConnection->getNdbError());
+ }//if
+ switch (aType) {
+ case stInsert: { // Insert case
+ if (theWriteFlag == 1 && theDirtyFlag == 1) {
+ localNdbOperation->dirtyWrite();
+ } else if (theWriteFlag == 1) {
+ localNdbOperation->writeTuple();
+ } else {
+ localNdbOperation->insertTuple();
+ }//if
+ break;
+ }//case
+ case stRead: { // Read Case
+ if (theSimpleFlag == 1) {
+ localNdbOperation->simpleRead();
+ } else if (theDirtyFlag == 1) {
+ localNdbOperation->dirtyRead();
+ } else {
+ localNdbOperation->readTuple();
+ }//if
+ break;
+ }//case
+ case stUpdate: { // Update Case
+ if (theWriteFlag == 1 && theDirtyFlag == 1) {
+ localNdbOperation->dirtyWrite();
+ } else if (theWriteFlag == 1) {
+ localNdbOperation->writeTuple();
+ } else if (theDirtyFlag == 1) {
+ localNdbOperation->dirtyUpdate();
+ } else {
+ localNdbOperation->updateTuple();
+ }//if
+ break;
+ }//case
+ case stDelete: { // Delete Case
+ localNdbOperation->deleteTuple();
+ break;
+ }//case
+ default: {
+ error_handler(localNdbOperation->getNdbError());
+ }//default
+ }//switch
+ localNdbOperation->equal((Uint32)0,(char*)&attrValue[0]);
+ switch (aType) {
+ case stInsert: // Insert case
+ case stUpdate: // Update Case
+ {
+ for (countAttributes = 1;
+ countAttributes < loopCountAttributes; countAttributes++) {
+ localNdbOperation->setValue(countAttributes,
+ (char*)&attrValue[0]);
+ }//for
+ break;
+ }//case
+ case stRead: { // Read Case
+ for (countAttributes = 1;
+ countAttributes < loopCountAttributes; countAttributes++) {
+ localNdbOperation->getValue(countAttributes,
+ (char*)&attrValue[0]);
+ }//for
+ break;
+ }//case
+ case stDelete: { // Delete Case
+ break;
+ }//case
+ default: {
+ //goto error_handler; < epaulsa
+ error_handler(localNdbOperation->getNdbError());
+ }//default
+ }//switch
+ return;
+}//defineOperation()
+
+static void setAttrNames()
+{
+ int i;
+
+ for (i = 0; i < MAXATTR ; i++){
+ snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ }
+}
+
+
+static void setTableNames()
+{
+ // Note! Uses only uppercase letters in table name's
+ // so that we can look at the tables wits SQL
+ int i;
+ for (i = 0; i < MAXTABLES ; i++){
+ if (theStdTableNameFlag==0){
+ snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
+ (int)(NdbTick_CurrentMillisecond()/1000));
+ } else {
+ snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
+ }
+ }
+}
+
+static
+int
+createTables(Ndb* pMyNdb){
+
+ NdbSchemaCon *MySchemaTransaction;
+ NdbSchemaOp *MySchemaOp;
+ int check;
+
+ if (theTableCreateFlag == 0) {
+ for(int i=0; i < 1 ;i++) {
+ ndbout << "Creating " << tableName[i] << "..." << endl;
+ MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pMyNdb);
+
+ if(MySchemaTransaction == NULL &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if(MySchemaOp == NULL &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+
+ check = MySchemaOp->createTable( tableName[i]
+ ,8 // Table Size
+ ,TupleKey // Key Type
+ ,40 // Nr of Pages
+ ,All
+ ,6
+ ,(tLoadFactor - 5)
+ ,(tLoadFactor)
+ ,1
+ ,!tempTable
+ );
+
+ if (check == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ check = MySchemaOp->createAttribute( (char*)attrName[0],
+ TupleKey,
+ 32,
+ PKSIZE,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+
+ if (check == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+ for (int j = 1; j < tNoOfAttributes ; j++){
+ check = MySchemaOp->createAttribute( (char*)attrName[j],
+ NoKey,
+ 32,
+ tAttributeSize,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if (check == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+ }
+
+ if (MySchemaTransaction->execute() == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ }
+ }
+
+ return 0;
+}
+
+static
+bool error_handler(const NdbError & err){
+ ndbout << err << endl ;
+ switch(err.classification){
+ case NdbError::TemporaryResourceError:
+ case NdbError::OverloadError:
+ case NdbError::SchemaError:
+ ndbout << endl << "Attempting to recover and continue now..." << endl ;
+ return true;
+ }
+ return false ; // return false to abort
+}
+static
+bool error_handler(const char* error_string, int error_int) {
+ ndbout << error_string << endl ;
+ if ((4008 == error_int) ||
+ (721 == error_int) ||
+ (266 == error_int)){
+ ndbout << endl << "Attempting to recover and continue now..." << endl ;
+ return true ; // return true to retry
+ }
+ return false ; // return false to abort
+}
+
+static
+int
+readArguments(int argc, const char** argv){
+
+ int i = 1;
+ while (argc > 1){
+ if (strcmp(argv[i], "-t") == 0){
+ tNoOfThreads = atoi(argv[i+1]);
+ if ((tNoOfThreads < 1) || (tNoOfThreads > MAXTHREADS)){
+ ndbout_c("Invalid no of threads");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-p") == 0){
+ tNoOfParallelTrans = atoi(argv[i+1]);
+ if ((tNoOfParallelTrans < 1) || (tNoOfParallelTrans > MAXPAR)){
+ ndbout_c("Invalid no of parallell transactions");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-load_factor") == 0){
+ tLoadFactor = atoi(argv[i+1]);
+ if ((tLoadFactor < 40) || (tLoadFactor > 99)){
+ ndbout_c("Invalid load factor");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-c") == 0) {
+ tNoOfOpsPerTrans = atoi(argv[i+1]);
+ if (tNoOfOpsPerTrans < 1){
+ ndbout_c("Invalid no of operations per transaction");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-o") == 0) {
+ tNoOfTransactions = atoi(argv[i+1]);
+ if (tNoOfTransactions < 1){
+ ndbout_c("Invalid no of transactions");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-a") == 0){
+ tNoOfAttributes = atoi(argv[i+1]);
+ if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR)){
+ ndbout_c("Invalid no of attributes");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-n") == 0){
+ theStdTableNameFlag = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-l") == 0){
+ tNoOfLoops = atoi(argv[i+1]);
+ if ((tNoOfLoops < 0) || (tNoOfLoops > 100000)){
+ ndbout_c("Invalid no of loops");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-s") == 0){
+ tAttributeSize = atoi(argv[i+1]);
+ if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE)){
+ ndbout_c("Invalid attributes size");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-local") == 0){
+ tLocalPart = atoi(argv[i+1]);
+ tLocal = true;
+ startTransGuess = true;
+ if ((tLocalPart < 0) || (tLocalPart > MAX_PARTS)){
+ ndbout_c("Invalid local part");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-simple") == 0){
+ theSimpleFlag = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-adaptive") == 0){
+ tSendForce = 0;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-force") == 0){
+ tSendForce = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-non_adaptive") == 0){
+ tSendForce = 2;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-write") == 0){
+ theWriteFlag = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-dirty") == 0){
+ theDirtyFlag = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-test") == 0){
+ theTestFlag = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-no_table_create") == 0){
+ theTableCreateFlag = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-temp") == 0){
+ tempTable = true;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-no_hint") == 0){
+ startTransGuess = false;
+ argc++;
+ i--;
+ } else {
+ return -1;
+ }
+
+ argc -= 2;
+ i = i + 2;
+ }//while
+ if (tLocal == true) {
+ if (tNoOfOpsPerTrans != 1) {
+ ndbout_c("Not valid to have more than one op per trans with local");
+ }//if
+ if (startTransGuess == false) {
+ ndbout_c("Not valid to use no_hint with local");
+ }//if
+ }//if
+ return 0;
+}
+
+static
+void
+input_error(){
+
+ ndbout_c("FLEXASYNCH");
+ ndbout_c(" Perform benchmark of insert, update and delete transactions");
+ ndbout_c("");
+ ndbout_c("Arguments:");
+ ndbout_c(" -t Number of threads to start, default 1");
+ ndbout_c(" -p Number of parallel transactions per thread, default 32");
+ ndbout_c(" -o Number of transactions per loop, default 500");
+ ndbout_c(" -l Number of loops to run, default 1, 0=infinite");
+ ndbout_c(" -load_factor Number Load factor in index in percent (40 -> 99)");
+ ndbout_c(" -a Number of attributes, default 25");
+ ndbout_c(" -c Number of operations per transaction");
+ ndbout_c(" -s Size of each attribute, default 1 ");
+ ndbout_c(" (PK is always of size 1, independent of this value)");
+ ndbout_c(" -simple Use simple read to read from database");
+ ndbout_c(" -dirty Use dirty read to read from database");
+ ndbout_c(" -write Use writeTuple in insert and update");
+ ndbout_c(" -n Use standard table names");
+ ndbout_c(" -no_table_create Don't create tables in db");
+ ndbout_c(" -temp Create table(s) without logging");
+ ndbout_c(" -no_hint Don't give hint on where to execute transaction coordinator");
+ ndbout_c(" -adaptive Use adaptive send algorithm (default)");
+ ndbout_c(" -force Force send when communicating");
+ ndbout_c(" -non_adaptive Send at a 10 millisecond interval");
+ ndbout_c(" -local Number of part, only use keys in one part out of 16");
+}
+
+
+
diff --git a/ndb/test/ndbapi/flexAsynch/flexAsynch.cpp b/ndb/test/ndbapi/flexAsynch/flexAsynch.cpp
deleted file mode 100644
index 0822f3ee999..00000000000
--- a/ndb/test/ndbapi/flexAsynch/flexAsynch.cpp
+++ /dev/null
@@ -1,982 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include "NdbApi.hpp"
-#include <NdbMain.h>
-#include <md5_hash.hpp>
-
-#include <NdbThread.h>
-#include <NdbSleep.h>
-#include <NdbTick.h>
-#include <NdbOut.hpp>
-#include <NdbTimer.hpp>
-#include <NDBT_Error.hpp>
-
-#include <NdbTest.hpp>
-
-#define MAX_PARTS 4
-#define MAX_SEEK 16
-#define MAXSTRLEN 16
-#define MAXATTR 64
-#define MAXTABLES 64
-#define MAXTHREADS 128
-#define MAXPAR 1024
-#define MAXATTRSIZE 1000
-#define PKSIZE 2
-
-enum StartType {
- stIdle,
- stInsert,
- stRead,
- stUpdate,
- stDelete,
- stStop
-} ;
-
-extern "C" { static void* threadLoop(void*); }
-static void setAttrNames(void);
-static void setTableNames(void);
-static int readArguments(int argc, const char** argv);
-static int createTables(Ndb*);
-static void defineOperation(NdbConnection* aTransObject, StartType aType,
- Uint32 base, Uint32 aIndex);
-static void execute(StartType aType);
-static bool executeThread(StartType aType, Ndb* aNdbObject, unsigned int);
-static void executeCallback(int result, NdbConnection* NdbObject,
- void* aObject);
-static bool error_handler(const NdbError & err);
-static Uint32 getKey(Uint32, Uint32) ;
-static void input_error();
-
-
-static int retry_opt = 3 ;
-static int failed = 0 ;
-
-ErrorData * flexAsynchErrorData;
-
-struct ThreadNdb
-{
- int NoOfOps;
- int ThreadNo;
-};
-
-static NdbThread* threadLife[MAXTHREADS];
-static int tNodeId;
-static int ThreadReady[MAXTHREADS];
-static StartType ThreadStart[MAXTHREADS];
-static char tableName[MAXTABLES][MAXSTRLEN+1];
-static char attrName[MAXATTR][MAXSTRLEN+1];
-
-// Program Parameters
-static bool tLocal = false;
-static int tLocalPart = 0;
-static int tSendForce = 0;
-static int tNoOfLoops = 1;
-static int tAttributeSize = 1;
-static unsigned int tNoOfThreads = 1;
-static unsigned int tNoOfParallelTrans = 32;
-static unsigned int tNoOfAttributes = 25;
-static unsigned int tNoOfTransactions = 500;
-static unsigned int tNoOfOpsPerTrans = 1;
-static unsigned int tLoadFactor = 80;
-static bool tempTable = false;
-static bool startTransGuess = true;
-
-//Program Flags
-static int theTestFlag = 0;
-static int theSimpleFlag = 0;
-static int theDirtyFlag = 0;
-static int theWriteFlag = 0;
-static int theStdTableNameFlag = 0;
-static int theTableCreateFlag = 0;
-
-#define START_REAL_TIME
-#define STOP_REAL_TIME
-#define START_TIMER { NdbTimer timer; timer.doStart();
-#define STOP_TIMER timer.doStop();
-#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
-
-static void
-resetThreads(){
-
- for (int i = 0; i < tNoOfThreads ; i++) {
- ThreadReady[i] = 0;
- ThreadStart[i] = stIdle;
- }//for
-}
-
-static void
-waitForThreads(void)
-{
- int cont = 0;
- do {
- cont = 0;
- NdbSleep_MilliSleep(20);
- for (int i = 0; i < tNoOfThreads ; i++) {
- if (ThreadReady[i] == 0) {
- cont = 1;
- }//if
- }//for
- } while (cont == 1);
-}
-
-static void
-tellThreads(StartType what)
-{
- for (int i = 0; i < tNoOfThreads ; i++)
- ThreadStart[i] = what;
-}
-
-NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
-{
- ThreadNdb* pThreadData;
- int tLoops=0;
- int returnValue = NDBT_OK;
-
- flexAsynchErrorData = new ErrorData;
- flexAsynchErrorData->resetErrorCounters();
-
- if (readArguments(argc, argv) != 0){
- input_error();
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- pThreadData = new ThreadNdb[MAXTHREADS];
-
- ndbout << endl << "FLEXASYNCH - Starting normal mode" << endl;
- ndbout << "Perform benchmark of insert, update and delete transactions";
- ndbout << endl;
- ndbout << " " << tNoOfThreads << " number of concurrent threads " << endl;
- ndbout << " " << tNoOfParallelTrans;
- ndbout << " number of parallel operation per thread " << endl;
- ndbout << " " << tNoOfTransactions << " transaction(s) per round " << endl;
- ndbout << " " << tNoOfLoops << " iterations " << endl;
- ndbout << " " << "Load Factor is " << tLoadFactor << "%" << endl;
- ndbout << " " << tNoOfAttributes << " attributes per table " << endl;
- ndbout << " " << tAttributeSize;
- ndbout << " is the number of 32 bit words per attribute " << endl;
- if (tempTable == true) {
- ndbout << " Tables are without logging " << endl;
- } else {
- ndbout << " Tables are with logging " << endl;
- }//if
- if (startTransGuess == true) {
- ndbout << " Transactions are executed with hint provided" << endl;
- } else {
- ndbout << " Transactions are executed with round robin scheme" << endl;
- }//if
- if (tSendForce == 0) {
- ndbout << " No force send is used, adaptive algorithm used" << endl;
- } else if (tSendForce == 1) {
- ndbout << " Force send used" << endl;
- } else {
- ndbout << " No force send is used, adaptive algorithm disabled" << endl;
- }//if
-
- ndbout << endl;
-
- NdbThread_SetConcurrencyLevel(2 + tNoOfThreads);
-
- /* print Setting */
- flexAsynchErrorData->printSettings(ndbout);
-
- setAttrNames();
- setTableNames();
-
- Ndb * pNdb = new Ndb("TEST_DB");
- pNdb->init();
- tNodeId = pNdb->getNodeId();
-
- ndbout << " NdbAPI node with id = " << pNdb->getNodeId() << endl;
- ndbout << endl;
-
- ndbout << "Waiting for ndb to become ready..." <<endl;
- if (pNdb->waitUntilReady(10000) != 0){
- ndbout << "NDB is not ready" << endl;
- ndbout << "Benchmark failed!" << endl;
- returnValue = NDBT_FAILED;
- }
-
- if(returnValue == NDBT_OK){
- if (createTables(pNdb) != 0){
- returnValue = NDBT_FAILED;
- }
- }
-
- if(returnValue == NDBT_OK){
- /****************************************************************
- * Create NDB objects. *
- ****************************************************************/
- resetThreads();
- for (int i = 0; i < tNoOfThreads ; i++) {
- pThreadData[i].ThreadNo = i
-;
- threadLife[i] = NdbThread_Create(threadLoop,
- (void**)&pThreadData[i],
- 32768,
- "flexAsynchThread",
- NDB_THREAD_PRIO_LOW);
- }//for
- ndbout << endl << "All NDB objects and table created" << endl << endl;
- int noOfTransacts = tNoOfParallelTrans*tNoOfTransactions*tNoOfThreads;
- /****************************************************************
- * Execute program. *
- ****************************************************************/
-
- for(;;) {
-
- int loopCount = tLoops + 1 ;
- ndbout << endl << "Loop # " << loopCount << endl << endl ;
-
- /****************************************************************
- * Perform inserts. *
- ****************************************************************/
-
- failed = 0 ;
-
- START_TIMER;
- execute(stInsert);
- STOP_TIMER;
- PRINT_TIMER("insert", noOfTransacts, tNoOfOpsPerTrans);
-
- if (0 < failed) {
- int i = retry_opt ;
- int ci = 1 ;
- while (0 < failed && 0 < i){
- ndbout << failed << " of the transactions returned errors!"
- << endl << endl;
- ndbout << "Attempting to redo the failed transactions now..."
- << endl ;
- ndbout << "Redo attempt " << ci <<" out of " << retry_opt
- << endl << endl;
- failed = 0 ;
- START_TIMER;
- execute(stInsert);
- STOP_TIMER;
- PRINT_TIMER("insert", noOfTransacts, tNoOfOpsPerTrans);
- i-- ;
- ci++;
- }
- if(0 == failed ){
- ndbout << endl <<"Redo attempt succeeded" << endl << endl;
- }else{
- ndbout << endl <<"Redo attempt failed, moving on now..." << endl
- << endl;
- }//if
- }//if
-
- /****************************************************************
- * Perform read. *
- ****************************************************************/
-
- failed = 0 ;
-
- START_TIMER;
- execute(stRead);
- STOP_TIMER;
- PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
-
- if (0 < failed) {
- int i = retry_opt ;
- int cr = 1;
- while (0 < failed && 0 < i){
- ndbout << failed << " of the transactions returned errors!"<<endl ;
- ndbout << endl;
- ndbout <<"Attempting to redo the failed transactions now..." << endl;
- ndbout << endl;
- ndbout <<"Redo attempt " << cr <<" out of ";
- ndbout << retry_opt << endl << endl;
- failed = 0 ;
- START_TIMER;
- execute(stRead);
- STOP_TIMER;
- PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
- i-- ;
- cr++ ;
- }//while
- if(0 == failed ) {
- ndbout << endl <<"Redo attempt succeeded" << endl << endl ;
- }else{
- ndbout << endl <<"Redo attempt failed, moving on now..." << endl << endl ;
- }//if
- }//if
-
-
- /****************************************************************
- * Perform update. *
- ****************************************************************/
-
- failed = 0 ;
-
- START_TIMER;
- execute(stUpdate);
- STOP_TIMER;
- PRINT_TIMER("update", noOfTransacts, tNoOfOpsPerTrans) ;
-
- if (0 < failed) {
- int i = retry_opt ;
- int cu = 1 ;
- while (0 < failed && 0 < i){
- ndbout << failed << " of the transactions returned errors!"<<endl ;
- ndbout << endl;
- ndbout <<"Attempting to redo the failed transactions now..." << endl;
- ndbout << endl <<"Redo attempt " << cu <<" out of ";
- ndbout << retry_opt << endl << endl;
- failed = 0 ;
- START_TIMER;
- execute(stUpdate);
- STOP_TIMER;
- PRINT_TIMER("update", noOfTransacts, tNoOfOpsPerTrans);
- i-- ;
- cu++ ;
- }//while
- if(0 == failed ){
- ndbout << endl <<"Redo attempt succeeded" << endl << endl;
- } else {
- ndbout << endl;
- ndbout <<"Redo attempt failed, moving on now..." << endl << endl;
- }//if
- }//if
-
- /****************************************************************
- * Perform read. *
- ****************************************************************/
-
- failed = 0 ;
-
- START_TIMER;
- execute(stRead);
- STOP_TIMER;
- PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
-
- if (0 < failed) {
- int i = retry_opt ;
- int cr2 = 1 ;
- while (0 < failed && 0 < i){
- ndbout << failed << " of the transactions returned errors!"<<endl ;
- ndbout << endl;
- ndbout <<"Attempting to redo the failed transactions now..." << endl;
- ndbout << endl <<"Redo attempt " << cr2 <<" out of ";
- ndbout << retry_opt << endl << endl;
- failed = 0 ;
- START_TIMER;
- execute(stRead);
- STOP_TIMER;
- PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
- i-- ;
- cr2++ ;
- }//while
- if(0 == failed ){
- ndbout << endl <<"Redo attempt succeeded" << endl << endl;
- }else{
- ndbout << endl;
- ndbout << "Redo attempt failed, moving on now..." << endl << endl;
- }//if
- }//if
-
-
- /****************************************************************
- * Perform delete. *
- ****************************************************************/
-
- failed = 0 ;
-
- START_TIMER;
- execute(stDelete);
- STOP_TIMER;
- PRINT_TIMER("delete", noOfTransacts, tNoOfOpsPerTrans);
-
- if (0 < failed) {
- int i = retry_opt ;
- int cd = 1 ;
- while (0 < failed && 0 < i){
- ndbout << failed << " of the transactions returned errors!"<< endl ;
- ndbout << endl;
- ndbout <<"Attempting to redo the failed transactions now:" << endl ;
- ndbout << endl <<"Redo attempt " << cd <<" out of ";
- ndbout << retry_opt << endl << endl;
- failed = 0 ;
- START_TIMER;
- execute(stDelete);
- STOP_TIMER;
- PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
- i-- ;
- cd++ ;
- }//while
- if(0 == failed ){
- ndbout << endl <<"Redo attempt succeeded" << endl << endl ;
- }else{
- ndbout << endl;
- ndbout << "Redo attempt failed, moving on now..." << endl << endl;
- }//if
- }//if
-
- tLoops++;
- ndbout << "--------------------------------------------------" << endl;
-
- if(tNoOfLoops != 0){
- if(tNoOfLoops <= tLoops)
- break ;
- }
- }//for
-
- execute(stStop);
- void * tmp;
- for(int i = 0; i<tNoOfThreads; i++){
- NdbThread_WaitFor(threadLife[i], &tmp);
- NdbThread_Destroy(&threadLife[i]);
- }
- }
- delete [] pThreadData;
- delete pNdb;
-
- //printing errorCounters
- flexAsynchErrorData->printErrorCounters(ndbout);
-
- return NDBT_ProgramExit(returnValue);
-}//main()
-
-
-static void execute(StartType aType)
-{
- resetThreads();
- tellThreads(aType);
- waitForThreads();
-}//execute()
-
-static void*
-threadLoop(void* ThreadData)
-{
- Ndb* localNdb;
- StartType tType;
- ThreadNdb* tabThread = (ThreadNdb*)ThreadData;
- int threadNo = tabThread->ThreadNo;
- localNdb = new Ndb("TEST_DB");
- localNdb->init(1024);
- localNdb->waitUntilReady(10000);
- unsigned int threadBase = (threadNo << 16) + tNodeId ;
-
- for (;;){
- while (ThreadStart[threadNo] == stIdle) {
- NdbSleep_MilliSleep(10);
- }//while
-
- // Check if signal to exit is received
- if (ThreadStart[threadNo] == stStop) {
- break;
- }//if
-
- tType = ThreadStart[threadNo];
- ThreadStart[threadNo] = stIdle;
- if(!executeThread(tType, localNdb, threadBase)){
- break;
- }
- ThreadReady[threadNo] = 1;
- }//for
-
- delete localNdb;
- ThreadReady[threadNo] = 1;
-
- NdbThread_Exit(0);
- return NULL; // Just to keep compiler happy
-}//threadLoop()
-
-static
-bool
-executeThread(StartType aType, Ndb* aNdbObject, unsigned int threadBase) {
- int i, j, k;
- NdbConnection* tConArray[1024];
- unsigned int tBase;
- unsigned int tBase2;
-
- for (i = 0; i < tNoOfTransactions; i++) {
- if (tLocal == false) {
- tBase = i * tNoOfParallelTrans * tNoOfOpsPerTrans;
- } else {
- tBase = i * tNoOfParallelTrans * MAX_SEEK;
- }//if
- START_REAL_TIME;
- for (j = 0; j < tNoOfParallelTrans; j++) {
- if (tLocal == false) {
- tBase2 = tBase + (j * tNoOfOpsPerTrans);
- } else {
- tBase2 = tBase + (j * MAX_SEEK);
- tBase2 = getKey(threadBase, tBase2);
- }//if
- if (startTransGuess == true) {
- Uint64 Tkey64;
- Uint32* Tkey32 = (Uint32*)&Tkey64;
- Tkey32[0] = threadBase;
- Tkey32[1] = tBase2;
- tConArray[j] = aNdbObject->startTransaction((Uint32)0, //Priority
- (const char*)&Tkey64, //Main PKey
- (Uint32)4); //Key Length
- } else {
- tConArray[j] = aNdbObject->startTransaction();
- }//if
- if (tConArray[j] == NULL &&
- !error_handler(aNdbObject->getNdbError()) ){
- ndbout << endl << "Unable to recover! Quiting now" << endl ;
- return false;
- }//if
-
- for (k = 0; k < tNoOfOpsPerTrans; k++) {
- //-------------------------------------------------------
- // Define the operation, but do not execute it yet.
- //-------------------------------------------------------
- defineOperation(tConArray[j], aType, threadBase, (tBase2 + k));
- }//for
-
- tConArray[j]->executeAsynchPrepare(Commit, &executeCallback, NULL);
- }//for
- STOP_REAL_TIME;
- //-------------------------------------------------------
- // Now we have defined a set of operations, it is now time
- // to execute all of them.
- //-------------------------------------------------------
- int Tcomp = aNdbObject->sendPollNdb(3000, 0, 0);
- while (Tcomp < tNoOfParallelTrans) {
- int TlocalComp = aNdbObject->pollNdb(3000, 0);
- Tcomp += TlocalComp;
- }//while
- for (j = 0 ; j < tNoOfParallelTrans ; j++) {
- aNdbObject->closeTransaction(tConArray[j]);
- }//for
- }//for
- return true;
-}//executeThread()
-
-static
-Uint32
-getKey(Uint32 aBase, Uint32 anIndex) {
- Uint32 Tfound = anIndex;
- Uint64 Tkey64;
- Uint32* Tkey32 = (Uint32*)&Tkey64;
- Tkey32[0] = aBase;
- Uint32 hash;
- for (Uint32 i = anIndex; i < (anIndex + MAX_SEEK); i++) {
- Tkey32[1] = (Uint32)i;
- hash = md5_hash((Uint64*)&Tkey64, (Uint32)2);
- hash = (hash >> 6) & (MAX_PARTS - 1);
- if (hash == tLocalPart) {
- Tfound = i;
- break;
- }//if
- }//for
- return Tfound;
-}//getKey()
-
-static void
-executeCallback(int result, NdbConnection* NdbObject, void* aObject)
-{
- if (result == -1) {
-
- // Add complete error handling here
-
- int retCode = flexAsynchErrorData->handleErrorCommon(NdbObject->getNdbError());
- if (retCode == 1) {
- if (NdbObject->getNdbError().code != 626 && NdbObject->getNdbError().code != 630){
- ndbout_c("execute: %s", NdbObject->getNdbError().message);
- ndbout_c("Error code = %d", NdbObject->getNdbError().code);}
- } else if (retCode == 2) {
- ndbout << "4115 should not happen in flexAsynch" << endl;
- } else if (retCode == 3) {
- /* What can we do here? */
- ndbout_c("execute: %s", NdbObject->getNdbError().message);
- }//if(retCode == 3)
-
- // ndbout << "Error occured in poll:" << endl;
- // ndbout << NdbObject->getNdbError() << endl;
- failed++ ;
- return;
- }//if
- return;
-}//executeCallback()
-
-
-
-static void
-defineOperation(NdbConnection* localNdbConnection, StartType aType,
- Uint32 threadBase, Uint32 aIndex)
-{
- NdbOperation* localNdbOperation;
- unsigned int loopCountAttributes = tNoOfAttributes;
- unsigned int countAttributes;
- Uint32 attrValue[MAXATTRSIZE];
-
- //-------------------------------------------------------
- // Set-up the attribute values for this operation.
- //-------------------------------------------------------
- attrValue[0] = threadBase;
- attrValue[1] = aIndex;
- for (int k = 2; k < loopCountAttributes; k++) {
- attrValue[k] = aIndex;
- }//for
- localNdbOperation = localNdbConnection->getNdbOperation(tableName[0]);
- if (localNdbOperation == NULL) {
- error_handler(localNdbConnection->getNdbError());
- }//if
- switch (aType) {
- case stInsert: { // Insert case
- if (theWriteFlag == 1 && theDirtyFlag == 1) {
- localNdbOperation->dirtyWrite();
- } else if (theWriteFlag == 1) {
- localNdbOperation->writeTuple();
- } else {
- localNdbOperation->insertTuple();
- }//if
- break;
- }//case
- case stRead: { // Read Case
- if (theSimpleFlag == 1) {
- localNdbOperation->simpleRead();
- } else if (theDirtyFlag == 1) {
- localNdbOperation->dirtyRead();
- } else {
- localNdbOperation->readTuple();
- }//if
- break;
- }//case
- case stUpdate: { // Update Case
- if (theWriteFlag == 1 && theDirtyFlag == 1) {
- localNdbOperation->dirtyWrite();
- } else if (theWriteFlag == 1) {
- localNdbOperation->writeTuple();
- } else if (theDirtyFlag == 1) {
- localNdbOperation->dirtyUpdate();
- } else {
- localNdbOperation->updateTuple();
- }//if
- break;
- }//case
- case stDelete: { // Delete Case
- localNdbOperation->deleteTuple();
- break;
- }//case
- default: {
- error_handler(localNdbOperation->getNdbError());
- }//default
- }//switch
- localNdbOperation->equal((Uint32)0,(char*)&attrValue[0]);
- switch (aType) {
- case stInsert: // Insert case
- case stUpdate: // Update Case
- {
- for (countAttributes = 1;
- countAttributes < loopCountAttributes; countAttributes++) {
- localNdbOperation->setValue(countAttributes,
- (char*)&attrValue[0]);
- }//for
- break;
- }//case
- case stRead: { // Read Case
- for (countAttributes = 1;
- countAttributes < loopCountAttributes; countAttributes++) {
- localNdbOperation->getValue(countAttributes,
- (char*)&attrValue[0]);
- }//for
- break;
- }//case
- case stDelete: { // Delete Case
- break;
- }//case
- default: {
- //goto error_handler; < epaulsa
- error_handler(localNdbOperation->getNdbError());
- }//default
- }//switch
- return;
-}//defineOperation()
-
-static void setAttrNames()
-{
- int i;
-
- for (i = 0; i < MAXATTR ; i++){
- snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
- }
-}
-
-
-static void setTableNames()
-{
- // Note! Uses only uppercase letters in table name's
- // so that we can look at the tables wits SQL
- int i;
- for (i = 0; i < MAXTABLES ; i++){
- if (theStdTableNameFlag==0){
- snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
- (int)(NdbTick_CurrentMillisecond()/1000));
- } else {
- snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
- }
- }
-}
-
-static
-int
-createTables(Ndb* pMyNdb){
-
- NdbSchemaCon *MySchemaTransaction;
- NdbSchemaOp *MySchemaOp;
- int check;
-
- if (theTableCreateFlag == 0) {
- for(int i=0; i < 1 ;i++) {
- ndbout << "Creating " << tableName[i] << "..." << endl;
- MySchemaTransaction = pMyNdb->startSchemaTransaction();
-
- if(MySchemaTransaction == NULL &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if(MySchemaOp == NULL &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- check = MySchemaOp->createTable( tableName[i]
- ,8 // Table Size
- ,TupleKey // Key Type
- ,40 // Nr of Pages
- ,All
- ,6
- ,(tLoadFactor - 5)
- ,(tLoadFactor)
- ,1
- ,!tempTable
- );
-
- if (check == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- check = MySchemaOp->createAttribute( (char*)attrName[0],
- TupleKey,
- 32,
- PKSIZE,
- UnSigned,
- MMBased,
- NotNullAttribute );
-
- if (check == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
- for (int j = 1; j < tNoOfAttributes ; j++){
- check = MySchemaOp->createAttribute( (char*)attrName[j],
- NoKey,
- 32,
- tAttributeSize,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if (check == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
- }
-
- if (MySchemaTransaction->execute() == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- }
- }
-
- return 0;
-}
-
-static
-bool error_handler(const NdbError & err){
- ndbout << err << endl ;
- switch(err.classification){
- case NdbError::TemporaryResourceError:
- case NdbError::OverloadError:
- case NdbError::SchemaError:
- ndbout << endl << "Attempting to recover and continue now..." << endl ;
- return true;
- }
- return false ; // return false to abort
-}
-static
-bool error_handler(const char* error_string, int error_int) {
- ndbout << error_string << endl ;
- if ((4008 == error_int) ||
- (721 == error_int) ||
- (266 == error_int)){
- ndbout << endl << "Attempting to recover and continue now..." << endl ;
- return true ; // return true to retry
- }
- return false ; // return false to abort
-}
-
-static
-int
-readArguments(int argc, const char** argv){
-
- int i = 1;
- while (argc > 1){
- if (strcmp(argv[i], "-t") == 0){
- tNoOfThreads = atoi(argv[i+1]);
- if ((tNoOfThreads < 1) || (tNoOfThreads > MAXTHREADS)){
- ndbout_c("Invalid no of threads");
- return -1;
- }
- } else if (strcmp(argv[i], "-p") == 0){
- tNoOfParallelTrans = atoi(argv[i+1]);
- if ((tNoOfParallelTrans < 1) || (tNoOfParallelTrans > MAXPAR)){
- ndbout_c("Invalid no of parallell transactions");
- return -1;
- }
- } else if (strcmp(argv[i], "-load_factor") == 0){
- tLoadFactor = atoi(argv[i+1]);
- if ((tLoadFactor < 40) || (tLoadFactor > 99)){
- ndbout_c("Invalid load factor");
- return -1;
- }
- } else if (strcmp(argv[i], "-c") == 0) {
- tNoOfOpsPerTrans = atoi(argv[i+1]);
- if (tNoOfOpsPerTrans < 1){
- ndbout_c("Invalid no of operations per transaction");
- return -1;
- }
- } else if (strcmp(argv[i], "-o") == 0) {
- tNoOfTransactions = atoi(argv[i+1]);
- if (tNoOfTransactions < 1){
- ndbout_c("Invalid no of transactions");
- return -1;
- }
- } else if (strcmp(argv[i], "-a") == 0){
- tNoOfAttributes = atoi(argv[i+1]);
- if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR)){
- ndbout_c("Invalid no of attributes");
- return -1;
- }
- } else if (strcmp(argv[i], "-n") == 0){
- theStdTableNameFlag = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-l") == 0){
- tNoOfLoops = atoi(argv[i+1]);
- if ((tNoOfLoops < 0) || (tNoOfLoops > 100000)){
- ndbout_c("Invalid no of loops");
- return -1;
- }
- } else if (strcmp(argv[i], "-s") == 0){
- tAttributeSize = atoi(argv[i+1]);
- if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE)){
- ndbout_c("Invalid attributes size");
- return -1;
- }
- } else if (strcmp(argv[i], "-local") == 0){
- tLocalPart = atoi(argv[i+1]);
- tLocal = true;
- startTransGuess = true;
- if ((tLocalPart < 0) || (tLocalPart > MAX_PARTS)){
- ndbout_c("Invalid local part");
- return -1;
- }
- } else if (strcmp(argv[i], "-simple") == 0){
- theSimpleFlag = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-adaptive") == 0){
- tSendForce = 0;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-force") == 0){
- tSendForce = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-non_adaptive") == 0){
- tSendForce = 2;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-write") == 0){
- theWriteFlag = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-dirty") == 0){
- theDirtyFlag = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-test") == 0){
- theTestFlag = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-no_table_create") == 0){
- theTableCreateFlag = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-temp") == 0){
- tempTable = true;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-no_hint") == 0){
- startTransGuess = false;
- argc++;
- i--;
- } else {
- return -1;
- }
-
- argc -= 2;
- i = i + 2;
- }//while
- if (tLocal == true) {
- if (tNoOfOpsPerTrans != 1) {
- ndbout_c("Not valid to have more than one op per trans with local");
- }//if
- if (startTransGuess == false) {
- ndbout_c("Not valid to use no_hint with local");
- }//if
- }//if
- return 0;
-}
-
-static
-void
-input_error(){
-
- ndbout_c("FLEXASYNCH");
- ndbout_c(" Perform benchmark of insert, update and delete transactions");
- ndbout_c("");
- ndbout_c("Arguments:");
- ndbout_c(" -t Number of threads to start, default 1");
- ndbout_c(" -p Number of parallel transactions per thread, default 32");
- ndbout_c(" -o Number of transactions per loop, default 500");
- ndbout_c(" -l Number of loops to run, default 1, 0=infinite");
- ndbout_c(" -load_factor Number Load factor in index in percent (40 -> 99)");
- ndbout_c(" -a Number of attributes, default 25");
- ndbout_c(" -c Number of operations per transaction");
- ndbout_c(" -s Size of each attribute, default 1 ");
- ndbout_c(" (PK is always of size 1, independent of this value)");
- ndbout_c(" -simple Use simple read to read from database");
- ndbout_c(" -dirty Use dirty read to read from database");
- ndbout_c(" -write Use writeTuple in insert and update");
- ndbout_c(" -n Use standard table names");
- ndbout_c(" -no_table_create Don't create tables in db");
- ndbout_c(" -temp Create table(s) without logging");
- ndbout_c(" -no_hint Don't give hint on where to execute transaction coordinator");
- ndbout_c(" -adaptive Use adaptive send algorithm (default)");
- ndbout_c(" -force Force send when communicating");
- ndbout_c(" -non_adaptive Send at a 10 millisecond interval");
- ndbout_c(" -local Number of part, only use keys in one part out of 16");
-}
-
-
-
diff --git a/ndb/test/ndbapi/flexBench/flexBench.cpp b/ndb/test/ndbapi/flexBench.cpp
index 809d11086bf..809d11086bf 100644
--- a/ndb/test/ndbapi/flexBench/flexBench.cpp
+++ b/ndb/test/ndbapi/flexBench.cpp
diff --git a/ndb/test/ndbapi/flexHammer.cpp b/ndb/test/ndbapi/flexHammer.cpp
new file mode 100644
index 00000000000..c1c47923de9
--- /dev/null
+++ b/ndb/test/ndbapi/flexHammer.cpp
@@ -0,0 +1,890 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ***************************************************
+ FLEXHAMMER
+ Hammer ndb with read, insert, update and delete transactions.
+
+ Arguments:
+ -t Number of threads to start, default 1
+ -o Number of operations per hammering-round, default 500
+ -l Number of loops to run, default 1, 0=infinite
+ -a Number of attributes, default 25
+ -c Number of tables, default 1
+ -s Size of each attribute, default 1
+ -simple Use simple read to read from database
+ -dirty Use dirty read to read from database
+ -write Use writeTuple to write to db
+ -r Number of records to Hammer
+ -no_table_create Don't create tables in db
+ -regulate To be able to regulate the load flexHammer produces.
+ -stdtables Use standard table names
+ -sleep Sleep a number of seconds before running the test, this
+ can be used so that another flexProgram have tome to create tables
+
+ Returns:
+ 0 - Test passed
+ -1 - Test failed
+ 1 - Invalid arguments
+
+Revision history:
+ 1.7 020208 epesson: Adapted to use NDBT
+ 1.10 020222 epesson: Finalised handling of thread results
+ 1.11 020222 epesson: Bug in checking results during delete fixed
+
+ * *************************************************** */
+
+#include <NdbApi.hpp>
+
+#include <NdbMain.h>
+#include <NdbThread.h>
+#include <NdbSleep.h>
+#include <NdbTick.h>
+#include <NdbOut.hpp>
+#include <NdbTimer.hpp>
+#include <NdbTick.h>
+#include <NdbTest.hpp>
+#include <NDBT_Error.hpp>
+#include <NdbSchemaCon.hpp>
+
+ErrorData * flexHammerErrorData;
+
+#if defined NDB_OSE || defined NDB_SOFTOSE
+#include <outfmt.h>
+#endif
+
+#define MAXSTRLEN 16
+#define MAXATTR 64
+#define MAXTABLES 64
+#define MAXTHREADS 256
+#define MAXATTRSIZE 100
+// Max number of retries if something fails
+#define MaxNoOfAttemptsC 10
+
+enum StartType {
+ stIdle,
+ stHammer,
+ stStop,
+ stLast};
+
+enum MyOpType {
+ otInsert,
+ otRead,
+ otDelete,
+ otUpdate,
+ otLast};
+
+struct ThreadNdb {
+ int threadNo;
+ NdbThread* threadLife;
+ int threadReady;
+ StartType threadStart;
+ int threadResult;};
+
+extern "C" void* flexHammerThread(void*);
+static int setAttrNames(void);
+static int setTableNames(void);
+static int readArguments(int, const char**);
+static int createTables(Ndb*);
+static void sleepBeforeStartingTest(int seconds);
+static int checkThreadResults(ThreadNdb *threadArrayP, char* phase);
+
+//enum OperationType {
+// otInsert,
+// otRead,
+// otUpdate,
+// otDelete,
+// otVerifyDelete,
+// otLast };
+
+enum ReadyType {
+ stReady,
+ stRunning
+} ;
+static int tNoOfThreads;
+static int tNoOfAttributes;
+static int tNoOfTables;
+static int tNoOfBackups;
+static int tAttributeSize;
+static int tNoOfOperations;
+static int tNoOfRecords;
+static int tNoOfLoops;
+static ReadyType ThreadReady[MAXTHREADS];
+static StartType ThreadStart[MAXTHREADS];
+static char tableName[MAXTABLES][MAXSTRLEN];
+static char attrName[MAXATTR][MAXSTRLEN];
+static int theSimpleFlag = 0;
+static int theWriteFlag = 0;
+static int theDirtyFlag = 0;
+static int theTableCreateFlag = 0;
+static int theStandardTableNameFlag = 0;
+static unsigned int tSleepTime = 0;
+
+#define START_TIMER { NdbTimer timer; timer.doStart();
+#define STOP_TIMER timer.doStop();
+#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
+
+
+// Initialise thread data
+void
+resetThreads(ThreadNdb *threadArrayP) {
+
+ for (int i = 0; i < tNoOfThreads ; i++)
+ {
+ threadArrayP[i].threadReady = 0;
+ threadArrayP[i].threadResult = 0;
+ threadArrayP[i].threadStart = stIdle;
+ }
+} // resetThreads
+
+void
+waitForThreads(ThreadNdb *threadArrayP)
+{
+ int cont = 1;
+
+ while (cont) {
+ NdbSleep_MilliSleep(100);
+ cont = 0;
+ for (int i = 0; i < tNoOfThreads ; i++) {
+ if (threadArrayP[i].threadReady == 0) {
+ cont = 1;
+ } // if
+ } // for
+ } // while
+} // waitForThreads
+
+void
+tellThreads(ThreadNdb* threadArrayP, const StartType what)
+{
+ for (int i = 0; i < tNoOfThreads ; i++)
+ {
+ threadArrayP[i].threadStart = what;
+ } // for
+} // tellThreads
+
+NDB_COMMAND(flexHammer, "flexHammer", "flexHammer", "flexHammer", 65535)
+//main(int argc, const char** argv)
+{
+ ThreadNdb* pThreads = NULL; // Pointer to thread data array
+ Ndb* pMyNdb = NULL; // Pointer to Ndb object
+ int tLoops = 0;
+ int returnValue = 0;
+ int check = 0;
+
+ flexHammerErrorData = new ErrorData;
+
+ flexHammerErrorData->resetErrorCounters();
+
+ if (readArguments(argc, argv) != 0) {
+ ndbout << "Wrong arguments to flexHammer" << endl;
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ } // if
+
+ /* print Setting */
+ flexHammerErrorData->printSettings(ndbout);
+
+ check = setAttrNames();
+ if (check == -1) {
+ ndbout << "Couldn't set attribute names" << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ } // if
+ check = setTableNames();
+ if (check == -1) {
+ ndbout << "Couldn't set table names" << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ } // if
+
+ // Create thread data array
+ pThreads = new ThreadNdb[tNoOfThreads];
+ // NdbThread_SetConcurrencyLevel(tNoOfThreads + 2);
+
+ // Create and init Ndb object
+ pMyNdb = new Ndb("TEST_DB");
+ pMyNdb->init();
+
+ // Wait for Ndb to become ready
+ if (pMyNdb->waitUntilReady(10000) != 0) {
+ ndbout << "NDB is not ready" << endl << "Benchmark failed" << endl;
+ returnValue = NDBT_FAILED;
+ }
+
+ else {
+ check = createTables(pMyNdb);
+ if (check != 0) {
+ returnValue = NDBT_FAILED;
+ } // if
+ else {
+ sleepBeforeStartingTest(tSleepTime);
+
+ // Create threads. *
+ resetThreads(pThreads);
+ for (int i = 0; i < tNoOfThreads ; i++) {
+ pThreads[i].threadNo = i;
+ pThreads[i].threadLife = NdbThread_Create(flexHammerThread,
+ (void**)&pThreads[i],
+ 65535,
+ "flexHammerThread",
+ NDB_THREAD_PRIO_LOW);
+ } // for
+
+ // And wait until they are ready
+ waitForThreads(pThreads);
+ if (checkThreadResults(pThreads, "init") != 0) {
+ returnValue = NDBT_FAILED;
+ } // if
+
+
+ if (returnValue == NDBT_OK) {
+ ndbout << endl << "All threads started" << endl << endl;
+
+ for(;;) {
+
+ // Check if it's time to exit program
+ if((tNoOfLoops != 0) && (tNoOfLoops <= tLoops))
+ break;
+
+ // Tell all threads to start hammer
+ ndbout << "Hammering..." << endl;
+
+ resetThreads(pThreads);
+
+ START_TIMER;
+ tellThreads(pThreads, stHammer);
+
+ waitForThreads(pThreads);
+ ndbout << "Threads ready to continue..." << endl;
+ STOP_TIMER;
+
+ // Check here if anything went wrong
+ if (checkThreadResults(pThreads, "hammer") != 0) {
+ ndbout << "Thread(s) failed." << endl;
+ returnValue = NDBT_FAILED;
+ } // if
+
+ PRINT_TIMER("hammer", tNoOfOperations*tNoOfThreads, tNoOfTables*6);
+
+ ndbout << endl;
+
+ tLoops++;
+
+ } // for
+ } // if
+
+ // Signaling threads to stop
+ resetThreads(pThreads);
+ tellThreads(pThreads, stStop);
+
+ // Wait for threads to stop
+ waitForThreads(pThreads);
+
+ ndbout << "----------------------------------------------" << endl << endl;
+ ndbout << "Benchmark completed" << endl;
+ } // else
+ } // else
+ // Clean up
+
+ flexHammerErrorData->printErrorCounters(ndbout);
+
+ // Kill them all!
+ void* tmp;
+ for(int i = 0; i < tNoOfThreads; i++){
+ NdbThread_WaitFor(pThreads[i].threadLife, &tmp);
+ NdbThread_Destroy(&pThreads[i].threadLife);
+ }
+ delete flexHammerErrorData;
+ delete [] pThreads;
+ delete pMyNdb;
+
+ // Exit via NDBT
+ return NDBT_ProgramExit(returnValue);
+
+} //main
+
+extern "C"
+void*
+flexHammerThread(void* pArg)
+{
+ ThreadNdb* pThreadData = (ThreadNdb*)pArg;
+ unsigned int threadNo = pThreadData->threadNo;
+ Ndb* pMyNdb = NULL ;
+ NdbConnection *pMyTransaction = NULL ;
+ // NdbOperation* pMyOperation[MAXTABLES] = {NULL};
+ NdbOperation* pMyOperation[MAXTABLES];
+ int check = 0;
+ int loop_count_ops = 0;
+ int loop_count_tables = 0;
+ int loop_count_attributes = 0;
+ int count_round = 0;
+ int count = 0;
+ int count_tables = 0;
+ int count_attributes = 0;
+ int i = 0;
+ int j = 0;
+ int tThreadResult = 0;
+ MyOpType tMyOpType = otLast;
+ int pkValue = 0;
+ int readValue[MAXATTR][MAXATTRSIZE] = {0};
+ int attrValue[MAXATTRSIZE];
+ NdbRecAttr* tTmp = NULL;
+ int tNoOfAttempts = 0;
+
+ for (i = 0; i < MAXATTRSIZE; i++)
+ attrValue[i] = 0;
+ // Ndb object for each thread
+ pMyNdb = new Ndb( "TEST_DB" );
+ pMyNdb->init();
+ if (pMyNdb->waitUntilReady(10000) != 0) {
+ // Error, NDB is not ready
+ tThreadResult = 99;
+ // Go to idle directly
+ pThreadData->threadStart = stIdle;
+ } // if
+
+ for(;;) {
+ pThreadData->threadResult = tThreadResult;
+ pThreadData->threadReady = 1; // Signalling ready to main
+
+ // If Idle just wait to be stopped from main
+ while (pThreadData->threadStart == stIdle) {
+ NdbSleep_MilliSleep(100);
+ } // while
+
+ // Check if signal to exit is received
+ if (pThreadData->threadStart == stStop) {
+ pThreadData->threadReady = 1;
+ // break out of eternal loop
+ break;
+ } // if
+
+ // Set to Idle to prepare for possible error break
+ pThreadData->threadStart = stIdle;
+
+ // Prepare transaction
+ loop_count_ops = tNoOfOperations;
+ loop_count_tables = tNoOfTables;
+ loop_count_attributes = tNoOfAttributes;
+
+ for (count=0 ; count < loop_count_ops ; count++) {
+
+ //pkValue = (int)(count + thread_base);
+ // This limits the number of records used in this test
+ pkValue = count % tNoOfRecords;
+
+ for (count_round = 0; count_round < 5; ) {
+ switch (count_round) {
+ case 0: // Insert
+ tMyOpType = otInsert;
+ // Increase attrValues
+ for (i=0; i < MAXATTRSIZE; i ++) {
+ attrValue[i]++;
+ }
+ break;
+ case 1:
+ case 3: // Read and verify
+ tMyOpType = otRead;
+ break;
+ case 2: // Update
+ // Increase attrValues
+ for(i=0; i < MAXATTRSIZE; i ++) {
+ attrValue[i]++;
+ }
+ tMyOpType = otUpdate;
+ break;
+ case 4: // Delete
+ tMyOpType = otDelete;
+ break;
+ default:
+ assert(false);
+ break;
+ } // switch
+
+ // Get transaction object
+ pMyTransaction = pMyNdb->startTransaction();
+ if (pMyTransaction == NULL) {
+ // Fatal error
+ tThreadResult = 1;
+ // break out of for count_round loop waiting to be stopped by main
+ break;
+ } // if
+
+ for (count_tables = 0; count_tables < loop_count_tables;
+ count_tables++) {
+ pMyOperation[count_tables] =
+ pMyTransaction->getNdbOperation(tableName[count_tables]);
+ if (pMyOperation[count_tables] == NULL) {
+ //Fatal error
+ tThreadResult = 2;
+ // break out of inner for count_tables loop
+ break;
+ } // if
+
+ switch (tMyOpType) {
+ case otInsert: // Insert case
+ if (theWriteFlag == 1 && theDirtyFlag == 1) {
+ check = pMyOperation[count_tables]->dirtyWrite();
+ } else if (theWriteFlag == 1) {
+ check = pMyOperation[count_tables]->writeTuple();
+ } else {
+ check = pMyOperation[count_tables]->insertTuple();
+ } // if else
+ break;
+ case otRead: // Read Case
+ if (theSimpleFlag == 1) {
+ check = pMyOperation[count_tables]->simpleRead();
+ } else if (theDirtyFlag == 1) {
+ check = pMyOperation[count_tables]->dirtyRead();
+ } else {
+ check = pMyOperation[count_tables]->readTuple();
+ } // if else
+ break;
+ case otUpdate: // Update Case
+ if (theWriteFlag == 1 && theDirtyFlag == 1) {
+ check = pMyOperation[count_tables]->dirtyWrite();
+ } else if (theWriteFlag == 1) {
+ check = pMyOperation[count_tables]->writeTuple();
+ } else if (theDirtyFlag == 1) {
+ check = pMyOperation[count_tables]->dirtyUpdate();
+ } else {
+ check = pMyOperation[count_tables]->updateTuple();
+ } // if else
+ break;
+ case otDelete: // Delete Case
+ check = pMyOperation[count_tables]->deleteTuple();
+ break;
+ default:
+ assert(false);
+ break;
+ } // switch
+ if (check == -1) {
+ // Fatal error
+ tThreadResult = 3;
+ // break out of inner for count_tables loop
+ break;
+ } // if
+
+ check = pMyOperation[count_tables]->equal( (char*)attrName[0],
+ (char*)&pkValue );
+
+ if (check == -1) {
+ // Fatal error
+ tThreadResult = 4;
+ ndbout << "pMyOperation equal failed" << endl;
+ // break out of inner for count_tables loop
+ break;
+ } // if
+
+ check = -1;
+ tTmp = NULL;
+ switch (tMyOpType) {
+ case otInsert: // Insert case
+ case otUpdate: // Update Case
+ for (count_attributes = 1; count_attributes < loop_count_attributes;
+ count_attributes++) {
+ check =
+ pMyOperation[count_tables]->setValue((char*)attrName[count_attributes], (char*)&attrValue[0]);
+ } // for
+ break;
+ case otRead: // Read Case
+ for (count_attributes = 1; count_attributes < loop_count_attributes;
+ count_attributes++) {
+ tTmp = pMyOperation[count_tables]->
+ getValue( (char*)attrName[count_attributes],
+ (char*)&readValue[count_attributes][0] );
+ } // for
+ break;
+ case otDelete: // Delete Case
+ break;
+ default:
+ assert(false);
+ break;
+ } // switch
+ if (check == -1 && tTmp == NULL && tMyOpType != otDelete) {
+ // Fatal error
+ tThreadResult = 5;
+ break;
+ } // if
+ } // for count_tables
+
+ // Only execute if everything is OK
+ if (tThreadResult != 0) {
+ // Close transaction (below)
+ // and continue with next count_round
+ count_round++;
+ tNoOfAttempts = 0;
+ } // if
+ else {
+ check = pMyTransaction->execute(Commit);
+ if (check == -1 ) {
+ const NdbError & err = pMyTransaction->getNdbError();
+
+ // Add complete error handling here
+
+ int retCode = flexHammerErrorData->handleErrorCommon(pMyTransaction->getNdbError());
+ if (retCode == 1) {
+ //if (strcmp(pMyTransaction->getNdbError().message, "Tuple did not exist") != 0 && strcmp(pMyTransaction->getNdbError().message,"Tuple already existed when attempting to insert") != 0) ndbout_c("execute: %s", pMyTransaction->getNdbError().message);
+
+ if (pMyTransaction->getNdbError().code != 626 && pMyTransaction->getNdbError().code != 630){
+ ndbout_c("Error code = %d", pMyTransaction->getNdbError().code);
+ ndbout_c("execute: %s", pMyTransaction->getNdbError().message);}
+
+ } else if (retCode == 2) {
+ ndbout << "4115 should not happen in flexHammer" << endl;
+ } else if (retCode == 3) {
+// --------------------------------------------------------------------
+// We are not certain if the transaction was successful or not.
+// We must reexecute but might very well find that the transaction
+// actually was updated. Updates and Reads are no problem here. Inserts
+// will not cause a problem if error code 630 arrives. Deletes will
+// not cause a problem if 626 arrives.
+// --------------------------------------------------------------------
+ /* What can we do here? */
+ ndbout_c("execute: %s", pMyTransaction->getNdbError().message);
+ }//if(retCode == 3)
+ // End of adding complete error handling
+
+ switch( err.classification) {
+ case NdbError::ConstraintViolation: // Tuple already existed
+ count_round++;
+ tNoOfAttempts = 0;
+ break;
+ case NdbError::TimeoutExpired:
+ case NdbError::NodeRecoveryError:
+ case NdbError::TemporaryResourceError:
+ case NdbError::OverloadError:
+ if (tNoOfAttempts <= MaxNoOfAttemptsC) {
+ // Retry
+ tNoOfAttempts++;
+ } else {
+ // Too many retries, continue with next
+ count_round++;
+ tNoOfAttempts = 0;
+ } // else if
+ break;
+ // Fatal, just continue
+ default:
+ count_round++;
+ tNoOfAttempts = 0;
+ break;
+ } // switch
+ } // if
+ else {
+ // Execute commit was OK
+ // This is verifying read values
+ //switch (tMyOpType) {
+ //case otRead: // Read case
+ //for (j = 0; j < tNoOfAttributes; j++) {
+ //for(i = 1; i < tAttributeSize; i++) {
+ //if ( readValue[j][i] != attrValue[i]) {
+ //ndbout << "pkValue = " << pkValue << endl;
+ //ndbout << "readValue != attrValue" << endl;
+ //ndbout << readValue[j][i] << " != " << attrValue[i] << endl;
+ //} // if
+ // } // for
+ //} // for
+ //break;
+ //} // switch
+ count_round++;
+ tNoOfAttempts = 0;
+ } // else if
+ } // else if
+ pMyNdb->closeTransaction(pMyTransaction);
+ } // for count_round
+ } // for count
+ } // for (;;)
+
+ // Clean up
+ delete pMyNdb;
+ pMyNdb = NULL;
+
+ flexHammerErrorData->resetErrorCounters();
+
+ // And exit using NDBT
+ NdbThread_Exit(0);
+
+ return NULL;
+
+} // flexHammerThread
+
+
+int
+readArguments (int argc, const char** argv)
+{
+ int i = 1;
+
+ tNoOfThreads = 5; // Default Value
+ tNoOfOperations = 500; // Default Value
+ tNoOfRecords = 1; // Default Value
+ tNoOfLoops = 1; // Default Value
+ tNoOfAttributes = 25; // Default Value
+ tNoOfTables = 1; // Default Value
+ tNoOfBackups = 0; // Default Value
+ tAttributeSize = 1; // Default Value
+ theTableCreateFlag = 0;
+
+ while (argc > 1) {
+ if (strcmp(argv[i], "-t") == 0) {
+ tNoOfThreads = atoi(argv[i+1]);
+ if ((tNoOfThreads < 1) || (tNoOfThreads > MAXTHREADS))
+ return(1);
+ }
+ else if (strcmp(argv[i], "-o") == 0) {
+ tNoOfOperations = atoi(argv[i+1]);
+ if (tNoOfOperations < 1)
+ return(1);
+ }
+ else if (strcmp(argv[i], "-r") == 0) {
+ tNoOfRecords = atoi(argv[i+1]);
+ if (tNoOfRecords < 1)
+ return(1);
+ }
+ else if (strcmp(argv[i], "-a") == 0) {
+ tNoOfAttributes = atoi(argv[i+1]);
+ if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR))
+ return(1);
+ }
+ else if (strcmp(argv[i], "-c") == 0) {
+ tNoOfTables = atoi(argv[i+1]);
+ if ((tNoOfTables < 1) || (tNoOfTables > MAXTABLES))
+ return(1);
+ }
+ else if (strcmp(argv[i], "-l") == 0) {
+ tNoOfLoops = atoi(argv[i+1]);
+ if ((tNoOfLoops < 0) || (tNoOfLoops > 100000))
+ return(1);
+ }
+ else if (strcmp(argv[i], "-s") == 0) {
+ tAttributeSize = atoi(argv[i+1]);
+ if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE))
+ return(1);
+ }
+ else if (strcmp(argv[i], "-sleep") == 0) {
+ tSleepTime = atoi(argv[i+1]);
+ if ((tSleepTime < 1) || (tSleepTime > 3600))
+ exit(-1);
+ }
+ else if (strcmp(argv[i], "-simple") == 0) {
+ theSimpleFlag = 1;
+ argc++;
+ i--;
+ }
+ else if (strcmp(argv[i], "-write") == 0) {
+ theWriteFlag = 1;
+ argc++;
+ i--;
+ }
+ else if (strcmp(argv[i], "-dirty") == 0) {
+ theDirtyFlag = 1;
+ argc++;
+ i--;
+ }
+ else if (strcmp(argv[i], "-no_table_create") == 0) {
+ theTableCreateFlag = 1;
+ argc++;
+ i--;
+ }
+ else if (strcmp(argv[i], "-stdtables") == 0) {
+ theStandardTableNameFlag = 1;
+ argc++;
+ i--;
+ } // if
+ else {
+ return(1);
+ }
+
+ argc -= 2;
+ i = i + 2;
+ } // while
+
+ ndbout << endl << "FLEXHAMMER - Starting normal mode" << endl;
+ ndbout << "Hammer ndb with read, insert, update and delete transactions"<< endl << endl;
+
+ ndbout << " " << tNoOfThreads << " thread(s) " << endl;
+ ndbout << " " << tNoOfLoops << " iterations " << endl;
+ ndbout << " " << tNoOfTables << " table(s) and " << 1 << " operation(s) per transaction " << endl;
+ ndbout << " " << tNoOfRecords << " records to hammer(limit this with the -r option)" << endl;
+ ndbout << " " << tNoOfAttributes << " attributes per table " << endl;
+ ndbout << " " << tNoOfOperations << " transaction(s) per thread and round " << endl;
+ ndbout << " " << tAttributeSize << " is the number of 32 bit words per attribute " << endl << endl;
+ return 0;
+} // readArguments
+
+
+void sleepBeforeStartingTest(int seconds)
+{
+ if (seconds > 0) {
+ ndbout << "Sleeping(" << seconds << ")...";
+ NdbSleep_SecSleep(seconds);
+ ndbout << " done!" << endl;
+ } // if
+} // sleepBeforeStartingTest
+
+static int
+createTables(Ndb* pMyNdb)
+{
+ int i = 0;
+ int j = 0;
+ int check = 0;
+ NdbSchemaCon *MySchemaTransaction = NULL;
+ NdbSchemaOp *MySchemaOp = NULL;
+
+ // Create Table and Attributes.
+ if (theTableCreateFlag == 0) {
+
+ for (i = 0; i < tNoOfTables; i++) {
+
+ ndbout << "Creating " << tableName[i] << "...";
+ // Check if table exists already
+ const void * p = pMyNdb->getDictionary()->getTable(tableName[i]);
+ if (p != 0) {
+ ndbout << " already exists." << endl;
+ // Continue with next table at once
+ continue;
+ } // if
+ ndbout << endl;
+
+ MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pMyNdb);
+ if (MySchemaTransaction == NULL) {
+ return(-1);
+ } // if
+
+ MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if (MySchemaOp == NULL) {
+ // Clean up opened schema transaction
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return(-1);
+ } // if
+
+ // Create tables, rest of parameters are default right now
+#if defined NDB_OSE || defined NDB_SOFTOSE
+ check = MySchemaOp->createTable(tableName[i],
+ 8, // Table Size
+ TupleKey, // Key Type
+ 40, // Nr of Pages
+ All,
+ 6,
+ 78,
+ 80,
+ 1,
+ false);
+
+#else
+ check = MySchemaOp->createTable(tableName[i],
+ 8, // Table Size
+ TupleKey, // Key Type
+ 40); // Nr of Pages
+#endif
+ if (check == -1) {
+ // Clean up opened schema transaction
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return(-1);
+ } // if
+
+ // Primary key
+ //ndbout << " pk " << (char*)&attrName[0] << "..." << endl;
+ check = MySchemaOp->createAttribute( (char*)attrName[0], TupleKey, 32,
+ 1, UnSigned, MMBased,
+ NotNullAttribute );
+ if (check == -1) {
+ // Clean up opened schema transaction
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return(-1);
+ } // if
+
+ // Rest of attributes
+ for (j = 1; j < tNoOfAttributes ; j++) {
+ //ndbout << " " << (char*)attrName[j] << "..." << endl;
+ check = MySchemaOp->createAttribute( (char*)attrName[j], NoKey, 32,
+ tAttributeSize, UnSigned, MMBased,
+ NotNullAttribute );
+ if (check == -1) {
+ // Clean up opened schema transaction
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return(-1);
+ } // if
+ } // for
+
+ // Execute creation
+ check = MySchemaTransaction->execute();
+ if (check == -1) {
+ // Clean up opened schema transaction
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return(-1);
+ } // if
+
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ } // for
+ } // if
+
+ return(0);
+
+} // createTables
+
+
+static int setAttrNames()
+{
+ int i = 0;
+ int retVal = 0;
+
+ for (i = 0; i < MAXATTR ; i++) {
+ retVal = snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ if (retVal < 0) {
+ // Error in conversion
+ return(-1);
+ } // if
+ } // for
+
+ return (0);
+} // setAttrNames
+
+static int setTableNames()
+{
+ // Note! Uses only uppercase letters in table name's
+ // so that we can look at the tables wits SQL
+ int i = 0;
+ int retVal = 0;
+
+ for (i = 0; i < MAXTABLES ; i++) {
+ if (theStandardTableNameFlag == 0) {
+ retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
+ NdbTick_CurrentMillisecond()/1000);
+ } // if
+ else {
+ retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
+ } // else
+ if (retVal < 0) {
+ // Error in conversion
+ return(-1);
+ } // if
+ } // for
+
+ return(0);
+} // setTableNames
+
+static int checkThreadResults(ThreadNdb *threadArrayP, char* phase)
+{
+ int i = 0;
+
+ for (i = 0; i < tNoOfThreads; i++) {
+ if (threadArrayP[i].threadResult != 0) {
+ ndbout << "Thread " << i << " reported fatal error "
+ << threadArrayP[i].threadResult << " during " << phase << endl;
+ return(-1);
+ } // if
+ } // for
+
+ return(0);
+}
+
diff --git a/ndb/test/ndbapi/flexHammer/flexHammer.cpp b/ndb/test/ndbapi/flexHammer/flexHammer.cpp
deleted file mode 100644
index 057efb31e74..00000000000
--- a/ndb/test/ndbapi/flexHammer/flexHammer.cpp
+++ /dev/null
@@ -1,889 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* ***************************************************
- FLEXHAMMER
- Hammer ndb with read, insert, update and delete transactions.
-
- Arguments:
- -t Number of threads to start, default 1
- -o Number of operations per hammering-round, default 500
- -l Number of loops to run, default 1, 0=infinite
- -a Number of attributes, default 25
- -c Number of tables, default 1
- -s Size of each attribute, default 1
- -simple Use simple read to read from database
- -dirty Use dirty read to read from database
- -write Use writeTuple to write to db
- -r Number of records to Hammer
- -no_table_create Don't create tables in db
- -regulate To be able to regulate the load flexHammer produces.
- -stdtables Use standard table names
- -sleep Sleep a number of seconds before running the test, this
- can be used so that another flexProgram have tome to create tables
-
- Returns:
- 0 - Test passed
- -1 - Test failed
- 1 - Invalid arguments
-
-Revision history:
- 1.7 020208 epesson: Adapted to use NDBT
- 1.10 020222 epesson: Finalised handling of thread results
- 1.11 020222 epesson: Bug in checking results during delete fixed
-
- * *************************************************** */
-
-#include <NdbApi.hpp>
-
-#include <NdbMain.h>
-#include <NdbThread.h>
-#include <NdbSleep.h>
-#include <NdbTick.h>
-#include <NdbOut.hpp>
-#include <NdbTimer.hpp>
-#include <NdbTick.h>
-#include <NdbTest.hpp>
-#include <NDBT_Error.hpp>
-
-ErrorData * flexHammerErrorData;
-
-#if defined NDB_OSE || defined NDB_SOFTOSE
-#include <outfmt.h>
-#endif
-
-#define MAXSTRLEN 16
-#define MAXATTR 64
-#define MAXTABLES 64
-#define MAXTHREADS 256
-#define MAXATTRSIZE 100
-// Max number of retries if something fails
-#define MaxNoOfAttemptsC 10
-
-enum StartType {
- stIdle,
- stHammer,
- stStop,
- stLast};
-
-enum MyOpType {
- otInsert,
- otRead,
- otDelete,
- otUpdate,
- otLast};
-
-struct ThreadNdb {
- int threadNo;
- NdbThread* threadLife;
- int threadReady;
- StartType threadStart;
- int threadResult;};
-
-extern "C" void* flexHammerThread(void*);
-static int setAttrNames(void);
-static int setTableNames(void);
-static int readArguments(int, const char**);
-static int createTables(Ndb*);
-static void sleepBeforeStartingTest(int seconds);
-static int checkThreadResults(ThreadNdb *threadArrayP, char* phase);
-
-//enum OperationType {
-// otInsert,
-// otRead,
-// otUpdate,
-// otDelete,
-// otVerifyDelete,
-// otLast };
-
-enum ReadyType {
- stReady,
- stRunning
-} ;
-static int tNoOfThreads;
-static int tNoOfAttributes;
-static int tNoOfTables;
-static int tNoOfBackups;
-static int tAttributeSize;
-static int tNoOfOperations;
-static int tNoOfRecords;
-static int tNoOfLoops;
-static ReadyType ThreadReady[MAXTHREADS];
-static StartType ThreadStart[MAXTHREADS];
-static char tableName[MAXTABLES][MAXSTRLEN];
-static char attrName[MAXATTR][MAXSTRLEN];
-static int theSimpleFlag = 0;
-static int theWriteFlag = 0;
-static int theDirtyFlag = 0;
-static int theTableCreateFlag = 0;
-static int theStandardTableNameFlag = 0;
-static unsigned int tSleepTime = 0;
-
-#define START_TIMER { NdbTimer timer; timer.doStart();
-#define STOP_TIMER timer.doStop();
-#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
-
-
-// Initialise thread data
-void
-resetThreads(ThreadNdb *threadArrayP) {
-
- for (int i = 0; i < tNoOfThreads ; i++)
- {
- threadArrayP[i].threadReady = 0;
- threadArrayP[i].threadResult = 0;
- threadArrayP[i].threadStart = stIdle;
- }
-} // resetThreads
-
-void
-waitForThreads(ThreadNdb *threadArrayP)
-{
- int cont = 1;
-
- while (cont) {
- NdbSleep_MilliSleep(100);
- cont = 0;
- for (int i = 0; i < tNoOfThreads ; i++) {
- if (threadArrayP[i].threadReady == 0) {
- cont = 1;
- } // if
- } // for
- } // while
-} // waitForThreads
-
-void
-tellThreads(ThreadNdb* threadArrayP, const StartType what)
-{
- for (int i = 0; i < tNoOfThreads ; i++)
- {
- threadArrayP[i].threadStart = what;
- } // for
-} // tellThreads
-
-NDB_COMMAND(flexHammer, "flexHammer", "flexHammer", "flexHammer", 65535)
-//main(int argc, const char** argv)
-{
- ThreadNdb* pThreads = NULL; // Pointer to thread data array
- Ndb* pMyNdb = NULL; // Pointer to Ndb object
- int tLoops = 0;
- int returnValue = 0;
- int check = 0;
-
- flexHammerErrorData = new ErrorData;
-
- flexHammerErrorData->resetErrorCounters();
-
- if (readArguments(argc, argv) != 0) {
- ndbout << "Wrong arguments to flexHammer" << endl;
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- } // if
-
- /* print Setting */
- flexHammerErrorData->printSettings(ndbout);
-
- check = setAttrNames();
- if (check == -1) {
- ndbout << "Couldn't set attribute names" << endl;
- return NDBT_ProgramExit(NDBT_FAILED);
- } // if
- check = setTableNames();
- if (check == -1) {
- ndbout << "Couldn't set table names" << endl;
- return NDBT_ProgramExit(NDBT_FAILED);
- } // if
-
- // Create thread data array
- pThreads = new ThreadNdb[tNoOfThreads];
- // NdbThread_SetConcurrencyLevel(tNoOfThreads + 2);
-
- // Create and init Ndb object
- pMyNdb = new Ndb("TEST_DB");
- pMyNdb->init();
-
- // Wait for Ndb to become ready
- if (pMyNdb->waitUntilReady(10000) != 0) {
- ndbout << "NDB is not ready" << endl << "Benchmark failed" << endl;
- returnValue = NDBT_FAILED;
- }
-
- else {
- check = createTables(pMyNdb);
- if (check != 0) {
- returnValue = NDBT_FAILED;
- } // if
- else {
- sleepBeforeStartingTest(tSleepTime);
-
- // Create threads. *
- resetThreads(pThreads);
- for (int i = 0; i < tNoOfThreads ; i++) {
- pThreads[i].threadNo = i;
- pThreads[i].threadLife = NdbThread_Create(flexHammerThread,
- (void**)&pThreads[i],
- 65535,
- "flexHammerThread",
- NDB_THREAD_PRIO_LOW);
- } // for
-
- // And wait until they are ready
- waitForThreads(pThreads);
- if (checkThreadResults(pThreads, "init") != 0) {
- returnValue = NDBT_FAILED;
- } // if
-
-
- if (returnValue == NDBT_OK) {
- ndbout << endl << "All threads started" << endl << endl;
-
- for(;;) {
-
- // Check if it's time to exit program
- if((tNoOfLoops != 0) && (tNoOfLoops <= tLoops))
- break;
-
- // Tell all threads to start hammer
- ndbout << "Hammering..." << endl;
-
- resetThreads(pThreads);
-
- START_TIMER;
- tellThreads(pThreads, stHammer);
-
- waitForThreads(pThreads);
- ndbout << "Threads ready to continue..." << endl;
- STOP_TIMER;
-
- // Check here if anything went wrong
- if (checkThreadResults(pThreads, "hammer") != 0) {
- ndbout << "Thread(s) failed." << endl;
- returnValue = NDBT_FAILED;
- } // if
-
- PRINT_TIMER("hammer", tNoOfOperations*tNoOfThreads, tNoOfTables*6);
-
- ndbout << endl;
-
- tLoops++;
-
- } // for
- } // if
-
- // Signaling threads to stop
- resetThreads(pThreads);
- tellThreads(pThreads, stStop);
-
- // Wait for threads to stop
- waitForThreads(pThreads);
-
- ndbout << "----------------------------------------------" << endl << endl;
- ndbout << "Benchmark completed" << endl;
- } // else
- } // else
- // Clean up
-
- flexHammerErrorData->printErrorCounters(ndbout);
-
- // Kill them all!
- void* tmp;
- for(int i = 0; i < tNoOfThreads; i++){
- NdbThread_WaitFor(pThreads[i].threadLife, &tmp);
- NdbThread_Destroy(&pThreads[i].threadLife);
- }
- delete flexHammerErrorData;
- delete [] pThreads;
- delete pMyNdb;
-
- // Exit via NDBT
- return NDBT_ProgramExit(returnValue);
-
-} //main
-
-extern "C"
-void*
-flexHammerThread(void* pArg)
-{
- ThreadNdb* pThreadData = (ThreadNdb*)pArg;
- unsigned int threadNo = pThreadData->threadNo;
- Ndb* pMyNdb = NULL ;
- NdbConnection *pMyTransaction = NULL ;
- // NdbOperation* pMyOperation[MAXTABLES] = {NULL};
- NdbOperation* pMyOperation[MAXTABLES];
- int check = 0;
- int loop_count_ops = 0;
- int loop_count_tables = 0;
- int loop_count_attributes = 0;
- int count_round = 0;
- int count = 0;
- int count_tables = 0;
- int count_attributes = 0;
- int i = 0;
- int j = 0;
- int tThreadResult = 0;
- MyOpType tMyOpType = otLast;
- int pkValue = 0;
- int readValue[MAXATTR][MAXATTRSIZE] = {0};
- int attrValue[MAXATTRSIZE];
- NdbRecAttr* tTmp = NULL;
- int tNoOfAttempts = 0;
-
- for (i = 0; i < MAXATTRSIZE; i++)
- attrValue[i] = 0;
- // Ndb object for each thread
- pMyNdb = new Ndb( "TEST_DB" );
- pMyNdb->init();
- if (pMyNdb->waitUntilReady(10000) != 0) {
- // Error, NDB is not ready
- tThreadResult = 99;
- // Go to idle directly
- pThreadData->threadStart = stIdle;
- } // if
-
- for(;;) {
- pThreadData->threadResult = tThreadResult;
- pThreadData->threadReady = 1; // Signalling ready to main
-
- // If Idle just wait to be stopped from main
- while (pThreadData->threadStart == stIdle) {
- NdbSleep_MilliSleep(100);
- } // while
-
- // Check if signal to exit is received
- if (pThreadData->threadStart == stStop) {
- pThreadData->threadReady = 1;
- // break out of eternal loop
- break;
- } // if
-
- // Set to Idle to prepare for possible error break
- pThreadData->threadStart = stIdle;
-
- // Prepare transaction
- loop_count_ops = tNoOfOperations;
- loop_count_tables = tNoOfTables;
- loop_count_attributes = tNoOfAttributes;
-
- for (count=0 ; count < loop_count_ops ; count++) {
-
- //pkValue = (int)(count + thread_base);
- // This limits the number of records used in this test
- pkValue = count % tNoOfRecords;
-
- for (count_round = 0; count_round < 5; ) {
- switch (count_round) {
- case 0: // Insert
- tMyOpType = otInsert;
- // Increase attrValues
- for (i=0; i < MAXATTRSIZE; i ++) {
- attrValue[i]++;
- }
- break;
- case 1:
- case 3: // Read and verify
- tMyOpType = otRead;
- break;
- case 2: // Update
- // Increase attrValues
- for(i=0; i < MAXATTRSIZE; i ++) {
- attrValue[i]++;
- }
- tMyOpType = otUpdate;
- break;
- case 4: // Delete
- tMyOpType = otDelete;
- break;
- default:
- assert(false);
- break;
- } // switch
-
- // Get transaction object
- pMyTransaction = pMyNdb->startTransaction();
- if (pMyTransaction == NULL) {
- // Fatal error
- tThreadResult = 1;
- // break out of for count_round loop waiting to be stopped by main
- break;
- } // if
-
- for (count_tables = 0; count_tables < loop_count_tables;
- count_tables++) {
- pMyOperation[count_tables] =
- pMyTransaction->getNdbOperation(tableName[count_tables]);
- if (pMyOperation[count_tables] == NULL) {
- //Fatal error
- tThreadResult = 2;
- // break out of inner for count_tables loop
- break;
- } // if
-
- switch (tMyOpType) {
- case otInsert: // Insert case
- if (theWriteFlag == 1 && theDirtyFlag == 1) {
- check = pMyOperation[count_tables]->dirtyWrite();
- } else if (theWriteFlag == 1) {
- check = pMyOperation[count_tables]->writeTuple();
- } else {
- check = pMyOperation[count_tables]->insertTuple();
- } // if else
- break;
- case otRead: // Read Case
- if (theSimpleFlag == 1) {
- check = pMyOperation[count_tables]->simpleRead();
- } else if (theDirtyFlag == 1) {
- check = pMyOperation[count_tables]->dirtyRead();
- } else {
- check = pMyOperation[count_tables]->readTuple();
- } // if else
- break;
- case otUpdate: // Update Case
- if (theWriteFlag == 1 && theDirtyFlag == 1) {
- check = pMyOperation[count_tables]->dirtyWrite();
- } else if (theWriteFlag == 1) {
- check = pMyOperation[count_tables]->writeTuple();
- } else if (theDirtyFlag == 1) {
- check = pMyOperation[count_tables]->dirtyUpdate();
- } else {
- check = pMyOperation[count_tables]->updateTuple();
- } // if else
- break;
- case otDelete: // Delete Case
- check = pMyOperation[count_tables]->deleteTuple();
- break;
- default:
- assert(false);
- break;
- } // switch
- if (check == -1) {
- // Fatal error
- tThreadResult = 3;
- // break out of inner for count_tables loop
- break;
- } // if
-
- check = pMyOperation[count_tables]->equal( (char*)attrName[0],
- (char*)&pkValue );
-
- if (check == -1) {
- // Fatal error
- tThreadResult = 4;
- ndbout << "pMyOperation equal failed" << endl;
- // break out of inner for count_tables loop
- break;
- } // if
-
- check = -1;
- tTmp = NULL;
- switch (tMyOpType) {
- case otInsert: // Insert case
- case otUpdate: // Update Case
- for (count_attributes = 1; count_attributes < loop_count_attributes;
- count_attributes++) {
- check =
- pMyOperation[count_tables]->setValue((char*)attrName[count_attributes], (char*)&attrValue[0]);
- } // for
- break;
- case otRead: // Read Case
- for (count_attributes = 1; count_attributes < loop_count_attributes;
- count_attributes++) {
- tTmp = pMyOperation[count_tables]->
- getValue( (char*)attrName[count_attributes],
- (char*)&readValue[count_attributes][0] );
- } // for
- break;
- case otDelete: // Delete Case
- break;
- default:
- assert(false);
- break;
- } // switch
- if (check == -1 && tTmp == NULL && tMyOpType != otDelete) {
- // Fatal error
- tThreadResult = 5;
- break;
- } // if
- } // for count_tables
-
- // Only execute if everything is OK
- if (tThreadResult != 0) {
- // Close transaction (below)
- // and continue with next count_round
- count_round++;
- tNoOfAttempts = 0;
- } // if
- else {
- check = pMyTransaction->execute(Commit);
- if (check == -1 ) {
- const NdbError & err = pMyTransaction->getNdbError();
-
- // Add complete error handling here
-
- int retCode = flexHammerErrorData->handleErrorCommon(pMyTransaction->getNdbError());
- if (retCode == 1) {
- //if (strcmp(pMyTransaction->getNdbError().message, "Tuple did not exist") != 0 && strcmp(pMyTransaction->getNdbError().message,"Tuple already existed when attempting to insert") != 0) ndbout_c("execute: %s", pMyTransaction->getNdbError().message);
-
- if (pMyTransaction->getNdbError().code != 626 && pMyTransaction->getNdbError().code != 630){
- ndbout_c("Error code = %d", pMyTransaction->getNdbError().code);
- ndbout_c("execute: %s", pMyTransaction->getNdbError().message);}
-
- } else if (retCode == 2) {
- ndbout << "4115 should not happen in flexHammer" << endl;
- } else if (retCode == 3) {
-// --------------------------------------------------------------------
-// We are not certain if the transaction was successful or not.
-// We must reexecute but might very well find that the transaction
-// actually was updated. Updates and Reads are no problem here. Inserts
-// will not cause a problem if error code 630 arrives. Deletes will
-// not cause a problem if 626 arrives.
-// --------------------------------------------------------------------
- /* What can we do here? */
- ndbout_c("execute: %s", pMyTransaction->getNdbError().message);
- }//if(retCode == 3)
- // End of adding complete error handling
-
- switch( err.classification) {
- case NdbError::ConstraintViolation: // Tuple already existed
- count_round++;
- tNoOfAttempts = 0;
- break;
- case NdbError::TimeoutExpired:
- case NdbError::NodeRecoveryError:
- case NdbError::TemporaryResourceError:
- case NdbError::OverloadError:
- if (tNoOfAttempts <= MaxNoOfAttemptsC) {
- // Retry
- tNoOfAttempts++;
- } else {
- // Too many retries, continue with next
- count_round++;
- tNoOfAttempts = 0;
- } // else if
- break;
- // Fatal, just continue
- default:
- count_round++;
- tNoOfAttempts = 0;
- break;
- } // switch
- } // if
- else {
- // Execute commit was OK
- // This is verifying read values
- //switch (tMyOpType) {
- //case otRead: // Read case
- //for (j = 0; j < tNoOfAttributes; j++) {
- //for(i = 1; i < tAttributeSize; i++) {
- //if ( readValue[j][i] != attrValue[i]) {
- //ndbout << "pkValue = " << pkValue << endl;
- //ndbout << "readValue != attrValue" << endl;
- //ndbout << readValue[j][i] << " != " << attrValue[i] << endl;
- //} // if
- // } // for
- //} // for
- //break;
- //} // switch
- count_round++;
- tNoOfAttempts = 0;
- } // else if
- } // else if
- pMyNdb->closeTransaction(pMyTransaction);
- } // for count_round
- } // for count
- } // for (;;)
-
- // Clean up
- delete pMyNdb;
- pMyNdb = NULL;
-
- flexHammerErrorData->resetErrorCounters();
-
- // And exit using NDBT
- NdbThread_Exit(0);
-
- return NULL;
-
-} // flexHammerThread
-
-
-int
-readArguments (int argc, const char** argv)
-{
- int i = 1;
-
- tNoOfThreads = 5; // Default Value
- tNoOfOperations = 500; // Default Value
- tNoOfRecords = 1; // Default Value
- tNoOfLoops = 1; // Default Value
- tNoOfAttributes = 25; // Default Value
- tNoOfTables = 1; // Default Value
- tNoOfBackups = 0; // Default Value
- tAttributeSize = 1; // Default Value
- theTableCreateFlag = 0;
-
- while (argc > 1) {
- if (strcmp(argv[i], "-t") == 0) {
- tNoOfThreads = atoi(argv[i+1]);
- if ((tNoOfThreads < 1) || (tNoOfThreads > MAXTHREADS))
- return(1);
- }
- else if (strcmp(argv[i], "-o") == 0) {
- tNoOfOperations = atoi(argv[i+1]);
- if (tNoOfOperations < 1)
- return(1);
- }
- else if (strcmp(argv[i], "-r") == 0) {
- tNoOfRecords = atoi(argv[i+1]);
- if (tNoOfRecords < 1)
- return(1);
- }
- else if (strcmp(argv[i], "-a") == 0) {
- tNoOfAttributes = atoi(argv[i+1]);
- if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR))
- return(1);
- }
- else if (strcmp(argv[i], "-c") == 0) {
- tNoOfTables = atoi(argv[i+1]);
- if ((tNoOfTables < 1) || (tNoOfTables > MAXTABLES))
- return(1);
- }
- else if (strcmp(argv[i], "-l") == 0) {
- tNoOfLoops = atoi(argv[i+1]);
- if ((tNoOfLoops < 0) || (tNoOfLoops > 100000))
- return(1);
- }
- else if (strcmp(argv[i], "-s") == 0) {
- tAttributeSize = atoi(argv[i+1]);
- if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE))
- return(1);
- }
- else if (strcmp(argv[i], "-sleep") == 0) {
- tSleepTime = atoi(argv[i+1]);
- if ((tSleepTime < 1) || (tSleepTime > 3600))
- exit(-1);
- }
- else if (strcmp(argv[i], "-simple") == 0) {
- theSimpleFlag = 1;
- argc++;
- i--;
- }
- else if (strcmp(argv[i], "-write") == 0) {
- theWriteFlag = 1;
- argc++;
- i--;
- }
- else if (strcmp(argv[i], "-dirty") == 0) {
- theDirtyFlag = 1;
- argc++;
- i--;
- }
- else if (strcmp(argv[i], "-no_table_create") == 0) {
- theTableCreateFlag = 1;
- argc++;
- i--;
- }
- else if (strcmp(argv[i], "-stdtables") == 0) {
- theStandardTableNameFlag = 1;
- argc++;
- i--;
- } // if
- else {
- return(1);
- }
-
- argc -= 2;
- i = i + 2;
- } // while
-
- ndbout << endl << "FLEXHAMMER - Starting normal mode" << endl;
- ndbout << "Hammer ndb with read, insert, update and delete transactions"<< endl << endl;
-
- ndbout << " " << tNoOfThreads << " thread(s) " << endl;
- ndbout << " " << tNoOfLoops << " iterations " << endl;
- ndbout << " " << tNoOfTables << " table(s) and " << 1 << " operation(s) per transaction " << endl;
- ndbout << " " << tNoOfRecords << " records to hammer(limit this with the -r option)" << endl;
- ndbout << " " << tNoOfAttributes << " attributes per table " << endl;
- ndbout << " " << tNoOfOperations << " transaction(s) per thread and round " << endl;
- ndbout << " " << tAttributeSize << " is the number of 32 bit words per attribute " << endl << endl;
- return 0;
-} // readArguments
-
-
-void sleepBeforeStartingTest(int seconds)
-{
- if (seconds > 0) {
- ndbout << "Sleeping(" << seconds << ")...";
- NdbSleep_SecSleep(seconds);
- ndbout << " done!" << endl;
- } // if
-} // sleepBeforeStartingTest
-
-static int
-createTables(Ndb* pMyNdb)
-{
- int i = 0;
- int j = 0;
- int check = 0;
- NdbSchemaCon *MySchemaTransaction = NULL;
- NdbSchemaOp *MySchemaOp = NULL;
-
- // Create Table and Attributes.
- if (theTableCreateFlag == 0) {
-
- for (i = 0; i < tNoOfTables; i++) {
-
- ndbout << "Creating " << tableName[i] << "...";
- // Check if table exists already
- const void * p = pMyNdb->getDictionary()->getTable(tableName[i]);
- if (p != 0) {
- ndbout << " already exists." << endl;
- // Continue with next table at once
- continue;
- } // if
- ndbout << endl;
-
- MySchemaTransaction = pMyNdb->startSchemaTransaction();
- if (MySchemaTransaction == NULL) {
- return(-1);
- } // if
-
- MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if (MySchemaOp == NULL) {
- // Clean up opened schema transaction
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- return(-1);
- } // if
-
- // Create tables, rest of parameters are default right now
-#if defined NDB_OSE || defined NDB_SOFTOSE
- check = MySchemaOp->createTable(tableName[i],
- 8, // Table Size
- TupleKey, // Key Type
- 40, // Nr of Pages
- All,
- 6,
- 78,
- 80,
- 1,
- false);
-
-#else
- check = MySchemaOp->createTable(tableName[i],
- 8, // Table Size
- TupleKey, // Key Type
- 40); // Nr of Pages
-#endif
- if (check == -1) {
- // Clean up opened schema transaction
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- return(-1);
- } // if
-
- // Primary key
- //ndbout << " pk " << (char*)&attrName[0] << "..." << endl;
- check = MySchemaOp->createAttribute( (char*)attrName[0], TupleKey, 32,
- 1, UnSigned, MMBased,
- NotNullAttribute );
- if (check == -1) {
- // Clean up opened schema transaction
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- return(-1);
- } // if
-
- // Rest of attributes
- for (j = 1; j < tNoOfAttributes ; j++) {
- //ndbout << " " << (char*)attrName[j] << "..." << endl;
- check = MySchemaOp->createAttribute( (char*)attrName[j], NoKey, 32,
- tAttributeSize, UnSigned, MMBased,
- NotNullAttribute );
- if (check == -1) {
- // Clean up opened schema transaction
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- return(-1);
- } // if
- } // for
-
- // Execute creation
- check = MySchemaTransaction->execute();
- if (check == -1) {
- // Clean up opened schema transaction
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- return(-1);
- } // if
-
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- } // for
- } // if
-
- return(0);
-
-} // createTables
-
-
-static int setAttrNames()
-{
- int i = 0;
- int retVal = 0;
-
- for (i = 0; i < MAXATTR ; i++) {
- retVal = snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
- if (retVal < 0) {
- // Error in conversion
- return(-1);
- } // if
- } // for
-
- return (0);
-} // setAttrNames
-
-static int setTableNames()
-{
- // Note! Uses only uppercase letters in table name's
- // so that we can look at the tables wits SQL
- int i = 0;
- int retVal = 0;
-
- for (i = 0; i < MAXTABLES ; i++) {
- if (theStandardTableNameFlag == 0) {
- retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
- NdbTick_CurrentMillisecond()/1000);
- } // if
- else {
- retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
- } // else
- if (retVal < 0) {
- // Error in conversion
- return(-1);
- } // if
- } // for
-
- return(0);
-} // setTableNames
-
-static int checkThreadResults(ThreadNdb *threadArrayP, char* phase)
-{
- int i = 0;
-
- for (i = 0; i < tNoOfThreads; i++) {
- if (threadArrayP[i].threadResult != 0) {
- ndbout << "Thread " << i << " reported fatal error "
- << threadArrayP[i].threadResult << " during " << phase << endl;
- return(-1);
- } // if
- } // for
-
- return(0);
-}
-
diff --git a/ndb/test/ndbapi/flexScan.cpp b/ndb/test/ndbapi/flexScan.cpp
new file mode 100644
index 00000000000..5b5b4dde730
--- /dev/null
+++ b/ndb/test/ndbapi/flexScan.cpp
@@ -0,0 +1,1667 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ***************************************************
+ FLEXSCAN
+ Perform benchmark of:
+ insert
+ read
+ scan read
+ update
+ scan update
+ read
+ scan delete
+ verify delete
+
+ Arguments:
+ -f Location of Ndb.cfg file, default Ndb.cfg
+ -t Number of threads to start, default 1
+ -o Number of operations per loop, default 500 -l Number of loops to run, default 1, 0=infinite
+ -a Number of attributes, default 25
+ -c Number of tables, default 1
+ -s Size of each attribute, default 1
+ -stdtables Use standard table names
+ -no_table_create Don't create tables in db
+ -sleep Sleep a number of seconds before running the test, this
+ can be used so that another flexBench hav etome to create tables
+ -p Parallellism to use 1-32, default:1
+ -abort <number> Test scan abort after a number of tuples
+ -h Print help text
+ -no_scan_update Don't do scan updates
+ -no_scan_delete Don't do scan deletes
+
+ Returns:
+ NDBT_OK - Test passed
+ NDBT_FAILED - Test failed
+
+ Revision history:
+ 1.12 020222 epesson: Rewritten to use NDBT. Major bugs fixed
+
+ * *************************************************** */
+
+#include "NdbApi.hpp"
+
+#include <NdbThread.h>
+#include <NdbSleep.h>
+#include <NdbTick.h>
+#include <NdbOut.hpp>
+#include <NdbTimer.hpp>
+#include <NdbMain.h>
+#include <NdbTest.hpp>
+#include <NDBT_Error.hpp>
+#include <NdbSchemaCon.hpp>
+
+#define PKSIZE 1
+#define FOREVER 1
+#define MAXSTRLEN 16
+#define MAXATTR 64
+#define MAXTABLES 64
+#define MAXTHREADS 256
+#define MAXATTRSIZE 64
+
+enum StartType {
+ stIdle,
+ stInsert,
+ stRead,
+ stScanRead,
+ stUpdate,
+ stScanUpdate,
+ stDelete,
+ stVerifyDelete,
+ stScanDelete,
+ stStop,
+ stLast} ;
+
+
+struct ThreadNdb
+{
+ int ThreadNo;
+ NdbThread* threadLife;
+ StartType threadStart;
+ int threadResult;
+ int threadReady;
+};
+
+extern "C" void* flexScanThread(void*);
+static int setAttrNames(void);
+static int setTableNames(void);
+static int createTables(Ndb* pMyNdb);
+static void sleepBeforeStartingTest(int seconds);
+static int readArguments(int argc, const char** argv);
+static void setAttrValues(int* attrValue,
+ int* readValue,
+ int Offset);
+static int insertRows(Ndb* pNdb, int* pkValue, int* attrValue, StartType tType);
+static int readRows(Ndb* pNdb, int* pkValue, int* readValue);
+static int deleteRows(Ndb* pNdb, int* pkValue);
+static int scanReadRows(Ndb* pNdb, int* readValue);
+static int scanUpdateRows(Ndb* pNdb, int* readValue, int* attrValue);
+static int scanDeleteRows(Ndb* pNdb, int* readValue);
+static int verifyDeleteRows(Ndb* pNdb, int* pkValue, int* readValue);
+static void Compare(int* attrValue, int* readValue);
+static void UpdateArray(int *attrValue);
+
+static int tNoOfThreads = 1;
+static int tNoOfAttributes = 25;
+static int tNoOfTables = 1;
+static int tAttributeSize = 1;
+static int tNodeId = 0;
+static int tNoOfOperations = 500;
+static int tNoOfLoops = 1;
+static int tAbortAfter = 0;
+static int tParallellism = 1;
+
+static char tableName[MAXTABLES][MAXSTRLEN];
+static char attrName[MAXATTR][MAXSTRLEN];
+
+static unsigned int tSleepTime = 0;
+
+static int theStdTableNameFlag = 0;
+static int theTableCreateFlag = 0;
+static int theScanAbortTestFlag = 0;
+static int theNoScanUpdateFlag = 0;
+static int theNoScanDeleteFlag = 0;
+
+//flexScanErrorData = new ErrorData;
+ErrorData * flexScanErrorData;
+NdbError * anerror;
+
+//static errorData theErrorData;
+//static unsigned int tErrorCounter[6000];
+
+#define START_TIMER { NdbTimer timer; timer.doStart();
+#define STOP_TIMER timer.doStop();
+#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
+
+static void UpdateArray(int *attrValue)
+{
+ int tableCount = 0;
+ int attrCount = 0;
+ int opCount = 0;
+ int sizeCount = 0;
+ int* pValue = attrValue;
+
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+ for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
+ for (opCount = 0; opCount < tNoOfOperations; opCount++) {
+ for (sizeCount = 0; sizeCount < tAttributeSize; sizeCount++) {
+ // Update value in array
+ (*pValue)++;
+ //ndbout << "attrValue[" << tableCount*tNoOfAttributes*tNoOfOperations*tAttributeSize +
+ //attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize + sizeCount <<
+ //"] = " << attrValue[tableCount*tNoOfAttributes*tNoOfOperations*tAttributeSize +
+ //attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize + sizeCount] << endl;
+ // Increment pointer
+ pValue++;
+ } // sizeCount
+ } // for opCount
+ } // for attrCount
+ } // for tableCount
+
+} // Update
+
+static void Compare(int* attrValue, int* readValue)
+{
+ int tableCount = 0;
+ int attrCount = 0;
+ int OpCount = 0;
+ int first = 0;
+
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+ for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
+ for (OpCount = 0; OpCount < tNoOfOperations; OpCount++) {
+ if (memcmp(&(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
+ attrCount*tNoOfOperations + OpCount]),
+ &(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
+ attrCount*tNoOfOperations + OpCount]),
+ tAttributeSize) != 0) {
+ // Values mismatch
+ if (first == 0) {
+ //ndbout << "Read and set values differ for:" << endl;
+ first = 1;
+ ndbout << "Mismatch found.";
+ } // if
+ // Comparision of values after scan update is meaningless right now
+ //ndbout << " table " << tableName[tableCount] <<
+ //" - attr " << attrName[attrCount+1];
+ //for (sizeCount = 0; sizeCount < tAttributeSize; sizeCount++) {
+ //ndbout << ": set " <<
+ //attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
+ //attrCount*tNoOfOperations*tAttributeSize +
+ //tNoOfOperations*tAttributeSize + sizeCount] << " read " <<
+ //readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
+ //attrCount*tNoOfOperations*tAttributeSize +
+ //tNoOfOperations*tAttributeSize + sizeCount] << endl;
+ //} // for
+ } // if
+ } // for OpCount
+ } // for attrCount
+ } // for tableCount
+
+ // A final pretty-print
+ if (first == 1) {
+ ndbout << endl;
+ } // if
+} // Compare
+
+static void printInfo()
+{
+ ndbout << endl << "FLEXSCAN - Starting normal mode" << endl;
+ ndbout << "Perform benchmark of insert, update and delete transactions"<< endl;
+ ndbout << " NdbAPI node with id = " << tNodeId << endl;
+ ndbout << " " << tNoOfThreads << " thread(s) " << endl;
+ ndbout << " " << tNoOfLoops << " iterations " << endl;
+ ndbout << " " << tNoOfTables << " table(s) and " << 1 << " operation(s) per transaction "
+ << endl;
+ ndbout << " " << tNoOfAttributes << " attributes per table incl. pk" << endl;
+ ndbout << " " << tNoOfOperations << " transaction(s) per thread and round " << endl;
+ if (theScanAbortTestFlag == 1) {
+ ndbout << " Scan abort test after " << tAbortAfter << " tuples" << endl;
+ } // if
+ ndbout << " " << tParallellism << " parallellism in scans" << endl;
+ ndbout << " " << tAttributeSize << " is the number of 32 bit words per attribute " <<
+ endl << endl;
+
+} // printInfo
+
+static void tellThreads(ThreadNdb *threadArrayP, StartType what)
+{
+ int i = 0;
+
+ for (i = 0; i < tNoOfThreads ; i++)
+ threadArrayP[i].threadStart = what;
+} // tellThreads
+
+static void waitForThreads(ThreadNdb *threadArrayP)
+{
+ int i = 0;
+ int cont = 1;
+
+ while (cont == 1){
+
+ NdbSleep_MilliSleep(10);
+ cont = 0;
+
+ for (i = 0; i < tNoOfThreads ; i++) {
+ if (threadArrayP[i].threadReady == 0) {
+// ndbout << "Main is reporting thread " << i << " not ready" << endl;
+ cont = 1;
+ } // if
+ } // for
+ } // while
+} // waitForThreads
+
+
+static void resetThreads(ThreadNdb *threadArrayP)
+{
+ int i = 0;
+
+ for (i = 0; i < tNoOfThreads ; i++) {
+ threadArrayP[i].threadReady = 0;
+ threadArrayP[i].threadResult = 0;
+ threadArrayP[i].threadStart = stIdle;
+ //ndbout << "threadStart[" << i << "]=" <<
+ //threadArrayP[i].threadStart << endl;
+ } // for
+} // resetThreads
+
+static int checkThreadResults(ThreadNdb *threadArrayP, char *action)
+{
+ int i = 0;
+ int retValue = 0;
+
+ for (i = 0; i < tNoOfThreads; i++) {
+ if (threadArrayP[i].threadResult != 0) {
+ ndbout << "Thread " << i << " reported fatal error "
+ << threadArrayP[i].threadResult << " during " << action << endl;
+ retValue = -1;
+ break;
+ } // if
+ } // for
+
+ return(retValue);
+} // checkThreadResults
+
+NDB_COMMAND(flexScan, "flexScan", "flexScan", "flexScan", 65535)
+{
+ ThreadNdb* pThreads = NULL;
+ Ndb* pMyNdb = NULL;
+ int tLoops = 0;
+ int check = 0;
+ int returnValue = NDBT_OK;
+ int every2ndScanDelete = 0; // Switch between scan delete and normal delete
+
+ flexScanErrorData = new ErrorData;
+
+ flexScanErrorData->resetErrorCounters();
+
+ if (readArguments(argc, argv) != 0) {
+ ndbout << "Wrong arguments to flexScan" << endl;
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ } // if
+
+ /* print Setting */
+ flexScanErrorData->printSettings(ndbout);
+
+ check = setAttrNames();
+ if (check != 0) {
+ ndbout << "Couldn't set attribute names" << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ } // if
+ check = setTableNames();
+ if (check != 0) {
+ ndbout << "Couldn't set table names" << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ } // if
+
+ pMyNdb = new Ndb ("TEST_DB");
+ pMyNdb->init();
+ tNodeId = pMyNdb->getNodeId();
+
+ printInfo();
+
+ NdbThread_SetConcurrencyLevel(tNoOfThreads + 2);
+ //NdbThread_SetConcurrencyLevel(tNoOfThreads + 8);
+
+ pThreads = new ThreadNdb[tNoOfThreads];
+
+ if (pMyNdb->waitUntilReady(10000) != 0) {
+ ndbout << "NDB is not ready" << endl << "Benchmark failed" << endl;
+ returnValue = NDBT_FAILED;
+ } // if
+
+ else {
+
+ if (createTables(pMyNdb) != 0) {
+ ndbout << "Could not create tables" << endl;
+ returnValue = NDBT_FAILED;
+ } // if
+ else {
+ sleepBeforeStartingTest(tSleepTime);
+
+ resetThreads(pThreads);
+ // Create threads
+ for (int i = 0; i < tNoOfThreads ; i++){
+ pThreads[i].ThreadNo = i;
+ // Ignore the case that thread creation may fail
+ pThreads[i].threadLife = NdbThread_Create(flexScanThread,
+ (void**)&pThreads[i],
+ 327680,
+ "flexScanThread", NDB_THREAD_PRIO_LOW);
+ if (pThreads[i].threadLife == NULL) {
+ ndbout << "Could not create thread " << i << endl;
+ returnValue = NDBT_FAILED;
+ // Use the number of threads that were actually created
+ tNoOfThreads = i;
+ break; // break for loop
+ } // if
+ } // for
+
+ waitForThreads(pThreads);
+ if (checkThreadResults(pThreads, "init") != 0) {
+ returnValue = NDBT_FAILED;
+ } // if
+
+ if (returnValue == NDBT_OK) {
+ ndbout << "All threads started" << endl;
+
+ while (FOREVER) {
+
+ resetThreads(pThreads);
+
+ if ((tNoOfLoops != 0) && (tNoOfLoops <= tLoops)) {
+ break;
+ } // if
+
+ // Insert
+ START_TIMER;
+
+ tellThreads(pThreads, stInsert);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "insert") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("insert", tNoOfOperations*tNoOfThreads, tNoOfTables);
+
+ resetThreads(pThreads);
+
+ // Read
+ START_TIMER;
+
+ tellThreads(pThreads, stRead);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "read") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
+
+ resetThreads(pThreads);
+
+ // Update
+ START_TIMER;
+
+ tellThreads(pThreads, stUpdate);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "update") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables);
+
+ resetThreads(pThreads);
+
+ // Scan read
+ START_TIMER;
+
+ tellThreads(pThreads, stScanRead);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "scanread") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("scanread", tNoOfTables*tNoOfThreads, 1);
+
+ resetThreads(pThreads);
+
+ // Update
+ START_TIMER;
+
+ tellThreads(pThreads, stUpdate);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "update") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables);
+
+ resetThreads(pThreads);
+
+ // Read
+ START_TIMER;
+
+ tellThreads(pThreads, stRead);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "read") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
+
+ resetThreads(pThreads);
+
+ // Only do scan update if told to do so
+ if (theNoScanUpdateFlag == 0) {
+ // Scan update
+ START_TIMER;
+
+ tellThreads(pThreads, stScanUpdate);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "scanupdate") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("scanupdate", tNoOfTables*tNoOfThreads, 1);
+
+ resetThreads(pThreads);
+
+ // Read
+ START_TIMER;
+
+ tellThreads(pThreads, stRead);
+ // tellThreads(pThreads, stScanRead);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "read") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
+
+ resetThreads(pThreads);
+ } // if theNoScanUpdateFlag
+
+ // Shift between delete and scan delete
+ if ((every2ndScanDelete % 2 == 0) || (theNoScanDeleteFlag == 1)){
+ // Delete
+ START_TIMER;
+ tellThreads(pThreads, stDelete);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "delete") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("delete", tNoOfOperations*tNoOfThreads, tNoOfTables);
+ resetThreads(pThreads);
+ } // if
+ else {
+ resetThreads(pThreads); // Scan delete
+ START_TIMER;
+ tellThreads(pThreads, stScanDelete);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "scandelete") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("scandelete", tNoOfTables*tNoOfThreads, 1);
+
+ resetThreads(pThreads);
+ } // else
+ every2ndScanDelete++;
+
+ resetThreads(pThreads); // Verify delete
+ START_TIMER;
+ tellThreads(pThreads, stVerifyDelete);
+ waitForThreads(pThreads);
+
+ STOP_TIMER;
+ if (checkThreadResults(pThreads, "verifydelete") != 0) {
+ returnValue = NDBT_FAILED;
+ break;
+ } // if
+ PRINT_TIMER("verifydelete", tNoOfOperations*tNoOfThreads*tNoOfTables, 1);
+
+ resetThreads(pThreads);
+
+ ndbout << "--------------------------------------------------" << endl;
+ tLoops++;
+
+ } // while
+ } // if
+ } // else
+ } // else
+
+ // Stop threads in a nice way
+ tellThreads(pThreads, stStop);
+ waitForThreads(pThreads);
+
+ // Clean up
+ delete [] pThreads;
+ delete pMyNdb;
+
+ flexScanErrorData->printErrorCounters(ndbout);
+
+ if (returnValue == NDBT_OK) {
+ ndbout << endl << "Benchmark completed successfully" << endl;
+ } // if
+ else {
+ ndbout << endl << "Benchmark failed" << endl;
+ } // else
+
+ // Exit via NDBT
+ return NDBT_ProgramExit(returnValue);;
+} // main
+
+void*
+flexScanThread(void* ThreadData)
+{
+ ThreadNdb* pThreadData = (ThreadNdb*)ThreadData;
+ unsigned int thread_no = pThreadData->ThreadNo;
+ unsigned int thread_base = (thread_no * 2000000) + (tNodeId * 26000);
+ int tThreadResult = 0;
+ Ndb* MyNdb = NULL;
+ int check = 0;
+ StartType tType = stLast;
+ int* pkValue = NULL;
+ int* attrValue = NULL;
+ int* readValue = NULL;
+ int AllocSize = 0;
+
+ AllocSize = tNoOfTables * (tNoOfAttributes-1) * tNoOfOperations *
+ tAttributeSize * sizeof(int);
+ attrValue = (int*)malloc(AllocSize);
+ readValue = (int*)malloc(AllocSize);
+ pkValue = (int*)malloc(tNoOfOperations * sizeof(int));
+ if ((attrValue == NULL) || (readValue == NULL) || (pkValue == NULL)) {
+ tThreadResult = 98;
+ pThreadData->threadStart = stIdle;
+ } // if
+
+ setAttrValues(attrValue, readValue, thread_base);
+
+ MyNdb = new Ndb( "TEST_DB" );
+ MyNdb->init();
+ if (MyNdb->waitUntilReady(10000) != 0) {
+ tThreadResult = 99;
+ pThreadData->threadStart = stIdle;
+ } // if
+
+ // Set primary key value, same for all tables
+ for (int c = 0; c < tNoOfOperations; c++) {
+ pkValue[c] = (int)(c + thread_base);
+ } // for
+
+ while (FOREVER) {
+ pThreadData->threadResult = tThreadResult;
+ pThreadData->threadReady = 1;
+
+ while (pThreadData->threadStart == stIdle) {
+ NdbSleep_MilliSleep(10);
+ } // while
+
+ // Check if signal to exit is received
+ if (pThreadData->threadStart >= stStop){
+ pThreadData->threadReady = 1;
+ break;
+ } // if
+ tType = pThreadData->threadStart;
+ pThreadData->threadStart = stIdle;
+
+ switch (tType) {
+ case stInsert:
+ check = insertRows(MyNdb, pkValue, attrValue, tType);
+ break;
+ case stRead:
+ check = readRows(MyNdb, pkValue, readValue);
+ Compare(attrValue, readValue);
+ break;
+ case stUpdate:
+ UpdateArray(attrValue);
+ check = insertRows(MyNdb, pkValue, attrValue, tType);
+ break;
+ case stScanRead:
+ //check = readRows(MyNdb, pkValue, readValue);
+ check = scanReadRows(MyNdb, readValue);
+ Compare(attrValue, readValue);
+ break;
+ case stScanUpdate:
+ UpdateArray(attrValue);
+ //tType = stUpdate;
+ //check = insertRows(MyNdb, pkValue, attrValue, tType);
+ check = scanUpdateRows(MyNdb, readValue, attrValue);
+ break;
+ case stDelete:
+ check = deleteRows(MyNdb, pkValue);
+ break;
+ case stScanDelete:
+ check = scanDeleteRows(MyNdb, readValue);
+ break;
+ case stVerifyDelete:
+ check = verifyDeleteRows(MyNdb, pkValue, readValue);
+ break;
+ default:
+ ndbout << "tType is " << tType << endl;
+ assert(false);
+ break;
+ } // switch
+
+ tThreadResult = check;
+
+ if (tThreadResult != 0) {
+ // Check if error is fatak or not
+ } // if
+ else {
+ continue;
+ } // else
+ } // while
+
+ // Clean up
+ delete MyNdb;
+ if (attrValue != NULL) {
+ free(attrValue);
+ } //if
+ if (readValue != NULL) {
+ free(readValue);
+ } // if
+ if (pkValue != NULL) {
+ free(pkValue);
+ } // if
+
+ NdbThread_Exit(0);
+ return NULL;
+
+} // flexScanThread
+
+
+static int setAttrNames()
+{
+ int i = 0;
+ int retVal = 0;
+
+ for (i = 0; i < MAXATTR ; i++) {
+ retVal = snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ if (retVal < 0) {
+ return(-1);
+ } // if
+ } // for
+
+ return(0);
+} // setAttrNames
+
+
+static int setTableNames()
+{
+ // Note! Uses only uppercase letters in table name's
+ // so that we can look at the tables with SQL
+ int i = 0;
+ int retVal = 0;
+
+ for (i = 0; i < MAXTABLES ; i++) {
+
+ if (theStdTableNameFlag == 0) {
+ retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
+ (int)(NdbTick_CurrentMillisecond() / 1000));
+ } // if
+ else {
+ retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
+ } // if else
+
+ if (retVal < 0) {
+ return(-1);
+ } // if
+ } // for
+
+ return(0);
+} // setTableNames
+
+
+// Create Table and Attributes.
+static int createTables(Ndb* pMyNdb)
+{
+
+ NdbSchemaCon *MySchemaTransaction = NULL;
+ NdbSchemaOp *MySchemaOp = NULL;
+ int i = 0;
+ int j = 0;
+ int check = 0;
+
+ if (theTableCreateFlag == 0) {
+
+ i = 0;
+ do {
+ i++;
+ ndbout << endl << "Creating " << tableName[i - 1] << "..." << endl;
+
+ MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pMyNdb);
+ if( MySchemaTransaction == NULL ) {
+ return (-1);
+ } // if
+
+ MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( MySchemaOp == NULL ) {
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return (-1);
+ } // if
+
+#if defined NDB_OSE || defined NDB_SOFTOSE
+ check = MySchemaOp->createTable(tableName[i - 1],
+ 8, // Table Size
+ TupleKey, // Key Type
+ 40, // Nr of Pages
+ All,
+ 6,
+ 78,
+ 80,
+ 1,
+ false);
+#else
+ check = MySchemaOp->createTable(tableName[i - 1]
+ ,8 // Table Size
+ ,TupleKey // Key Type
+ ,40); // Nr of Pages
+#endif
+ if (check == -1) {
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return -1;
+ } // if
+
+ check = MySchemaOp->createAttribute( (char*)attrName[0], TupleKey, 32, PKSIZE,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) {
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return -1;
+ } // if
+
+ for (j = 1; j < tNoOfAttributes ; j++) {
+ check = MySchemaOp->createAttribute( (char*)attrName[j], NoKey, 32, tAttributeSize,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) {
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return -1;
+ } // if
+ } // for
+
+ if (MySchemaTransaction->execute() == -1) {
+ ndbout << MySchemaTransaction->getNdbError().message << endl;
+ ndbout << "Probably, " << tableName[i - 1] << " already exist" << endl;
+ } // if
+
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ } while (tNoOfTables > i);
+ }
+
+ return 0;
+} // createTables
+
+static void printUsage()
+{
+ ndbout << "Usage of flexScan:" << endl;
+ ndbout << "-f <path> Location of Ndb.cfg file, default: Ndb.cfg" << endl;
+ ndbout << "-t <int> Number of threads to start, default 1" << endl;
+ ndbout << "-o <int> Number of operations per loop, default 500" << endl;
+ ndbout << "-l <int> Number of loops to run, default 1, 0=infinite" << endl;
+ ndbout << "-a <int> Number of attributes, default 25" << endl;
+ ndbout << "-c <int> Number of tables, default 1" << endl;
+ ndbout << "-s <int> Size of each attribute, default 1" << endl;
+ ndbout << "-stdtables Use standard table names" << endl;
+ ndbout << "-no_table_create Don't create tables in db" << endl;
+ ndbout << "-sleep <int> Sleep a number of seconds before running the test" << endl;
+ ndbout << "-p <int> Parallellism to use 1-32, default:1" << endl;
+ ndbout << "-abort <int> Test scan abort after a number of tuples" << endl;
+ ndbout << "-no_scan_update Don't do scan updates" << endl;
+ ndbout << "-no_scan_delete Don't do scan deletes" << endl;
+ ndbout << "-h Print this text" << endl;
+ // inputErrorArg();
+ flexScanErrorData->printCmdLineArgs(ndbout);
+}
+
+static int readArguments(int argc, const char** argv)
+{
+ int i = 1;
+ int retValue = 0;
+ int printFlag = 0;
+
+ tNoOfThreads = 1; // Set default Value
+ tNoOfTables = 1; // Default Value
+
+ while (argc > 1) {
+ if (strcmp(argv[i], "-t") == 0) {
+ if (argv[i + 1] != NULL) {
+ tNoOfThreads = atoi(argv[i + 1]);
+ if ((tNoOfThreads < 1) || (tNoOfThreads > MAXTHREADS)) {
+ retValue = -1;
+ } // if
+ } // if
+ else {
+ retValue = -1;
+ } // else
+ } // if
+ else if (strcmp(argv[i], "-o") == 0) {
+ if (argv[i + 1] != NULL) {
+ tNoOfOperations = atoi(argv[i + 1]);
+ if (tNoOfOperations < 1) {
+ retValue = -1;
+ } // if
+ } // if
+ else {
+ retValue = -1;
+ } // else
+ } // else if
+ else if (strcmp(argv[i], "-a") == 0) {
+ if (argv[i + 1] != NULL) {
+ tNoOfAttributes = atoi(argv[i + 1]);
+ if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR)) {
+ retValue = -1;
+ } // if
+ } // if
+ else {
+ retValue = -1;
+ } // else
+ } // else if
+ else if (strcmp(argv[i], "-c") == 0) {
+ if (argv[i + 1] != NULL) {
+ tNoOfTables = atoi(argv[i+1]);
+ if ((tNoOfTables < 1) || (tNoOfTables > MAXTABLES)) {
+ retValue = -1;
+ } // if
+ } // if
+ else {
+ retValue = -1;
+ } // else
+ } // else if
+ else if (strcmp(argv[i], "-l") == 0) {
+ if (argv[i + 1] != NULL) {
+ tNoOfLoops = atoi(argv[i+1]);
+ if ((tNoOfLoops < 0) || (tNoOfLoops > 100000)) {
+ retValue = -1;
+ } // if
+ } // if
+ else {
+ retValue = -1;
+ } // else
+ } // else if
+ else if (strcmp(argv[i], "-s") == 0) {
+ if (argv[i + 1] != NULL) {
+ tAttributeSize = atoi(argv[i+1]);
+ if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE)) {
+ retValue = -1;
+ } // if
+ } // if
+ else {
+ retValue = -1;
+ } // else
+ } // else if
+ else if (strcmp(argv[i], "-no_table_create") == 0) {
+ theTableCreateFlag = 1;
+ argc++;
+ i--;
+ } // else if
+ else if (strcmp(argv[i], "-stdtables") == 0) {
+ theStdTableNameFlag = 1;
+ argc++;
+ i--;
+ } // else if
+ else if (strcmp(argv[i], "-sleep") == 0) {
+ if (argv[i + 1] != NULL) {
+ tSleepTime = atoi(argv[i+1]);
+ if ((tSleepTime < 1) || (tSleepTime > 3600)) {
+ retValue = -1;
+ } // if
+ } // if
+ else {
+ retValue = -1;
+ } // else
+ } // else if
+ else if (strcmp(argv[i], "-abort") == 0) {
+ // Test scan abort after a number of tuples
+ theScanAbortTestFlag = 1;
+ if (argv[i + 1] != NULL) {
+ tAbortAfter = atoi(argv[i + 1]);
+ } // if
+ else {
+ retValue = -1;
+ } // else
+ } // else if
+ else if (strcmp(argv[i], "-p") == 0) {
+ if (argv[i + 1] != NULL) {
+ tParallellism = atoi(argv[i + 1]);
+ if ((tParallellism < 1) || (tParallellism > 32)) {
+ retValue = -1;
+ } // if
+ } // if
+ else {
+ retValue = -1;
+ } // else
+ } // else if
+ else if (strcmp(argv[i], "-h") == 0) {
+ printFlag = 1;
+ argc++;
+ i--;
+ } // else if
+ else if (strcmp(argv[i], "-no_scan_update") == 0) {
+ theNoScanUpdateFlag = 1;
+ argc++;
+ i--;
+ } // else if
+ else if (strcmp(argv[i], "-no_scan_delete") == 0) {
+ theNoScanDeleteFlag = 1;
+ argc++;
+ i--;
+ } // else if
+ else {
+ retValue = -1;
+ } // else
+
+ argc -= 2;
+ i = i + 2;
+ }
+
+ if ((retValue != 0) || (printFlag == 1)) {
+ printUsage();
+ } // if
+
+ return(retValue);
+
+} // readArguments
+
+static void sleepBeforeStartingTest(int seconds)
+{
+ if (seconds > 0) {
+ ndbout << "Sleeping(" <<seconds << ")...";
+ NdbSleep_SecSleep(seconds);
+ ndbout << " done!" << endl;
+ } // if
+} // sleepBeforeStartingTest
+
+static void setAttrValues(int* attrValue,
+ int* readValue,
+ int Offset)
+{
+ int tableCount = 0;
+ int attrCount = 0;
+ int OpCount = 0;
+ int attrSize = 0;
+ int* pAttr = NULL;
+ int* pRead = NULL;
+
+ // Set attribute values in memory array
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+ for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
+ for (OpCount = 0; OpCount < tNoOfOperations; OpCount++) {
+ pAttr = &(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
+ attrCount*tNoOfOperations + OpCount]);
+ pRead = &(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
+ attrCount*tNoOfOperations + OpCount]);
+ for (attrSize = 0; attrSize < tAttributeSize; attrSize++){
+ *pAttr = (int)(Offset + tableCount + attrCount + OpCount + attrSize);
+ //ndbout << "attrValue[" << tableCount*(tNoOfAttributes-1)*tNoOfOperations +
+ //attrCount*tNoOfOperations + OpCount + attrSize << "] = " <<
+ //attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
+ //attrCount*tNoOfOperations + OpCount + attrSize] << endl;
+ *pRead = 0;
+ pAttr++;
+ pRead++;
+ } // for attrSize
+ } // for OpCount
+ } // for attrCount
+ } // for tableCount
+
+} // setAttrValues
+
+static int insertRows(Ndb* pNdb, // NDB object
+ int* pkValue, // Primary key values
+ int* attrValue, // Attribute values
+ StartType tType)
+{
+ int tResult = 0;
+ int check = 0;
+ int tableCount = 0;
+ int attrCount = 0;
+ NdbConnection* MyTransaction = NULL;
+ NdbOperation* MyOperations[MAXTABLES] = {NULL};
+ int opCount = 0;
+
+ for (opCount = 0; opCount < tNoOfOperations; opCount++) {
+ MyTransaction = pNdb->startTransaction();
+ if (MyTransaction == NULL) {
+ tResult = 1;
+ } // if
+ else {
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+
+ MyOperations[tableCount] =
+ MyTransaction->getNdbOperation(tableName[tableCount]);
+ if (MyOperations[tableCount] == NULL) {
+ tResult = 2;
+ // Break for tableCount loop
+ break;
+ } // if
+
+ if (tType == stUpdate) {
+ check = MyOperations[tableCount]->updateTuple();
+ } // if
+ else if (tType == stInsert) {
+ check = MyOperations[tableCount]->insertTuple();
+ } // else if
+ else {
+ assert(false);
+ } // else
+
+ if (check == -1) {
+ tResult = 3;
+ break;
+ } // if
+ check = MyOperations[tableCount]->equal((char*)attrName[0],
+ (char*)&(pkValue[opCount]));
+ if (check == -1) {
+ tResult = 7;
+ break;
+ } // if
+
+ for (attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) {
+ int Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize +
+ attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize;
+ check = MyOperations[tableCount]->
+ setValue((char*)attrName[attrCount + 1],
+ (char*)&(attrValue[Index]));
+ if (check == -1) {
+ tResult = 8;
+ break; // break attrCount loop
+ } // if
+ } // for
+ } // for tableCount
+
+ // Execute transaction with insert one tuple in every table
+ check = MyTransaction->execute(Commit);
+ if (check == -1) {
+ ndbout << MyTransaction->getNdbError().message << endl;
+
+ // Add complete error handling here
+
+ int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError());
+ if (retCode == 1) {
+ if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){
+ ndbout_c("execute: %d, %d, %s", opCount, tType, MyTransaction->getNdbError().message);
+ ndbout_c("Error code = %d", MyTransaction->getNdbError().code);}
+ tResult = 20;
+ } else if (retCode == 2) {
+ ndbout << "4115 should not happen in flexBench" << endl;
+ tResult = 20;
+ } else if (retCode == 3) {
+// --------------------------------------------------------------------
+// We are not certain if the transaction was successful or not.
+// We must reexecute but might very well find that the transaction
+// actually was updated. Updates and Reads are no problem here. Inserts
+// will not cause a problem if error code 630 arrives. Deletes will
+// not cause a problem if 626 arrives.
+// --------------------------------------------------------------------
+ /* What can we do here? */
+ ndbout_c("execute: %s", MyTransaction->getNdbError().message);
+ }//if(retCode == 3)
+
+ } // if(check == -1)
+
+ pNdb->closeTransaction(MyTransaction);
+ } // else
+ } // for opCount
+
+ return(tResult);
+} // insertRows
+
+static int readRows(Ndb* pNdb,
+ int* pkValue,
+ int* readValue)
+{
+ int tResult = 0;
+ int tableCount = 0;
+ int attrCount = 0;
+ int check = 0;
+ NdbConnection* MyTransaction = NULL;
+ NdbOperation* MyOperations[MAXTABLES] = {NULL};
+ NdbRecAttr* tmp = NULL;
+ int Value = 0;
+ int Index = 0;
+ int opCount = 0;
+
+ for (opCount = 0; opCount < tNoOfOperations; opCount++) {
+ MyTransaction = pNdb->startTransaction();
+ if (MyTransaction == NULL) {
+ tResult = 1;
+ } // if
+ else {
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+
+ MyOperations[tableCount] =
+ MyTransaction->getNdbOperation(tableName[tableCount]);
+ if (MyOperations[tableCount] == NULL) {
+ tResult = 2;
+ // Break for tableCount loop
+ break;
+ } // if
+
+ check = MyOperations[tableCount]->readTuple();
+ if (check == -1) {
+ tResult = 3;
+ break;
+ } // if
+
+ check = MyOperations[tableCount]->
+ equal((char*)attrName[0], (char*)&(pkValue[opCount]));
+ if (check == -1) {
+ tResult = 7;
+ break;
+ } // if
+
+ for (int attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) {
+ Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize +
+ attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize;
+ tmp = MyOperations[tableCount]->
+ getValue((char*)attrName[attrCount + 1], (char*)&(readValue[Index]));
+
+ if (tmp == NULL) {
+ tResult = 9;
+ break;
+ } // if
+ } // for attrCount
+ } // for tableCount
+ // Execute transaction reading one tuple in every table
+ check = MyTransaction->execute(Commit);
+ if (check == -1) {
+ ndbout << MyTransaction->getNdbError().message << endl;
+
+ // Add complete error handling here
+
+ int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError());
+ if (retCode == 1) {
+ if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){
+ ndbout_c("execute: %d, %s", opCount, MyTransaction ->getNdbError().message );
+ ndbout_c("Error code = %d", MyTransaction->getNdbError().code );}
+ tResult = 20;
+ } else if (retCode == 2) {
+ ndbout << "4115 should not happen in flexBench" << endl;
+ tResult = 20;
+ } else if (retCode == 3) {
+// --------------------------------------------------------------------
+// We are not certain if the transaction was successful or not.
+// We must reexecute but might very well find that the transaction
+// actually was updated. Updates and Reads are no problem here. Inserts
+// will not cause a problem if error code 630 arrives. Deletes will
+// not cause a problem if 626 arrives.
+// --------------------------------------------------------------------
+ /* What can we do here? */
+ ndbout_c("execute: %s", MyTransaction ->getNdbError().message );
+ }//if(retCode == 3)
+
+ } // if
+
+ pNdb->closeTransaction(MyTransaction);
+ } // else
+ } // for opCount
+
+ return(tResult);
+} // readRows
+
+static int scanReadRows(Ndb* pNdb, int* readValue)
+{
+ int tResult = 0;
+ int tableCount = 0;
+ int attrCount = 0;
+ int check = 0;
+ int countAbort = 0; // Counts loops until scan abort if requested
+ NdbConnection* MyTransaction = NULL;
+ NdbOperation* MyOperation = NULL;
+ NdbRecAttr* tmp = NULL;
+
+
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+ MyTransaction = pNdb->startTransaction();
+ if (MyTransaction == NULL) {
+ tResult = 1;
+ break;
+ } // if
+ MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]);
+ if (MyOperation == NULL) {
+ tResult = 2;
+ break;
+ } // if
+
+ check = MyOperation->openScanRead(tParallellism);
+ if (check == -1) {
+ tResult = 10;
+ break;
+ } // if
+
+ for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
+ // Get all attributes
+ tmp = MyOperation->
+ getValue((char*)attrName[attrCount+1],
+ (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
+ attrCount*tNoOfOperations*tAttributeSize]));
+ if (tmp == NULL) {
+ tResult = 9;
+ break;
+ } // if
+ } // for attrCount
+
+ check = MyTransaction->executeScan();
+ if (check == -1) {
+ tResult = 12;
+ break;
+ } // if
+
+ check = MyTransaction->nextScanResult();
+ while (check == 0) {
+ // Check if scan abort is requested
+ if (theScanAbortTestFlag == 1) {
+ if (countAbort == tAbortAfter) {
+ MyTransaction->stopScan();
+ ndbout << "scanread aborted on request after " << countAbort*tParallellism <<
+ " tuples" << endl;
+ break; // break while loop
+ } // if
+ countAbort++;
+ } // if
+ check = MyTransaction->nextScanResult();
+ } // while
+
+ pNdb->closeTransaction(MyTransaction);
+ } // for tableCount
+
+ return(tResult);
+} // scanReadRows
+
+static int scanUpdateRows(Ndb* pNdb,
+ int* readValue,
+ int* attrValue)
+{
+ int tResult = 0;
+ int tableCount = 0;
+ int attrCount = 0;
+ int check = 0;
+ int opCount = 0;
+ NdbConnection* MyTransaction = NULL;
+ NdbOperation* MyOperation = NULL;
+ NdbConnection* MyTakeOverTrans = NULL;
+ NdbOperation* MyTakeOverOp = NULL;
+ NdbRecAttr* tTmp = NULL;
+
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+ MyTransaction = pNdb->startTransaction();
+ if (MyTransaction == NULL) {
+ tResult = 1;
+ break; // break tableCount for loop
+ } // if
+ MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]);
+ if (MyOperation == NULL) {
+ tResult = 2;
+ break;
+ } // if
+
+ check = MyOperation->openScanExclusive(tParallellism);
+ if (check == -1) {
+ tResult = 11;
+ break;
+ } // if
+
+ MyOperation->interpret_exit_ok();
+ // Fetch all attributes
+ for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
+ tTmp = MyOperation->
+ getValue((char*)attrName[attrCount+1],
+ (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
+ attrCount*tNoOfOperations*tAttributeSize]));
+ if (tTmp == NULL) {
+ tResult = 9;
+ break; // break for loop
+ } // if
+ } // for
+ if (tResult != 0) {
+ break; // break while loop also
+ } // if
+
+ check = MyTransaction->executeScan();
+ if (check == -1) {
+ tResult = 12;
+ break;
+ } // if
+ check = MyTransaction->nextScanResult();
+ opCount = 0;
+ while (check == 0) {
+ MyTakeOverTrans = pNdb->startTransaction();
+ MyTakeOverOp = MyOperation->takeOverForUpdate(MyTakeOverTrans);
+ for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
+ check = MyTakeOverOp->setValue((char*)attrName[attrCount+1],
+ (char*)&(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
+ attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize]));
+ } // for
+
+ check = MyTakeOverTrans->execute(Commit);
+ if (check == 0) {
+ check = MyTransaction->nextScanResult();
+ opCount++;
+ } // if
+ else {
+ tResult = 95;
+
+ /* MyTransaction, MyTakeOverTrans, Which one? */
+
+ // Any further error handling?
+ int retCode = flexScanErrorData->handleErrorCommon(MyTakeOverTrans->getNdbError());
+ if (retCode == 1) {
+ if (MyTakeOverTrans->getNdbError().code != 626 && MyTakeOverTrans->getNdbError().code != 630){
+ ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message);
+ ndbout_c("Error code = %d", MyTakeOverTrans->getNdbError().code);}
+ tResult = 20;
+ } else if (retCode == 2) {
+ ndbout << "4115 should not happen in flexBench" << endl;
+ tResult = 20;
+ } else if (retCode == 3) {
+ // --------------------------------------------------------------------
+ // We are not certain if the transaction was successful or not.
+ // We must reexecute but might very well find that the transaction
+ // actually was updated. Updates and Reads are no problem here. Inserts
+ // will not cause a problem if error code 630 arrives. Deletes will
+ // not cause a problem if 626 arrives.
+ // --------------------------------------------------------------------
+ /* What can we do here? */
+ ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message);
+ }//if(retCode == 3)
+
+ } // else
+ pNdb->closeTransaction(MyTakeOverTrans);
+ } // while
+
+ pNdb->closeTransaction(MyTransaction);
+ } // for
+
+ return(tResult);
+} // scanUpdateRows
+
+static int scanDeleteRows(Ndb* pNdb, int* readValue)
+{
+ int tResult = 0;
+ int tableCount = 0;
+ int attrCount = 0;
+ int check = 0;
+ NdbRecAttr* tTmp = NULL;
+ NdbConnection* MyTransaction = NULL;
+ NdbOperation* MyOperation = NULL;
+ NdbConnection* MyTakeOverTrans = NULL;
+ NdbOperation* MyTakeOverOp = NULL;
+
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+ MyTransaction = pNdb->startTransaction();
+ if (MyTransaction == NULL) {
+ tResult = 1;
+ break; // break tableCount for loop
+ } // if
+
+ MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]);
+ if (MyOperation == NULL) {
+ tResult = 2;
+ break;
+ } // if
+
+ check = MyOperation->openScanExclusive(tParallellism);
+ if (check == -1) {
+ tResult = 11;
+ break;
+ } // if
+
+ MyOperation->interpret_exit_ok();
+ for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
+ tTmp = MyOperation->
+ getValue((char*)attrName[attrCount+1],
+ (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
+ attrCount*tNoOfOperations]));
+ if (tTmp == NULL) {
+ tResult = 9;
+ break;
+ } // if
+ } // for
+
+ check = MyTransaction->executeScan();
+ if (check == -1) {
+ tResult = 12;
+ break;
+ } // if
+ check = MyTransaction->nextScanResult();
+ while (check == 0) {
+ MyTakeOverTrans = pNdb->startTransaction();
+ MyTakeOverOp = MyOperation->takeOverForDelete(MyTakeOverTrans);
+ check = MyTakeOverOp->deleteTuple();
+
+ check = MyTakeOverTrans->execute(Commit);
+
+ //Error handling here
+
+ int retCode =flexScanErrorData->handleErrorCommon(MyTakeOverTrans->getNdbError());
+ if (retCode == 1) {
+ if (MyTakeOverTrans->getNdbError().code != 626 && MyTakeOverTrans->getNdbError().code != 630){
+ ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message );
+ ndbout_c("Error code = %d", MyTakeOverTrans->getNdbError().code );}
+ tResult = 20;
+ } else if (retCode == 2) {
+ ndbout << "4115 should not happen in flexBench" << endl;
+ tResult = 20;
+ } else if (retCode == 3) {
+// --------------------------------------------------------------------
+// We are not certain if the transaction was successful or not.
+// We must reexecute but might very well find that the transaction
+// actually was updated. Updates and Reads are no problem here. Inserts
+// will not cause a problem if error code 630 arrives. Deletes will
+// not cause a problem if 626 arrives.
+// --------------------------------------------------------------------
+ /* What can we do here? */
+ ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message );
+ }//if(retCode == 3) End of error handling
+
+ pNdb->closeTransaction(MyTakeOverTrans);
+ check = MyTransaction->nextScanResult();
+ } // while
+ pNdb->closeTransaction(MyTransaction);
+ } // for tableCount
+ return(tResult);
+} // scanDeleteRows
+
+static int deleteRows(Ndb* pNdb,
+ int* pkValue)
+{
+ int tResult = 0;
+ NdbConnection* MyTransaction = NULL;
+ int tableCount = 0;
+ int opCount = 0;
+ int check = 0;
+ NdbOperation* MyOperations[MAXTABLES] = {NULL};
+
+ for (opCount = 0; opCount < tNoOfOperations; opCount++) {
+ MyTransaction = pNdb->startTransaction();
+ if (MyTransaction == NULL) {
+ tResult = 1;
+ } // if
+ else {
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+
+ MyOperations[tableCount] =
+ MyTransaction->getNdbOperation(tableName[tableCount]);
+ if (MyOperations[tableCount] == NULL) {
+ tResult = 2;
+ // Break for tableCount loop
+ break;
+ } // if
+
+ check = MyOperations[tableCount]->deleteTuple();
+ if (check == -1) {
+ tResult = 3;
+ break;
+ } // if
+
+ check = MyOperations[tableCount]->
+ equal((char*)attrName[0], (char*)&(pkValue[opCount]));
+ if (check == -1) {
+ tResult = 7;
+ break;
+ } // if
+
+ } // for tableCount
+
+ // Execute transaction deleting one tuple in every table
+ check = MyTransaction->execute(Commit);
+ if (check == -1) {
+ ndbout << MyTransaction->getNdbError().message << endl;
+ // Add complete error handling here
+
+ int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError());
+ if (retCode == 1) {
+ if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){
+ ndbout_c("execute: %d, %s", opCount, MyTransaction->getNdbError().message );
+ ndbout_c("Error code = %d", MyTransaction->getNdbError().code );}
+ tResult = 20;
+ } else if (retCode == 2) {
+ ndbout << "4115 should not happen in flexBench" << endl;
+ tResult = 20;
+ } else if (retCode == 3) {
+// --------------------------------------------------------------------
+// We are not certain if the transaction was successful or not.
+// We must reexecute but might very well find that the transaction
+// actually was updated. Updates and Reads are no problem here. Inserts
+// will not cause a problem if error code 630 arrives. Deletes will
+// not cause a problem if 626 arrives.
+// --------------------------------------------------------------------
+ /* What can we do here? */
+ ndbout_c("execute: %s", MyTransaction->getNdbError().message );
+ }//if(retCode == 3)
+
+ } // if
+
+ pNdb->closeTransaction(MyTransaction);
+ } // else
+ } // for opCount
+
+ return(tResult);
+
+} // deleteRows
+
+////////////////////////////////////////
+//
+// Name: verifyDeleteRows
+//
+// Purpose: Verifies that all tables are empty by reading every tuple
+// No deletions made here
+//
+// Returns: 'Standard' error codes
+//
+/////////////////////////////////////
+static int verifyDeleteRows(Ndb* pNdb,
+ int* pkValue,
+ int* readValue)
+{
+ int tResult = 0;
+ int tableCount = 0;
+ int attrCount = 0;
+ int check = 0;
+ NdbConnection* MyTransaction = NULL;
+ NdbOperation* MyOperations = NULL;
+ NdbRecAttr* tmp = NULL;
+ int Value = 0;
+ int Index = 0;
+ int opCount = 0;
+
+ for (opCount = 0; opCount < tNoOfOperations; opCount++) {
+ for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
+ MyTransaction = pNdb->startTransaction();
+ if (MyTransaction == NULL) {
+ tResult = 1;
+ } // if
+ else {
+
+ MyOperations =
+ MyTransaction->getNdbOperation(tableName[tableCount]);
+ if (MyOperations == NULL) {
+ tResult = 2;
+ // Break for tableCount loop
+ break;
+ } // if
+
+ check = MyOperations->readTuple();
+ if (check == -1) {
+ tResult = 3;
+ break;
+ } // if
+
+ check = MyOperations->
+ equal((char*)attrName[0], (char*)&(pkValue[opCount]));
+ if (check == -1) {
+ tResult = 7;
+ break;
+ } // if
+
+ for (int attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) {
+ Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize +
+ attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize;
+ tmp = MyOperations->
+ getValue((char*)attrName[attrCount + 1], (char*)&(readValue[Index]));
+
+ if (tmp == NULL) {
+ tResult = 9;
+ break;
+ } // if
+ } // for attrCount
+ // Execute transaction reading one tuple in every table
+ check = MyTransaction->execute(Commit);
+ if ((check == -1) && (MyTransaction->getNdbError().code == 626)){
+ // This is expected because everything should be deleted
+ } // if
+ else if (check == 0) {
+ // We have found a tuple that should have been deleted
+ ndbout << "tuple " << tableName[tableCount] << ":" <<
+ opCount << " was never deleted" << endl;
+ tResult = 97;
+ } // else if
+ else {
+ // Unexpected error
+ ndbout << "Unexpected error during delete" << endl;
+ assert(false);
+ } // else
+
+ pNdb->closeTransaction(MyTransaction);
+
+ } // else
+ } // for tableCount
+ } // for opCount
+
+ return(tResult);
+} // verifyDeleteRows
diff --git a/ndb/test/ndbapi/flexScan/flexScan.cpp b/ndb/test/ndbapi/flexScan/flexScan.cpp
deleted file mode 100644
index 19fb6dc5ab0..00000000000
--- a/ndb/test/ndbapi/flexScan/flexScan.cpp
+++ /dev/null
@@ -1,1674 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* ***************************************************
- FLEXSCAN
- Perform benchmark of:
- insert
- read
- scan read
- update
- scan update
- read
- scan delete
- verify delete
-
- Arguments:
- -f Location of Ndb.cfg file, default Ndb.cfg
- -t Number of threads to start, default 1
- -o Number of operations per loop, default 500 -l Number of loops to run, default 1, 0=infinite
- -a Number of attributes, default 25
- -c Number of tables, default 1
- -s Size of each attribute, default 1
- -stdtables Use standard table names
- -no_table_create Don't create tables in db
- -sleep Sleep a number of seconds before running the test, this
- can be used so that another flexBench hav etome to create tables
- -p Parallellism to use 1-32, default:1
- -abort <number> Test scan abort after a number of tuples
- -h Print help text
- -no_scan_update Don't do scan updates
- -no_scan_delete Don't do scan deletes
-
- Returns:
- NDBT_OK - Test passed
- NDBT_FAILED - Test failed
-
- Revision history:
- 1.12 020222 epesson: Rewritten to use NDBT. Major bugs fixed
-
- * *************************************************** */
-
-#include "NdbApi.hpp"
-
-#include <NdbThread.h>
-#include <NdbSleep.h>
-#include <NdbTick.h>
-#include <NdbOut.hpp>
-#include <NdbTimer.hpp>
-#include <NdbMain.h>
-#include <NdbTest.hpp>
-#include <NDBT_Error.hpp>
-
-#define PKSIZE 1
-#define FOREVER 1
-#define MAXSTRLEN 16
-#define MAXATTR 64
-#define MAXTABLES 64
-#define MAXTHREADS 256
-#define MAXATTRSIZE 64
-
-enum StartType {
- stIdle,
- stInsert,
- stRead,
- stScanRead,
- stUpdate,
- stScanUpdate,
- stDelete,
- stVerifyDelete,
- stScanDelete,
- stStop,
- stLast} ;
-
-
-struct ThreadNdb
-{
- int ThreadNo;
- NdbThread* threadLife;
- StartType threadStart;
- int threadResult;
- int threadReady;
-};
-
-extern "C" void* flexScanThread(void*);
-static int setAttrNames(void);
-static int setTableNames(void);
-static int createTables(Ndb* pMyNdb);
-static void sleepBeforeStartingTest(int seconds);
-static int readArguments(int argc, const char** argv);
-static void setAttrValues(int* attrValue,
- int* readValue,
- int Offset);
-static int insertRows(Ndb* pNdb, int* pkValue, int* attrValue, StartType tType);
-static int readRows(Ndb* pNdb, int* pkValue, int* readValue);
-static int deleteRows(Ndb* pNdb, int* pkValue);
-static int scanReadRows(Ndb* pNdb, int* readValue);
-static int scanUpdateRows(Ndb* pNdb, int* readValue, int* attrValue);
-static int scanDeleteRows(Ndb* pNdb, int* readValue);
-static int verifyDeleteRows(Ndb* pNdb, int* pkValue, int* readValue);
-static void Compare(int* attrValue, int* readValue);
-static void UpdateArray(int *attrValue);
-
-static int tNoOfThreads = 1;
-static int tNoOfAttributes = 25;
-static int tNoOfTables = 1;
-static int tAttributeSize = 1;
-static int tNodeId = 0;
-static int tNoOfOperations = 500;
-static int tNoOfLoops = 1;
-static int tAbortAfter = 0;
-static int tParallellism = 1;
-
-static char tableName[MAXTABLES][MAXSTRLEN];
-static char attrName[MAXATTR][MAXSTRLEN];
-
-static unsigned int tSleepTime = 0;
-
-static int theStdTableNameFlag = 0;
-static int theTableCreateFlag = 0;
-static int theScanAbortTestFlag = 0;
-static int theNoScanUpdateFlag = 0;
-static int theNoScanDeleteFlag = 0;
-
-//flexScanErrorData = new ErrorData;
-ErrorData * flexScanErrorData;
-NdbError * anerror;
-
-//static errorData theErrorData;
-//static unsigned int tErrorCounter[6000];
-
-#define START_TIMER { NdbTimer timer; timer.doStart();
-#define STOP_TIMER timer.doStop();
-#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
-
-static void UpdateArray(int *attrValue)
-{
- int tableCount = 0;
- int attrCount = 0;
- int opCount = 0;
- int sizeCount = 0;
- int Index = 0;
- int* pValue = attrValue;
-
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
- for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
- for (opCount = 0; opCount < tNoOfOperations; opCount++) {
- for (sizeCount = 0; sizeCount < tAttributeSize; sizeCount++) {
- // Update value in array
- (*pValue)++;
- //ndbout << "attrValue[" << tableCount*tNoOfAttributes*tNoOfOperations*tAttributeSize +
- //attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize + sizeCount <<
- //"] = " << attrValue[tableCount*tNoOfAttributes*tNoOfOperations*tAttributeSize +
- //attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize + sizeCount] << endl;
- // Increment pointer
- pValue++;
- } // sizeCount
- } // for opCount
- } // for attrCount
- } // for tableCount
-
-} // Update
-
-static void Compare(int* attrValue, int* readValue)
-{
- int tableCount = 0;
- int attrCount = 0;
- int OpCount = 0;
- int first = 0;
- int sizeCount = 0;
-
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
- for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
- for (OpCount = 0; OpCount < tNoOfOperations; OpCount++) {
- if (memcmp(&(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
- attrCount*tNoOfOperations + OpCount]),
- &(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
- attrCount*tNoOfOperations + OpCount]),
- tAttributeSize) != 0) {
- // Values mismatch
- if (first == 0) {
- //ndbout << "Read and set values differ for:" << endl;
- first = 1;
- ndbout << "Mismatch found.";
- } // if
- // Comparision of values after scan update is meaningless right now
- //ndbout << " table " << tableName[tableCount] <<
- //" - attr " << attrName[attrCount+1];
- //for (sizeCount = 0; sizeCount < tAttributeSize; sizeCount++) {
- //ndbout << ": set " <<
- //attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
- //attrCount*tNoOfOperations*tAttributeSize +
- //tNoOfOperations*tAttributeSize + sizeCount] << " read " <<
- //readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
- //attrCount*tNoOfOperations*tAttributeSize +
- //tNoOfOperations*tAttributeSize + sizeCount] << endl;
- //} // for
- } // if
- } // for OpCount
- } // for attrCount
- } // for tableCount
-
- // A final pretty-print
- if (first == 1) {
- ndbout << endl;
- } // if
-} // Compare
-
-static void printInfo()
-{
- ndbout << endl << "FLEXSCAN - Starting normal mode" << endl;
- ndbout << "Perform benchmark of insert, update and delete transactions"<< endl;
- ndbout << " NdbAPI node with id = " << tNodeId << endl;
- ndbout << " " << tNoOfThreads << " thread(s) " << endl;
- ndbout << " " << tNoOfLoops << " iterations " << endl;
- ndbout << " " << tNoOfTables << " table(s) and " << 1 << " operation(s) per transaction "
- << endl;
- ndbout << " " << tNoOfAttributes << " attributes per table incl. pk" << endl;
- ndbout << " " << tNoOfOperations << " transaction(s) per thread and round " << endl;
- if (theScanAbortTestFlag == 1) {
- ndbout << " Scan abort test after " << tAbortAfter << " tuples" << endl;
- } // if
- ndbout << " " << tParallellism << " parallellism in scans" << endl;
- ndbout << " " << tAttributeSize << " is the number of 32 bit words per attribute " <<
- endl << endl;
-
-} // printInfo
-
-static void tellThreads(ThreadNdb *threadArrayP, StartType what)
-{
- int i = 0;
-
- for (i = 0; i < tNoOfThreads ; i++)
- threadArrayP[i].threadStart = what;
-} // tellThreads
-
-static void waitForThreads(ThreadNdb *threadArrayP)
-{
- int i = 0;
- int cont = 1;
-
- while (cont == 1){
-
- NdbSleep_MilliSleep(10);
- cont = 0;
-
- for (i = 0; i < tNoOfThreads ; i++) {
- if (threadArrayP[i].threadReady == 0) {
-// ndbout << "Main is reporting thread " << i << " not ready" << endl;
- cont = 1;
- } // if
- } // for
- } // while
-} // waitForThreads
-
-
-static void resetThreads(ThreadNdb *threadArrayP)
-{
- int i = 0;
-
- for (i = 0; i < tNoOfThreads ; i++) {
- threadArrayP[i].threadReady = 0;
- threadArrayP[i].threadResult = 0;
- threadArrayP[i].threadStart = stIdle;
- //ndbout << "threadStart[" << i << "]=" <<
- //threadArrayP[i].threadStart << endl;
- } // for
-} // resetThreads
-
-static int checkThreadResults(ThreadNdb *threadArrayP, char *action)
-{
- int i = 0;
- int retValue = 0;
-
- for (i = 0; i < tNoOfThreads; i++) {
- if (threadArrayP[i].threadResult != 0) {
- ndbout << "Thread " << i << " reported fatal error "
- << threadArrayP[i].threadResult << " during " << action << endl;
- retValue = -1;
- break;
- } // if
- } // for
-
- return(retValue);
-} // checkThreadResults
-
-NDB_COMMAND(flexScan, "flexScan", "flexScan", "flexScan", 65535)
-{
- ThreadNdb* pThreads = NULL;
- Ndb* pMyNdb = NULL;
- int tLoops = 0;
- int check = 0;
- int returnValue = NDBT_OK;
- int every2ndScanDelete = 0; // Switch between scan delete and normal delete
-
- flexScanErrorData = new ErrorData;
-
- flexScanErrorData->resetErrorCounters();
-
- if (readArguments(argc, argv) != 0) {
- ndbout << "Wrong arguments to flexScan" << endl;
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- } // if
-
- /* print Setting */
- flexScanErrorData->printSettings(ndbout);
-
- check = setAttrNames();
- if (check != 0) {
- ndbout << "Couldn't set attribute names" << endl;
- return NDBT_ProgramExit(NDBT_FAILED);
- } // if
- check = setTableNames();
- if (check != 0) {
- ndbout << "Couldn't set table names" << endl;
- return NDBT_ProgramExit(NDBT_FAILED);
- } // if
-
- pMyNdb = new Ndb ("TEST_DB");
- pMyNdb->init();
- tNodeId = pMyNdb->getNodeId();
-
- printInfo();
-
- NdbThread_SetConcurrencyLevel(tNoOfThreads + 2);
- //NdbThread_SetConcurrencyLevel(tNoOfThreads + 8);
-
- pThreads = new ThreadNdb[tNoOfThreads];
-
- if (pMyNdb->waitUntilReady(10000) != 0) {
- ndbout << "NDB is not ready" << endl << "Benchmark failed" << endl;
- returnValue = NDBT_FAILED;
- } // if
-
- else {
-
- if (createTables(pMyNdb) != 0) {
- ndbout << "Could not create tables" << endl;
- returnValue = NDBT_FAILED;
- } // if
- else {
- sleepBeforeStartingTest(tSleepTime);
-
- resetThreads(pThreads);
- // Create threads
- for (int i = 0; i < tNoOfThreads ; i++){
- pThreads[i].ThreadNo = i;
- // Ignore the case that thread creation may fail
- pThreads[i].threadLife = NdbThread_Create(flexScanThread,
- (void**)&pThreads[i],
- 327680,
- "flexScanThread", NDB_THREAD_PRIO_LOW);
- if (pThreads[i].threadLife == NULL) {
- ndbout << "Could not create thread " << i << endl;
- returnValue = NDBT_FAILED;
- // Use the number of threads that were actually created
- tNoOfThreads = i;
- break; // break for loop
- } // if
- } // for
-
- waitForThreads(pThreads);
- if (checkThreadResults(pThreads, "init") != 0) {
- returnValue = NDBT_FAILED;
- } // if
-
- if (returnValue == NDBT_OK) {
- ndbout << "All threads started" << endl;
-
- while (FOREVER) {
-
- resetThreads(pThreads);
-
- if ((tNoOfLoops != 0) && (tNoOfLoops <= tLoops)) {
- break;
- } // if
-
- // Insert
- START_TIMER;
-
- tellThreads(pThreads, stInsert);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "insert") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("insert", tNoOfOperations*tNoOfThreads, tNoOfTables);
-
- resetThreads(pThreads);
-
- // Read
- START_TIMER;
-
- tellThreads(pThreads, stRead);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "read") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
-
- resetThreads(pThreads);
-
- // Update
- START_TIMER;
-
- tellThreads(pThreads, stUpdate);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "update") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables);
-
- resetThreads(pThreads);
-
- // Scan read
- START_TIMER;
-
- tellThreads(pThreads, stScanRead);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "scanread") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("scanread", tNoOfTables*tNoOfThreads, 1);
-
- resetThreads(pThreads);
-
- // Update
- START_TIMER;
-
- tellThreads(pThreads, stUpdate);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "update") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables);
-
- resetThreads(pThreads);
-
- // Read
- START_TIMER;
-
- tellThreads(pThreads, stRead);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "read") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
-
- resetThreads(pThreads);
-
- // Only do scan update if told to do so
- if (theNoScanUpdateFlag == 0) {
- // Scan update
- START_TIMER;
-
- tellThreads(pThreads, stScanUpdate);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "scanupdate") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("scanupdate", tNoOfTables*tNoOfThreads, 1);
-
- resetThreads(pThreads);
-
- // Read
- START_TIMER;
-
- tellThreads(pThreads, stRead);
- // tellThreads(pThreads, stScanRead);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "read") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
-
- resetThreads(pThreads);
- } // if theNoScanUpdateFlag
-
- // Shift between delete and scan delete
- if ((every2ndScanDelete % 2 == 0) || (theNoScanDeleteFlag == 1)){
- // Delete
- START_TIMER;
- tellThreads(pThreads, stDelete);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "delete") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("delete", tNoOfOperations*tNoOfThreads, tNoOfTables);
- resetThreads(pThreads);
- } // if
- else {
- resetThreads(pThreads); // Scan delete
- START_TIMER;
- tellThreads(pThreads, stScanDelete);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "scandelete") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("scandelete", tNoOfTables*tNoOfThreads, 1);
-
- resetThreads(pThreads);
- } // else
- every2ndScanDelete++;
-
- resetThreads(pThreads); // Verify delete
- START_TIMER;
- tellThreads(pThreads, stVerifyDelete);
- waitForThreads(pThreads);
-
- STOP_TIMER;
- if (checkThreadResults(pThreads, "verifydelete") != 0) {
- returnValue = NDBT_FAILED;
- break;
- } // if
- PRINT_TIMER("verifydelete", tNoOfOperations*tNoOfThreads*tNoOfTables, 1);
-
- resetThreads(pThreads);
-
- ndbout << "--------------------------------------------------" << endl;
- tLoops++;
-
- } // while
- } // if
- } // else
- } // else
-
- // Stop threads in a nice way
- tellThreads(pThreads, stStop);
- waitForThreads(pThreads);
-
- // Clean up
- delete [] pThreads;
- delete pMyNdb;
-
- flexScanErrorData->printErrorCounters(ndbout);
-
- if (returnValue == NDBT_OK) {
- ndbout << endl << "Benchmark completed successfully" << endl;
- } // if
- else {
- ndbout << endl << "Benchmark failed" << endl;
- } // else
-
- // Exit via NDBT
- return NDBT_ProgramExit(returnValue);;
-} // main
-
-void*
-flexScanThread(void* ThreadData)
-{
- ThreadNdb* pThreadData = (ThreadNdb*)ThreadData;
- unsigned int thread_no = pThreadData->ThreadNo;
- unsigned int thread_base = (thread_no * 2000000) + (tNodeId * 26000);
- int NrOfScannedRecords = 0;
- int tThreadResult = 0;
- Ndb* MyNdb = NULL;
- NdbConnection *MyTransaction = NULL;
- NdbOperation* MyOperation[MAXTABLES];
- int check = 0;
- StartType tType = stLast;
- int* pkValue = NULL;
- int* attrValue = NULL;
- int* readValue = NULL;
- int AllocSize = 0;
- NdbRecAttr* tTmp = NULL;
- OperationType opType;
-
- AllocSize = tNoOfTables * (tNoOfAttributes-1) * tNoOfOperations *
- tAttributeSize * sizeof(int);
- attrValue = (int*)malloc(AllocSize);
- readValue = (int*)malloc(AllocSize);
- pkValue = (int*)malloc(tNoOfOperations * sizeof(int));
- if ((attrValue == NULL) || (readValue == NULL) || (pkValue == NULL)) {
- tThreadResult = 98;
- pThreadData->threadStart = stIdle;
- } // if
-
- setAttrValues(attrValue, readValue, thread_base);
-
- MyNdb = new Ndb( "TEST_DB" );
- MyNdb->init();
- if (MyNdb->waitUntilReady(10000) != 0) {
- tThreadResult = 99;
- pThreadData->threadStart = stIdle;
- } // if
-
- // Set primary key value, same for all tables
- for (int c = 0; c < tNoOfOperations; c++) {
- pkValue[c] = (int)(c + thread_base);
- } // for
-
- while (FOREVER) {
- pThreadData->threadResult = tThreadResult;
- pThreadData->threadReady = 1;
-
- while (pThreadData->threadStart == stIdle) {
- NdbSleep_MilliSleep(10);
- } // while
-
- // Check if signal to exit is received
- if (pThreadData->threadStart >= stStop){
- pThreadData->threadReady = 1;
- break;
- } // if
- tType = pThreadData->threadStart;
- pThreadData->threadStart = stIdle;
-
- switch (tType) {
- case stInsert:
- check = insertRows(MyNdb, pkValue, attrValue, tType);
- break;
- case stRead:
- check = readRows(MyNdb, pkValue, readValue);
- Compare(attrValue, readValue);
- break;
- case stUpdate:
- UpdateArray(attrValue);
- check = insertRows(MyNdb, pkValue, attrValue, tType);
- break;
- case stScanRead:
- //check = readRows(MyNdb, pkValue, readValue);
- check = scanReadRows(MyNdb, readValue);
- Compare(attrValue, readValue);
- break;
- case stScanUpdate:
- UpdateArray(attrValue);
- //tType = stUpdate;
- //check = insertRows(MyNdb, pkValue, attrValue, tType);
- check = scanUpdateRows(MyNdb, readValue, attrValue);
- break;
- case stDelete:
- check = deleteRows(MyNdb, pkValue);
- break;
- case stScanDelete:
- check = scanDeleteRows(MyNdb, readValue);
- break;
- case stVerifyDelete:
- check = verifyDeleteRows(MyNdb, pkValue, readValue);
- break;
- default:
- ndbout << "tType is " << tType << endl;
- assert(false);
- break;
- } // switch
-
- tThreadResult = check;
-
- if (tThreadResult != 0) {
- // Check if error is fatak or not
- } // if
- else {
- continue;
- } // else
- } // while
-
- // Clean up
- delete MyNdb;
- if (attrValue != NULL) {
- free(attrValue);
- } //if
- if (readValue != NULL) {
- free(readValue);
- } // if
- if (pkValue != NULL) {
- free(pkValue);
- } // if
-
- NdbThread_Exit(0);
- return NULL;
-
-} // flexScanThread
-
-
-static int setAttrNames()
-{
- int i = 0;
- int retVal = 0;
-
- for (i = 0; i < MAXATTR ; i++) {
- retVal = snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
- if (retVal < 0) {
- return(-1);
- } // if
- } // for
-
- return(0);
-} // setAttrNames
-
-
-static int setTableNames()
-{
- // Note! Uses only uppercase letters in table name's
- // so that we can look at the tables with SQL
- int i = 0;
- int retVal = 0;
-
- for (i = 0; i < MAXTABLES ; i++) {
-
- if (theStdTableNameFlag == 0) {
- retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
- (int)(NdbTick_CurrentMillisecond() / 1000));
- } // if
- else {
- retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
- } // if else
-
- if (retVal < 0) {
- return(-1);
- } // if
- } // for
-
- return(0);
-} // setTableNames
-
-
-// Create Table and Attributes.
-static int createTables(Ndb* pMyNdb)
-{
-
- NdbSchemaCon *MySchemaTransaction = NULL;
- NdbSchemaOp *MySchemaOp = NULL;
- int i = 0;
- int j = 0;
- int check = 0;
-
- if (theTableCreateFlag == 0) {
-
- i = 0;
- do {
- i++;
- ndbout << endl << "Creating " << tableName[i - 1] << "..." << endl;
-
- MySchemaTransaction = pMyNdb->startSchemaTransaction();
- if( MySchemaTransaction == NULL ) {
- return (-1);
- } // if
-
- MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if( MySchemaOp == NULL ) {
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- return (-1);
- } // if
-
-#if defined NDB_OSE || defined NDB_SOFTOSE
- check = MySchemaOp->createTable(tableName[i - 1],
- 8, // Table Size
- TupleKey, // Key Type
- 40, // Nr of Pages
- All,
- 6,
- 78,
- 80,
- 1,
- false);
-#else
- check = MySchemaOp->createTable(tableName[i - 1]
- ,8 // Table Size
- ,TupleKey // Key Type
- ,40); // Nr of Pages
-#endif
- if (check == -1) {
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- return -1;
- } // if
-
- check = MySchemaOp->createAttribute( (char*)attrName[0], TupleKey, 32, PKSIZE,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) {
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- return -1;
- } // if
-
- for (j = 1; j < tNoOfAttributes ; j++) {
- check = MySchemaOp->createAttribute( (char*)attrName[j], NoKey, 32, tAttributeSize,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) {
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- return -1;
- } // if
- } // for
-
- if (MySchemaTransaction->execute() == -1) {
- ndbout << MySchemaTransaction->getNdbError().message << endl;
- ndbout << "Probably, " << tableName[i - 1] << " already exist" << endl;
- } // if
-
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- } while (tNoOfTables > i);
- }
-
- return 0;
-} // createTables
-
-static void printUsage()
-{
- ndbout << "Usage of flexScan:" << endl;
- ndbout << "-f <path> Location of Ndb.cfg file, default: Ndb.cfg" << endl;
- ndbout << "-t <int> Number of threads to start, default 1" << endl;
- ndbout << "-o <int> Number of operations per loop, default 500" << endl;
- ndbout << "-l <int> Number of loops to run, default 1, 0=infinite" << endl;
- ndbout << "-a <int> Number of attributes, default 25" << endl;
- ndbout << "-c <int> Number of tables, default 1" << endl;
- ndbout << "-s <int> Size of each attribute, default 1" << endl;
- ndbout << "-stdtables Use standard table names" << endl;
- ndbout << "-no_table_create Don't create tables in db" << endl;
- ndbout << "-sleep <int> Sleep a number of seconds before running the test" << endl;
- ndbout << "-p <int> Parallellism to use 1-32, default:1" << endl;
- ndbout << "-abort <int> Test scan abort after a number of tuples" << endl;
- ndbout << "-no_scan_update Don't do scan updates" << endl;
- ndbout << "-no_scan_delete Don't do scan deletes" << endl;
- ndbout << "-h Print this text" << endl;
- // inputErrorArg();
- flexScanErrorData->printCmdLineArgs(ndbout);
-}
-
-static int readArguments(int argc, const char** argv)
-{
- int i = 1;
- int retValue = 0;
- int printFlag = 0;
-
- tNoOfThreads = 1; // Set default Value
- tNoOfTables = 1; // Default Value
-
- while (argc > 1) {
- if (strcmp(argv[i], "-t") == 0) {
- if (argv[i + 1] != NULL) {
- tNoOfThreads = atoi(argv[i + 1]);
- if ((tNoOfThreads < 1) || (tNoOfThreads > MAXTHREADS)) {
- retValue = -1;
- } // if
- } // if
- else {
- retValue = -1;
- } // else
- } // if
- else if (strcmp(argv[i], "-o") == 0) {
- if (argv[i + 1] != NULL) {
- tNoOfOperations = atoi(argv[i + 1]);
- if (tNoOfOperations < 1) {
- retValue = -1;
- } // if
- } // if
- else {
- retValue = -1;
- } // else
- } // else if
- else if (strcmp(argv[i], "-a") == 0) {
- if (argv[i + 1] != NULL) {
- tNoOfAttributes = atoi(argv[i + 1]);
- if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR)) {
- retValue = -1;
- } // if
- } // if
- else {
- retValue = -1;
- } // else
- } // else if
- else if (strcmp(argv[i], "-c") == 0) {
- if (argv[i + 1] != NULL) {
- tNoOfTables = atoi(argv[i+1]);
- if ((tNoOfTables < 1) || (tNoOfTables > MAXTABLES)) {
- retValue = -1;
- } // if
- } // if
- else {
- retValue = -1;
- } // else
- } // else if
- else if (strcmp(argv[i], "-l") == 0) {
- if (argv[i + 1] != NULL) {
- tNoOfLoops = atoi(argv[i+1]);
- if ((tNoOfLoops < 0) || (tNoOfLoops > 100000)) {
- retValue = -1;
- } // if
- } // if
- else {
- retValue = -1;
- } // else
- } // else if
- else if (strcmp(argv[i], "-s") == 0) {
- if (argv[i + 1] != NULL) {
- tAttributeSize = atoi(argv[i+1]);
- if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE)) {
- retValue = -1;
- } // if
- } // if
- else {
- retValue = -1;
- } // else
- } // else if
- else if (strcmp(argv[i], "-no_table_create") == 0) {
- theTableCreateFlag = 1;
- argc++;
- i--;
- } // else if
- else if (strcmp(argv[i], "-stdtables") == 0) {
- theStdTableNameFlag = 1;
- argc++;
- i--;
- } // else if
- else if (strcmp(argv[i], "-sleep") == 0) {
- if (argv[i + 1] != NULL) {
- tSleepTime = atoi(argv[i+1]);
- if ((tSleepTime < 1) || (tSleepTime > 3600)) {
- retValue = -1;
- } // if
- } // if
- else {
- retValue = -1;
- } // else
- } // else if
- else if (strcmp(argv[i], "-abort") == 0) {
- // Test scan abort after a number of tuples
- theScanAbortTestFlag = 1;
- if (argv[i + 1] != NULL) {
- tAbortAfter = atoi(argv[i + 1]);
- } // if
- else {
- retValue = -1;
- } // else
- } // else if
- else if (strcmp(argv[i], "-p") == 0) {
- if (argv[i + 1] != NULL) {
- tParallellism = atoi(argv[i + 1]);
- if ((tParallellism < 1) || (tParallellism > 32)) {
- retValue = -1;
- } // if
- } // if
- else {
- retValue = -1;
- } // else
- } // else if
- else if (strcmp(argv[i], "-h") == 0) {
- printFlag = 1;
- argc++;
- i--;
- } // else if
- else if (strcmp(argv[i], "-no_scan_update") == 0) {
- theNoScanUpdateFlag = 1;
- argc++;
- i--;
- } // else if
- else if (strcmp(argv[i], "-no_scan_delete") == 0) {
- theNoScanDeleteFlag = 1;
- argc++;
- i--;
- } // else if
- else {
- retValue = -1;
- } // else
-
- argc -= 2;
- i = i + 2;
- }
-
- if ((retValue != 0) || (printFlag == 1)) {
- printUsage();
- } // if
-
- return(retValue);
-
-} // readArguments
-
-static void sleepBeforeStartingTest(int seconds)
-{
- if (seconds > 0) {
- ndbout << "Sleeping(" <<seconds << ")...";
- NdbSleep_SecSleep(seconds);
- ndbout << " done!" << endl;
- } // if
-} // sleepBeforeStartingTest
-
-static void setAttrValues(int* attrValue,
- int* readValue,
- int Offset)
-{
- int tableCount = 0;
- int attrCount = 0;
- int OpCount = 0;
- int attrSize = 0;
- int* pAttr = NULL;
- int* pRead = NULL;
-
- // Set attribute values in memory array
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
- for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
- for (OpCount = 0; OpCount < tNoOfOperations; OpCount++) {
- pAttr = &(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
- attrCount*tNoOfOperations + OpCount]);
- pRead = &(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
- attrCount*tNoOfOperations + OpCount]);
- for (attrSize = 0; attrSize < tAttributeSize; attrSize++){
- *pAttr = (int)(Offset + tableCount + attrCount + OpCount + attrSize);
- //ndbout << "attrValue[" << tableCount*(tNoOfAttributes-1)*tNoOfOperations +
- //attrCount*tNoOfOperations + OpCount + attrSize << "] = " <<
- //attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
- //attrCount*tNoOfOperations + OpCount + attrSize] << endl;
- *pRead = 0;
- pAttr++;
- pRead++;
- } // for attrSize
- } // for OpCount
- } // for attrCount
- } // for tableCount
-
-} // setAttrValues
-
-static int insertRows(Ndb* pNdb, // NDB object
- int* pkValue, // Primary key values
- int* attrValue, // Attribute values
- StartType tType)
-{
- int tResult = 0;
- int check = 0;
- int tableCount = 0;
- int attrCount = 0;
- NdbConnection* MyTransaction = NULL;
- NdbOperation* MyOperations[MAXTABLES] = {NULL};
- int Index = 0;
- int opCount = 0;
-
- for (opCount = 0; opCount < tNoOfOperations; opCount++) {
- MyTransaction = pNdb->startTransaction();
- if (MyTransaction == NULL) {
- tResult = 1;
- } // if
- else {
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
-
- MyOperations[tableCount] =
- MyTransaction->getNdbOperation(tableName[tableCount]);
- if (MyOperations[tableCount] == NULL) {
- tResult = 2;
- // Break for tableCount loop
- break;
- } // if
-
- if (tType == stUpdate) {
- check = MyOperations[tableCount]->updateTuple();
- } // if
- else if (tType == stInsert) {
- check = MyOperations[tableCount]->insertTuple();
- } // else if
- else {
- assert(false);
- } // else
-
- if (check == -1) {
- tResult = 3;
- break;
- } // if
- check = MyOperations[tableCount]->equal((char*)attrName[0],
- (char*)&(pkValue[opCount]));
- if (check == -1) {
- tResult = 7;
- break;
- } // if
-
- for (attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) {
- Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize +
- attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize;
- check = MyOperations[tableCount]->
- setValue((char*)attrName[attrCount + 1],
- (char*)&(attrValue[Index]));
- if (check == -1) {
- tResult = 8;
- break; // break attrCount loop
- } // if
- } // for
- } // for tableCount
-
- // Execute transaction with insert one tuple in every table
- check = MyTransaction->execute(Commit);
- if (check == -1) {
- ndbout << MyTransaction->getNdbError().message << endl;
-
- // Add complete error handling here
-
- int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError());
- if (retCode == 1) {
- if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){
- ndbout_c("execute: %d, %d, %s", opCount, tType, MyTransaction->getNdbError().message);
- ndbout_c("Error code = %d", MyTransaction->getNdbError().code);}
- tResult = 20;
- } else if (retCode == 2) {
- ndbout << "4115 should not happen in flexBench" << endl;
- tResult = 20;
- } else if (retCode == 3) {
-// --------------------------------------------------------------------
-// We are not certain if the transaction was successful or not.
-// We must reexecute but might very well find that the transaction
-// actually was updated. Updates and Reads are no problem here. Inserts
-// will not cause a problem if error code 630 arrives. Deletes will
-// not cause a problem if 626 arrives.
-// --------------------------------------------------------------------
- /* What can we do here? */
- ndbout_c("execute: %s", MyTransaction->getNdbError().message);
- }//if(retCode == 3)
-
- } // if(check == -1)
-
- pNdb->closeTransaction(MyTransaction);
- } // else
- } // for opCount
-
- return(tResult);
-} // insertRows
-
-static int readRows(Ndb* pNdb,
- int* pkValue,
- int* readValue)
-{
- int tResult = 0;
- int tableCount = 0;
- int attrCount = 0;
- int check = 0;
- NdbConnection* MyTransaction = NULL;
- NdbOperation* MyOperations[MAXTABLES] = {NULL};
- NdbRecAttr* tmp = NULL;
- int Value = 0;
- int Index = 0;
- int opCount = 0;
-
- for (opCount = 0; opCount < tNoOfOperations; opCount++) {
- MyTransaction = pNdb->startTransaction();
- if (MyTransaction == NULL) {
- tResult = 1;
- } // if
- else {
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
-
- MyOperations[tableCount] =
- MyTransaction->getNdbOperation(tableName[tableCount]);
- if (MyOperations[tableCount] == NULL) {
- tResult = 2;
- // Break for tableCount loop
- break;
- } // if
-
- check = MyOperations[tableCount]->readTuple();
- if (check == -1) {
- tResult = 3;
- break;
- } // if
-
- check = MyOperations[tableCount]->
- equal((char*)attrName[0], (char*)&(pkValue[opCount]));
- if (check == -1) {
- tResult = 7;
- break;
- } // if
-
- for (int attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) {
- Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize +
- attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize;
- tmp = MyOperations[tableCount]->
- getValue((char*)attrName[attrCount + 1], (char*)&(readValue[Index]));
-
- if (tmp == NULL) {
- tResult = 9;
- break;
- } // if
- } // for attrCount
- } // for tableCount
- // Execute transaction reading one tuple in every table
- check = MyTransaction->execute(Commit);
- if (check == -1) {
- ndbout << MyTransaction->getNdbError().message << endl;
-
- // Add complete error handling here
-
- int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError());
- if (retCode == 1) {
- if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){
- ndbout_c("execute: %d, %s", opCount, MyTransaction ->getNdbError().message );
- ndbout_c("Error code = %d", MyTransaction->getNdbError().code );}
- tResult = 20;
- } else if (retCode == 2) {
- ndbout << "4115 should not happen in flexBench" << endl;
- tResult = 20;
- } else if (retCode == 3) {
-// --------------------------------------------------------------------
-// We are not certain if the transaction was successful or not.
-// We must reexecute but might very well find that the transaction
-// actually was updated. Updates and Reads are no problem here. Inserts
-// will not cause a problem if error code 630 arrives. Deletes will
-// not cause a problem if 626 arrives.
-// --------------------------------------------------------------------
- /* What can we do here? */
- ndbout_c("execute: %s", MyTransaction ->getNdbError().message );
- }//if(retCode == 3)
-
- } // if
-
- pNdb->closeTransaction(MyTransaction);
- } // else
- } // for opCount
-
- return(tResult);
-} // readRows
-
-static int scanReadRows(Ndb* pNdb, int* readValue)
-{
- int tResult = 0;
- int tableCount = 0;
- int attrCount = 0;
- int check = 0;
- int countAbort = 0; // Counts loops until scan abort if requested
- NdbConnection* MyTransaction = NULL;
- NdbOperation* MyOperation = NULL;
- NdbRecAttr* tmp = NULL;
-
-
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
- MyTransaction = pNdb->startTransaction();
- if (MyTransaction == NULL) {
- tResult = 1;
- break;
- } // if
- MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]);
- if (MyOperation == NULL) {
- tResult = 2;
- break;
- } // if
-
- check = MyOperation->openScanRead(tParallellism);
- if (check == -1) {
- tResult = 10;
- break;
- } // if
-
- for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
- // Get all attributes
- tmp = MyOperation->
- getValue((char*)attrName[attrCount+1],
- (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
- attrCount*tNoOfOperations*tAttributeSize]));
- if (tmp == NULL) {
- tResult = 9;
- break;
- } // if
- } // for attrCount
-
- check = MyTransaction->executeScan();
- if (check == -1) {
- tResult = 12;
- break;
- } // if
-
- check = MyTransaction->nextScanResult();
- while (check == 0) {
- // Check if scan abort is requested
- if (theScanAbortTestFlag == 1) {
- if (countAbort == tAbortAfter) {
- MyTransaction->stopScan();
- ndbout << "scanread aborted on request after " << countAbort*tParallellism <<
- " tuples" << endl;
- break; // break while loop
- } // if
- countAbort++;
- } // if
- check = MyTransaction->nextScanResult();
- } // while
-
- pNdb->closeTransaction(MyTransaction);
- } // for tableCount
-
- return(tResult);
-} // scanReadRows
-
-static int scanUpdateRows(Ndb* pNdb,
- int* readValue,
- int* attrValue)
-{
- int tResult = 0;
- int tableCount = 0;
- int attrCount = 0;
- int check = 0;
- int opCount = 0;
- NdbConnection* MyTransaction = NULL;
- NdbOperation* MyOperation = NULL;
- NdbConnection* MyTakeOverTrans = NULL;
- NdbOperation* MyTakeOverOp = NULL;
- NdbRecAttr* tTmp = NULL;
-
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
- MyTransaction = pNdb->startTransaction();
- if (MyTransaction == NULL) {
- tResult = 1;
- break; // break tableCount for loop
- } // if
- MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]);
- if (MyOperation == NULL) {
- tResult = 2;
- break;
- } // if
-
- check = MyOperation->openScanExclusive(tParallellism);
- if (check == -1) {
- tResult = 11;
- break;
- } // if
-
- MyOperation->interpret_exit_ok();
- // Fetch all attributes
- for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
- tTmp = MyOperation->
- getValue((char*)attrName[attrCount+1],
- (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
- attrCount*tNoOfOperations*tAttributeSize]));
- if (tTmp == NULL) {
- tResult = 9;
- break; // break for loop
- } // if
- } // for
- if (tResult != 0) {
- break; // break while loop also
- } // if
-
- check = MyTransaction->executeScan();
- if (check == -1) {
- tResult = 12;
- break;
- } // if
- check = MyTransaction->nextScanResult();
- opCount = 0;
- while (check == 0) {
- MyTakeOverTrans = pNdb->startTransaction();
- MyTakeOverOp = MyOperation->takeOverForUpdate(MyTakeOverTrans);
- for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
- check = MyTakeOverOp->setValue((char*)attrName[attrCount+1],
- (char*)&(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
- attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize]));
- } // for
-
- check = MyTakeOverTrans->execute(Commit);
- if (check == 0) {
- check = MyTransaction->nextScanResult();
- opCount++;
- } // if
- else {
- tResult = 95;
-
- /* MyTransaction, MyTakeOverTrans, Which one? */
-
- // Any further error handling?
- int retCode = flexScanErrorData->handleErrorCommon(MyTakeOverTrans->getNdbError());
- if (retCode == 1) {
- if (MyTakeOverTrans->getNdbError().code != 626 && MyTakeOverTrans->getNdbError().code != 630){
- ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message);
- ndbout_c("Error code = %d", MyTakeOverTrans->getNdbError().code);}
- tResult = 20;
- } else if (retCode == 2) {
- ndbout << "4115 should not happen in flexBench" << endl;
- tResult = 20;
- } else if (retCode == 3) {
- // --------------------------------------------------------------------
- // We are not certain if the transaction was successful or not.
- // We must reexecute but might very well find that the transaction
- // actually was updated. Updates and Reads are no problem here. Inserts
- // will not cause a problem if error code 630 arrives. Deletes will
- // not cause a problem if 626 arrives.
- // --------------------------------------------------------------------
- /* What can we do here? */
- ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message);
- }//if(retCode == 3)
-
- } // else
- pNdb->closeTransaction(MyTakeOverTrans);
- } // while
-
- pNdb->closeTransaction(MyTransaction);
- } // for
-
- return(tResult);
-} // scanUpdateRows
-
-static int scanDeleteRows(Ndb* pNdb, int* readValue)
-{
- int tResult = 0;
- int tableCount = 0;
- int attrCount = 0;
- int check = 0;
- NdbRecAttr* tTmp = NULL;
- NdbConnection* MyTransaction = NULL;
- NdbOperation* MyOperation = NULL;
- NdbConnection* MyTakeOverTrans = NULL;
- NdbOperation* MyTakeOverOp = NULL;
-
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
- MyTransaction = pNdb->startTransaction();
- if (MyTransaction == NULL) {
- tResult = 1;
- break; // break tableCount for loop
- } // if
-
- MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]);
- if (MyOperation == NULL) {
- tResult = 2;
- break;
- } // if
-
- check = MyOperation->openScanExclusive(tParallellism);
- if (check == -1) {
- tResult = 11;
- break;
- } // if
-
- MyOperation->interpret_exit_ok();
- for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
- tTmp = MyOperation->
- getValue((char*)attrName[attrCount+1],
- (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
- attrCount*tNoOfOperations]));
- if (tTmp == NULL) {
- tResult = 9;
- break;
- } // if
- } // for
-
- check = MyTransaction->executeScan();
- if (check == -1) {
- tResult = 12;
- break;
- } // if
- check = MyTransaction->nextScanResult();
- while (check == 0) {
- MyTakeOverTrans = pNdb->startTransaction();
- MyTakeOverOp = MyOperation->takeOverForDelete(MyTakeOverTrans);
- check = MyTakeOverOp->deleteTuple();
-
- check = MyTakeOverTrans->execute(Commit);
-
- //Error handling here
-
- int retCode =flexScanErrorData->handleErrorCommon(MyTakeOverTrans->getNdbError());
- if (retCode == 1) {
- if (MyTakeOverTrans->getNdbError().code != 626 && MyTakeOverTrans->getNdbError().code != 630){
- ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message );
- ndbout_c("Error code = %d", MyTakeOverTrans->getNdbError().code );}
- tResult = 20;
- } else if (retCode == 2) {
- ndbout << "4115 should not happen in flexBench" << endl;
- tResult = 20;
- } else if (retCode == 3) {
-// --------------------------------------------------------------------
-// We are not certain if the transaction was successful or not.
-// We must reexecute but might very well find that the transaction
-// actually was updated. Updates and Reads are no problem here. Inserts
-// will not cause a problem if error code 630 arrives. Deletes will
-// not cause a problem if 626 arrives.
-// --------------------------------------------------------------------
- /* What can we do here? */
- ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message );
- }//if(retCode == 3) End of error handling
-
- pNdb->closeTransaction(MyTakeOverTrans);
- check = MyTransaction->nextScanResult();
- } // while
- pNdb->closeTransaction(MyTransaction);
- } // for tableCount
- return(tResult);
-} // scanDeleteRows
-
-static int deleteRows(Ndb* pNdb,
- int* pkValue)
-{
- int tResult = 0;
- NdbConnection* MyTransaction = NULL;
- int tableCount = 0;
- int opCount = 0;
- int check = 0;
- NdbOperation* MyOperations[MAXTABLES] = {NULL};
-
- for (opCount = 0; opCount < tNoOfOperations; opCount++) {
- MyTransaction = pNdb->startTransaction();
- if (MyTransaction == NULL) {
- tResult = 1;
- } // if
- else {
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
-
- MyOperations[tableCount] =
- MyTransaction->getNdbOperation(tableName[tableCount]);
- if (MyOperations[tableCount] == NULL) {
- tResult = 2;
- // Break for tableCount loop
- break;
- } // if
-
- check = MyOperations[tableCount]->deleteTuple();
- if (check == -1) {
- tResult = 3;
- break;
- } // if
-
- check = MyOperations[tableCount]->
- equal((char*)attrName[0], (char*)&(pkValue[opCount]));
- if (check == -1) {
- tResult = 7;
- break;
- } // if
-
- } // for tableCount
-
- // Execute transaction deleting one tuple in every table
- check = MyTransaction->execute(Commit);
- if (check == -1) {
- ndbout << MyTransaction->getNdbError().message << endl;
- // Add complete error handling here
-
- int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError());
- if (retCode == 1) {
- if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){
- ndbout_c("execute: %d, %s", opCount, MyTransaction->getNdbError().message );
- ndbout_c("Error code = %d", MyTransaction->getNdbError().code );}
- tResult = 20;
- } else if (retCode == 2) {
- ndbout << "4115 should not happen in flexBench" << endl;
- tResult = 20;
- } else if (retCode == 3) {
-// --------------------------------------------------------------------
-// We are not certain if the transaction was successful or not.
-// We must reexecute but might very well find that the transaction
-// actually was updated. Updates and Reads are no problem here. Inserts
-// will not cause a problem if error code 630 arrives. Deletes will
-// not cause a problem if 626 arrives.
-// --------------------------------------------------------------------
- /* What can we do here? */
- ndbout_c("execute: %s", MyTransaction->getNdbError().message );
- }//if(retCode == 3)
-
- } // if
-
- pNdb->closeTransaction(MyTransaction);
- } // else
- } // for opCount
-
- return(tResult);
-
-} // deleteRows
-
-////////////////////////////////////////
-//
-// Name: verifyDeleteRows
-//
-// Purpose: Verifies that all tables are empty by reading every tuple
-// No deletions made here
-//
-// Returns: 'Standard' error codes
-//
-/////////////////////////////////////
-static int verifyDeleteRows(Ndb* pNdb,
- int* pkValue,
- int* readValue)
-{
- int tResult = 0;
- int tableCount = 0;
- int attrCount = 0;
- int check = 0;
- NdbConnection* MyTransaction = NULL;
- NdbOperation* MyOperations = NULL;
- NdbRecAttr* tmp = NULL;
- int Value = 0;
- int Index = 0;
- int opCount = 0;
-
- for (opCount = 0; opCount < tNoOfOperations; opCount++) {
- for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
- MyTransaction = pNdb->startTransaction();
- if (MyTransaction == NULL) {
- tResult = 1;
- } // if
- else {
-
- MyOperations =
- MyTransaction->getNdbOperation(tableName[tableCount]);
- if (MyOperations == NULL) {
- tResult = 2;
- // Break for tableCount loop
- break;
- } // if
-
- check = MyOperations->readTuple();
- if (check == -1) {
- tResult = 3;
- break;
- } // if
-
- check = MyOperations->
- equal((char*)attrName[0], (char*)&(pkValue[opCount]));
- if (check == -1) {
- tResult = 7;
- break;
- } // if
-
- for (int attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) {
- Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize +
- attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize;
- tmp = MyOperations->
- getValue((char*)attrName[attrCount + 1], (char*)&(readValue[Index]));
-
- if (tmp == NULL) {
- tResult = 9;
- break;
- } // if
- } // for attrCount
- // Execute transaction reading one tuple in every table
- check = MyTransaction->execute(Commit);
- if ((check == -1) && (MyTransaction->getNdbError().code == 626)){
- // This is expected because everything should be deleted
- } // if
- else if (check == 0) {
- // We have found a tuple that should have been deleted
- ndbout << "tuple " << tableName[tableCount] << ":" <<
- opCount << " was never deleted" << endl;
- tResult = 97;
- } // else if
- else {
- // Unexpected error
- ndbout << "Unexpected error during delete" << endl;
- assert(false);
- } // else
-
- pNdb->closeTransaction(MyTransaction);
-
- } // else
- } // for tableCount
- } // for opCount
-
- return(tResult);
-} // verifyDeleteRows
diff --git a/ndb/test/ndbapi/flexTT.cpp b/ndb/test/ndbapi/flexTT.cpp
new file mode 100644
index 00000000000..a82875de5c2
--- /dev/null
+++ b/ndb/test/ndbapi/flexTT.cpp
@@ -0,0 +1,928 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+
+#include <NdbApi.hpp>
+#include <NdbSchemaCon.hpp>
+#include <NdbMain.h>
+#include <md5_hash.hpp>
+
+#include <NdbThread.h>
+#include <NdbSleep.h>
+#include <NdbTick.h>
+#include <NdbOut.hpp>
+#include <NdbTimer.hpp>
+
+#include <NdbTest.hpp>
+#include <NDBT_Error.hpp>
+
+#define MAX_PARTS 4
+#define MAX_SEEK 16
+#define MAXSTRLEN 16
+#define MAXATTR 64
+#define MAXTABLES 64
+#define MAXTHREADS 128
+#define MAXPAR 1024
+#define MAXATTRSIZE 1000
+#define PKSIZE 1
+
+
+#ifdef NDB_WIN32
+inline long lrand48(void) { return rand(); };
+#endif
+
+
+enum StartType {
+ stIdle,
+ stInsert,
+ stRead,
+ stUpdate,
+ stDelete,
+ stStop
+} ;
+
+struct ThreadNdb
+{
+ int threadNo;
+ Ndb* threadNdb;
+ Uint32 threadBase;
+ Uint32 threadLoopCounter;
+ Uint32 threadNextStart;
+ Uint32 threadStop;
+ Uint32 threadLoopStop;
+ Uint32 threadIncrement;
+ Uint32 threadNoCompleted;
+ bool threadCompleted;
+ StartType threadStartType;
+};
+
+struct TransNdb
+{
+ char transRecord[128];
+ Ndb* transNdb;
+ StartType transStartType;
+ Uint32 vpn_number;
+ Uint32 vpn_identity;
+ Uint32 transErrorCount;
+ NdbOperation* transOperation;
+ ThreadNdb* transThread;
+};
+
+extern "C" { static void* threadLoop(void*); }
+static void setAttrNames(void);
+static void setTableNames(void);
+static int readArguments(int argc, const char** argv);
+static int createTables(Ndb*);
+static bool defineOperation(NdbConnection* aTransObject, TransNdb*,
+ Uint32 vpn_nb, Uint32 vpn_id);
+static bool executeTransaction(TransNdb* transNdbRef);
+static StartType random_choice();
+static void execute(StartType aType);
+static bool executeThread(ThreadNdb*, TransNdb*);
+static void executeCallback(int result, NdbConnection* NdbObject,
+ void* aObject);
+static bool error_handler(const NdbError & err) ;
+static Uint32 getKey(Uint32, Uint32) ;
+static void input_error();
+
+ErrorData * flexTTErrorData;
+
+static NdbThread* threadLife[MAXTHREADS];
+static int tNodeId;
+static int ThreadReady[MAXTHREADS];
+static StartType ThreadStart[MAXTHREADS];
+static char tableName[1][MAXSTRLEN+1];
+static char attrName[5][MAXSTRLEN+1];
+
+// Program Parameters
+static bool tInsert = false;
+static bool tDelete = false;
+static bool tReadUpdate = true;
+static int tUpdateFreq = 20;
+static bool tLocal = false;
+static int tLocalPart = 0;
+static int tMinEvents = 0;
+static int tSendForce = 0;
+static int tNoOfLoops = 1;
+static Uint32 tNoOfThreads = 1;
+static Uint32 tNoOfParallelTrans = 32;
+static Uint32 tNoOfTransactions = 500;
+static Uint32 tLoadFactor = 80;
+static bool tempTable = false;
+static bool startTransGuess = true;
+
+//Program Flags
+static int theSimpleFlag = 0;
+static int theDirtyFlag = 0;
+static int theWriteFlag = 0;
+static int theTableCreateFlag = 1;
+
+#define START_REAL_TIME
+#define STOP_REAL_TIME
+#define START_TIMER { NdbTimer timer; timer.doStart();
+#define STOP_TIMER timer.doStop();
+#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
+
+static void
+resetThreads(){
+
+ for (int i = 0; i < tNoOfThreads ; i++) {
+ ThreadReady[i] = 0;
+ ThreadStart[i] = stIdle;
+ }//for
+}
+
+static void
+waitForThreads(void)
+{
+ int cont = 0;
+ do {
+ cont = 0;
+ NdbSleep_MilliSleep(20);
+ for (int i = 0; i < tNoOfThreads ; i++) {
+ if (ThreadReady[i] == 0) {
+ cont = 1;
+ }//if
+ }//for
+ } while (cont == 1);
+}
+
+static void
+tellThreads(StartType what)
+{
+ for (int i = 0; i < tNoOfThreads ; i++)
+ ThreadStart[i] = what;
+}
+
+NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535)
+{
+ ThreadNdb* pThreadData;
+ int returnValue = NDBT_OK;
+
+ flexTTErrorData = new ErrorData;
+ flexTTErrorData->resetErrorCounters();
+
+ if (readArguments(argc, argv) != 0){
+ input_error();
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ pThreadData = new ThreadNdb[MAXTHREADS];
+
+ ndbout << endl << "FLEXTT - Starting normal mode" << endl;
+ ndbout << "Perform TimesTen benchmark" << endl;
+ ndbout << " " << tNoOfThreads << " number of concurrent threads " << endl;
+ ndbout << " " << tNoOfParallelTrans;
+ ndbout << " number of parallel transaction per thread " << endl;
+ ndbout << " " << tNoOfTransactions << " transaction(s) per round " << endl;
+ ndbout << " " << tNoOfLoops << " iterations " << endl;
+ ndbout << " " << "Update Frequency is " << tUpdateFreq << "%" << endl;
+ ndbout << " " << "Load Factor is " << tLoadFactor << "%" << endl;
+ if (tLocal == true) {
+ ndbout << " " << "We only use Local Part = ";
+ ndbout << tLocalPart << endl;
+ }//if
+ if (tempTable == true) {
+ ndbout << " Tables are without logging " << endl;
+ } else {
+ ndbout << " Tables are with logging " << endl;
+ }//if
+ if (startTransGuess == true) {
+ ndbout << " Transactions are executed with hint provided" << endl;
+ } else {
+ ndbout << " Transactions are executed with round robin scheme" << endl;
+ }//if
+ if (tSendForce == 0) {
+ ndbout << " No force send is used, adaptive algorithm used" << endl;
+ } else if (tSendForce == 1) {
+ ndbout << " Force send used" << endl;
+ } else {
+ ndbout << " No force send is used, adaptive algorithm disabled" << endl;
+ }//if
+
+ ndbout << endl;
+
+ /* print Setting */
+ flexTTErrorData->printSettings(ndbout);
+
+ NdbThread_SetConcurrencyLevel(2 + tNoOfThreads);
+
+ setAttrNames();
+ setTableNames();
+
+ Ndb * pNdb = new Ndb("TEST_DB");
+ pNdb->init();
+ tNodeId = pNdb->getNodeId();
+
+ ndbout << " NdbAPI node with id = " << pNdb->getNodeId() << endl;
+ ndbout << endl;
+
+ ndbout << "Waiting for ndb to become ready..." <<endl;
+ if (pNdb->waitUntilReady(2000) != 0){
+ ndbout << "NDB is not ready" << endl;
+ ndbout << "Benchmark failed!" << endl;
+ returnValue = NDBT_FAILED;
+ }
+
+ if(returnValue == NDBT_OK){
+ if (createTables(pNdb) != 0){
+ returnValue = NDBT_FAILED;
+ }
+ }
+
+ if(returnValue == NDBT_OK){
+ /****************************************************************
+ * Create NDB objects. *
+ ****************************************************************/
+ resetThreads();
+ for (int i = 0; i < tNoOfThreads ; i++) {
+ pThreadData[i].threadNo = i;
+ threadLife[i] = NdbThread_Create(threadLoop,
+ (void**)&pThreadData[i],
+ 32768,
+ "flexAsynchThread",
+ NDB_THREAD_PRIO_LOW);
+ }//for
+ ndbout << endl << "All NDB objects and table created" << endl << endl;
+ int noOfTransacts = tNoOfParallelTrans * tNoOfTransactions *
+ tNoOfThreads * tNoOfLoops;
+ /****************************************************************
+ * Execute program. *
+ ****************************************************************/
+ /****************************************************************
+ * Perform inserts. *
+ ****************************************************************/
+
+ if (tInsert == true) {
+ tInsert = false;
+ tReadUpdate = false;
+ START_TIMER;
+ execute(stInsert);
+ STOP_TIMER;
+ PRINT_TIMER("insert", noOfTransacts, 1);
+ }//if
+ /****************************************************************
+ * Perform read + updates. *
+ ****************************************************************/
+
+ if (tReadUpdate == true) {
+ START_TIMER;
+ execute(stRead);
+ STOP_TIMER;
+ PRINT_TIMER("update + read", noOfTransacts, 1);
+ }//if
+ /****************************************************************
+ * Perform delete. *
+ ****************************************************************/
+
+ if (tDelete == true) {
+ tDelete = false;
+ START_TIMER;
+ execute(stDelete);
+ STOP_TIMER;
+ PRINT_TIMER("delete", noOfTransacts, 1);
+ }//if
+ ndbout << "--------------------------------------------------" << endl;
+
+ execute(stStop);
+ void * tmp;
+ for(int i = 0; i<tNoOfThreads; i++){
+ NdbThread_WaitFor(threadLife[i], &tmp);
+ NdbThread_Destroy(&threadLife[i]);
+ }
+ }
+ delete [] pThreadData;
+ delete pNdb;
+
+ //printing errorCounters
+ flexTTErrorData->printErrorCounters(ndbout);
+
+ return NDBT_ProgramExit(returnValue);
+}//main()
+
+
+static void execute(StartType aType)
+{
+ resetThreads();
+ tellThreads(aType);
+ waitForThreads();
+}//execute()
+
+static void*
+threadLoop(void* ThreadData)
+{
+ Ndb* localNdb;
+ ThreadNdb* tabThread = (ThreadNdb*)ThreadData;
+ int loc_threadNo = tabThread->threadNo;
+
+ void * mem = malloc(sizeof(TransNdb)*tNoOfParallelTrans);
+ TransNdb* pTransData = (TransNdb*)mem;
+
+ localNdb = new Ndb("TEST_DB");
+ localNdb->init(1024);
+ localNdb->waitUntilReady();
+
+ if (tLocal == false) {
+ tabThread->threadIncrement = 1;
+ } else {
+ tabThread->threadIncrement = MAX_SEEK;
+ }//if
+ tabThread->threadBase = (loc_threadNo << 16) + tNodeId;
+ tabThread->threadNdb = localNdb;
+ tabThread->threadStop = tNoOfParallelTrans * tNoOfTransactions;
+ tabThread->threadStop *= tabThread->threadIncrement;
+ tabThread->threadLoopStop = tNoOfLoops;
+ Uint32 i, j;
+ for (i = 0; i < tNoOfParallelTrans; i++) {
+ pTransData[i].transNdb = localNdb;
+ pTransData[i].transThread = tabThread;
+ pTransData[i].transOperation = NULL;
+ pTransData[i].transStartType = stIdle;
+ pTransData[i].vpn_number = tabThread->threadBase;
+ pTransData[i].vpn_identity = 0;
+ pTransData[i].transErrorCount = 0;
+ for (j = 0; j < 128; j++) {
+ pTransData[i].transRecord[j] = 0x30;
+ }//for
+ }//for
+
+ for (;;){
+ while (ThreadStart[loc_threadNo] == stIdle) {
+ NdbSleep_MilliSleep(10);
+ }//while
+
+ // Check if signal to exit is received
+ if (ThreadStart[loc_threadNo] == stStop) {
+ break;
+ }//if
+
+ tabThread->threadStartType = ThreadStart[loc_threadNo];
+ tabThread->threadLoopCounter = 0;
+ tabThread->threadCompleted = false;
+ tabThread->threadNoCompleted = 0;
+ tabThread->threadNextStart = 0;
+
+ ThreadStart[loc_threadNo] = stIdle;
+ if(!executeThread(tabThread, pTransData)){
+ break;
+ }
+ ThreadReady[loc_threadNo] = 1;
+ }//for
+
+ free(mem);
+ delete localNdb;
+ ThreadReady[loc_threadNo] = 1;
+
+ NdbThread_Exit(0);
+ return NULL; // Just to keep compiler happy
+}//threadLoop()
+
+static
+bool
+executeThread(ThreadNdb* tabThread, TransNdb* atransDataArrayPtr) {
+ Uint32 i;
+ for (i = 0; i < tNoOfParallelTrans; i++) {
+ TransNdb* transNdbPtr = &atransDataArrayPtr[i];
+ transNdbPtr->vpn_identity = i * tabThread->threadIncrement;
+ transNdbPtr->transStartType = tabThread->threadStartType;
+ if (executeTransaction(transNdbPtr) == false) {
+ return false;
+ }//if
+ }//for
+ tabThread->threadNextStart = tNoOfParallelTrans * tabThread->threadIncrement;
+ do {
+ tabThread->threadNdb->sendPollNdb(3000, tMinEvents, tSendForce);
+ } while (tabThread->threadCompleted == false);
+ return true;
+}//executeThread()
+
+static
+bool executeTransaction(TransNdb* transNdbRef)
+{
+ NdbConnection* MyTrans;
+ ThreadNdb* tabThread = transNdbRef->transThread;
+ Ndb* aNdbObject = transNdbRef->transNdb;
+ Uint32 threadBase = tabThread->threadBase;
+ Uint32 startKey = transNdbRef->vpn_identity;
+ if (tLocal == true) {
+ startKey = getKey(startKey, threadBase);
+ }//if
+ if (startTransGuess == true) {
+ Uint32 tKey[2];
+ tKey[0] = startKey;
+ tKey[1] = threadBase;
+ MyTrans = aNdbObject->startTransaction((Uint32)0, //Priority
+ (const char*)&tKey[0], //Main PKey
+ (Uint32)8); //Key Length
+ } else {
+ MyTrans = aNdbObject->startTransaction();
+ }//if
+ if (MyTrans == NULL) {
+ error_handler(aNdbObject->getNdbError());
+ ndbout << endl << "Unable to recover! Quiting now" << endl ;
+ return false;
+ }//if
+ //-------------------------------------------------------
+ // Define the operation, but do not execute it yet.
+ //-------------------------------------------------------
+ if (!defineOperation(MyTrans, transNdbRef, startKey, threadBase))
+ return false;
+
+ return true;
+}//executeTransaction()
+
+
+static
+Uint32
+getKey(Uint32 aBase, Uint32 aThreadBase) {
+ Uint32 Tfound = aBase;
+ Uint32 hash;
+ Uint64 Tkey64;
+ Uint32* tKey32 = (Uint32*)&Tkey64;
+ tKey32[0] = aThreadBase;
+ for (int i = aBase; i < (aBase + MAX_SEEK); i++) {
+ tKey32[1] = (Uint32)i;
+ hash = md5_hash((Uint64*)&Tkey64, (Uint32)2);
+ hash = (hash >> 6) & (MAX_PARTS - 1);
+ if (hash == tLocalPart) {
+ Tfound = i;
+ break;
+ }//if
+ }//for
+ return Tfound;
+}//getKey()
+
+static void
+executeCallback(int result, NdbConnection* NdbObject, void* aObject)
+{
+ TransNdb* transNdbRef = (TransNdb*)aObject;
+ ThreadNdb* tabThread = transNdbRef->transThread;
+ Ndb* tNdb = transNdbRef->transNdb;
+ Uint32 vpn_id = transNdbRef->vpn_identity;
+ Uint32 vpn_nb = tabThread->threadBase;
+
+ if (result == -1) {
+// Add complete error handling here
+ int retCode = flexTTErrorData->handleErrorCommon(NdbObject->getNdbError());
+ if (retCode == 1) {
+ if (NdbObject->getNdbError().code != 626 &&
+ NdbObject->getNdbError().code != 630) {
+ ndbout_c("execute: %s", NdbObject->getNdbError().message);
+ ndbout_c("Error code = %d", NdbObject->getNdbError().code);
+ }
+ } else if (retCode == 2) {
+ ndbout << "4115 should not happen in flexTT" << endl;
+ } else if (retCode == 3) {
+ /* What can we do here? */
+ ndbout_c("execute: %s", NdbObject->getNdbError().message);
+ }//if(retCode == 3)
+ transNdbRef->transErrorCount++;
+ const NdbError & err = NdbObject->getNdbError();
+ switch (err.classification) {
+ case NdbError::NoDataFound:
+ case NdbError::ConstraintViolation:
+ ndbout << "Error with vpn_id = " << vpn_id << " and vpn_nb = ";
+ ndbout << vpn_nb << endl;
+ ndbout << err << endl;
+ goto checkCompleted;
+ case NdbError::OverloadError:
+ NdbSleep_MilliSleep(10);
+ case NdbError::NodeRecoveryError:
+ case NdbError::UnknownResultError:
+ case NdbError::TimeoutExpired:
+ break;
+ default:
+ goto checkCompleted;
+ }//if
+ if ((transNdbRef->transErrorCount > 10) ||
+ (tabThread->threadNoCompleted > 0)) {
+ goto checkCompleted;
+ }//if
+ } else {
+ if (tabThread->threadNoCompleted == 0) {
+ transNdbRef->transErrorCount = 0;
+ transNdbRef->vpn_identity = tabThread->threadNextStart;
+ if (tabThread->threadNextStart == tabThread->threadStop) {
+ tabThread->threadLoopCounter++;
+ transNdbRef->vpn_identity = 0;
+ tabThread->threadNextStart = 0;
+ if (tabThread->threadLoopCounter == tNoOfLoops) {
+ goto checkCompleted;
+ }//if
+ }//if
+ tabThread->threadNextStart += tabThread->threadIncrement;
+ } else {
+ goto checkCompleted;
+ }//if
+ }//if
+ tNdb->closeTransaction(NdbObject);
+ executeTransaction(transNdbRef);
+ return;
+
+checkCompleted:
+ tNdb->closeTransaction(NdbObject);
+ tabThread->threadNoCompleted++;
+ if (tabThread->threadNoCompleted == tNoOfParallelTrans) {
+ tabThread->threadCompleted = true;
+ }//if
+ return;
+}//executeCallback()
+
+static
+StartType
+random_choice()
+{
+//----------------------------------------------------
+// Generate a random key between 0 and tNoOfRecords - 1
+//----------------------------------------------------
+ UintR random_number = lrand48() % 100;
+ if (random_number < tUpdateFreq)
+ return stUpdate;
+ else
+ return stRead;
+}//random_choice()
+
+static bool
+defineOperation(NdbConnection* localNdbConnection, TransNdb* transNdbRef,
+ unsigned int vpn_id, unsigned int vpn_nb)
+{
+ NdbOperation* localNdbOperation;
+ StartType TType = transNdbRef->transStartType;
+
+ //-------------------------------------------------------
+ // Set-up the attribute values for this operation.
+ //-------------------------------------------------------
+ localNdbOperation = localNdbConnection->getNdbOperation(tableName[0]);
+ if (localNdbOperation == NULL) {
+ error_handler(localNdbConnection->getNdbError());
+ return false;
+ }//if
+ switch (TType) {
+ case stInsert: // Insert case
+ if (theWriteFlag == 1 && theDirtyFlag == 1) {
+ localNdbOperation->dirtyWrite();
+ } else if (theWriteFlag == 1) {
+ localNdbOperation->writeTuple();
+ } else {
+ localNdbOperation->insertTuple();
+ }//if
+ break;
+ case stRead: // Read Case
+ TType = random_choice();
+ if (TType == stRead) {
+ if (theSimpleFlag == 1) {
+ localNdbOperation->simpleRead();
+ } else if (theDirtyFlag == 1) {
+ localNdbOperation->dirtyRead();
+ } else {
+ localNdbOperation->readTuple();
+ }//if
+ } else {
+ if (theWriteFlag == 1 && theDirtyFlag == 1) {
+ localNdbOperation->dirtyWrite();
+ } else if (theWriteFlag == 1) {
+ localNdbOperation->writeTuple();
+ } else if (theDirtyFlag == 1) {
+ localNdbOperation->dirtyUpdate();
+ } else {
+ localNdbOperation->updateTuple();
+ }//if
+ }//if
+ break;
+ case stDelete: // Delete Case
+ localNdbOperation->deleteTuple();
+ break;
+ default:
+ error_handler(localNdbOperation->getNdbError());
+ }//switch
+ localNdbOperation->equal((Uint32)0,vpn_id);
+ localNdbOperation->equal((Uint32)1,vpn_nb);
+ char* attrValue = &transNdbRef->transRecord[0];
+ switch (TType) {
+ case stInsert: // Insert case
+ localNdbOperation->setValue((Uint32)2, attrValue);
+ localNdbOperation->setValue((Uint32)3, attrValue);
+ localNdbOperation->setValue((Uint32)4, attrValue);
+ break;
+ case stUpdate: // Update Case
+ localNdbOperation->setValue((Uint32)3, attrValue);
+ break;
+ case stRead: // Read Case
+ localNdbOperation->getValue((Uint32)2, attrValue);
+ localNdbOperation->getValue((Uint32)3, attrValue);
+ localNdbOperation->getValue((Uint32)4, attrValue);
+ break;
+ case stDelete: // Delete Case
+ break;
+ default:
+ error_handler(localNdbOperation->getNdbError());
+ }//switch
+ localNdbConnection->executeAsynchPrepare(Commit, &executeCallback,
+ (void*)transNdbRef);
+ return true;
+}//defineOperation()
+
+
+static void setAttrNames()
+{
+ snprintf(attrName[0], MAXSTRLEN, "VPN_ID");
+ snprintf(attrName[1], MAXSTRLEN, "VPN_NB");
+ snprintf(attrName[2], MAXSTRLEN, "DIRECTORY_NB");
+ snprintf(attrName[3], MAXSTRLEN, "LAST_CALL_PARTY");
+ snprintf(attrName[4], MAXSTRLEN, "DESCR");
+}
+
+
+static void setTableNames()
+{
+ snprintf(tableName[0], MAXSTRLEN, "VPN_USERS");
+}
+
+static
+int
+createTables(Ndb* pMyNdb){
+
+ NdbSchemaCon *MySchemaTransaction;
+ NdbSchemaOp *MySchemaOp;
+ int check;
+
+ if (theTableCreateFlag == 0) {
+ ndbout << "Creating Table: vpn_users " << "..." << endl;
+ MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pMyNdb);
+
+ if(MySchemaTransaction == NULL &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if(MySchemaOp == NULL &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ check = MySchemaOp->createTable( tableName[0]
+ ,8 // Table Size
+ ,TupleKey // Key Type
+ ,40 // Nr of Pages
+ ,All
+ ,6
+ ,(tLoadFactor - 5)
+ ,tLoadFactor
+ ,1
+ ,!tempTable
+ );
+
+ if (check == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ check = MySchemaOp->createAttribute( (char*)attrName[0],
+ TupleKey,
+ 32,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+
+ if (check == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+ check = MySchemaOp->createAttribute( (char*)attrName[1],
+ TupleKey,
+ 32,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+
+ if (check == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+ check = MySchemaOp->createAttribute( (char*)attrName[2],
+ NoKey,
+ 8,
+ 10,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if (check == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ check = MySchemaOp->createAttribute( (char*)attrName[3],
+ NoKey,
+ 8,
+ 10,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if (check == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ check = MySchemaOp->createAttribute( (char*)attrName[4],
+ NoKey,
+ 8,
+ 100,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if (check == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ if (MySchemaTransaction->execute() == -1 &&
+ (!error_handler(MySchemaTransaction->getNdbError())))
+ return -1;
+
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ }//if
+
+ return 0;
+}
+
+bool error_handler(const NdbError& err){
+ ndbout << err << endl ;
+ switch(err.classification){
+ case NdbError::NodeRecoveryError:
+ case NdbError::SchemaError:
+ case NdbError::TimeoutExpired:
+ ndbout << endl << "Attempting to recover and continue now..." << endl ;
+ return true ; // return true to retry
+ }
+ return false;
+}
+#if 0
+bool error_handler(const char* error_string, int error_int) {
+ ndbout << error_string << endl ;
+ if ((4008 == error_int) ||
+ (677 == error_int) ||
+ (891 == error_int) ||
+ (1221 == error_int) ||
+ (721 == error_int) ||
+ (266 == error_int)) {
+ ndbout << endl << "Attempting to recover and continue now..." << endl ;
+ return true ; // return true to retry
+ }
+ return false ; // return false to abort
+}
+#endif
+
+static
+int
+readArguments(int argc, const char** argv){
+
+ int i = 1;
+ while (argc > 1){
+ if (strcmp(argv[i], "-t") == 0){
+ tNoOfThreads = atoi(argv[i+1]);
+ if ((tNoOfThreads < 1) || (tNoOfThreads > MAXTHREADS)){
+ ndbout_c("Invalid no of threads");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-p") == 0){
+ tNoOfParallelTrans = atoi(argv[i+1]);
+ if ((tNoOfParallelTrans < 1) || (tNoOfParallelTrans > MAXPAR)){
+ ndbout_c("Invalid no of parallell transactions");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-o") == 0) {
+ tNoOfTransactions = atoi(argv[i+1]);
+ if (tNoOfTransactions < 1){
+ ndbout_c("Invalid no of transactions");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-l") == 0){
+ tNoOfLoops = atoi(argv[i+1]);
+ if (tNoOfLoops < 1) {
+ ndbout_c("Invalid no of loops");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-e") == 0){
+ tMinEvents = atoi(argv[i+1]);
+ if ((tMinEvents < 1) || (tMinEvents > tNoOfParallelTrans)) {
+ ndbout_c("Invalid no of loops");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-local") == 0){
+ tLocalPart = atoi(argv[i+1]);
+ tLocal = true;
+ startTransGuess = true;
+ if ((tLocalPart < 0) || (tLocalPart > MAX_PARTS)){
+ ndbout_c("Invalid local part");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-ufreq") == 0){
+ tUpdateFreq = atoi(argv[i+1]);
+ if ((tUpdateFreq < 0) || (tUpdateFreq > 100)){
+ ndbout_c("Invalid Update Frequency");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-load_factor") == 0){
+ tLoadFactor = atoi(argv[i+1]);
+ if ((tLoadFactor < 40) || (tLoadFactor >= 100)){
+ ndbout_c("Invalid LoadFactor");
+ return -1;
+ }
+ } else if (strcmp(argv[i], "-d") == 0){
+ tDelete = true;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-i") == 0){
+ tInsert = true;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-simple") == 0){
+ theSimpleFlag = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-adaptive") == 0){
+ tSendForce = 0;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-force") == 0){
+ tSendForce = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-non_adaptive") == 0){
+ tSendForce = 2;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-write") == 0){
+ theWriteFlag = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-dirty") == 0){
+ theDirtyFlag = 1;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-table_create") == 0){
+ theTableCreateFlag = 0;
+ tInsert = true;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-temp") == 0){
+ tempTable = true;
+ argc++;
+ i--;
+ } else if (strcmp(argv[i], "-no_hint") == 0){
+ startTransGuess = false;
+ argc++;
+ i--;
+ } else {
+ return -1;
+ }
+
+ argc -= 2;
+ i = i + 2;
+ }//while
+ if (tLocal == true) {
+ if (startTransGuess == false) {
+ ndbout_c("Not valid to use no_hint with local");
+ }//if
+ }//if
+ return 0;
+}
+
+static
+void
+input_error(){
+
+ ndbout_c("FLEXTT");
+ ndbout_c(" Perform benchmark of insert, update and delete transactions");
+ ndbout_c("");
+ ndbout_c("Arguments:");
+ ndbout_c(" -t Number of threads to start, default 1");
+ ndbout_c(" -p Number of parallel transactions per thread, default 32");
+ ndbout_c(" -o Number of transactions per loop, default 500");
+ ndbout_c(" -ufreq Number Update Frequency in percent (0 -> 100), rest is read");
+ ndbout_c(" -load_factor Number Fill level in index in percent (40 -> 99)");
+ ndbout_c(" -l Number of loops to run, default 1, 0=infinite");
+ ndbout_c(" -i Start by inserting all records");
+ ndbout_c(" -d End by deleting all records (only one loop)");
+ ndbout_c(" -simple Use simple read to read from database");
+ ndbout_c(" -dirty Use dirty read to read from database");
+ ndbout_c(" -write Use writeTuple in insert and update");
+ ndbout_c(" -n Use standard table names");
+ ndbout_c(" -table_create Create tables in db");
+ ndbout_c(" -temp Create table(s) without logging");
+ ndbout_c(" -no_hint Don't give hint on where to execute transaction coordinator");
+ ndbout_c(" -adaptive Use adaptive send algorithm (default)");
+ ndbout_c(" -force Force send when communicating");
+ ndbout_c(" -non_adaptive Send at a 10 millisecond interval");
+ ndbout_c(" -local Number of part, only use keys in one part out of 16");
+}
diff --git a/ndb/test/ndbapi/flexTT/flexTT.cpp b/ndb/test/ndbapi/flexTT/flexTT.cpp
deleted file mode 100644
index c45cbd95762..00000000000
--- a/ndb/test/ndbapi/flexTT/flexTT.cpp
+++ /dev/null
@@ -1,927 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include <ndb_global.h>
-
-#include <NdbApi.hpp>
-#include <NdbMain.h>
-#include <md5_hash.hpp>
-
-#include <NdbThread.h>
-#include <NdbSleep.h>
-#include <NdbTick.h>
-#include <NdbOut.hpp>
-#include <NdbTimer.hpp>
-
-#include <NdbTest.hpp>
-#include <NDBT_Error.hpp>
-
-#define MAX_PARTS 4
-#define MAX_SEEK 16
-#define MAXSTRLEN 16
-#define MAXATTR 64
-#define MAXTABLES 64
-#define MAXTHREADS 128
-#define MAXPAR 1024
-#define MAXATTRSIZE 1000
-#define PKSIZE 1
-
-
-#ifdef NDB_WIN32
-inline long lrand48(void) { return rand(); };
-#endif
-
-
-enum StartType {
- stIdle,
- stInsert,
- stRead,
- stUpdate,
- stDelete,
- stStop
-} ;
-
-struct ThreadNdb
-{
- int threadNo;
- Ndb* threadNdb;
- Uint32 threadBase;
- Uint32 threadLoopCounter;
- Uint32 threadNextStart;
- Uint32 threadStop;
- Uint32 threadLoopStop;
- Uint32 threadIncrement;
- Uint32 threadNoCompleted;
- bool threadCompleted;
- StartType threadStartType;
-};
-
-struct TransNdb
-{
- char transRecord[128];
- Ndb* transNdb;
- StartType transStartType;
- Uint32 vpn_number;
- Uint32 vpn_identity;
- Uint32 transErrorCount;
- NdbOperation* transOperation;
- ThreadNdb* transThread;
-};
-
-extern "C" { static void* threadLoop(void*); }
-static void setAttrNames(void);
-static void setTableNames(void);
-static int readArguments(int argc, const char** argv);
-static int createTables(Ndb*);
-static bool defineOperation(NdbConnection* aTransObject, TransNdb*,
- Uint32 vpn_nb, Uint32 vpn_id);
-static bool executeTransaction(TransNdb* transNdbRef);
-static StartType random_choice();
-static void execute(StartType aType);
-static bool executeThread(ThreadNdb*, TransNdb*);
-static void executeCallback(int result, NdbConnection* NdbObject,
- void* aObject);
-static bool error_handler(const NdbError & err) ;
-static Uint32 getKey(Uint32, Uint32) ;
-static void input_error();
-
-ErrorData * flexTTErrorData;
-
-static NdbThread* threadLife[MAXTHREADS];
-static int tNodeId;
-static int ThreadReady[MAXTHREADS];
-static StartType ThreadStart[MAXTHREADS];
-static char tableName[1][MAXSTRLEN+1];
-static char attrName[5][MAXSTRLEN+1];
-
-// Program Parameters
-static bool tInsert = false;
-static bool tDelete = false;
-static bool tReadUpdate = true;
-static int tUpdateFreq = 20;
-static bool tLocal = false;
-static int tLocalPart = 0;
-static int tMinEvents = 0;
-static int tSendForce = 0;
-static int tNoOfLoops = 1;
-static Uint32 tNoOfThreads = 1;
-static Uint32 tNoOfParallelTrans = 32;
-static Uint32 tNoOfTransactions = 500;
-static Uint32 tLoadFactor = 80;
-static bool tempTable = false;
-static bool startTransGuess = true;
-
-//Program Flags
-static int theSimpleFlag = 0;
-static int theDirtyFlag = 0;
-static int theWriteFlag = 0;
-static int theTableCreateFlag = 1;
-
-#define START_REAL_TIME
-#define STOP_REAL_TIME
-#define START_TIMER { NdbTimer timer; timer.doStart();
-#define STOP_TIMER timer.doStop();
-#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
-
-static void
-resetThreads(){
-
- for (int i = 0; i < tNoOfThreads ; i++) {
- ThreadReady[i] = 0;
- ThreadStart[i] = stIdle;
- }//for
-}
-
-static void
-waitForThreads(void)
-{
- int cont = 0;
- do {
- cont = 0;
- NdbSleep_MilliSleep(20);
- for (int i = 0; i < tNoOfThreads ; i++) {
- if (ThreadReady[i] == 0) {
- cont = 1;
- }//if
- }//for
- } while (cont == 1);
-}
-
-static void
-tellThreads(StartType what)
-{
- for (int i = 0; i < tNoOfThreads ; i++)
- ThreadStart[i] = what;
-}
-
-NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535)
-{
- ThreadNdb* pThreadData;
- int returnValue = NDBT_OK;
-
- flexTTErrorData = new ErrorData;
- flexTTErrorData->resetErrorCounters();
-
- if (readArguments(argc, argv) != 0){
- input_error();
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- pThreadData = new ThreadNdb[MAXTHREADS];
-
- ndbout << endl << "FLEXTT - Starting normal mode" << endl;
- ndbout << "Perform TimesTen benchmark" << endl;
- ndbout << " " << tNoOfThreads << " number of concurrent threads " << endl;
- ndbout << " " << tNoOfParallelTrans;
- ndbout << " number of parallel transaction per thread " << endl;
- ndbout << " " << tNoOfTransactions << " transaction(s) per round " << endl;
- ndbout << " " << tNoOfLoops << " iterations " << endl;
- ndbout << " " << "Update Frequency is " << tUpdateFreq << "%" << endl;
- ndbout << " " << "Load Factor is " << tLoadFactor << "%" << endl;
- if (tLocal == true) {
- ndbout << " " << "We only use Local Part = ";
- ndbout << tLocalPart << endl;
- }//if
- if (tempTable == true) {
- ndbout << " Tables are without logging " << endl;
- } else {
- ndbout << " Tables are with logging " << endl;
- }//if
- if (startTransGuess == true) {
- ndbout << " Transactions are executed with hint provided" << endl;
- } else {
- ndbout << " Transactions are executed with round robin scheme" << endl;
- }//if
- if (tSendForce == 0) {
- ndbout << " No force send is used, adaptive algorithm used" << endl;
- } else if (tSendForce == 1) {
- ndbout << " Force send used" << endl;
- } else {
- ndbout << " No force send is used, adaptive algorithm disabled" << endl;
- }//if
-
- ndbout << endl;
-
- /* print Setting */
- flexTTErrorData->printSettings(ndbout);
-
- NdbThread_SetConcurrencyLevel(2 + tNoOfThreads);
-
- setAttrNames();
- setTableNames();
-
- Ndb * pNdb = new Ndb("TEST_DB");
- pNdb->init();
- tNodeId = pNdb->getNodeId();
-
- ndbout << " NdbAPI node with id = " << pNdb->getNodeId() << endl;
- ndbout << endl;
-
- ndbout << "Waiting for ndb to become ready..." <<endl;
- if (pNdb->waitUntilReady(2000) != 0){
- ndbout << "NDB is not ready" << endl;
- ndbout << "Benchmark failed!" << endl;
- returnValue = NDBT_FAILED;
- }
-
- if(returnValue == NDBT_OK){
- if (createTables(pNdb) != 0){
- returnValue = NDBT_FAILED;
- }
- }
-
- if(returnValue == NDBT_OK){
- /****************************************************************
- * Create NDB objects. *
- ****************************************************************/
- resetThreads();
- for (int i = 0; i < tNoOfThreads ; i++) {
- pThreadData[i].threadNo = i;
- threadLife[i] = NdbThread_Create(threadLoop,
- (void**)&pThreadData[i],
- 32768,
- "flexAsynchThread",
- NDB_THREAD_PRIO_LOW);
- }//for
- ndbout << endl << "All NDB objects and table created" << endl << endl;
- int noOfTransacts = tNoOfParallelTrans * tNoOfTransactions *
- tNoOfThreads * tNoOfLoops;
- /****************************************************************
- * Execute program. *
- ****************************************************************/
- /****************************************************************
- * Perform inserts. *
- ****************************************************************/
-
- if (tInsert == true) {
- tInsert = false;
- tReadUpdate = false;
- START_TIMER;
- execute(stInsert);
- STOP_TIMER;
- PRINT_TIMER("insert", noOfTransacts, 1);
- }//if
- /****************************************************************
- * Perform read + updates. *
- ****************************************************************/
-
- if (tReadUpdate == true) {
- START_TIMER;
- execute(stRead);
- STOP_TIMER;
- PRINT_TIMER("update + read", noOfTransacts, 1);
- }//if
- /****************************************************************
- * Perform delete. *
- ****************************************************************/
-
- if (tDelete == true) {
- tDelete = false;
- START_TIMER;
- execute(stDelete);
- STOP_TIMER;
- PRINT_TIMER("delete", noOfTransacts, 1);
- }//if
- ndbout << "--------------------------------------------------" << endl;
-
- execute(stStop);
- void * tmp;
- for(int i = 0; i<tNoOfThreads; i++){
- NdbThread_WaitFor(threadLife[i], &tmp);
- NdbThread_Destroy(&threadLife[i]);
- }
- }
- delete [] pThreadData;
- delete pNdb;
-
- //printing errorCounters
- flexTTErrorData->printErrorCounters(ndbout);
-
- return NDBT_ProgramExit(returnValue);
-}//main()
-
-
-static void execute(StartType aType)
-{
- resetThreads();
- tellThreads(aType);
- waitForThreads();
-}//execute()
-
-static void*
-threadLoop(void* ThreadData)
-{
- Ndb* localNdb;
- ThreadNdb* tabThread = (ThreadNdb*)ThreadData;
- int loc_threadNo = tabThread->threadNo;
-
- void * mem = malloc(sizeof(TransNdb)*tNoOfParallelTrans);
- TransNdb* pTransData = (TransNdb*)mem;
-
- localNdb = new Ndb("TEST_DB");
- localNdb->init(1024);
- localNdb->waitUntilReady();
-
- if (tLocal == false) {
- tabThread->threadIncrement = 1;
- } else {
- tabThread->threadIncrement = MAX_SEEK;
- }//if
- tabThread->threadBase = (loc_threadNo << 16) + tNodeId;
- tabThread->threadNdb = localNdb;
- tabThread->threadStop = tNoOfParallelTrans * tNoOfTransactions;
- tabThread->threadStop *= tabThread->threadIncrement;
- tabThread->threadLoopStop = tNoOfLoops;
- Uint32 i, j;
- for (i = 0; i < tNoOfParallelTrans; i++) {
- pTransData[i].transNdb = localNdb;
- pTransData[i].transThread = tabThread;
- pTransData[i].transOperation = NULL;
- pTransData[i].transStartType = stIdle;
- pTransData[i].vpn_number = tabThread->threadBase;
- pTransData[i].vpn_identity = 0;
- pTransData[i].transErrorCount = 0;
- for (j = 0; j < 128; j++) {
- pTransData[i].transRecord[j] = 0x30;
- }//for
- }//for
-
- for (;;){
- while (ThreadStart[loc_threadNo] == stIdle) {
- NdbSleep_MilliSleep(10);
- }//while
-
- // Check if signal to exit is received
- if (ThreadStart[loc_threadNo] == stStop) {
- break;
- }//if
-
- tabThread->threadStartType = ThreadStart[loc_threadNo];
- tabThread->threadLoopCounter = 0;
- tabThread->threadCompleted = false;
- tabThread->threadNoCompleted = 0;
- tabThread->threadNextStart = 0;
-
- ThreadStart[loc_threadNo] = stIdle;
- if(!executeThread(tabThread, pTransData)){
- break;
- }
- ThreadReady[loc_threadNo] = 1;
- }//for
-
- free(mem);
- delete localNdb;
- ThreadReady[loc_threadNo] = 1;
-
- NdbThread_Exit(0);
- return NULL; // Just to keep compiler happy
-}//threadLoop()
-
-static
-bool
-executeThread(ThreadNdb* tabThread, TransNdb* atransDataArrayPtr) {
- Uint32 i;
- for (i = 0; i < tNoOfParallelTrans; i++) {
- TransNdb* transNdbPtr = &atransDataArrayPtr[i];
- transNdbPtr->vpn_identity = i * tabThread->threadIncrement;
- transNdbPtr->transStartType = tabThread->threadStartType;
- if (executeTransaction(transNdbPtr) == false) {
- return false;
- }//if
- }//for
- tabThread->threadNextStart = tNoOfParallelTrans * tabThread->threadIncrement;
- do {
- tabThread->threadNdb->sendPollNdb(3000, tMinEvents, tSendForce);
- } while (tabThread->threadCompleted == false);
- return true;
-}//executeThread()
-
-static
-bool executeTransaction(TransNdb* transNdbRef)
-{
- NdbConnection* MyTrans;
- ThreadNdb* tabThread = transNdbRef->transThread;
- Ndb* aNdbObject = transNdbRef->transNdb;
- Uint32 threadBase = tabThread->threadBase;
- Uint32 startKey = transNdbRef->vpn_identity;
- if (tLocal == true) {
- startKey = getKey(startKey, threadBase);
- }//if
- if (startTransGuess == true) {
- Uint32 tKey[2];
- tKey[0] = startKey;
- tKey[1] = threadBase;
- MyTrans = aNdbObject->startTransaction((Uint32)0, //Priority
- (const char*)&tKey[0], //Main PKey
- (Uint32)8); //Key Length
- } else {
- MyTrans = aNdbObject->startTransaction();
- }//if
- if (MyTrans == NULL) {
- error_handler(aNdbObject->getNdbError());
- ndbout << endl << "Unable to recover! Quiting now" << endl ;
- return false;
- }//if
- //-------------------------------------------------------
- // Define the operation, but do not execute it yet.
- //-------------------------------------------------------
- if (!defineOperation(MyTrans, transNdbRef, startKey, threadBase))
- return false;
-
- return true;
-}//executeTransaction()
-
-
-static
-Uint32
-getKey(Uint32 aBase, Uint32 aThreadBase) {
- Uint32 Tfound = aBase;
- Uint32 hash;
- Uint64 Tkey64;
- Uint32* tKey32 = (Uint32*)&Tkey64;
- tKey32[0] = aThreadBase;
- for (int i = aBase; i < (aBase + MAX_SEEK); i++) {
- tKey32[1] = (Uint32)i;
- hash = md5_hash((Uint64*)&Tkey64, (Uint32)2);
- hash = (hash >> 6) & (MAX_PARTS - 1);
- if (hash == tLocalPart) {
- Tfound = i;
- break;
- }//if
- }//for
- return Tfound;
-}//getKey()
-
-static void
-executeCallback(int result, NdbConnection* NdbObject, void* aObject)
-{
- TransNdb* transNdbRef = (TransNdb*)aObject;
- ThreadNdb* tabThread = transNdbRef->transThread;
- Ndb* tNdb = transNdbRef->transNdb;
- Uint32 vpn_id = transNdbRef->vpn_identity;
- Uint32 vpn_nb = tabThread->threadBase;
-
- if (result == -1) {
-// Add complete error handling here
- int retCode = flexTTErrorData->handleErrorCommon(NdbObject->getNdbError());
- if (retCode == 1) {
- if (NdbObject->getNdbError().code != 626 &&
- NdbObject->getNdbError().code != 630) {
- ndbout_c("execute: %s", NdbObject->getNdbError().message);
- ndbout_c("Error code = %d", NdbObject->getNdbError().code);
- }
- } else if (retCode == 2) {
- ndbout << "4115 should not happen in flexTT" << endl;
- } else if (retCode == 3) {
- /* What can we do here? */
- ndbout_c("execute: %s", NdbObject->getNdbError().message);
- }//if(retCode == 3)
- transNdbRef->transErrorCount++;
- const NdbError & err = NdbObject->getNdbError();
- switch (err.classification) {
- case NdbError::NoDataFound:
- case NdbError::ConstraintViolation:
- ndbout << "Error with vpn_id = " << vpn_id << " and vpn_nb = ";
- ndbout << vpn_nb << endl;
- ndbout << err << endl;
- goto checkCompleted;
- case NdbError::OverloadError:
- NdbSleep_MilliSleep(10);
- case NdbError::NodeRecoveryError:
- case NdbError::UnknownResultError:
- case NdbError::TimeoutExpired:
- break;
- default:
- goto checkCompleted;
- }//if
- if ((transNdbRef->transErrorCount > 10) ||
- (tabThread->threadNoCompleted > 0)) {
- goto checkCompleted;
- }//if
- } else {
- if (tabThread->threadNoCompleted == 0) {
- transNdbRef->transErrorCount = 0;
- transNdbRef->vpn_identity = tabThread->threadNextStart;
- if (tabThread->threadNextStart == tabThread->threadStop) {
- tabThread->threadLoopCounter++;
- transNdbRef->vpn_identity = 0;
- tabThread->threadNextStart = 0;
- if (tabThread->threadLoopCounter == tNoOfLoops) {
- goto checkCompleted;
- }//if
- }//if
- tabThread->threadNextStart += tabThread->threadIncrement;
- } else {
- goto checkCompleted;
- }//if
- }//if
- tNdb->closeTransaction(NdbObject);
- executeTransaction(transNdbRef);
- return;
-
-checkCompleted:
- tNdb->closeTransaction(NdbObject);
- tabThread->threadNoCompleted++;
- if (tabThread->threadNoCompleted == tNoOfParallelTrans) {
- tabThread->threadCompleted = true;
- }//if
- return;
-}//executeCallback()
-
-static
-StartType
-random_choice()
-{
-//----------------------------------------------------
-// Generate a random key between 0 and tNoOfRecords - 1
-//----------------------------------------------------
- UintR random_number = lrand48() % 100;
- if (random_number < tUpdateFreq)
- return stUpdate;
- else
- return stRead;
-}//random_choice()
-
-static bool
-defineOperation(NdbConnection* localNdbConnection, TransNdb* transNdbRef,
- unsigned int vpn_id, unsigned int vpn_nb)
-{
- NdbOperation* localNdbOperation;
- StartType TType = transNdbRef->transStartType;
-
- //-------------------------------------------------------
- // Set-up the attribute values for this operation.
- //-------------------------------------------------------
- localNdbOperation = localNdbConnection->getNdbOperation(tableName[0]);
- if (localNdbOperation == NULL) {
- error_handler(localNdbConnection->getNdbError());
- return false;
- }//if
- switch (TType) {
- case stInsert: // Insert case
- if (theWriteFlag == 1 && theDirtyFlag == 1) {
- localNdbOperation->dirtyWrite();
- } else if (theWriteFlag == 1) {
- localNdbOperation->writeTuple();
- } else {
- localNdbOperation->insertTuple();
- }//if
- break;
- case stRead: // Read Case
- TType = random_choice();
- if (TType == stRead) {
- if (theSimpleFlag == 1) {
- localNdbOperation->simpleRead();
- } else if (theDirtyFlag == 1) {
- localNdbOperation->dirtyRead();
- } else {
- localNdbOperation->readTuple();
- }//if
- } else {
- if (theWriteFlag == 1 && theDirtyFlag == 1) {
- localNdbOperation->dirtyWrite();
- } else if (theWriteFlag == 1) {
- localNdbOperation->writeTuple();
- } else if (theDirtyFlag == 1) {
- localNdbOperation->dirtyUpdate();
- } else {
- localNdbOperation->updateTuple();
- }//if
- }//if
- break;
- case stDelete: // Delete Case
- localNdbOperation->deleteTuple();
- break;
- default:
- error_handler(localNdbOperation->getNdbError());
- }//switch
- localNdbOperation->equal((Uint32)0,vpn_id);
- localNdbOperation->equal((Uint32)1,vpn_nb);
- char* attrValue = &transNdbRef->transRecord[0];
- switch (TType) {
- case stInsert: // Insert case
- localNdbOperation->setValue((Uint32)2, attrValue);
- localNdbOperation->setValue((Uint32)3, attrValue);
- localNdbOperation->setValue((Uint32)4, attrValue);
- break;
- case stUpdate: // Update Case
- localNdbOperation->setValue((Uint32)3, attrValue);
- break;
- case stRead: // Read Case
- localNdbOperation->getValue((Uint32)2, attrValue);
- localNdbOperation->getValue((Uint32)3, attrValue);
- localNdbOperation->getValue((Uint32)4, attrValue);
- break;
- case stDelete: // Delete Case
- break;
- default:
- error_handler(localNdbOperation->getNdbError());
- }//switch
- localNdbConnection->executeAsynchPrepare(Commit, &executeCallback,
- (void*)transNdbRef);
- return true;
-}//defineOperation()
-
-
-static void setAttrNames()
-{
- snprintf(attrName[0], MAXSTRLEN, "VPN_ID");
- snprintf(attrName[1], MAXSTRLEN, "VPN_NB");
- snprintf(attrName[2], MAXSTRLEN, "DIRECTORY_NB");
- snprintf(attrName[3], MAXSTRLEN, "LAST_CALL_PARTY");
- snprintf(attrName[4], MAXSTRLEN, "DESCR");
-}
-
-
-static void setTableNames()
-{
- snprintf(tableName[0], MAXSTRLEN, "VPN_USERS");
-}
-
-static
-int
-createTables(Ndb* pMyNdb){
-
- NdbSchemaCon *MySchemaTransaction;
- NdbSchemaOp *MySchemaOp;
- int check;
-
- if (theTableCreateFlag == 0) {
- ndbout << "Creating Table: vpn_users " << "..." << endl;
- MySchemaTransaction = pMyNdb->startSchemaTransaction();
-
- if(MySchemaTransaction == NULL &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if(MySchemaOp == NULL &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- check = MySchemaOp->createTable( tableName[0]
- ,8 // Table Size
- ,TupleKey // Key Type
- ,40 // Nr of Pages
- ,All
- ,6
- ,(tLoadFactor - 5)
- ,tLoadFactor
- ,1
- ,!tempTable
- );
-
- if (check == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- check = MySchemaOp->createAttribute( (char*)attrName[0],
- TupleKey,
- 32,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
-
- if (check == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
- check = MySchemaOp->createAttribute( (char*)attrName[1],
- TupleKey,
- 32,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
-
- if (check == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
- check = MySchemaOp->createAttribute( (char*)attrName[2],
- NoKey,
- 8,
- 10,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if (check == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- check = MySchemaOp->createAttribute( (char*)attrName[3],
- NoKey,
- 8,
- 10,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if (check == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- check = MySchemaOp->createAttribute( (char*)attrName[4],
- NoKey,
- 8,
- 100,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if (check == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- if (MySchemaTransaction->execute() == -1 &&
- (!error_handler(MySchemaTransaction->getNdbError())))
- return -1;
-
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
- }//if
-
- return 0;
-}
-
-bool error_handler(const NdbError& err){
- ndbout << err << endl ;
- switch(err.classification){
- case NdbError::NodeRecoveryError:
- case NdbError::SchemaError:
- case NdbError::TimeoutExpired:
- ndbout << endl << "Attempting to recover and continue now..." << endl ;
- return true ; // return true to retry
- }
- return false;
-}
-#if 0
-bool error_handler(const char* error_string, int error_int) {
- ndbout << error_string << endl ;
- if ((4008 == error_int) ||
- (677 == error_int) ||
- (891 == error_int) ||
- (1221 == error_int) ||
- (721 == error_int) ||
- (266 == error_int)) {
- ndbout << endl << "Attempting to recover and continue now..." << endl ;
- return true ; // return true to retry
- }
- return false ; // return false to abort
-}
-#endif
-
-static
-int
-readArguments(int argc, const char** argv){
-
- int i = 1;
- while (argc > 1){
- if (strcmp(argv[i], "-t") == 0){
- tNoOfThreads = atoi(argv[i+1]);
- if ((tNoOfThreads < 1) || (tNoOfThreads > MAXTHREADS)){
- ndbout_c("Invalid no of threads");
- return -1;
- }
- } else if (strcmp(argv[i], "-p") == 0){
- tNoOfParallelTrans = atoi(argv[i+1]);
- if ((tNoOfParallelTrans < 1) || (tNoOfParallelTrans > MAXPAR)){
- ndbout_c("Invalid no of parallell transactions");
- return -1;
- }
- } else if (strcmp(argv[i], "-o") == 0) {
- tNoOfTransactions = atoi(argv[i+1]);
- if (tNoOfTransactions < 1){
- ndbout_c("Invalid no of transactions");
- return -1;
- }
- } else if (strcmp(argv[i], "-l") == 0){
- tNoOfLoops = atoi(argv[i+1]);
- if (tNoOfLoops < 1) {
- ndbout_c("Invalid no of loops");
- return -1;
- }
- } else if (strcmp(argv[i], "-e") == 0){
- tMinEvents = atoi(argv[i+1]);
- if ((tMinEvents < 1) || (tMinEvents > tNoOfParallelTrans)) {
- ndbout_c("Invalid no of loops");
- return -1;
- }
- } else if (strcmp(argv[i], "-local") == 0){
- tLocalPart = atoi(argv[i+1]);
- tLocal = true;
- startTransGuess = true;
- if ((tLocalPart < 0) || (tLocalPart > MAX_PARTS)){
- ndbout_c("Invalid local part");
- return -1;
- }
- } else if (strcmp(argv[i], "-ufreq") == 0){
- tUpdateFreq = atoi(argv[i+1]);
- if ((tUpdateFreq < 0) || (tUpdateFreq > 100)){
- ndbout_c("Invalid Update Frequency");
- return -1;
- }
- } else if (strcmp(argv[i], "-load_factor") == 0){
- tLoadFactor = atoi(argv[i+1]);
- if ((tLoadFactor < 40) || (tLoadFactor >= 100)){
- ndbout_c("Invalid LoadFactor");
- return -1;
- }
- } else if (strcmp(argv[i], "-d") == 0){
- tDelete = true;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-i") == 0){
- tInsert = true;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-simple") == 0){
- theSimpleFlag = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-adaptive") == 0){
- tSendForce = 0;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-force") == 0){
- tSendForce = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-non_adaptive") == 0){
- tSendForce = 2;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-write") == 0){
- theWriteFlag = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-dirty") == 0){
- theDirtyFlag = 1;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-table_create") == 0){
- theTableCreateFlag = 0;
- tInsert = true;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-temp") == 0){
- tempTable = true;
- argc++;
- i--;
- } else if (strcmp(argv[i], "-no_hint") == 0){
- startTransGuess = false;
- argc++;
- i--;
- } else {
- return -1;
- }
-
- argc -= 2;
- i = i + 2;
- }//while
- if (tLocal == true) {
- if (startTransGuess == false) {
- ndbout_c("Not valid to use no_hint with local");
- }//if
- }//if
- return 0;
-}
-
-static
-void
-input_error(){
-
- ndbout_c("FLEXTT");
- ndbout_c(" Perform benchmark of insert, update and delete transactions");
- ndbout_c("");
- ndbout_c("Arguments:");
- ndbout_c(" -t Number of threads to start, default 1");
- ndbout_c(" -p Number of parallel transactions per thread, default 32");
- ndbout_c(" -o Number of transactions per loop, default 500");
- ndbout_c(" -ufreq Number Update Frequency in percent (0 -> 100), rest is read");
- ndbout_c(" -load_factor Number Fill level in index in percent (40 -> 99)");
- ndbout_c(" -l Number of loops to run, default 1, 0=infinite");
- ndbout_c(" -i Start by inserting all records");
- ndbout_c(" -d End by deleting all records (only one loop)");
- ndbout_c(" -simple Use simple read to read from database");
- ndbout_c(" -dirty Use dirty read to read from database");
- ndbout_c(" -write Use writeTuple in insert and update");
- ndbout_c(" -n Use standard table names");
- ndbout_c(" -table_create Create tables in db");
- ndbout_c(" -temp Create table(s) without logging");
- ndbout_c(" -no_hint Don't give hint on where to execute transaction coordinator");
- ndbout_c(" -adaptive Use adaptive send algorithm (default)");
- ndbout_c(" -force Force send when communicating");
- ndbout_c(" -non_adaptive Send at a 10 millisecond interval");
- ndbout_c(" -local Number of part, only use keys in one part out of 16");
-}
diff --git a/ndb/test/ndbapi/flexTimedAsynch/flexTimedAsynch.cpp b/ndb/test/ndbapi/flexTimedAsynch.cpp
index 761be53fdd3..761be53fdd3 100644
--- a/ndb/test/ndbapi/flexTimedAsynch/flexTimedAsynch.cpp
+++ b/ndb/test/ndbapi/flexTimedAsynch.cpp
diff --git a/ndb/test/ndbapi/flex_bench_mysql/flex_bench_mysql.cpp b/ndb/test/ndbapi/flex_bench_mysql.cpp
index 7cc883ab3e6..7cc883ab3e6 100644
--- a/ndb/test/ndbapi/flex_bench_mysql/flex_bench_mysql.cpp
+++ b/ndb/test/ndbapi/flex_bench_mysql.cpp
diff --git a/ndb/test/ndbapi/indexTest/index.cpp b/ndb/test/ndbapi/index.cpp
index 508186de529..508186de529 100644
--- a/ndb/test/ndbapi/indexTest/index.cpp
+++ b/ndb/test/ndbapi/index.cpp
diff --git a/ndb/test/ndbapi/indexTest2/index2.cpp b/ndb/test/ndbapi/index2.cpp
index e49113d2f1b..e49113d2f1b 100644
--- a/ndb/test/ndbapi/indexTest2/index2.cpp
+++ b/ndb/test/ndbapi/index2.cpp
diff --git a/ndb/test/ndbapi/initronja.cpp b/ndb/test/ndbapi/initronja.cpp
new file mode 100644
index 00000000000..b3215104822
--- /dev/null
+++ b/ndb/test/ndbapi/initronja.cpp
@@ -0,0 +1,350 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/* ***************************************************
+ INITRONJA
+ Initialise benchmark for Ronja Database
+ * *************************************************** */
+
+#include "NdbApi.hpp"
+#include "NdbSchemaCon.hpp"
+#include <NdbOut.hpp>
+#include <NdbMain.h>
+#include <NdbTest.hpp>
+#include <string.h>
+
+#define MAXSTRLEN 16
+#define MAXATTR 64
+#define MAXTABLES 64
+#define MAXTHREADS 256
+#define MAXATTRSIZE 8000
+
+static unsigned int tNoOfRecords;
+static unsigned int tNoOfLoops;
+static unsigned int tNoOfTables;
+static int tAttributeSize;
+static int tNodeId;
+static unsigned int tValue;
+static unsigned int tNoOfOperations;
+static char tableName[MAXTABLES][MAXSTRLEN];
+static char attrName[MAXATTR][MAXSTRLEN];
+
+inline int InsertRecords(Ndb*, int) ;
+
+NDB_COMMAND(initronja, "initronja", "initronja", "initronja", 65535){
+
+ Ndb* pNdb = NULL ;
+ NdbSchemaCon *MySchemaTransaction = NULL ;
+ NdbSchemaOp *MySchemaOp = NULL ;
+
+
+ int check, status, i, j, cont ;
+ check = status = i = j = cont = 0 ;
+ tNoOfRecords = 500 ;
+ tNoOfLoops = tNoOfRecords / 10;
+
+ i = 1;
+ while (argc > 1){
+
+ if (strcmp(argv[i], "-r") == 0){
+ if( NULL == argv[i+1] ) goto error_input ;
+ tNoOfRecords = atoi(argv[i+1]);
+ tNoOfRecords = tNoOfRecords - (tNoOfRecords % 10);
+ tNoOfLoops = tNoOfRecords / 10;
+ if ((tNoOfRecords < 1) || (tNoOfRecords > 1000000000)) goto error_input;
+ }else{
+ goto error_input;
+ }
+
+ argc -= 2;
+ i = i + 2; //
+ }
+
+ pNdb = new Ndb( "TEST_DB" ) ;
+ ndbout << "Initialisation started. " << endl;
+ pNdb->init();
+ ndbout << "Initialisation completed. " << endl;
+
+ tNodeId = pNdb->getNodeId();
+ ndbout << endl << "Initial loading of Ronja Database" << endl;
+ ndbout << " NdbAPI node with id = " << tNodeId << endl;
+
+ if (pNdb->waitUntilReady(30) != 0) {
+ ndbout << "Benchmark failed - NDB is not ready" << endl;
+ delete pNdb ;
+ return NDBT_ProgramExit(NDBT_FAILED) ;
+ }//if
+
+ ndbout << endl << "Creating the table SHORT_REC" << "..." << endl;
+
+ MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if(!MySchemaTransaction) goto error_handler;
+ MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if(!MySchemaOp) goto error_handler;
+#if defined NDB_OSE || defined NDB_SOFTOSE
+ check = MySchemaOp->createTable( "SHORT_REC"
+ ,8 // Table Size
+ ,TupleKey // Key Type
+ ,40 // Nr of Pages
+ ,All
+ ,6
+ ,78
+ ,80
+ ,1
+ ,false);
+#else
+ check = MySchemaOp->createTable( "SHORT_REC"
+ ,8 // Table Size
+ ,TupleKey // Key Type
+ ,40 // Nr of Pages
+ );
+#endif
+ if (check == -1) goto error_handler;
+
+ ndbout << "Key attribute..." ;
+ check = MySchemaOp->createAttribute( (char*)"Key", TupleKey, 32, 1,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) goto error_handler;
+ ndbout << "\t\tOK" << endl ;
+
+ ndbout << "Flip attribute..." ;
+ check = MySchemaOp->createAttribute("Flip", NoKey, 32, 1,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) goto error_handler;
+ ndbout << "\t\tOK" << endl ;
+
+ ndbout << "Count attribute..." ;
+ check = MySchemaOp->createAttribute("Count", NoKey, 32, 1,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) goto error_handler;
+ ndbout << "\t\tOK" << endl ;
+
+ ndbout << "Placeholder attribute..." ;
+ check = MySchemaOp->createAttribute("Placeholder", NoKey, 8, 90,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) goto error_handler;
+ ndbout << "\tOK" << endl ;
+
+ if (MySchemaTransaction->execute() == -1) {
+ if(721 == MySchemaOp->getNdbError().code){
+ ndbout << "Table SHORT_REC already exists" << endl ;
+ }else{
+ ndbout << MySchemaTransaction->getNdbError() << endl;
+ }
+ }else{
+ ndbout << "SHORT_REC created " << endl;
+ }// if
+
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+
+ ndbout << endl << "Creating the table LONG_REC..." << endl;
+
+ MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if(!MySchemaTransaction) goto error_handler;
+
+ MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if(!MySchemaOp) goto error_handler;
+#if defined NDB_OSE || defined NDB_SOFTOSE
+ check = MySchemaOp->createTable( "LONG_REC"
+ ,8 // Table Size
+ ,TupleKey // Key Type
+ ,40 // Nr of Pages
+ ,All
+ ,6
+ ,78
+ ,80
+ ,1
+ ,false);
+#else
+ check = MySchemaOp->createTable( "LONG_REC"
+ ,8 // Table Size
+ ,TupleKey // Key Type
+ ,40 // Nr of Pages
+ );
+#endif
+
+ if (check == -1) goto error_handler;
+
+ ndbout << "Key attribute..." ;
+ check = MySchemaOp->createAttribute( (char*)"Key", TupleKey, 32, 1,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) goto error_handler;
+ ndbout << "\t\tOK" << endl ;
+
+ ndbout << "Flip attribute..." ;
+ check = MySchemaOp->createAttribute("Flip", NoKey, 32, 1,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) goto error_handler;
+ ndbout << "\t\tOK" << endl ;
+
+ ndbout << "Count attribute..." ;
+ check = MySchemaOp->createAttribute("Count", NoKey, 32, 1,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) goto error_handler;
+ ndbout << "\t\tOK" << endl ;
+
+ ndbout << "Placeholder attribute..." ;
+ check = MySchemaOp->createAttribute("Placeholder", NoKey, 8, 1014,
+ UnSigned, MMBased, NotNullAttribute );
+ if (check == -1) goto error_handler;
+ ndbout << "\tOK" << endl ;
+
+ if (MySchemaTransaction->execute() == -1) {
+ if(721 == MySchemaOp->getNdbError().code){
+ ndbout << "Table LONG_REC already exists" << endl ;
+ }else{
+ ndbout << MySchemaTransaction->getNdbError() << endl;
+ }
+ }else{
+ ndbout << "LONG_REC created" << endl;
+ }// if
+
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+
+
+ check = InsertRecords(pNdb, tNoOfRecords);
+
+ delete pNdb ;
+
+ if(-1 == check){
+ ndbout << endl << "Initial loading of Ronja Database failed" << endl;
+ return NDBT_ProgramExit(NDBT_FAILED) ;
+ }else{
+ ndbout << endl << "Initial loading of Ronja Database completed" << endl;
+ return NDBT_ProgramExit(NDBT_OK) ;
+ }
+
+
+
+
+
+error_handler:
+ ndbout << "SchemaTransaction returned error:" ;
+ ndbout << MySchemaTransaction->getNdbError() << endl;
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ delete pNdb ;
+ NDBT_ProgramExit(NDBT_FAILED) ;
+ exit(-1);
+
+error_input:
+ ndbout << endl << " Ivalid parameter(s)" << endl;
+ ndbout << " Usage: initronja [-r n] , where 'n' is the number of records to be inserted" << endl;
+ ndbout << " If omitted, 500 records will be created by default" << endl;
+ ndbout << " Note: use this number in combination with '-r' argument when running 'benchronja'" << endl << endl;
+ NDBT_ProgramExit(NDBT_WRONGARGS) ;
+ exit(1);
+}
+////////////////////////////////////////
+
+inline int InsertRecords(Ndb* pNdb, int nNoRecords){
+
+ NdbConnection *MyTransaction = NULL ;
+ NdbOperation* MyOperation[10];
+
+ int Tsuccess = 0 ;
+ int loop_count_ops = 2 * tNoOfLoops;
+ int loop_count_tables = 10;
+ int loop_count_attributes = 0 ;
+ int check = 0;
+ int count = 0 ;
+ int count_tables = 0;
+ int count_attributes = 0 ;
+ int i = 0 ;
+ int tType = 0 ;
+ unsigned int attrValue[1000];
+ unsigned int setAttrValue = 0;
+ unsigned int keyValue[3];
+
+ for (i = 0; i < 1000; i ++) attrValue[i] = 1;
+
+ for (count=0 ; count < loop_count_ops ; count++){
+ if ((((count / 100)* 100) == count) && (count != 0)){
+ ndbout << "1000 records inserted again, " << (count/100) << "000 records now inserted" << endl;
+ }
+
+ MyTransaction = pNdb->startTransaction();
+ if(!MyTransaction){
+ ndbout << "startTransaction: " << pNdb->getNdbError();
+ ndbout << " count = " << count << endl;
+ return -1 ;
+ }
+
+ for (count_tables = 0; count_tables < loop_count_tables; count_tables++) {
+ if (count < tNoOfLoops) {
+ keyValue[0] = count*10 + count_tables ;
+ MyOperation[count_tables] = MyTransaction->getNdbOperation("SHORT_REC") ;
+ }else{
+ keyValue[0] = (count - tNoOfLoops)*10 + count_tables;
+ MyOperation[count_tables] = MyTransaction->getNdbOperation("LONG_REC");
+ }//if
+
+ if (!MyOperation[count_tables]) goto error_handler1;
+
+ check = MyOperation[count_tables]->insertTuple();
+ if (check == -1) goto error_handler2;
+
+ check = MyOperation[count_tables]->equal("Key",(char*)&keyValue[0]);
+ if (check == -1) goto error_handler4;
+
+ check = MyOperation[count_tables]->setValue("Flip",(char*)&setAttrValue);
+ if (check == -1) goto error_handler5;
+
+ check = MyOperation[count_tables]->setValue("Count",(char*)&setAttrValue);
+ if (check == -1) goto error_handler5;
+
+ check = MyOperation[count_tables]->setValue("Placeholder",(char*)&attrValue[0]);
+ if (check == -1) goto error_handler5;
+ }//for
+
+ if (MyTransaction->execute( Commit ) == -1){
+ ndbout << MyTransaction->getNdbError()<< endl ;
+ ndbout << "count = " << count << endl;
+ }//if
+
+ pNdb->closeTransaction(MyTransaction) ;
+ }//for
+ return 0;
+
+error_handler1:
+ ndbout << "Error occured in getNdbOperation " << endl;
+ ndbout << MyTransaction->getNdbError() << endl;
+ pNdb->closeTransaction(MyTransaction);
+ return -1 ;
+
+error_handler2:
+ ndbout << "Error occured in defining operation " << endl;
+ ndbout << MyOperation[count_tables]->getNdbError() << endl;
+ pNdb->closeTransaction(MyTransaction);
+ return -1 ;
+
+error_handler3:
+ pNdb->closeTransaction(MyTransaction);
+ return -1 ;
+
+error_handler4:
+ ndbout << "Error occured in equal " << endl;
+ ndbout << MyOperation[count_tables]->getNdbError() << endl;
+ pNdb->closeTransaction(MyTransaction);
+ return -1 ;
+
+error_handler5:
+ ndbout << "Error occured in get/setValue " << endl;
+ ndbout << MyOperation[count_tables]->getNdbError() << endl;
+ pNdb->closeTransaction(MyTransaction);
+ return -1 ;
+
+}
diff --git a/ndb/test/ndbapi/interpreterInTup.cpp b/ndb/test/ndbapi/interpreterInTup.cpp
new file mode 100644
index 00000000000..47960cd5d12
--- /dev/null
+++ b/ndb/test/ndbapi/interpreterInTup.cpp
@@ -0,0 +1,1517 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ***************************************************
+ TEST OF INTERPRETER IN TUP
+ Verify that the interpreter in TUP is able to
+ handle and execute all the commands that the
+ NdbApi can isssue
+
+ Arguments:
+
+ operationType 1 openScanRead,
+ 2 openScanExclusive,
+ 3 interpretedUpdateTuple,
+ 4 interpretedDirtyUpdate,
+ 5 interpretedDeleteTuple
+ 6 deleteTuple
+ 7 insertTuple
+ 8 updateTuple
+ 9 writeTuple
+ 10 readTuple
+ 11 readTupleExclusive
+ 12 simpleRead
+ 13 dirtyRead
+ 14 dirtyUpdate
+ 15 dirtyWrite
+
+ tupTest 1 exitMethods
+ 2 incValue
+ 3 subValue
+ 4 readAttr
+ 5 writeAttr
+ 6 loadConst
+ 7 branch
+ 8 branchIfNull
+ 9 addReg
+ 10 subReg
+ 11 subroutineWithBranchLabel
+
+ scanTest Number of the test within each tupTest
+
+* *************************************************** */
+
+#include <NdbOut.hpp>
+#include <NdbThread.h>
+#include <NdbMutex.h>
+#include <NdbApi.hpp>
+#include <NdbSchemaCon.hpp>
+#include <NDBT.hpp>
+
+#define MAXATTR 3
+#define MAXTABLES 12
+#define MAXSTRLEN 8
+#define NUMBEROFRECORDS 1000
+
+typedef enum {
+ FAIL = 0,
+ NO_FAIL,
+ UNDEF
+} TTYPE;
+
+inline void setAttrNames() ;
+inline void setTableNames() ;
+void error_handler(const NdbError & err, TTYPE);
+void create_table(Ndb*);
+void write_rows(Ndb*);
+void update_rows(Ndb*, int, int);
+void delete_rows(Ndb*, int, int);
+void verify_deleted(Ndb*);
+void read_and_verify_rows(Ndb*, bool pre);
+void scan_rows(Ndb*, int, int, int);
+TTYPE t_exitMethods(int, NdbOperation*, int);
+TTYPE t_incValue(int, NdbOperation*);
+TTYPE t_subValue(int, NdbOperation*);
+TTYPE t_readAttr(int, NdbOperation*);
+TTYPE t_writeAttr(int, NdbOperation*);
+TTYPE t_loadConst(int, NdbOperation*, int);
+TTYPE t_branch(int, NdbOperation*);
+TTYPE t_branchIfNull(int, NdbOperation*);
+TTYPE t_addReg(int, NdbOperation*);
+TTYPE t_subReg(int, NdbOperation*);
+TTYPE t_subroutineWithBranchLabel(int, NdbOperation*);
+
+char tableName[MAXSTRLEN+1];
+char attrName[MAXATTR][MAXSTRLEN+1];
+int attrValue[NUMBEROFRECORDS] = {0};
+int pkValue[NUMBEROFRECORDS] = {0};
+const int tAttributeSize = 1 ;
+const int nRecords = 20 ;
+int bTestPassed = 0;
+
+
+
+int main(int argc, const char** argv) {
+
+ int operationType = 0;
+ int tupTest = 0;
+ int scanTest = 0;
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ pNdb->init();
+
+ if (argc != 4 || sscanf(argv[1],"%d", &operationType) != 1) {
+ operationType = 1 ;
+ }
+ if (argc != 4 || sscanf(argv[2],"%d", &tupTest) != 1) {
+ tupTest = 1 ;
+ }
+ if (argc != 4 || sscanf(argv[3],"%d", &scanTest) != 1) {
+ scanTest = 1 ;
+ }
+
+ ndbout << endl
+ << "Test the interpreter in TUP using SimpleTable with\n"
+ << nRecords << " records" << endl << endl ;
+
+ if (pNdb->waitUntilReady(30) != 0) {
+ ndbout << "NDB is not ready" << endl;
+ return -1;
+ }
+
+ // Init the pk and attr values.
+ for (int i = 0; i < NUMBEROFRECORDS; i ++)
+ pkValue[i] = attrValue[i] = i ;
+
+ setAttrNames() ;
+ setTableNames() ;
+
+ const void * p = NDBT_Table::discoverTableFromDb(pNdb, tableName);
+ if (p != 0){
+ create_table(pNdb);
+ }
+
+ write_rows(pNdb);
+
+ ndbout << endl << "Starting interpreter in TUP test." << endl << "Operation type: " ;
+
+ switch(operationType) {
+ case 1:
+ ndbout << "openScanRead" << endl;
+ scan_rows(pNdb, operationType, tupTest, scanTest);
+ break;
+ case 2:
+ ndbout << "openScanExclusive" << endl;
+ scan_rows(pNdb, operationType, tupTest, scanTest);
+ break;
+ case 3:
+ ndbout << "interpretedUpdateTuple" << endl;
+ update_rows(pNdb, tupTest, operationType);
+ break;
+ case 4:
+ ndbout << "interpretedDirtyUpdate" << endl;
+ update_rows(pNdb, tupTest, operationType);
+ break;
+ case 5:
+ ndbout << "interpretedDeleteTuple" << endl;
+ delete_rows(pNdb, tupTest, operationType);
+ break;
+ case 6:
+ ndbout << "deleteTuple" << endl;
+ break;
+ case 7:
+ ndbout << "insertTuple" << endl;
+ break;
+ case 8:
+ ndbout << "updateTuple" << endl;
+ break;
+ case 9:
+ ndbout << "writeTuple" << endl;
+ break;
+ case 10:
+ ndbout << "readTuple" << endl;
+ break;
+ case 11:
+ ndbout << "readTupleExclusive" << endl;
+ break;
+ case 12:
+ ndbout << "simpleRead" << endl;
+ break;
+ case 13:
+ ndbout << "dirtyRead" << endl;
+ break;
+ case 14:
+ ndbout << "dirtyUpdate" << endl;
+ break;
+ case 15:
+ ndbout << "dirtyWrite" << endl;
+ break;
+ default:
+ break ;
+
+ }
+
+// read_and_verify_rows(pNdb, false);
+
+// delete_rows(pNdb, 0, 0) ;
+ delete pNdb ;
+
+ if (bTestPassed == 0) {
+ ndbout << "OK: test passed" << endl;
+ exit(0);
+ }else{
+ ndbout << "FAIL: test failed" << endl;
+ exit(-1);
+ }
+}
+
+void error_handler(const NdbError & err, TTYPE type_expected) {
+
+ ndbout << err << endl ;
+
+ switch (type_expected){
+ case NO_FAIL:
+ bTestPassed = -1 ;
+ break ;
+ case FAIL:
+ ndbout << "OK: error is expected" << endl;
+ break ;
+ case UNDEF:
+ ndbout << "assumed OK: expected result undefined" << endl ;
+ break ;
+ default:
+ break ;
+ }
+}
+
+void create_table(Ndb* pMyNdb) {
+
+ /****************************************************************
+ * Create SimpleTable and Attributes.
+ *
+ * create table SimpleTable1(
+ * col0 int,
+ * col1 int not null,
+ * col2 int not null,
+ * col3 int not null ... 129)
+ *
+ ***************************************************************/
+
+ int check = -1 ;
+ NdbSchemaOp *MySchemaOp = NULL ;
+
+ ndbout << endl << "Creating " << tableName << " ... " << endl;
+
+ NdbSchemaCon* MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pMyNdb);
+ if(!MySchemaTransaction) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
+
+ MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( !MySchemaOp ) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
+ // Create table
+ check = MySchemaOp->createTable( tableName,
+ 8, // Table size
+ TupleKey, // Key Type
+ 40 // Nr of Pages
+ );
+
+ if( check == -1 ) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
+
+ ndbout << "Creating attributes ... " << flush;
+
+ // Create first column, primary key
+ check = MySchemaOp->createAttribute( attrName[0],
+ TupleKey,
+ 32,
+ 1/*3, tAttributeSize */,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+
+ if( check == -1 ) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
+
+ // create the 2 .. n columns.
+ for ( int i = 1; i < MAXATTR; i++ ){
+ check = MySchemaOp->createAttribute( attrName[i],
+ NoKey,
+ 32,
+ tAttributeSize,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+
+ if( check == -1 ) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
+ }
+
+ ndbout << "OK" << endl;
+
+ if( MySchemaTransaction->execute() == -1 ) {
+ ndbout << MySchemaTransaction->getNdbError() << endl;
+ }else{
+ ndbout << tableName[0] << " created" << endl;
+ }
+
+
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+
+ return;
+
+}
+
+
+
+void write_rows (Ndb* pMyNdb) {
+
+ /****************************************************************
+ * Insert rows into SimpleTable
+ *
+ ***************************************************************/
+
+ int check = -1 ;
+ int loop_count_ops = nRecords ;
+ NdbOperation *MyOperation = NULL ;
+ NdbConnection *MyTransaction = NULL ;
+
+ ndbout << endl << "Writing records ..." << flush;
+
+ for (int count=0 ; count < loop_count_ops ; count++){
+ MyTransaction = pMyNdb->startTransaction();
+ if (!MyTransaction) {
+ error_handler(pMyNdb->getNdbError(), NO_FAIL);
+ }//if
+
+ MyOperation = MyTransaction->getNdbOperation(tableName);
+ if (!MyOperation) {
+ error_handler(pMyNdb->getNdbError(), NO_FAIL);
+ }//if
+
+ check = MyOperation->writeTuple();
+ if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL);
+
+ check = MyOperation->equal( attrName[0],(char*)&pkValue[count] );
+ if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL);
+
+ // Update the columns, index column already ok.
+ for (int i = 1 ; i < MAXATTR; i++){
+ if ((i == 2) && (count > 4)){
+ check = MyOperation->setValue(attrName[i], (char*)&attrValue[count + 1]);
+ }else{
+ check = MyOperation->setValue(attrName[i], (char*)&attrValue[count]);
+ }
+ if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL);
+ }
+ check = MyTransaction->execute( Commit );
+ if(check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL);
+
+ pMyNdb->closeTransaction(MyTransaction);
+ }
+ ndbout <<" \tOK" << endl;
+ return;
+}
+
+void verify_deleted(Ndb* pMyNdb) {
+
+ int check = -1 ;
+ int loop_count_ops = nRecords;
+ NdbOperation* pMyOperation = NULL ;
+
+ ndbout << "Verifying deleted records..."<< flush;
+
+ for (int count=0 ; count < loop_count_ops ; count++){
+
+ NdbConnection* pMyTransaction = pMyNdb->startTransaction();
+ if (!pMyTransaction) error_handler(pMyNdb->getNdbError(), NO_FAIL);
+
+ pMyOperation = pMyTransaction->getNdbOperation(tableName);
+ if (!pMyOperation) error_handler(pMyNdb->getNdbError(), NO_FAIL);
+
+ check = pMyOperation->readTuple();
+ if( check == -1 ) error_handler( pMyTransaction->getNdbError(), NO_FAIL);
+
+ check = pMyOperation->equal( attrName[0],(char*)&pkValue[count] );
+ if( check == -1 ) error_handler( pMyTransaction->getNdbError(), NO_FAIL);
+
+ // Exepect to receive an error
+ if(pMyTransaction->execute(Commit) != -1)
+ if( 626 == pMyTransaction->getNdbError().code){
+ ndbout << pMyTransaction->getNdbError() << endl ;
+ ndbout << "OK" << endl ;
+ }else{
+ error_handler(pMyTransaction->getNdbError(), NO_FAIL) ;
+ }
+
+ pMyNdb->closeTransaction(pMyTransaction);
+ }
+
+ ndbout << "OK" << endl;
+ return;
+};
+
+void read_and_verify_rows(Ndb* pMyNdb, bool pre) {
+
+ int check = -1 ;
+ int loop_count_ops = nRecords;
+ char expectedCOL1[NUMBEROFRECORDS] = {0} ;
+ char expectedCOL2[NUMBEROFRECORDS] = {0} ;
+ NdbConnection *pMyTransaction = NULL ;
+ NdbOperation *MyOp = NULL ;
+ NdbRecAttr* tTmp = NULL ;
+ int readValue[MAXATTR] = {0} ;
+
+ ndbout << "Verifying records...\n"<< endl;
+
+ for (int count=0 ; count < loop_count_ops ; count++){
+
+ pMyTransaction = pMyNdb->startTransaction();
+ if (!pMyTransaction) error_handler(pMyNdb->getNdbError(), NO_FAIL);
+
+ MyOp = pMyTransaction->getNdbOperation(tableName);
+ if (!MyOp) error_handler( pMyTransaction->getNdbError(), NO_FAIL);
+
+
+ check = MyOp->readTuple();
+ if( check == -1 ) error_handler( MyOp->getNdbError(), NO_FAIL);
+
+ check = MyOp->equal( attrName[0],(char*)&pkValue[count] );
+ if( check == -1 ) error_handler( MyOp->getNdbError(), NO_FAIL);
+
+ for (int count_attributes = 1; count_attributes < MAXATTR; count_attributes++){
+
+ tTmp = MyOp->getValue( (char*)attrName[count_attributes], (char*)&readValue[count_attributes] );
+ if(!tTmp) error_handler( MyOp->getNdbError(), NO_FAIL);
+ }
+
+ if( pMyTransaction->execute( Commit ) == -1 ) {
+ error_handler(pMyTransaction->getNdbError(), NO_FAIL);
+ } else {
+ if (pre) {
+ expectedCOL1[count] = readValue[1];
+ expectedCOL2[count] = readValue[2];
+ }
+
+ ndbout << attrName[1] << "\t " << readValue[1] << "\t "
+ << attrName[2] << "\t " << readValue[2] << endl;
+ }
+
+ pMyNdb->closeTransaction(pMyTransaction);
+
+ }
+
+ ndbout << "\nOK\n" << endl;
+
+ return;
+
+};
+
+TTYPE t_exitMethods(int nCalls, NdbOperation * pOp, int opType) {
+
+ ndbout << "Defining exitMethods test " << nCalls << ": " << endl ;;
+ TTYPE ret_val = NO_FAIL ;
+
+ switch(nCalls){
+ case 1: // exit_nok if attr value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 14);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_ok() ;
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break;
+ case 2: // exit_ok if attr value doesn't match
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 14);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_nok() ;
+ pOp->def_label(0);
+ if (opType == 3) {
+ // For update transactions use incValue to update the tuple
+ Uint32 val32 = 5;
+ pOp->incValue("COL2", val32);
+ }
+ pOp->interpret_exit_ok();
+ break ;
+ case 3: // Non-existent value (128): exit_ok if if the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 128);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ pOp->interpret_exit_ok();
+ ret_val = FAIL ;
+ break;
+ case 4: // Non-existent value (128): exit_nok if the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 128);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ ret_val = FAIL ;
+ break;
+ case 5: // exit_nok of the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 2);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break ;
+ case 6: // exit_ok of the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 2);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ if (opType == 3) {
+ // For update transactions use incValue to update the tuple
+ Uint32 val32 = 5;
+ pOp->incValue("COL2", val32);
+ }
+ pOp->interpret_exit_ok();
+ break;
+ case 7: // exit_nok if the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 6);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break;
+ case 8: // exit_ok if the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 6);
+ pOp->branch_ne(1, 2, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ if (opType == 3) {
+ // For update transactions use incValue to update the tuple
+ Uint32 val32 = 5;
+ pOp->incValue("COL2", val32);
+ }
+ pOp->interpret_exit_ok();
+ break ;
+ case 9: // exit_nok if the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 8);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break;
+ case 10: // exit_ok if the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 8);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ if (opType == 3) {
+ // For update transactions use incValue to update the tuple
+ Uint32 val32 = 5;
+ pOp->incValue("COL2", val32);
+ }
+ pOp->interpret_exit_ok();
+ break;
+ case 11: // exit_nok if the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 10);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break;
+ case 12:
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 10);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ if (opType == 3) {
+ // For update transactions use incValue to update the tuple
+ Uint32 val32 = 5;
+ pOp->incValue("COL2", val32);
+ }
+ pOp->interpret_exit_ok();
+ break;
+ case 13:
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 10);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break;
+ case 14: // exit_nok if the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 12);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break;
+ case 15: // exit_ok if the value matches
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, 12);
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ if (opType == 3) {
+ // For update transactions use incValue to update the tuple
+ Uint32 val32 = 5;
+ pOp->incValue("COL2", val32);
+ }
+ pOp->interpret_exit_ok();
+ case 16:
+ pOp->interpret_exit_nok();
+ ret_val = FAIL ;
+ break;
+ case 17:
+ pOp->interpret_exit_ok();
+ break ;
+ case 18:
+ pOp->interpret_exit_nok();
+ ret_val = FAIL ;
+ break ;
+ default:
+ break ;
+ }
+ return ret_val;
+}
+
+TTYPE t_incValue(int nCalls, NdbOperation* pOp) {
+
+ ndbout << "Defining incValue test " << nCalls << ": ";
+ TTYPE ret_val = NO_FAIL;
+
+ Uint32 val32 = 5;
+ Uint64 val64 = 5;
+ Uint32 attr0 = 0;
+ Uint32 attr1 = 1;
+ Uint32 attr20 = 20;
+
+ switch(nCalls) {
+ case 1:
+ pOp->incValue(attrName[1], val32);
+ break;
+ case 2:
+ pOp->incValue(attr1, val32);
+ break;
+ case 3:
+ pOp->incValue(attrName[1], val64);
+ break;
+ case 4:
+ pOp->incValue(attr1, val64);
+ break;
+ case 5:
+ pOp->incValue(attrName[0], val32);
+ ret_val = FAIL ;
+ break;
+ case 6:
+ pOp->incValue(attrName[0], val64);
+ ret_val = FAIL ;
+ break;
+ case 7:
+ pOp->incValue(attr0, val32);
+ ret_val = FAIL ;
+ break;
+ case 8:
+ pOp->incValue(attr0, val64);
+ ret_val = FAIL ;
+ break;
+ case 9:
+ pOp->incValue("COL20", val32);
+ ret_val = FAIL ;
+ break;
+ case 10:
+ pOp->incValue("COL20", val64);
+ ret_val = FAIL ;
+ break;
+ case 11:
+ pOp->incValue(attr20, val32);
+ ret_val = FAIL ;
+ break;
+ case 12:
+ pOp->incValue(attr20, val64);
+ ret_val = FAIL ;
+ break;
+ default:
+ break ;
+ }
+ return ret_val;
+}
+
+TTYPE t_subValue(int nCalls, NdbOperation* pOp) {
+
+ ndbout << "Defining subValue test " << nCalls << ": ";
+
+ Uint32 val32 = 5;
+ Uint64 val64 = 5;
+ Uint32 attr0 = 0;
+ Uint32 attr1 = 1;
+ Uint32 attr20 = 20;
+
+ TTYPE ret_val = NO_FAIL;
+
+ switch(nCalls) {
+ case 1:
+ pOp->subValue("COL2", val32);
+ break;
+ case 2:
+ pOp->subValue(attr1, val32);
+ break;
+ case 3:
+ pOp->subValue("COL0", val32);
+ ret_val = FAIL ;
+ break;
+ case 4:
+ pOp->subValue(attr0, val32);
+ ret_val = FAIL ;
+ break;
+ case 5:
+ pOp->subValue("COL20", val32);
+ ret_val = FAIL ;
+ break;
+ case 6:
+ pOp->subValue(attr20, val32);
+ ret_val = FAIL ;
+ break;
+ case 7:
+ // Missing implementation
+ //pOp->subValue("COL20", val64);
+ ndbout << "Missing implementation" << endl;
+ break;
+ case 8:
+ // Missing implementation
+ //pOp->subValue("COL2", val64);
+ ndbout << "Missing implementation" << endl;
+ break;
+ case 9:
+ // Missing implementation
+ //pOp->subValue("COL0", val64);
+ ndbout << "Missing implementation" << endl;
+ break;
+ case 10:
+ // Missing implementation
+ //pOp->subValue(attr1, val64);
+ ndbout << "Missing implementation" << endl;
+ break;
+ case 11:
+ // Missing implementation
+ //pOp->subValue(attr0, val64);
+ ndbout << "Missing implementation" << endl;
+ break;
+ case 12:
+ // Missing implementation
+ //pOp->subValue(attr20, val64);
+ ndbout << "Missing implementation" << endl;
+ break;
+ default:
+ break ;
+ }
+ return ret_val ;
+}
+
+TTYPE t_readAttr(int nCalls, NdbOperation* pOp) {
+
+ ndbout << "Defining readAttr test " << nCalls << ": ";
+
+ Uint32 attr0 = 0;
+ Uint32 attr1 = 1;
+ Uint32 attr20 = 20;
+ TTYPE ret_val = NO_FAIL;
+
+ switch(nCalls) {
+ case 1:
+ pOp->read_attr("COL1", 1);
+ break;
+ case 2:
+ pOp->read_attr(attr1, 1);
+ ret_val = NO_FAIL ;
+ break;
+ case 3:
+ pOp->read_attr("COL0", 1);
+ ret_val = NO_FAIL ;
+ break;
+ case 4:
+ pOp->read_attr(attr0, 1);
+ ret_val = NO_FAIL ;
+ break;
+ case 5:
+ pOp->read_attr("COL20", 1);
+ ret_val = FAIL ;
+ break;
+ case 6:
+ pOp->read_attr(20, 1);
+ ret_val = FAIL ;
+ break;
+ case 7:
+ pOp->read_attr("COL1", 8);
+ ret_val = FAIL ;
+ break;
+ case 8:
+ pOp->read_attr(attr1, 8);
+ ret_val = FAIL ;
+ break;
+ default:
+ break ;
+ }
+ return ret_val;
+}
+
+TTYPE t_writeAttr(int nCalls, NdbOperation* pOp) {
+
+ ndbout << "Defining writeAttr test " << nCalls << ": ";
+
+ pOp->load_const_u32(1, 5);
+
+ Uint32 attr0 = 0;
+ Uint32 attr1 = 1;
+ Uint32 attr20 = 20;
+ TTYPE ret_val = NO_FAIL ;
+
+ switch(nCalls) {
+ case 1:
+ pOp->write_attr("COL1", 1);
+ break;
+ case 2:
+ pOp->write_attr(attr1, 1);
+ break;
+ case 3:
+ pOp->write_attr("COL0", 1);
+ ret_val = FAIL ;
+ break;
+ case 4:
+ pOp->write_attr(attr0, 1);
+ ret_val = FAIL ;
+ break;
+ case 5:
+ pOp->write_attr("COL20", 1);
+ ret_val = FAIL ;
+ break;
+ case 6:
+ pOp->write_attr(20, 1);
+ ret_val = FAIL ;
+ break;
+ case 7:
+ pOp->write_attr("COL1", 2);
+ ret_val = FAIL ;
+ break;
+ case 8:
+ pOp->write_attr(attr1, 2);
+ ret_val = FAIL ;
+ break;
+ case 9:
+ pOp->write_attr("COL1", 8);
+ ret_val = FAIL ;
+ break;
+ case 10:
+ pOp->write_attr(attr1, 8);
+ ret_val = FAIL ;
+ break;
+ default:
+ break ;
+ }
+ return ret_val ;
+}
+
+TTYPE t_loadConst(int nCalls, NdbOperation* pOp, int opType) {
+
+ ndbout << "Defining loadConst test " << nCalls << " : ";
+ TTYPE ret_val = NO_FAIL ;
+
+ switch(nCalls) {
+ case 1:
+ // Loading null into a valid register
+ pOp->load_const_null(1);
+ break;
+ case 2:
+ // Loading null into an invalid register
+ pOp->load_const_null(8);
+ ret_val = FAIL ;
+ break;
+ case 3:
+ // Test loading a 32-bit value (>65536)
+ pOp->load_const_u32(1, 65600);
+ break;
+ case 4:
+ // Test loading a 16-bit value (<65536)
+ pOp->load_const_u32(1, 65500);
+ break;
+ case 5:
+ // Test by loading to a non-valid register
+ pOp->load_const_u32(8, 2);
+ ret_val = FAIL ;
+ break;
+ case 6:
+ // Test by loading a 64-bit value
+ pOp->load_const_u64(1, 65600);
+ break;
+ case 7:
+ // Test by loading a non-valid register
+ pOp->load_const_u64(8, 2);
+ ret_val = FAIL ;
+ break;
+ case 8:
+ // Test by loading a valid register with -1
+ pOp->load_const_u64(1, -1);
+ ret_val = FAIL ;
+ break;
+
+ default:
+ break ;
+ }
+
+ if (opType == 3 && FAIL != ret_val)
+ pOp->write_attr("COL1", 1);
+ return ret_val;
+}
+
+TTYPE t_branch(int nCalls, NdbOperation* pOp) {
+
+ ndbout << "Defining branch test " << nCalls << ": " ;
+
+ TTYPE ret_val = NO_FAIL ;
+ Uint32 val32=5;
+
+ pOp->read_attr("COL1", 1);
+ pOp->load_const_u32(2, val32);
+
+ switch(nCalls) {
+ case 1:
+ pOp->branch_eq(1, 2, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ pOp->interpret_exit_ok();
+ break;
+ case 2:
+ pOp->branch_eq(2, 1, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ pOp->interpret_exit_ok();
+ break;
+ case 3:
+ pOp->branch_eq(1, 1, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ pOp->interpret_exit_ok();
+ break;
+ default:
+ //ndbout << "t_branch: default case (no test case)" << endl ;
+ //return ret_val = NO_FAIL ;
+ break ;
+ }
+ return ret_val;
+}
+
+TTYPE t_branchIfNull(int nCalls, NdbOperation* pOp) {
+
+ TTYPE ret_val = NO_FAIL;
+ ndbout << "Defining branchIfNull test " << nCalls << ": " << endl ;
+
+ switch(nCalls) {
+ case 1:
+ pOp->load_const_u32(1, 1);
+ pOp->branch_ne_null(1, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ pOp->interpret_exit_ok();
+ break;
+ case 2:
+ pOp->load_const_null(1);
+ pOp->branch_ne_null(1, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break;
+ case 3:
+ pOp->load_const_u32(1, 1);
+ pOp->branch_eq_null(1, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break;
+ case 4:
+ pOp->load_const_null(1);
+ pOp->branch_ne_null(1, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ break;
+ case 5:
+ // Test with a non-initialized register
+ pOp->branch_ne_null(3, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ ret_val = FAIL ;
+ break;
+ case 6:
+ // Test with a non-existing register
+ pOp->branch_ne_null(8, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ ret_val = FAIL ;
+ break;
+ case 7:
+ // Test with a non-initialized register
+ pOp->branch_eq_null(3, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ ret_val = FAIL ;
+ break;
+ case 8:
+ // Test with a non-existing register
+ pOp->branch_ne_null(8, 0);
+ pOp->interpret_exit_ok();
+ pOp->def_label(0);
+ pOp->interpret_exit_nok();
+ ret_val = FAIL ;
+ break;
+ default:
+ break ;
+ }
+
+ return ret_val;
+}
+
+TTYPE t_addReg(int nCalls, NdbOperation* pOp) {
+
+ TTYPE ret_val = NO_FAIL ;
+
+ ndbout << "Defining addReg test " << nCalls << ": ";
+
+ pOp->load_const_u32(1, 65500);
+ pOp->load_const_u32(2, 500);
+ pOp->load_const_u64(3, 65600);
+ pOp->load_const_u64(4, 95600);
+
+ switch(nCalls) {
+ case 1:
+ pOp->add_reg(1, 2, 5);
+ break;
+ case 2:
+ pOp->add_reg(1, 3, 5);
+ break;
+ case 3:
+ pOp->add_reg(3, 1, 5);
+ break;
+ case 4:
+ pOp->add_reg(3, 4, 5);
+ break;
+ case 5:
+ pOp->add_reg(1, 6, 5);
+ break;
+ case 6:
+ pOp->add_reg(6, 1, 5);
+ break;
+ case 7: // illegal register
+ pOp->add_reg(1, 8, 5);
+ ret_val = FAIL ;
+ break;
+ case 8: // another illegal register
+ pOp->add_reg(8, 1, 5);
+ ret_val = FAIL ;
+ break;
+ case 9: // and another one
+ pOp->add_reg(1, 2, 8);
+ ret_val = FAIL ;
+ break;
+ default:
+ break ;
+ }
+ pOp->load_const_u32(7, 65000);
+ pOp->branch_eq(5, 7, 0);
+ pOp->interpret_exit_nok();
+ pOp->def_label(0);
+ pOp->interpret_exit_ok();
+
+ return ret_val ;
+}
+
+TTYPE t_subReg(int nCalls, NdbOperation* pOp) {
+
+ TTYPE ret_val = NO_FAIL ;
+ ndbout << "Defining subReg test: " << nCalls << endl;
+
+ pOp->load_const_u32(1, 65500);
+ pOp->load_const_u32(2, 500);
+ pOp->load_const_u64(3, 65600);
+ pOp->load_const_u64(4, 95600);
+
+ switch(nCalls) {
+ case 1:
+ pOp->sub_reg(1, 2, 5);
+ pOp->load_const_u32(7, 65000);
+ break;
+ case 2:
+ pOp->sub_reg(1, 3, 5);
+ pOp->load_const_u64(7, (Uint64)-100);
+ break;
+ case 3:
+ pOp->sub_reg(3, 1, 5);
+ pOp->load_const_u64(7, (Uint64)100);
+ break;
+ case 4:
+ pOp->sub_reg(3, 4, 5);
+ pOp->load_const_u64(7, (Uint64)-30000);
+ break;
+ case 5:
+ pOp->sub_reg(1, 6, 5);
+ pOp->load_const_u64(7, 0);
+ ret_val = FAIL ;
+ break;
+ case 6:
+ pOp->sub_reg(6, 1, 5);
+ pOp->load_const_u64(7, 0);
+ ret_val = FAIL ;
+ break;
+ case 7:
+ pOp->sub_reg(1, 8, 5);
+ pOp->load_const_u64(7, 0);
+ ret_val = FAIL ;
+ break;
+ case 8:
+ pOp->sub_reg(8, 1, 5);
+ pOp->load_const_u64(7, 0);
+ ret_val = FAIL ;
+ break;
+ case 9:
+ pOp->sub_reg(1, 2, 8);
+ pOp->load_const_u32(7, (Uint32)65000);
+ ret_val = FAIL;
+ break;
+ default:
+ //ndbout << "t_subReg: default case (no test case)" << endl ;
+ //return ret_val = NO_FAIL ;
+ break ;
+ }
+ pOp->branch_eq(5, 7, 0);
+ pOp->interpret_exit_nok() ;
+ pOp->def_label(0);
+ pOp->interpret_exit_ok() ;
+
+ return ret_val;
+}
+
+TTYPE t_subroutineWithBranchLabel(int nCalls, NdbOperation* pOp) {
+
+ TTYPE ret_val = NO_FAIL ;
+ ndbout << "Defining subroutineWithBranchLabel test:" << nCalls << endl;
+
+ pOp->load_const_u32(1, 65500);
+ pOp->load_const_u32(2, 500);
+ pOp->load_const_u64(3, 65600);
+ pOp->load_const_u64(4, 95600);
+ pOp->load_const_u32(7, 65000);
+ pOp->call_sub(0) ;
+
+ switch(nCalls) {
+ case 1:
+ pOp->def_subroutine(0) ;
+ pOp->add_reg(1, 2, 5);
+ break;
+ case 2:
+ pOp->def_subroutine(0) ;
+ pOp->add_reg(1, 3, 5);
+ break;
+ case 3:
+ pOp->def_subroutine(0) ;
+ pOp->add_reg(3, 1, 5);
+ break;
+ case 4:
+ pOp->def_subroutine(0) ;
+ pOp->add_reg(3, 4, 5);
+ break;
+ case 5:
+ pOp->def_subroutine(0) ;
+ pOp->add_reg(1, 6, 5);
+ break;
+ case 6:
+ pOp->def_subroutine(0) ;
+ pOp->add_reg(6, 1, 5);
+ break;
+ case 7: // illegal register
+ pOp->def_subroutine(0) ;
+ pOp->add_reg(1, 8, 5);
+ ret_val = FAIL ;
+ break;
+ case 8: // another illegal register
+ pOp->def_subroutine(0) ;
+ pOp->add_reg(8, 1, 5);
+ ret_val = FAIL ;
+ break;
+ case 9: // and another one
+ pOp->def_subroutine(0) ;
+ pOp->add_reg(1, 2, 8);
+ ret_val = FAIL ;
+ break;
+ case 10: // test subroutine nesting
+ for(int sub = 0; sub < 25 ; ++sub){
+ pOp->call_sub(sub) ;
+ pOp->def_subroutine(sub + 1) ;
+ pOp->interpret_exit_ok() ;
+ pOp->ret_sub() ;
+ }
+ ret_val = FAIL ;
+ default:
+ break ;
+ }
+
+ pOp->branch_label(0) ;
+ pOp->interpret_exit_nok() ;
+ pOp->def_label(0) ;
+ pOp->interpret_exit_ok() ;
+ pOp->ret_sub() ;
+
+ return ret_val ;
+}
+
+
+void scan_rows(Ndb* pMyNdb, int opType, int tupleType, int scanType) {
+
+ int check = -1 ;
+ int loop_count_ops = nRecords ;
+ int eOf = -1 ;
+ int readValue = 0 ;
+ int readValue2 = 0 ;
+ int scanCount = 0 ;
+ TTYPE fail = NO_FAIL ;
+
+ for (int count=0 ; count < loop_count_ops ; count++) {
+ NdbConnection* MyTransaction = pMyNdb->startTransaction();
+ if (!MyTransaction) error_handler(pMyNdb->getNdbError(), NO_FAIL);
+
+ NdbOperation* MyOperation = MyTransaction->getNdbOperation(tableName);
+ if (!MyOperation) error_handler(pMyNdb->getNdbError(), NO_FAIL);
+
+ if (opType == 1)
+ // Open for scan read, Creates the SCAN_TABREQ and if needed
+ // SCAN_TABINFO signals.
+ check = MyOperation->openScanRead(1);
+ else if (opType == 2)
+ // Open for scan with update of rows.
+ check = MyOperation->openScanExclusive(1);
+
+ // Create ATTRINFO signal(s) for interpreted program used for
+ // defining search criteria and column values that should be returned.
+
+ scanCount = count+1 ;
+
+ switch(tupleType) {
+ case 1:
+ fail = t_exitMethods(scanCount, MyOperation, opType);
+ break;
+ case 2:
+ fail = t_incValue(scanCount, MyOperation);
+ break;
+ case 3:
+ fail = t_subValue(scanCount, MyOperation);
+ break;
+ case 4:
+ fail = t_readAttr(scanCount, MyOperation);
+ break;
+ case 5:
+ fail = t_writeAttr(scanCount, MyOperation);
+ break;
+ case 6:
+ fail = t_loadConst(scanCount, MyOperation, opType);
+ break;
+ case 7:
+ fail = t_branch(scanCount, MyOperation);
+ break;
+ case 8:
+ fail = t_branchIfNull(scanCount, MyOperation);
+ break;
+ case 9:
+ fail = t_addReg(scanCount, MyOperation);
+ break;
+ case 10:
+ fail = t_subReg(scanCount, MyOperation);
+ break;
+ case 11:
+ fail = t_subroutineWithBranchLabel(scanCount, MyOperation);
+ break;
+ default:
+ break ;
+ }
+
+ if(11 != tupleType) MyOperation->getValue(attrName[1], (char*)&readValue);
+
+ // Sends the SCAN_TABREQ, (SCAN_TABINFO) and ATTRINFO signals and then
+ // reads the answer in TRANSID_AI. Confirmation is received through SCAN_TABCONF or
+ // SCAN_TABREF if failure.
+ check = MyTransaction->executeScan();
+ if (check == -1) {
+ //ndbout << endl << "executeScan returned: " << MyTransaction->getNdbError() << endl;
+ error_handler(MyTransaction->getNdbError(), fail) ;
+ pMyNdb->closeTransaction(MyTransaction);
+ }else{
+ // Sends the SCAN_NEXTREQ signal(s) and reads the answer in TRANS_ID signals.
+ // SCAN_TABCONF or SCAN_TABREF is the confirmation.
+ while ((eOf = MyTransaction->nextScanResult()) == 0) {
+ ndbout << readValue <<"; ";
+ // Here we call takeOverScanOp for update of the tuple.
+ }
+ ndbout << endl ;
+
+ pMyNdb->closeTransaction(MyTransaction);
+ if (eOf == -1) {
+ ndbout << endl << "nextScanResult returned: "<< MyTransaction->getNdbError() << endl;
+ } else {
+ ndbout << "OK" << endl;
+ }
+ }
+ }
+ return;
+
+};
+
+
+void update_rows(Ndb* pMyNdb, int tupleType, int opType) {
+ /****************************************************************
+ * Update rows in SimpleTable
+ * Only updates the first 3 cols.
+ ***************************************************************/
+
+ int check = -1 ;
+ int loop_count_ops = nRecords ;
+ int readValue[MAXATTR] = {0} ;
+ TTYPE ret_val = NO_FAIL ;
+ NdbConnection *MyTransaction = NULL ;
+ NdbOperation *MyOperation = NULL ;
+
+ ndbout << "Updating records ..." << endl << endl;
+
+ for (int count=0 ; count < loop_count_ops ; count++){
+
+ MyTransaction = pMyNdb->startTransaction();
+ if (!MyTransaction) {
+ error_handler(pMyNdb->getNdbError(), NO_FAIL);
+ return;
+ }//if
+
+ MyOperation = MyTransaction->getNdbOperation(tableName);
+ if (MyOperation == NULL) {
+ error_handler(pMyNdb->getNdbError(), NO_FAIL);
+ return;
+ }//if
+
+ // if (operationType == 3)
+ check = MyOperation->interpretedUpdateTuple();
+ // else if (operationType == 4)
+ // check = MyOperation->interpretedDirtyUpdate();
+ if( check == -1 )
+ error_handler(MyTransaction->getNdbError(), NO_FAIL);
+
+ check = MyOperation->equal( attrName[0], (char*)&pkValue[count] );
+ if( check == -1 )
+ error_handler(MyTransaction->getNdbError(), NO_FAIL);
+
+ switch(tupleType) {
+ case 1:
+ ret_val = t_exitMethods(count+1, MyOperation, opType);
+ break;
+ case 2:
+ ret_val = t_incValue(count+1, MyOperation);
+ break;
+ case 3:
+ ret_val = t_subValue(count+1, MyOperation);
+ break;
+ case 4:
+ ret_val = t_readAttr(count+1, MyOperation);
+ break;
+ case 5:
+ ret_val = t_writeAttr(count+1, MyOperation);
+ break;
+ case 6:
+ ret_val = t_loadConst(count+1, MyOperation, opType);
+ break;
+ case 7:
+ ret_val = t_branch(count+1, MyOperation);
+ break;
+ case 8:
+ ret_val = t_branchIfNull(count+1, MyOperation);
+ break;
+ case 9:
+ ret_val = t_addReg(count+1, MyOperation);
+ break;
+ case 10:
+ ret_val = t_subReg(count+1, MyOperation);
+ break;
+ case 11:
+ ret_val = t_subroutineWithBranchLabel(count+1, MyOperation);
+ break;
+ default:
+ break ;
+ }
+
+ MyOperation->getValue("COL1", (char*)&readValue);
+
+ if (MyTransaction->execute( Commit ) == -1 ) {
+ error_handler(MyTransaction->getNdbError(), ret_val);
+ }else if (NO_FAIL == ret_val ) {
+ ndbout << "OK" << endl;
+ } else {
+ bTestPassed = -1;
+ ndbout << "Test passed when expected to fail" << endl;
+ }//if
+ pMyNdb->closeTransaction(MyTransaction);
+
+ }
+
+ ndbout << "Finished updating records" << endl;
+ return;
+};
+
+void delete_rows(Ndb* pMyNdb, int tupleTest, int opType) {
+
+ /****************************************************************
+ * Delete rows from SimpleTable
+ *
+ ***************************************************************/
+
+ int check = 1 ;
+ int loop_count_ops = nRecords ;
+ int readValue[MAXATTR] = {0};
+ NdbConnection *MyTransaction = NULL ;
+ NdbOperation *MyOperation = NULL ;
+ TTYPE ret_val = NO_FAIL ;
+
+ ndbout << "Deleting records ..."<< endl << endl;
+
+ for (int count=0 ; count < loop_count_ops ; count++) {
+
+ MyTransaction = pMyNdb->startTransaction();
+ if (!MyTransaction) error_handler(pMyNdb->getNdbError(), NO_FAIL) ;
+
+ MyOperation = MyTransaction->getNdbOperation(tableName);
+ if (!MyOperation) error_handler(pMyNdb->getNdbError(), NO_FAIL) ;
+
+ check = MyOperation->interpretedDeleteTuple();
+ if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL) ;
+
+ check = MyOperation->equal( attrName[0], (char*)&pkValue[count] );
+ if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL) ;
+
+ switch(tupleTest) {
+ case 1:
+ ret_val = t_exitMethods(count+1, MyOperation, opType);
+ break;
+ case 2:
+ ret_val = t_incValue(count+1, MyOperation);
+ break;
+ case 3:
+ ret_val = t_subValue(count+1, MyOperation);
+ break;
+ case 4:
+ ret_val = t_readAttr(count+1, MyOperation);
+ break;
+ case 5:
+ ret_val = t_writeAttr(count+1, MyOperation);
+ break;
+ case 6:
+ ret_val = t_loadConst(count+1, MyOperation, opType);
+ break;
+ case 7:
+ ret_val = t_branch(count+1, MyOperation);
+ break;
+ case 8:
+ ret_val = t_branchIfNull(count+1, MyOperation);
+ break;
+ case 9:
+ ret_val = t_addReg(count+1, MyOperation);
+ break;
+ case 10:
+ ret_val = t_subReg(count+1, MyOperation);
+ break;
+ case 11:
+ ret_val = t_subroutineWithBranchLabel(count+1, MyOperation);
+ break;
+ default:
+ break ;
+ }
+
+ if(11 != tupleTest)MyOperation->getValue(attrName[1], (char*)&readValue) ;
+
+ if (MyTransaction->execute( Commit ) == -1 ) {
+ error_handler(MyTransaction->getNdbError(), ret_val);
+ } else if (NO_FAIL == ret_val /*|| UNDEF == ret_val*/ ) {
+ ndbout << "OK" << endl;
+ } else {
+ bTestPassed = -1;
+ ndbout << "Test passed when expected to fail" << endl;
+ }//if
+ ndbout << endl;
+ pMyNdb->closeTransaction(MyTransaction);
+ }
+
+ ndbout << "Finished deleting records" << endl;
+ return;
+
+};
+
+
+inline void setAttrNames(){
+ for (int i = 0; i < MAXATTR; i++){
+ snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ }
+}
+
+
+inline void setTableNames(){
+ snprintf(tableName, MAXSTRLEN, "TAB1");
+}
+
diff --git a/ndb/test/ndbapi/interpreterInTup/interpreterInTup.cpp b/ndb/test/ndbapi/interpreterInTup/interpreterInTup.cpp
deleted file mode 100644
index a2352edf707..00000000000
--- a/ndb/test/ndbapi/interpreterInTup/interpreterInTup.cpp
+++ /dev/null
@@ -1,1524 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* ***************************************************
- TEST OF INTERPRETER IN TUP
- Verify that the interpreter in TUP is able to
- handle and execute all the commands that the
- NdbApi can isssue
-
- Arguments:
-
- operationType 1 openScanRead,
- 2 openScanExclusive,
- 3 interpretedUpdateTuple,
- 4 interpretedDirtyUpdate,
- 5 interpretedDeleteTuple
- 6 deleteTuple
- 7 insertTuple
- 8 updateTuple
- 9 writeTuple
- 10 readTuple
- 11 readTupleExclusive
- 12 simpleRead
- 13 dirtyRead
- 14 dirtyUpdate
- 15 dirtyWrite
-
- tupTest 1 exitMethods
- 2 incValue
- 3 subValue
- 4 readAttr
- 5 writeAttr
- 6 loadConst
- 7 branch
- 8 branchIfNull
- 9 addReg
- 10 subReg
- 11 subroutineWithBranchLabel
-
- scanTest Number of the test within each tupTest
-
-* *************************************************** */
-
-#include <NdbOut.hpp>
-#include <NdbThread.h>
-#include <NdbMutex.h>
-#include <NdbApi.hpp>
-#include <NDBT.hpp>
-
-#define MAXATTR 3
-#define MAXTABLES 12
-#define MAXSTRLEN 8
-#define NUMBEROFRECORDS 1000
-
-typedef enum {
- FAIL = 0,
- NO_FAIL,
- UNDEF
-} TTYPE;
-
-inline void setAttrNames() ;
-inline void setTableNames() ;
-void error_handler(const NdbError & err, TTYPE);
-void create_table(Ndb*);
-void write_rows(Ndb*);
-void update_rows(Ndb*, int, int);
-void delete_rows(Ndb*, int, int);
-void verify_deleted(Ndb*);
-void read_and_verify_rows(Ndb*, bool pre);
-void scan_rows(Ndb*, int, int, int);
-TTYPE t_exitMethods(int, NdbOperation*, int);
-TTYPE t_incValue(int, NdbOperation*);
-TTYPE t_subValue(int, NdbOperation*);
-TTYPE t_readAttr(int, NdbOperation*);
-TTYPE t_writeAttr(int, NdbOperation*);
-TTYPE t_loadConst(int, NdbOperation*, int);
-TTYPE t_branch(int, NdbOperation*);
-TTYPE t_branchIfNull(int, NdbOperation*);
-TTYPE t_addReg(int, NdbOperation*);
-TTYPE t_subReg(int, NdbOperation*);
-TTYPE t_subroutineWithBranchLabel(int, NdbOperation*);
-
-char tableName[MAXTABLES][MAXSTRLEN+1] = {0};
-char attrName[MAXATTR][MAXSTRLEN+1] = {0};
-int attrValue[NUMBEROFRECORDS] = {0};
-int pkValue[NUMBEROFRECORDS] = {0};
-const int tAttributeSize = 1 ;
-const int nRecords = 20 ;
-int bTestPassed = 0;
-
-
-
-int main(int argc, const char** argv) {
-
- int tTableId = 0;
- int operationType = 0;
- int tupTest = 0 ;
- int scanTest = 0 ;
- bool loop = 0 ;
-
- Ndb* pNdb = new Ndb("TEST_DB");
- pNdb->init();
-
- if (argc != 4 || sscanf(argv[1],"%d", &operationType) != 1) {
- operationType = 1 ;
- }
- if (argc != 4 || sscanf(argv[2],"%d", &tupTest) != 1) {
- tupTest = 1 ;
- }
- if (argc != 4 || sscanf(argv[3],"%d", &scanTest) != 1) {
- scanTest = 1 ;
- }
-
- ndbout << endl
- << "Test the interpreter in TUP using SimpleTable with\n"
- << nRecords << " records" << endl << endl ;
-
- if (pNdb->waitUntilReady(30) != 0) {
- ndbout << "NDB is not ready" << endl;
- return -1;
- }
-
- // Init the pk and attr values.
- for (int i = 0; i < NUMBEROFRECORDS; i ++)
- pkValue[i] = attrValue[i] = i ;
-
- setAttrNames() ;
- setTableNames() ;
-
- const void * p = NDBT_Table::discoverTableFromDb(pNdb, tableName[0]);
- if (p != 0){
- create_table(pNdb);
- }
-
- write_rows(pNdb);
-
- ndbout << endl << "Starting interpreter in TUP test." << endl << "Operation type: " ;
-
- switch(operationType) {
- case 1:
- ndbout << "openScanRead" << endl;
- scan_rows(pNdb, operationType, tupTest, scanTest);
- break;
- case 2:
- ndbout << "openScanExclusive" << endl;
- scan_rows(pNdb, operationType, tupTest, scanTest);
- break;
- case 3:
- ndbout << "interpretedUpdateTuple" << endl;
- update_rows(pNdb, tupTest, operationType);
- break;
- case 4:
- ndbout << "interpretedDirtyUpdate" << endl;
- update_rows(pNdb, tupTest, operationType);
- break;
- case 5:
- ndbout << "interpretedDeleteTuple" << endl;
- delete_rows(pNdb, tupTest, operationType);
- break;
- case 6:
- ndbout << "deleteTuple" << endl;
- break;
- case 7:
- ndbout << "insertTuple" << endl;
- break;
- case 8:
- ndbout << "updateTuple" << endl;
- break;
- case 9:
- ndbout << "writeTuple" << endl;
- break;
- case 10:
- ndbout << "readTuple" << endl;
- break;
- case 11:
- ndbout << "readTupleExclusive" << endl;
- break;
- case 12:
- ndbout << "simpleRead" << endl;
- break;
- case 13:
- ndbout << "dirtyRead" << endl;
- break;
- case 14:
- ndbout << "dirtyUpdate" << endl;
- break;
- case 15:
- ndbout << "dirtyWrite" << endl;
- break;
- default:
- break ;
-
- }
-
-// read_and_verify_rows(pNdb, false);
-
-// delete_rows(pNdb, 0, 0) ;
- delete pNdb ;
-
- if (bTestPassed == 0) {
- ndbout << "OK: test passed" << endl;
- exit(0);
- }else{
- ndbout << "FAIL: test failed" << endl;
- exit(-1);
- }
-}
-
-void error_handler(const NdbError & err, TTYPE type_expected) {
-
- ndbout << err << endl ;
-
- switch (type_expected){
- case NO_FAIL:
- bTestPassed = -1 ;
- break ;
- case FAIL:
- ndbout << "OK: error is expected" << endl;
- break ;
- case UNDEF:
- ndbout << "assumed OK: expected result undefined" << endl ;
- break ;
- default:
- break ;
- }
-}
-
-void create_table(Ndb* pMyNdb) {
-
- /****************************************************************
- * Create SimpleTable and Attributes.
- *
- * create table SimpleTable1(
- * col0 int,
- * col1 int not null,
- * col2 int not null,
- * col3 int not null ... 129)
- *
- ***************************************************************/
-
- int check = -1 ;
- NdbSchemaCon *MySchemaTransaction = NULL ;
- NdbSchemaOp *MySchemaOp = NULL ;
-
- ndbout << endl << "Creating " << tableName[0] << " ... " << endl;
-
- MySchemaTransaction = pMyNdb->startSchemaTransaction();
- if(!MySchemaTransaction) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
-
- MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if( !MySchemaOp ) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
- // Create table
- check = MySchemaOp->createTable( tableName[0],
- 8, // Table size
- TupleKey, // Key Type
- 40 // Nr of Pages
- );
-
- if( check == -1 ) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
-
- ndbout << "Creating attributes ... " << flush;
-
- // Create first column, primary key
- check = MySchemaOp->createAttribute( attrName[0],
- TupleKey,
- 32,
- 1/*3, tAttributeSize */,
- UnSigned,
- MMBased,
- NotNullAttribute );
-
- if( check == -1 ) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
-
- // create the 2 .. n columns.
- for ( int i = 1; i < MAXATTR; i++ ){
- check = MySchemaOp->createAttribute( attrName[i],
- NoKey,
- 32,
- tAttributeSize,
- UnSigned,
- MMBased,
- NotNullAttribute );
-
- if( check == -1 ) error_handler(MySchemaTransaction->getNdbError(), NO_FAIL);
- }
-
- ndbout << "OK" << endl;
-
- if( MySchemaTransaction->execute() == -1 ) {
- ndbout << MySchemaTransaction->getNdbError() << endl;
- }else{
- ndbout << tableName[0] << " created" << endl;
- }
-
- pMyNdb->closeSchemaTransaction(MySchemaTransaction);
-
- return;
-
-}
-
-
-
-void write_rows (Ndb* pMyNdb) {
-
- /****************************************************************
- * Insert rows into SimpleTable
- *
- ***************************************************************/
-
- int check = -1 ;
- int loop_count_ops = nRecords ;
- NdbOperation *MyOperation = NULL ;
- NdbConnection *MyTransaction = NULL ;
-
- ndbout << endl << "Writing records ..." << flush;
-
- for (int count=0 ; count < loop_count_ops ; count++){
- MyTransaction = pMyNdb->startTransaction();
- if (!MyTransaction) {
- error_handler(pMyNdb->getNdbError(), NO_FAIL);
- }//if
-
- MyOperation = MyTransaction->getNdbOperation(tableName[0]);
- if (!MyOperation) {
- error_handler(pMyNdb->getNdbError(), NO_FAIL);
- }//if
-
- check = MyOperation->writeTuple();
- if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL);
-
- check = MyOperation->equal( attrName[0],(char*)&pkValue[count] );
- if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL);
-
- // Update the columns, index column already ok.
- for (int i = 1 ; i < MAXATTR; i++){
- if ((i == 2) && (count > 4)){
- check = MyOperation->setValue(attrName[i], (char*)&attrValue[count + 1]);
- }else{
- check = MyOperation->setValue(attrName[i], (char*)&attrValue[count]);
- }
- if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL);
- }
- check = MyTransaction->execute( Commit );
- if(check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL);
-
- pMyNdb->closeTransaction(MyTransaction);
- }
- ndbout <<" \tOK" << endl;
- return;
-}
-
-void verify_deleted(Ndb* pMyNdb) {
-
- int check = -1 ;
- int loop_count_ops = nRecords;
- NdbRecAttr* tTmp;
- int readValue[MAXATTR];
- NdbConnection* pMyTransaction = NULL ;
- NdbOperation* pMyOperation = NULL ;
-
- ndbout << "Verifying deleted records..."<< flush;
-
- for (int count=0 ; count < loop_count_ops ; count++){
-
- NdbConnection* pMyTransaction = pMyNdb->startTransaction();
- if (!pMyTransaction) error_handler(pMyNdb->getNdbError(), NO_FAIL);
-
- pMyOperation = pMyTransaction->getNdbOperation(tableName[0]);
- if (!pMyOperation) error_handler(pMyNdb->getNdbError(), NO_FAIL);
-
- check = pMyOperation->readTuple();
- if( check == -1 ) error_handler( pMyTransaction->getNdbError(), NO_FAIL);
-
- check = pMyOperation->equal( attrName[0],(char*)&pkValue[count] );
- if( check == -1 ) error_handler( pMyTransaction->getNdbError(), NO_FAIL);
-
- // Exepect to receive an error
- if(pMyTransaction->execute(Commit) != -1)
- if( 626 == pMyTransaction->getNdbError().code){
- ndbout << pMyTransaction->getNdbError() << endl ;
- ndbout << "OK" << endl ;
- }else{
- error_handler(pMyTransaction->getNdbError(), NO_FAIL) ;
- }
-
- pMyNdb->closeTransaction(pMyTransaction);
- }
-
- ndbout << "OK" << endl;
- return;
-};
-
-void read_and_verify_rows(Ndb* pMyNdb, bool pre) {
-
- int check = -1 ;
- int loop_count_ops = nRecords;
- char expectedCOL1[NUMBEROFRECORDS] = {0} ;
- char expectedCOL2[NUMBEROFRECORDS] = {0} ;
- NdbConnection *pMyTransaction = NULL ;
- NdbOperation *MyOp = NULL ;
- NdbRecAttr* tTmp = NULL ;
- int readValue[MAXATTR] = {0} ;
-
- ndbout << "Verifying records...\n"<< endl;
-
- for (int count=0 ; count < loop_count_ops ; count++){
-
- pMyTransaction = pMyNdb->startTransaction();
- if (!pMyTransaction) error_handler(pMyNdb->getNdbError(), NO_FAIL);
-
- MyOp = pMyTransaction->getNdbOperation(tableName[0]);
- if (!MyOp) error_handler( pMyTransaction->getNdbError(), NO_FAIL);
-
-
- check = MyOp->readTuple();
- if( check == -1 ) error_handler( MyOp->getNdbError(), NO_FAIL);
-
- check = MyOp->equal( attrName[0],(char*)&pkValue[count] );
- if( check == -1 ) error_handler( MyOp->getNdbError(), NO_FAIL);
-
- for (int count_attributes = 1; count_attributes < MAXATTR; count_attributes++){
-
- tTmp = MyOp->getValue( (char*)attrName[count_attributes], (char*)&readValue[count_attributes] );
- if(!tTmp) error_handler( MyOp->getNdbError(), NO_FAIL);
- }
-
- if( pMyTransaction->execute( Commit ) == -1 ) {
- error_handler(pMyTransaction->getNdbError(), NO_FAIL);
- } else {
- if (pre) {
- expectedCOL1[count] = readValue[1];
- expectedCOL2[count] = readValue[2];
- }
-
- ndbout << attrName[1] << "\t " << readValue[1] << "\t "
- << attrName[2] << "\t " << readValue[2] << endl;
- }
-
- pMyNdb->closeTransaction(pMyTransaction);
-
- }
-
- ndbout << "\nOK\n" << endl;
-
- return;
-
-};
-
-TTYPE t_exitMethods(int nCalls, NdbOperation * pOp, int opType) {
-
- ndbout << "Defining exitMethods test " << nCalls << ": " << endl ;;
- TTYPE ret_val = NO_FAIL ;
-
- switch(nCalls){
- case 1: // exit_nok if attr value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 14);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_ok() ;
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break;
- case 2: // exit_ok if attr value doesn't match
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 14);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_nok() ;
- pOp->def_label(0);
- if (opType == 3) {
- // For update transactions use incValue to update the tuple
- Uint32 val32 = 5;
- pOp->incValue("COL2", val32);
- }
- pOp->interpret_exit_ok();
- break ;
- case 3: // Non-existent value (128): exit_ok if if the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 128);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- pOp->interpret_exit_ok();
- ret_val = FAIL ;
- break;
- case 4: // Non-existent value (128): exit_nok if the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 128);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- ret_val = FAIL ;
- break;
- case 5: // exit_nok of the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 2);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break ;
- case 6: // exit_ok of the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 2);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- if (opType == 3) {
- // For update transactions use incValue to update the tuple
- Uint32 val32 = 5;
- pOp->incValue("COL2", val32);
- }
- pOp->interpret_exit_ok();
- break;
- case 7: // exit_nok if the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 6);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break;
- case 8: // exit_ok if the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 6);
- pOp->branch_ne(1, 2, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- if (opType == 3) {
- // For update transactions use incValue to update the tuple
- Uint32 val32 = 5;
- pOp->incValue("COL2", val32);
- }
- pOp->interpret_exit_ok();
- break ;
- case 9: // exit_nok if the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 8);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break;
- case 10: // exit_ok if the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 8);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- if (opType == 3) {
- // For update transactions use incValue to update the tuple
- Uint32 val32 = 5;
- pOp->incValue("COL2", val32);
- }
- pOp->interpret_exit_ok();
- break;
- case 11: // exit_nok if the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 10);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break;
- case 12:
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 10);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- if (opType == 3) {
- // For update transactions use incValue to update the tuple
- Uint32 val32 = 5;
- pOp->incValue("COL2", val32);
- }
- pOp->interpret_exit_ok();
- break;
- case 13:
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 10);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break;
- case 14: // exit_nok if the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 12);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break;
- case 15: // exit_ok if the value matches
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, 12);
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- if (opType == 3) {
- // For update transactions use incValue to update the tuple
- Uint32 val32 = 5;
- pOp->incValue("COL2", val32);
- }
- pOp->interpret_exit_ok();
- case 16:
- pOp->interpret_exit_nok();
- ret_val = FAIL ;
- break;
- case 17:
- pOp->interpret_exit_ok();
- break ;
- case 18:
- pOp->interpret_exit_nok();
- ret_val = FAIL ;
- break ;
- default:
- break ;
- }
- return ret_val;
-}
-
-TTYPE t_incValue(int nCalls, NdbOperation* pOp) {
-
- ndbout << "Defining incValue test " << nCalls << ": ";
- TTYPE ret_val = NO_FAIL;
-
- Uint32 val32 = 5;
- Uint64 val64 = 5;
- Uint32 attr0 = 0;
- Uint32 attr1 = 1;
- Uint32 attr20 = 20;
-
- switch(nCalls) {
- case 1:
- pOp->incValue(attrName[1], val32);
- break;
- case 2:
- pOp->incValue(attr1, val32);
- break;
- case 3:
- pOp->incValue(attrName[1], val64);
- break;
- case 4:
- pOp->incValue(attr1, val64);
- break;
- case 5:
- pOp->incValue(attrName[0], val32);
- ret_val = FAIL ;
- break;
- case 6:
- pOp->incValue(attrName[0], val64);
- ret_val = FAIL ;
- break;
- case 7:
- pOp->incValue(attr0, val32);
- ret_val = FAIL ;
- break;
- case 8:
- pOp->incValue(attr0, val64);
- ret_val = FAIL ;
- break;
- case 9:
- pOp->incValue("COL20", val32);
- ret_val = FAIL ;
- break;
- case 10:
- pOp->incValue("COL20", val64);
- ret_val = FAIL ;
- break;
- case 11:
- pOp->incValue(attr20, val32);
- ret_val = FAIL ;
- break;
- case 12:
- pOp->incValue(attr20, val64);
- ret_val = FAIL ;
- break;
- default:
- break ;
- }
- return ret_val;
-}
-
-TTYPE t_subValue(int nCalls, NdbOperation* pOp) {
-
- ndbout << "Defining subValue test " << nCalls << ": ";
-
- Uint32 val32 = 5;
- Uint64 val64 = 5;
- Uint32 attr0 = 0;
- Uint32 attr1 = 1;
- Uint32 attr20 = 20;
-
- TTYPE ret_val = NO_FAIL;
-
- switch(nCalls) {
- case 1:
- pOp->subValue("COL2", val32);
- break;
- case 2:
- pOp->subValue(attr1, val32);
- break;
- case 3:
- pOp->subValue("COL0", val32);
- ret_val = FAIL ;
- break;
- case 4:
- pOp->subValue(attr0, val32);
- ret_val = FAIL ;
- break;
- case 5:
- pOp->subValue("COL20", val32);
- ret_val = FAIL ;
- break;
- case 6:
- pOp->subValue(attr20, val32);
- ret_val = FAIL ;
- break;
- case 7:
- // Missing implementation
- //pOp->subValue("COL20", val64);
- ndbout << "Missing implementation" << endl;
- break;
- case 8:
- // Missing implementation
- //pOp->subValue("COL2", val64);
- ndbout << "Missing implementation" << endl;
- break;
- case 9:
- // Missing implementation
- //pOp->subValue("COL0", val64);
- ndbout << "Missing implementation" << endl;
- break;
- case 10:
- // Missing implementation
- //pOp->subValue(attr1, val64);
- ndbout << "Missing implementation" << endl;
- break;
- case 11:
- // Missing implementation
- //pOp->subValue(attr0, val64);
- ndbout << "Missing implementation" << endl;
- break;
- case 12:
- // Missing implementation
- //pOp->subValue(attr20, val64);
- ndbout << "Missing implementation" << endl;
- break;
- default:
- break ;
- }
- return ret_val ;
-}
-
-TTYPE t_readAttr(int nCalls, NdbOperation* pOp) {
-
- ndbout << "Defining readAttr test " << nCalls << ": ";
-
- Uint32 attr0 = 0;
- Uint32 attr1 = 1;
- Uint32 attr20 = 20;
- TTYPE ret_val = NO_FAIL;
-
- switch(nCalls) {
- case 1:
- pOp->read_attr("COL1", 1);
- break;
- case 2:
- pOp->read_attr(attr1, 1);
- ret_val = NO_FAIL ;
- break;
- case 3:
- pOp->read_attr("COL0", 1);
- ret_val = NO_FAIL ;
- break;
- case 4:
- pOp->read_attr(attr0, 1);
- ret_val = NO_FAIL ;
- break;
- case 5:
- pOp->read_attr("COL20", 1);
- ret_val = FAIL ;
- break;
- case 6:
- pOp->read_attr(20, 1);
- ret_val = FAIL ;
- break;
- case 7:
- pOp->read_attr("COL1", 8);
- ret_val = FAIL ;
- break;
- case 8:
- pOp->read_attr(attr1, 8);
- ret_val = FAIL ;
- break;
- default:
- break ;
- }
- return ret_val;
-}
-
-TTYPE t_writeAttr(int nCalls, NdbOperation* pOp) {
-
- ndbout << "Defining writeAttr test " << nCalls << ": ";
-
- pOp->load_const_u32(1, 5);
-
- Uint32 attr0 = 0;
- Uint32 attr1 = 1;
- Uint32 attr20 = 20;
- TTYPE ret_val = NO_FAIL ;
-
- switch(nCalls) {
- case 1:
- pOp->write_attr("COL1", 1);
- break;
- case 2:
- pOp->write_attr(attr1, 1);
- break;
- case 3:
- pOp->write_attr("COL0", 1);
- ret_val = FAIL ;
- break;
- case 4:
- pOp->write_attr(attr0, 1);
- ret_val = FAIL ;
- break;
- case 5:
- pOp->write_attr("COL20", 1);
- ret_val = FAIL ;
- break;
- case 6:
- pOp->write_attr(20, 1);
- ret_val = FAIL ;
- break;
- case 7:
- pOp->write_attr("COL1", 2);
- ret_val = FAIL ;
- break;
- case 8:
- pOp->write_attr(attr1, 2);
- ret_val = FAIL ;
- break;
- case 9:
- pOp->write_attr("COL1", 8);
- ret_val = FAIL ;
- break;
- case 10:
- pOp->write_attr(attr1, 8);
- ret_val = FAIL ;
- break;
- default:
- break ;
- }
- return ret_val ;
-}
-
-TTYPE t_loadConst(int nCalls, NdbOperation* pOp, int opType) {
-
- ndbout << "Defining loadConst test " << nCalls << " : ";
- TTYPE ret_val = NO_FAIL ;
-
- switch(nCalls) {
- case 1:
- // Loading null into a valid register
- pOp->load_const_null(1);
- break;
- case 2:
- // Loading null into an invalid register
- pOp->load_const_null(8);
- ret_val = FAIL ;
- break;
- case 3:
- // Test loading a 32-bit value (>65536)
- pOp->load_const_u32(1, 65600);
- break;
- case 4:
- // Test loading a 16-bit value (<65536)
- pOp->load_const_u32(1, 65500);
- break;
- case 5:
- // Test by loading to a non-valid register
- pOp->load_const_u32(8, 2);
- ret_val = FAIL ;
- break;
- case 6:
- // Test by loading a 64-bit value
- pOp->load_const_u64(1, 65600);
- break;
- case 7:
- // Test by loading a non-valid register
- pOp->load_const_u64(8, 2);
- ret_val = FAIL ;
- break;
- case 8:
- // Test by loading a valid register with -1
- pOp->load_const_u64(1, -1);
- ret_val = FAIL ;
- break;
-
- default:
- break ;
- }
-
- if (opType == 3 && FAIL != ret_val)
- pOp->write_attr("COL1", 1);
- return ret_val;
-}
-
-TTYPE t_branch(int nCalls, NdbOperation* pOp) {
-
- ndbout << "Defining branch test " << nCalls << ": " ;
-
- TTYPE ret_val = NO_FAIL ;
- Uint32 val32=5;
-
- pOp->read_attr("COL1", 1);
- pOp->load_const_u32(2, val32);
-
- switch(nCalls) {
- case 1:
- pOp->branch_eq(1, 2, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- pOp->interpret_exit_ok();
- break;
- case 2:
- pOp->branch_eq(2, 1, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- pOp->interpret_exit_ok();
- break;
- case 3:
- pOp->branch_eq(1, 1, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- pOp->interpret_exit_ok();
- break;
- default:
- //ndbout << "t_branch: default case (no test case)" << endl ;
- //return ret_val = NO_FAIL ;
- break ;
- }
- return ret_val;
-}
-
-TTYPE t_branchIfNull(int nCalls, NdbOperation* pOp) {
-
- TTYPE ret_val = NO_FAIL;
- ndbout << "Defining branchIfNull test " << nCalls << ": " << endl ;
-
- switch(nCalls) {
- case 1:
- pOp->load_const_u32(1, 1);
- pOp->branch_ne_null(1, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- pOp->interpret_exit_ok();
- break;
- case 2:
- pOp->load_const_null(1);
- pOp->branch_ne_null(1, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break;
- case 3:
- pOp->load_const_u32(1, 1);
- pOp->branch_eq_null(1, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break;
- case 4:
- pOp->load_const_null(1);
- pOp->branch_ne_null(1, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- break;
- case 5:
- // Test with a non-initialized register
- pOp->branch_ne_null(3, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- ret_val = FAIL ;
- break;
- case 6:
- // Test with a non-existing register
- pOp->branch_ne_null(8, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- ret_val = FAIL ;
- break;
- case 7:
- // Test with a non-initialized register
- pOp->branch_eq_null(3, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- ret_val = FAIL ;
- break;
- case 8:
- // Test with a non-existing register
- pOp->branch_ne_null(8, 0);
- pOp->interpret_exit_ok();
- pOp->def_label(0);
- pOp->interpret_exit_nok();
- ret_val = FAIL ;
- break;
- default:
- break ;
- }
-
- return ret_val;
-}
-
-TTYPE t_addReg(int nCalls, NdbOperation* pOp) {
-
- TTYPE ret_val = NO_FAIL ;
-
- ndbout << "Defining addReg test " << nCalls << ": ";
-
- pOp->load_const_u32(1, 65500);
- pOp->load_const_u32(2, 500);
- pOp->load_const_u64(3, 65600);
- pOp->load_const_u64(4, 95600);
-
- switch(nCalls) {
- case 1:
- pOp->add_reg(1, 2, 5);
- break;
- case 2:
- pOp->add_reg(1, 3, 5);
- break;
- case 3:
- pOp->add_reg(3, 1, 5);
- break;
- case 4:
- pOp->add_reg(3, 4, 5);
- break;
- case 5:
- pOp->add_reg(1, 6, 5);
- break;
- case 6:
- pOp->add_reg(6, 1, 5);
- break;
- case 7: // illegal register
- pOp->add_reg(1, 8, 5);
- ret_val = FAIL ;
- break;
- case 8: // another illegal register
- pOp->add_reg(8, 1, 5);
- ret_val = FAIL ;
- break;
- case 9: // and another one
- pOp->add_reg(1, 2, 8);
- ret_val = FAIL ;
- break;
- default:
- break ;
- }
- pOp->load_const_u32(7, 65000);
- pOp->branch_eq(5, 7, 0);
- pOp->interpret_exit_nok();
- pOp->def_label(0);
- pOp->interpret_exit_ok();
-
- return ret_val ;
-}
-
-TTYPE t_subReg(int nCalls, NdbOperation* pOp) {
-
- TTYPE ret_val = NO_FAIL ;
- ndbout << "Defining subReg test: " << nCalls << endl;
-
- pOp->load_const_u32(1, 65500);
- pOp->load_const_u32(2, 500);
- pOp->load_const_u64(3, 65600);
- pOp->load_const_u64(4, 95600);
-
- switch(nCalls) {
- case 1:
- pOp->sub_reg(1, 2, 5);
- pOp->load_const_u32(7, 65000);
- break;
- case 2:
- pOp->sub_reg(1, 3, 5);
- pOp->load_const_u64(7, (Uint64)-100);
- break;
- case 3:
- pOp->sub_reg(3, 1, 5);
- pOp->load_const_u64(7, (Uint64)100);
- break;
- case 4:
- pOp->sub_reg(3, 4, 5);
- pOp->load_const_u64(7, (Uint64)-30000);
- break;
- case 5:
- pOp->sub_reg(1, 6, 5);
- pOp->load_const_u64(7, 0);
- ret_val = FAIL ;
- break;
- case 6:
- pOp->sub_reg(6, 1, 5);
- pOp->load_const_u64(7, 0);
- ret_val = FAIL ;
- break;
- case 7:
- pOp->sub_reg(1, 8, 5);
- pOp->load_const_u64(7, 0);
- ret_val = FAIL ;
- break;
- case 8:
- pOp->sub_reg(8, 1, 5);
- pOp->load_const_u64(7, 0);
- ret_val = FAIL ;
- break;
- case 9:
- pOp->sub_reg(1, 2, 8);
- pOp->load_const_u32(7, (Uint32)65000);
- ret_val = FAIL;
- break;
- default:
- //ndbout << "t_subReg: default case (no test case)" << endl ;
- //return ret_val = NO_FAIL ;
- break ;
- }
- pOp->branch_eq(5, 7, 0);
- pOp->interpret_exit_nok() ;
- pOp->def_label(0);
- pOp->interpret_exit_ok() ;
-
- return ret_val;
-}
-
-TTYPE t_subroutineWithBranchLabel(int nCalls, NdbOperation* pOp) {
-
- TTYPE ret_val = NO_FAIL ;
- ndbout << "Defining subroutineWithBranchLabel test:" << nCalls << endl;
-
- pOp->load_const_u32(1, 65500);
- pOp->load_const_u32(2, 500);
- pOp->load_const_u64(3, 65600);
- pOp->load_const_u64(4, 95600);
- pOp->load_const_u32(7, 65000);
- pOp->call_sub(0) ;
-
- switch(nCalls) {
- case 1:
- pOp->def_subroutine(0) ;
- pOp->add_reg(1, 2, 5);
- break;
- case 2:
- pOp->def_subroutine(0) ;
- pOp->add_reg(1, 3, 5);
- break;
- case 3:
- pOp->def_subroutine(0) ;
- pOp->add_reg(3, 1, 5);
- break;
- case 4:
- pOp->def_subroutine(0) ;
- pOp->add_reg(3, 4, 5);
- break;
- case 5:
- pOp->def_subroutine(0) ;
- pOp->add_reg(1, 6, 5);
- break;
- case 6:
- pOp->def_subroutine(0) ;
- pOp->add_reg(6, 1, 5);
- break;
- case 7: // illegal register
- pOp->def_subroutine(0) ;
- pOp->add_reg(1, 8, 5);
- ret_val = FAIL ;
- break;
- case 8: // another illegal register
- pOp->def_subroutine(0) ;
- pOp->add_reg(8, 1, 5);
- ret_val = FAIL ;
- break;
- case 9: // and another one
- pOp->def_subroutine(0) ;
- pOp->add_reg(1, 2, 8);
- ret_val = FAIL ;
- break;
- case 10: // test subroutine nesting
- for(int sub = 0; sub < 25 ; ++sub){
- pOp->call_sub(sub) ;
- pOp->def_subroutine(sub + 1) ;
- pOp->interpret_exit_ok() ;
- pOp->ret_sub() ;
- }
- ret_val = FAIL ;
- default:
- break ;
- }
-
- pOp->branch_label(0) ;
- pOp->interpret_exit_nok() ;
- pOp->def_label(0) ;
- pOp->interpret_exit_ok() ;
- pOp->ret_sub() ;
-
- return ret_val ;
-}
-
-
-void scan_rows(Ndb* pMyNdb, int opType, int tupleType, int scanType) {
-
- int check = -1 ;
- int loop_count_ops = nRecords ;
- int eOf = -1 ;
- int readValue = 0 ;
- int readValue2 = 0 ;
- int scanCount = 0 ;
- NdbRecAttr* tTmp = NULL ;
- TTYPE fail = NO_FAIL ;
-
- for (int count=0 ; count < loop_count_ops ; count++) {
- NdbConnection* MyTransaction = pMyNdb->startTransaction();
- if (!MyTransaction) error_handler(pMyNdb->getNdbError(), NO_FAIL);
-
- NdbOperation* MyOperation = MyTransaction->getNdbOperation(tableName[0]);
- if (!MyOperation) error_handler(pMyNdb->getNdbError(), NO_FAIL);
-
- if (opType == 1)
- // Open for scan read, Creates the SCAN_TABREQ and if needed
- // SCAN_TABINFO signals.
- check = MyOperation->openScanRead(1);
- else if (opType == 2)
- // Open for scan with update of rows.
- check = MyOperation->openScanExclusive(1);
-
- // Create ATTRINFO signal(s) for interpreted program used for
- // defining search criteria and column values that should be returned.
-
- scanCount = count+1 ;
-
- switch(tupleType) {
- case 1:
- fail = t_exitMethods(scanCount, MyOperation, opType);
- break;
- case 2:
- fail = t_incValue(scanCount, MyOperation);
- break;
- case 3:
- fail = t_subValue(scanCount, MyOperation);
- break;
- case 4:
- fail = t_readAttr(scanCount, MyOperation);
- break;
- case 5:
- fail = t_writeAttr(scanCount, MyOperation);
- break;
- case 6:
- fail = t_loadConst(scanCount, MyOperation, opType);
- break;
- case 7:
- fail = t_branch(scanCount, MyOperation);
- break;
- case 8:
- fail = t_branchIfNull(scanCount, MyOperation);
- break;
- case 9:
- fail = t_addReg(scanCount, MyOperation);
- break;
- case 10:
- fail = t_subReg(scanCount, MyOperation);
- break;
- case 11:
- fail = t_subroutineWithBranchLabel(scanCount, MyOperation);
- break;
- default:
- break ;
- }
-
- if(11 != tupleType) MyOperation->getValue(attrName[1], (char*)&readValue);
-
- // Sends the SCAN_TABREQ, (SCAN_TABINFO) and ATTRINFO signals and then
- // reads the answer in TRANSID_AI. Confirmation is received through SCAN_TABCONF or
- // SCAN_TABREF if failure.
- check = MyTransaction->executeScan();
- if (check == -1) {
- //ndbout << endl << "executeScan returned: " << MyTransaction->getNdbError() << endl;
- error_handler(MyTransaction->getNdbError(), fail) ;
- pMyNdb->closeTransaction(MyTransaction);
- }else{
- // Sends the SCAN_NEXTREQ signal(s) and reads the answer in TRANS_ID signals.
- // SCAN_TABCONF or SCAN_TABREF is the confirmation.
- while (eOf = MyTransaction->nextScanResult() == 0) {
- ndbout << readValue <<"; ";
- // Here we call takeOverScanOp for update of the tuple.
- }
- ndbout << endl ;
-
- pMyNdb->closeTransaction(MyTransaction);
- if (eOf == -1) {
- ndbout << endl << "nextScanResult returned: "<< MyTransaction->getNdbError() << endl;
- } else {
- ndbout << "OK" << endl;
- }
- }
- }
- return;
-
-};
-
-
-void update_rows(Ndb* pMyNdb, int tupleType, int opType) {
- /****************************************************************
- * Update rows in SimpleTable
- * Only updates the first 3 cols.
- ***************************************************************/
-
- int check = -1 ;
- int loop_count_ops = nRecords ;
- int readValue[MAXATTR] = {0} ;
- TTYPE ret_val = NO_FAIL ;
- NdbConnection *MyTransaction = NULL ;
- NdbOperation *MyOperation = NULL ;
-
- ndbout << "Updating records ..." << endl << endl;
-
- for (int count=0 ; count < loop_count_ops ; count++){
-
- MyTransaction = pMyNdb->startTransaction();
- if (!MyTransaction) {
- error_handler(pMyNdb->getNdbError(), NO_FAIL);
- return;
- }//if
-
- MyOperation = MyTransaction->getNdbOperation(tableName[0]);
- if (MyOperation == NULL) {
- error_handler(pMyNdb->getNdbError(), NO_FAIL);
- return;
- }//if
-
- // if (operationType == 3)
- check = MyOperation->interpretedUpdateTuple();
- // else if (operationType == 4)
- // check = MyOperation->interpretedDirtyUpdate();
- if( check == -1 )
- error_handler(MyTransaction->getNdbError(), NO_FAIL);
-
- check = MyOperation->equal( attrName[0], (char*)&pkValue[count] );
- if( check == -1 )
- error_handler(MyTransaction->getNdbError(), NO_FAIL);
-
- switch(tupleType) {
- case 1:
- ret_val = t_exitMethods(count+1, MyOperation, opType);
- break;
- case 2:
- ret_val = t_incValue(count+1, MyOperation);
- break;
- case 3:
- ret_val = t_subValue(count+1, MyOperation);
- break;
- case 4:
- ret_val = t_readAttr(count+1, MyOperation);
- break;
- case 5:
- ret_val = t_writeAttr(count+1, MyOperation);
- break;
- case 6:
- ret_val = t_loadConst(count+1, MyOperation, opType);
- break;
- case 7:
- ret_val = t_branch(count+1, MyOperation);
- break;
- case 8:
- ret_val = t_branchIfNull(count+1, MyOperation);
- break;
- case 9:
- ret_val = t_addReg(count+1, MyOperation);
- break;
- case 10:
- ret_val = t_subReg(count+1, MyOperation);
- break;
- case 11:
- ret_val = t_subroutineWithBranchLabel(count+1, MyOperation);
- break;
- default:
- break ;
- }
-
- MyOperation->getValue("COL1", (char*)&readValue);
-
- if (MyTransaction->execute( Commit ) == -1 ) {
- error_handler(MyTransaction->getNdbError(), ret_val);
- }else if (NO_FAIL == ret_val ) {
- ndbout << "OK" << endl;
- } else {
- bTestPassed = -1;
- ndbout << "Test passed when expected to fail" << endl;
- }//if
- pMyNdb->closeTransaction(MyTransaction);
-
- }
-
- ndbout << "Finished updating records" << endl;
- return;
-};
-
-void delete_rows(Ndb* pMyNdb, int tupleTest, int opType) {
-
- /****************************************************************
- * Delete rows from SimpleTable
- *
- ***************************************************************/
-
- int check = 1 ;
- int loop_count_ops = nRecords ;
- int readValue[MAXATTR] = {0};
- NdbConnection *MyTransaction = NULL ;
- NdbOperation *MyOperation = NULL ;
- TTYPE ret_val = NO_FAIL ;
-
- ndbout << "Deleting records ..."<< endl << endl;
-
- for (int count=0 ; count < loop_count_ops ; count++) {
-
- MyTransaction = pMyNdb->startTransaction();
- if (!MyTransaction) error_handler(pMyNdb->getNdbError(), NO_FAIL) ;
-
- MyOperation = MyTransaction->getNdbOperation(tableName[0]);
- if (!MyOperation) error_handler(pMyNdb->getNdbError(), NO_FAIL) ;
-
- check = MyOperation->interpretedDeleteTuple();
- if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL) ;
-
- check = MyOperation->equal( attrName[0], (char*)&pkValue[count] );
- if( check == -1 ) error_handler(MyTransaction->getNdbError(), NO_FAIL) ;
-
- switch(tupleTest) {
- case 1:
- ret_val = t_exitMethods(count+1, MyOperation, opType);
- break;
- case 2:
- ret_val = t_incValue(count+1, MyOperation);
- break;
- case 3:
- ret_val = t_subValue(count+1, MyOperation);
- break;
- case 4:
- ret_val = t_readAttr(count+1, MyOperation);
- break;
- case 5:
- ret_val = t_writeAttr(count+1, MyOperation);
- break;
- case 6:
- ret_val = t_loadConst(count+1, MyOperation, opType);
- break;
- case 7:
- ret_val = t_branch(count+1, MyOperation);
- break;
- case 8:
- ret_val = t_branchIfNull(count+1, MyOperation);
- break;
- case 9:
- ret_val = t_addReg(count+1, MyOperation);
- break;
- case 10:
- ret_val = t_subReg(count+1, MyOperation);
- break;
- case 11:
- ret_val = t_subroutineWithBranchLabel(count+1, MyOperation);
- break;
- default:
- break ;
- }
-
- if(11 != tupleTest)MyOperation->getValue(attrName[1], (char*)&readValue) ;
-
- if (MyTransaction->execute( Commit ) == -1 ) {
- error_handler(MyTransaction->getNdbError(), ret_val);
- } else if (NO_FAIL == ret_val /*|| UNDEF == ret_val*/ ) {
- ndbout << "OK" << endl;
- } else {
- bTestPassed = -1;
- ndbout << "Test passed when expected to fail" << endl;
- }//if
- ndbout << endl;
- pMyNdb->closeTransaction(MyTransaction);
- }
-
- ndbout << "Finished deleting records" << endl;
- return;
-
-};
-
-
-inline void setAttrNames(){
- for (int i = 0; i < MAXATTR; i++){
- snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
- }
-}
-
-
-inline void setTableNames(){
- for (int i = 0; i < MAXTABLES; i++){
- snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
- }
-}
-
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/userInterface.cpp b/ndb/test/ndbapi/lmc-bench/src/user/userInterface.cpp
deleted file mode 100644
index 67c4e037215..00000000000
--- a/ndb/test/ndbapi/lmc-bench/src/user/userInterface.cpp
+++ /dev/null
@@ -1,740 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/***************************************************************
-* I N C L U D E D F I L E S *
-***************************************************************/
-
-#include <ndb_global.h>
-#ifndef NDB_WIN32
-#include <sys/time.h>
-#endif
-
-#include "ndb_error.hpp"
-#include "userHandle.h"
-#include "userInterface.h"
-#include <NdbThread.h>
-#include <NdbTick.h>
-#include <NdbMutex.h>
-#include <NdbSleep.h>
-#include "ndb_schema.hpp"
-#include <NDBT.hpp>
-
-/***************************************************************
-* L O C A L C O N S T A N T S *
-***************************************************************/
-
-/***************************************************************
-* L O C A L D A T A S T R U C T U R E S *
-***************************************************************/
-
-/***************************************************************
-* L O C A L F U N C T I O N S *
-***************************************************************/
-
-extern int localDbPrepare(UserHandle *uh);
-
-static int dbCreate(UserHandle *uh);
-
-/***************************************************************
-* L O C A L D A T A *
-***************************************************************/
-
-/***************************************************************
-* P U B L I C D A T A *
-***************************************************************/
-
-
-/***************************************************************
-****************************************************************
-* L O C A L F U N C T I O N S C O D E S E C T I O N *
-****************************************************************
-***************************************************************/
-
-/***************************************************************
-****************************************************************
-* P U B L I C F U N C T I O N S C O D E S E C T I O N *
-****************************************************************
-***************************************************************/
-
-/*-----------------------------------*/
-/* Time related Functions */
-/* */
-/* Returns a double value in seconds */
-/*-----------------------------------*/
-double userGetTimeSync(void)
-{
- static int initialized = 0;
- static NDB_TICKS initSecs = 0;
- static Uint32 initMicros = 0;
- double timeValue = 0;
-
- if ( !initialized ) {
- initialized = 1;
- NdbTick_CurrentMicrosecond(&initSecs, &initMicros);
- timeValue = 0.0;
- } else {
- NDB_TICKS secs = 0;
- Uint32 micros = 0;
-
- NdbTick_CurrentMicrosecond(&secs, &micros);
-
- double s = (double)secs - (double)initSecs;
- double us = (double)secs - (double)initMicros;
-
- timeValue = s + (us / 1000000.0);
- }
-
- return timeValue;
-}
-
-// 0 - OK
-// 1 - Retry transaction
-// 2 - Permanent
-int
-userDbCommit(UserHandle *uh){
- if(uh->pCurrTrans != 0){
- int check = uh->pCurrTrans->execute( Commit );
- NdbError err = uh->pCurrTrans->getNdbError();
- uh->pNDB->closeTransaction(uh->pCurrTrans);
- uh->pCurrTrans = 0;
-
- if(err.status != NdbError::Success)
- ndbout << err << endl;
-
- if(err.status == NdbError::TemporaryError &&
- err.classification == NdbError::OverloadError){
- NdbSleep_SecSleep(3);
- }
-
- return err.status;
- }
- return 2;
-}
-
-/**
- * TRUE - Normal table
- * FALSE - Table w.o. checkpoing and logging
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern int useTableLogging;
-extern int useIndexTables;
-#ifdef __cplusplus
-}
-#endif
-
-
-int
-create_table_server(Ndb * pNDB){
-
- int check;
-
- NdbSchemaCon * MySchemaTransaction = pNDB->startSchemaTransaction();
- if( MySchemaTransaction == NULL )
- error_handler("startSchemaTransaction", pNDB->getNdbError(), 0);
-
- NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if( MySchemaOp == NULL )
- error_handler("getNdbSchemaOp", MySchemaTransaction->getNdbError(), 0);
-
- // Create table
- check = MySchemaOp->createTable( SERVER_TABLE,
- 8, // Table size
- TupleKey, // Key Type
- 1 // Nr of Pages
- ,DistributionGroup,
- 6,
- 78,
- 80,
- 1,
- useTableLogging
- );
- if( check == -1 )
- error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute
- ( SERVER_SUBSCRIBER_SUFFIX,
- TupleKey,
- sizeof(char) << 3,
- SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
- String,
- MMBased,
- NotNullAttribute,
- NormalStorageAttribute,
- 0,
- 1,
- 16);
- if( check == -1 )
- error_handler("createAttribute (subscriber suffix)",
- MySchemaTransaction->getNdbError(), 0);
-
- // Create first column, primary key
- check = MySchemaOp->createAttribute( SERVER_ID,
- TupleKey,
- sizeof(ServerId) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (serverid)",
- MySchemaTransaction->getNdbError(), 0);
-
-
- check = MySchemaOp->createAttribute( SERVER_NAME,
- NoKey,
- sizeof(char) << 3,
- SERVER_NAME_LENGTH,
- String,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (server name)",
- MySchemaTransaction->getNdbError(), 0);
-
-
- check = MySchemaOp->createAttribute( SERVER_READS,
- NoKey,
- sizeof(Counter) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (server reads)",
- MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute( SERVER_INSERTS,
- NoKey,
- sizeof(Counter) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (server inserts)",
- MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute( SERVER_DELETES,
- NoKey,
- sizeof(Counter) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (server deletes)",
- MySchemaTransaction->getNdbError(), 0);
-
- if( MySchemaTransaction->execute() == -1 ) {
- error_handler("schemaTransaction->execute()",
- MySchemaTransaction->getNdbError(), 0);
- }
- pNDB->closeSchemaTransaction(MySchemaTransaction);
- return 0;
-}
-
-int
-create_table_group(Ndb * pNDB){
- int check;
-
- NdbSchemaCon * MySchemaTransaction = pNDB->startSchemaTransaction();
- if( MySchemaTransaction == NULL )
- error_handler("startSchemaTransaction", pNDB->getNdbError(), 0);
-
- NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if( MySchemaOp == NULL )
- error_handler("getNdbSchemaOp", MySchemaTransaction->getNdbError(), 0);
-
- // Create table
- check = MySchemaOp->createTable( GROUP_TABLE,
- 8, // Table size
- TupleKey, // Key Type
- 1 // Nr of Pages
- ,All,
- 6,
- 78,
- 80,
- 1,
- useTableLogging
- );
-
- if( check == -1 )
- error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
-
- // Create first column, primary key
- check = MySchemaOp->createAttribute( GROUP_ID,
- TupleKey,
- sizeof(GroupId) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (group id)",
- MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute( GROUP_NAME,
- NoKey,
- sizeof(char) << 3,
- GROUP_NAME_LENGTH,
- String,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (group name)",
- MySchemaTransaction->getNdbError(), 0);
-
-
- check = MySchemaOp->createAttribute( GROUP_ALLOW_READ,
- NoKey,
- sizeof(Permission) << 3,
- 1,
- String,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (group read)",
- MySchemaTransaction->getNdbError(), 0);
-
-
- check = MySchemaOp->createAttribute( GROUP_ALLOW_INSERT,
- NoKey,
- sizeof(Permission) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (group insert)",
- MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute( GROUP_ALLOW_DELETE,
- NoKey,
- sizeof(Permission) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (group delete)",
- MySchemaTransaction->getNdbError(), 0);
-
- if( MySchemaTransaction->execute() == -1 ) {
- error_handler("schemaTransaction->execute()",
- MySchemaTransaction->getNdbError(), 0);
- }
- pNDB->closeSchemaTransaction(MySchemaTransaction);
- return 0;
-}
-
-int
-create_table_subscriber(Ndb * pNDB){
- int check;
- NdbSchemaCon * MySchemaTransaction = pNDB->startSchemaTransaction();
- if( MySchemaTransaction == NULL )
- error_handler("startSchemaTransaction", pNDB->getNdbError(), 0);
-
- NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if( MySchemaOp == NULL )
- error_handler("getNdbSchemaOp", MySchemaTransaction->getNdbError(), 0);
-
- // Create table
- check = MySchemaOp->createTable( SUBSCRIBER_TABLE,
- 8, // Table size
- TupleKey, // Key Type
- 1 // Nr of Pages
- ,DistributionGroup,
- 6,
- 78,
- 80,
- 1,
- useTableLogging
- );
- if( check == -1 )
- error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
-
- // Create first column, primary key
- check = MySchemaOp->createAttribute
- ( SUBSCRIBER_NUMBER,
- TupleKey,
- sizeof(char) << 3,
- SUBSCRIBER_NUMBER_LENGTH,
- String,
- MMBased,
- NotNullAttribute,
- (useIndexTables ? IndexStorageAttribute : NormalStorageAttribute),
- 0,
- 1,
- 16);
- if( check == -1 )
- error_handler("createAttribute (subscriber number)",
- MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute( SUBSCRIBER_NAME,
- NoKey,
- sizeof(char) << 3,
- SUBSCRIBER_NAME_LENGTH,
- String,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (subscriber name)",
- MySchemaTransaction->getNdbError(), 0);
-
-
- check = MySchemaOp->createAttribute( SUBSCRIBER_GROUP,
- NoKey,
- sizeof(GroupId) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (subscriber_group)",
- MySchemaTransaction->getNdbError(), 0);
-
-
- check = MySchemaOp->createAttribute( SUBSCRIBER_LOCATION,
- NoKey,
- sizeof(Location) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (server reads)",
- MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute( SUBSCRIBER_SESSIONS,
- NoKey,
- sizeof(ActiveSessions) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (subscriber_sessions)",
- MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute( SUBSCRIBER_CHANGED_BY,
- NoKey,
- sizeof(char) << 3,
- CHANGED_BY_LENGTH,
- String,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (subscriber_changed_by)",
- MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute( SUBSCRIBER_CHANGED_TIME,
- NoKey,
- sizeof(char) << 3,
- CHANGED_TIME_LENGTH,
- String,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (subscriber_changed_time)",
- MySchemaTransaction->getNdbError(), 0);
-
- if( MySchemaTransaction->execute() == -1 ) {
- error_handler("schemaTransaction->execute()",
- MySchemaTransaction->getNdbError(), 0);
- }
- pNDB->closeSchemaTransaction(MySchemaTransaction);
- return 0;
-}
-
-int
-create_table_session(Ndb * pNDB){
- int check;
- NdbSchemaCon * MySchemaTransaction = pNDB->startSchemaTransaction();
- if( MySchemaTransaction == NULL )
- error_handler("startSchemaTransaction", pNDB->getNdbError(), 0);
-
- NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if( MySchemaOp == NULL )
- error_handler("getNdbSchemaOp",
- MySchemaTransaction->getNdbError(), 0);
-
- // Create table
- check = MySchemaOp->createTable( SESSION_TABLE,
- 8, // Table size
- TupleKey, // Key Type
- 1 // Nr of Pages
- ,DistributionGroup,
- 6,
- 78,
- 80,
- 1,
- useTableLogging
- );
- if( check == -1 )
- error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
-
- check = MySchemaOp->createAttribute( SESSION_SUBSCRIBER,
- TupleKey,
- sizeof(char) << 3,
- SUBSCRIBER_NUMBER_LENGTH,
- String,
- MMBased,
- NotNullAttribute,
- NormalStorageAttribute,
- 0,
- 1,
- 16);
- if( check == -1 )
- error_handler("createAttribute (session_subscriber)",
- MySchemaTransaction->getNdbError(), 0);
-
- // Create first column, primary key
- check = MySchemaOp->createAttribute( SESSION_SERVER,
- TupleKey,
- sizeof(ServerId) << 3,
- 1,
- UnSigned,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (session_server)",
- MySchemaTransaction->getNdbError(), 0);
-
-
- check = MySchemaOp->createAttribute( SESSION_DATA,
- NoKey,
- sizeof(char) << 3,
- SESSION_DETAILS_LENGTH,
- String,
- MMBased,
- NotNullAttribute );
- if( check == -1 )
- error_handler("createAttribute (session_data)",
- MySchemaTransaction->getNdbError(), 0);
-
- if( MySchemaTransaction->execute() == -1 ) {
- error_handler("schemaTransaction->execute()",
- MySchemaTransaction->getNdbError(), 0);
- }
- pNDB->closeSchemaTransaction(MySchemaTransaction);
- return 0;
-}
-
-void
-create_table(const char * name, int (* function)(Ndb * pNDB), Ndb* pNDB){
- printf("creating table %s...", name);
- if(pNDB->getDictionary()->getTable(name) != 0){
- printf(" it already exists\n");
- return;
- } else {
- printf("\n");
- }
- function(pNDB);
- printf("creating table %s... done\n", name);
-}
-
-static int dbCreate(Ndb * pNDB)
-{
- create_table(SUBSCRIBER_TABLE, create_table_subscriber, pNDB);
- create_table(GROUP_TABLE , create_table_group, pNDB);
- create_table(SESSION_TABLE , create_table_session, pNDB);
- create_table(SERVER_TABLE , create_table_server, pNDB);
- return 0;
-}
-
-#ifndef NDB_WIN32
-#include <unistd.h>
-#endif
-
-static NdbMutex* startupMutex = NdbMutex_Create();
-
-UserHandle*
-userDbConnect(uint32 createDb, char *dbName)
-{
- NdbMutex_Lock(startupMutex);
-
- Ndb * pNDB = new Ndb("");
-
- //printf("Initializing...\n");
- pNDB->init();
-
- //printf("Waiting...");
- while(pNDB->waitUntilReady() != 0){
- //printf("...");
- }
- // printf("done\n");
-
- if( createDb )
- dbCreate(pNDB);
-
-
- UserHandle * uh = new UserHandle;
- uh->pNDB = pNDB;
- uh->pCurrTrans = 0;
-
- NdbMutex_Unlock(startupMutex);
-
- return uh;
-}
-
-void userDbDisconnect(UserHandle *uh)
-{
- delete uh;
-}
-
-int userDbInsertServer(UserHandle *uh,
- ServerId serverId,
- SubscriberSuffix suffix,
- ServerName name)
-{
- int check;
-
- uint32 noOfRead = 0;
- uint32 noOfInsert = 0;
- uint32 noOfDelete = 0;
-
- NdbConnection * MyTransaction = 0;
- if(uh->pCurrTrans != 0){
- MyTransaction = uh->pCurrTrans;
- } else {
- uh->pCurrTrans = MyTransaction = uh->pNDB->startTransaction();
- }
- if (MyTransaction == NULL)
- error_handler("startTranscation", uh->pNDB->getNdbError(), 0);
-
- NdbOperation *MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
- CHECK_NULL(MyOperation, "getNdbOperation", MyTransaction);
-
- check = MyOperation->insertTuple();
- CHECK_MINUS_ONE(check, "insert tuple", MyTransaction);
-
- check = MyOperation->equal(SERVER_ID, (char*)&serverId);
- CHECK_MINUS_ONE(check, "setValue id", MyTransaction);
-
- check = MyOperation->setValue(SERVER_SUBSCRIBER_SUFFIX, suffix);
- CHECK_MINUS_ONE(check, "setValue suffix", MyTransaction);
-
- check = MyOperation->setValue(SERVER_NAME, name);
- CHECK_MINUS_ONE(check, "setValue name", MyTransaction);
-
- check = MyOperation->setValue(SERVER_READS, (char*)&noOfRead);
- CHECK_MINUS_ONE(check, "setValue reads", MyTransaction);
-
- check = MyOperation->setValue(SERVER_INSERTS, (char*)&noOfInsert);
- CHECK_MINUS_ONE(check, "setValue inserts", MyTransaction);
-
- check = MyOperation->setValue(SERVER_DELETES, (char*)&noOfDelete);
- CHECK_MINUS_ONE(check, "setValue deletes", MyTransaction);
-
- return 0;
-}
-
-int userDbInsertSubscriber(UserHandle *uh,
- SubscriberNumber number,
- uint32 groupId,
- SubscriberName name)
-{
- int check;
- uint32 activeSessions = 0;
- Location l = 0;
- ChangedBy changedBy; snprintf(changedBy, sizeof(changedBy), "ChangedBy");
- ChangedTime changedTime; snprintf(changedTime, sizeof(changedTime), "ChangedTime");
-
- NdbConnection * MyTransaction = 0;
- if(uh->pCurrTrans != 0){
- MyTransaction = uh->pCurrTrans;
- } else {
- uh->pCurrTrans = MyTransaction = uh->pNDB->startTransaction();
- }
- if (MyTransaction == NULL)
- error_handler("startTranscation", uh->pNDB->getNdbError(), 0);
-
- NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
- CHECK_NULL(MyOperation, "getNdbOperation", MyTransaction);
-
- check = MyOperation->insertTuple();
- CHECK_MINUS_ONE(check, "insertTuple", MyTransaction);
-
- check = MyOperation->equal(SUBSCRIBER_NUMBER, number);
- CHECK_MINUS_ONE(check, "equal", MyTransaction);
-
- check = MyOperation->setValue(SUBSCRIBER_NAME, name);
- CHECK_MINUS_ONE(check, "setValue name", MyTransaction);
-
- check = MyOperation->setValue(SUBSCRIBER_GROUP, (char*)&groupId);
- CHECK_MINUS_ONE(check, "setValue group", MyTransaction);
-
- check = MyOperation->setValue(SUBSCRIBER_LOCATION, (char*)&l);
- CHECK_MINUS_ONE(check, "setValue location", MyTransaction);
-
- check = MyOperation->setValue(SUBSCRIBER_SESSIONS, (char*)&activeSessions);
- CHECK_MINUS_ONE(check, "setValue sessions", MyTransaction);
-
- check = MyOperation->setValue(SUBSCRIBER_CHANGED_BY, changedBy);
- CHECK_MINUS_ONE(check, "setValue changedBy", MyTransaction);
-
- check = MyOperation->setValue(SUBSCRIBER_CHANGED_TIME, changedTime);
- CHECK_MINUS_ONE(check, "setValue changedTime", MyTransaction);
-
- return 0;
-}
-
-int userDbInsertGroup(UserHandle *uh,
- GroupId groupId,
- GroupName name,
- Permission allowRead,
- Permission allowInsert,
- Permission allowDelete)
-{
- int check;
-
- NdbConnection * MyTransaction = 0;
- if(uh->pCurrTrans != 0){
- MyTransaction = uh->pCurrTrans;
- } else {
- uh->pCurrTrans = MyTransaction = uh->pNDB->startTransaction();
- }
- if (MyTransaction == NULL)
- error_handler("startTranscation", uh->pNDB->getNdbError(), 0);
-
- NdbOperation *MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
- CHECK_NULL(MyOperation, "getNdbOperation", MyTransaction);
-
- check = MyOperation->insertTuple();
- CHECK_MINUS_ONE(check, "insertTuple", MyTransaction);
-
- check = MyOperation->equal(GROUP_ID, (char*)&groupId);
- CHECK_MINUS_ONE(check, "equal", MyTransaction);
-
- check = MyOperation->setValue(GROUP_NAME, name);
- CHECK_MINUS_ONE(check, "setValue name", MyTransaction);
-
- check = MyOperation->setValue(GROUP_ALLOW_READ, (char*)&allowRead);
- CHECK_MINUS_ONE(check, "setValue allowRead", MyTransaction);
-
- check = MyOperation->setValue(GROUP_ALLOW_INSERT, (char*)&allowInsert);
- CHECK_MINUS_ONE(check, "setValue allowInsert", MyTransaction);
-
- check = MyOperation->setValue(GROUP_ALLOW_DELETE, (char*)&allowDelete);
- CHECK_MINUS_ONE(check, "setValue allowDelete", MyTransaction);
-
- return 0;
-}
-
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/generator/mainAsyncGenerator.cpp b/ndb/test/ndbapi/mainAsyncGenerator.cpp
index f613c66d07b..f613c66d07b 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/generator/mainAsyncGenerator.cpp
+++ b/ndb/test/ndbapi/mainAsyncGenerator.cpp
diff --git a/ndb/test/ndbapi/msa.cpp b/ndb/test/ndbapi/msa.cpp
new file mode 100644
index 00000000000..7a734f9cb79
--- /dev/null
+++ b/ndb/test/ndbapi/msa.cpp
@@ -0,0 +1,1205 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+
+#include <NdbApi.hpp>
+#include <NdbSchemaCon.hpp>
+#include <NdbCondition.h>
+#include <NdbMutex.h>
+#include <NdbSleep.h>
+#include <NdbThread.h>
+#include <NdbTick.h>
+
+const char* const c_szDatabaseName = "TEST_DB";
+
+const char* const c_szTableNameStored = "CCStored";
+const char* const c_szTableNameTemp = "CCTemp";
+
+const char* const c_szContextId = "ContextId";
+const char* const c_szVersion = "Version";
+const char* const c_szLockFlag = "LockFlag";
+const char* const c_szLockTime = "LockTime";
+const char* const c_szLockTimeUSec = "LockTimeUSec";
+const char* const c_szContextData = "ContextData";
+
+const char* g_szTableName = c_szTableNameStored;
+
+
+#ifdef NDB_WIN32
+HANDLE hShutdownEvent = 0;
+#else
+#include <signal.h>
+bool bShutdownEvent = false;
+#endif
+long g_nMaxContextIdPerThread = 5000;
+long g_nNumThreads = 0;
+long g_nMaxCallsPerSecond = 0;
+long g_nMaxRetry = 50;
+bool g_bWriteTuple = false;
+bool g_bInsertInitial = false;
+bool g_bVerifyInitial = false;
+
+NdbMutex* g_pNdbMutexPrintf = 0;
+NdbMutex* g_pNdbMutexIncrement = 0;
+long g_nNumCallsProcessed = 0;
+NDB_TICKS g_tStartTime = 0;
+NDB_TICKS g_tEndTime = 0;
+
+long g_nNumberOfInitialInsert = 0;
+long g_nNumberOfInitialVerify = 0;
+
+const long c_nMaxMillisecForAllCall = 5000;
+long* g_plCountMillisecForCall = 0;
+const long c_nMaxMillisecForAllTrans = 5000;
+long* g_plCountMillisecForTrans = 0;
+bool g_bReport = false;
+bool g_bReportPlus = false;
+
+
+// data for CALL_CONTEXT and GROUP_RESOURCE
+static char STATUS_DATA[]=
+"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
+"101112131415161718191A1B1C1D1E1F000102030405060708090A0B0C0D0E0F"
+"202122232425262728292A2B2C2D2E2F000102030405060708090A0B0C0D0E0F"
+"303132333435363738393A3B3C3D3E3F000102030405060708090A0B0C0D0E0F"
+"404142434445464748494A4B4C4D4E4F000102030405060708090A0B0C0D0E0F"
+"505152535455565758595A5B5C5D5E5F000102030405060708090A0B0C0D0E0F"
+"606162636465666768696A6B6C6D6E6F000102030405060708090A0B0C0D0E0F"
+"707172737475767778797A7B7C7D7E7F000102030405060708090A0B0C0D0E0F"
+"808182838485868788898A8B8C8D8E8F000102030405060708090A0B0C0D0E0F"
+"909192939495969798999A9B9C9D9E9F000102030405060708090A0B0C0D0E0F"
+"10010110210310410510610710810910A000102030405060708090A0B0C0D0EF"
+"10B10C10D10E10F110111112113114115000102030405060708090A0B0C0D0EF"
+"11611711811911A11B11C11D11E11F120000102030405060708090A0B0C0D0EF"
+"12112212312412512612712812912A12B000102030405060708090A0B0C0D0EF"
+"12C12D12E12F130131132134135136137000102030405060708090A0B0C0D0EF"
+"13813913A13B13C13D13E13F140141142000102030405060708090A0B0C0D0EF"
+"14314414514614714814914A14B14C14D000102030405060708090A0B0C0D0EF"
+"14E14F150151152153154155156157158000102030405060708090A0B0C0D0EF"
+"15915A15B15C15D15E15F160161162163000102030405060708090A0B0C0D0EF"
+"16416516616716816916A16B16C16D16E000102030405060708090A0B0C0D0EF"
+"16F170171172173174175176177178179000102030405060708090A0B0C0D0EF"
+"17A17B17C17D17E17F180181182183184000102030405060708090A0B0C0D0EF"
+"18518618718818918A18B18C18D18E18F000102030405060708090A0B0C0D0EF"
+"19019119219319419519619719819919A000102030405060708090A0B0C0D0EF"
+"19B19C19D19E19F200201202203204205000102030405060708090A0B0C0D0EF"
+"20620720820920A20B20C20D20F210211000102030405060708090A0B0C0D0EF"
+"21221321421521621721821921A21B21C000102030405060708090A0B0C0D0EF"
+"21D21E21F220221222223224225226227000102030405060708090A0B0C0D0EF"
+"22822922A22B22C22D22E22F230231232000102030405060708090A0B0C0D0EF"
+"23323423523623723823923A23B23C23D000102030405060708090A0B0C0D0EF"
+"23E23F240241242243244245246247248000102030405060708090A0B0C0D0EF"
+"24924A24B24C24D24E24F250251252253000102030405060708090A0B0C0D0EF"
+"101112131415161718191A1B1C1D1E1F000102030405060708090A0B0C0D0E0F"
+"202122232425262728292A2B2C2D2E2F000102030405060708090A0B0C0D0E0F"
+"303132333435363738393A3B3C3D3E3F000102030405060708090A0B0C0D0E0F"
+"404142434445464748494A4B4C4D4E4F000102030405060708090A0B0C0D0E0F"
+"505152535455565758595A5B5C5D5E5F000102030405060708090A0B0C0D0E0F"
+"606162636465666768696A6B6C6D6E6F000102030405060708090A0B0C0D0E0F"
+"707172737475767778797A7B7C7D7E7F000102030405060708090A0B0C0D0E0F"
+"808182838485868788898A8B8C8D8E8F000102030405060708090A0B0C0D0E0F"
+"909192939495969798999A9B9C9D9E9F000102030405060708090A0B0C0D0E0F"
+"10010110210310410510610710810910A000102030405060708090A0B0C0D0EF"
+"10B10C10D10E10F110111112113114115000102030405060708090A0B0C0D0EF"
+"11611711811911A11B11C11D11E11F120000102030405060708090A0B0C0D0EF"
+"12112212312412512612712812912A12B000102030405060708090A0B0C0D0EF"
+"12C12D12E12F130131132134135136137000102030405060708090A0B0C0D0EF"
+"13813913A13B13C13D13E13F140141142000102030405060708090A0B0C0D0EF"
+"14314414514614714814914A14B14C14D000102030405060708090A0B0C0D0EF"
+"14E14F150151152153154155156157158000102030405060708090A0B0C0D0EF"
+"15915A15B15C15D15E15F160161162163000102030405060708090A0B0C0D0EF"
+"16416516616716816916A16B16C16D16E000102030405060708090A0B0C0D0EF"
+"16F170171172173174175176177178179000102030405060708090A0B0C0D0EF"
+"17A17B17C17D17E17F180181182183184000102030405060708090A0B0C0D0EF"
+"18518618718818918A18B18C18D18E18F000102030405060708090A0B0C0D0EF"
+"19019119219319419519619719819919A000102030405060708090A0B0C0D0EF"
+"19B19C19D19E19F200201202203204205000102030405060708090A0B0C0D0EF"
+"20620720820920A20B20C20D20F210211000102030405060708090A0B0C0D0EF"
+"21221321421521621721821921A21B21C000102030405060708090A0B0C0D0EF"
+"21D21E21F220221222223224225226227000102030405060708090A0B0C0D0EF"
+"22822922A22B22C22D22E22F230231232000102030405060708090A0B0C0D0EF"
+"23323423523623723823923A23B23C23D000102030405060708090A0B0C0D0EF"
+"2366890FE1438751097E7F6325DC0E6326F"
+"25425525625725825925A25B25C25D25E25F000102030405060708090A0B0C0F";
+
+long g_nStatusDataSize = sizeof(STATUS_DATA);
+
+
+// Thread function for Call Context Inserts
+
+
+#ifdef NDB_WIN32
+
+BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
+{
+ if(CTRL_C_EVENT == dwCtrlType)
+ {
+ SetEvent(hShutdownEvent);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#else
+
+void CtrlCHandler(int)
+{
+ bShutdownEvent = true;
+}
+
+#endif
+
+
+
+void ReportNdbError(const char* szMsg, const NdbError& err)
+{
+ NdbMutex_Lock(g_pNdbMutexPrintf);
+ printf("%s: %d: %s\n", szMsg, err.code, (err.message ? err.message : ""));
+ NdbMutex_Unlock(g_pNdbMutexPrintf);
+}
+
+
+void
+ReportCallsPerSecond(long nNumCallsProcessed,
+ NDB_TICKS tStartTime,
+ NDB_TICKS tEndTime)
+{
+ NDB_TICKS tElapsed = tEndTime - tStartTime;
+ long lCallsPerSec;
+ if(tElapsed>0)
+ lCallsPerSec = (long)((1000*nNumCallsProcessed)/tElapsed);
+ else
+ lCallsPerSec = 0;
+
+ NdbMutex_Lock(g_pNdbMutexPrintf);
+ printf("Time Taken for %ld Calls is %ld msec (= %ld calls/sec)\n",
+ nNumCallsProcessed, (long)tElapsed, lCallsPerSec);
+ NdbMutex_Unlock(g_pNdbMutexPrintf);
+}
+
+
+#ifndef NDB_WIN32
+void InterlockedIncrement(long* lp) // expensive
+{
+ NdbMutex_Lock(g_pNdbMutexIncrement);
+ (*lp)++;
+ NdbMutex_Unlock(g_pNdbMutexIncrement);
+}
+#endif
+
+
+void InterlockedIncrementAndReport(void)
+{
+ NdbMutex_Lock(g_pNdbMutexIncrement);
+ ++g_nNumCallsProcessed;
+ if((g_nNumCallsProcessed%1000)==0)
+ {
+ g_tEndTime = NdbTick_CurrentMillisecond();
+ if(g_tStartTime)
+ ReportCallsPerSecond(1000, g_tStartTime, g_tEndTime);
+
+ g_tStartTime = g_tEndTime;
+ }
+ NdbMutex_Unlock(g_pNdbMutexIncrement);
+}
+
+
+void SleepOneCall(void)
+{
+ int iMillisecToSleep;
+ if(g_nMaxCallsPerSecond>0)
+ iMillisecToSleep = (1000*g_nNumThreads)/g_nMaxCallsPerSecond;
+ else
+ iMillisecToSleep = 50;
+
+ if(iMillisecToSleep>0)
+ NdbSleep_MilliSleep(iMillisecToSleep);
+
+}
+
+
+
+int QueryTransaction(Ndb* pNdb,
+ long iContextId,
+ long* piVersion,
+ long* piLockFlag,
+ long* piLockTime,
+ long* piLockTimeUSec,
+ char* pchContextData,
+ NdbError& err)
+{
+ int iRes = -1;
+ NdbConnection* pNdbConnection = pNdb->startTransaction(0, (const char*)&iContextId, 4);
+ if(pNdbConnection)
+ {
+ NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName);
+ if(pNdbOperation)
+ {
+ NdbRecAttr* pNdbRecAttrVersion;
+ NdbRecAttr* pNdbRecAttrLockFlag;
+ NdbRecAttr* pNdbRecAttrLockTime;
+ NdbRecAttr* pNdbRecAttrLockTimeUSec;
+ NdbRecAttr* pNdbRecAttrContextData;
+ if(!pNdbOperation->readTuple()
+ && !pNdbOperation->equal(c_szContextId, (Int32)iContextId)
+ && (pNdbRecAttrVersion=pNdbOperation->getValue(c_szVersion, (char*)piVersion))
+ && (pNdbRecAttrLockFlag=pNdbOperation->getValue(c_szLockFlag, (char*)piLockFlag))
+ && (pNdbRecAttrLockTime=pNdbOperation->getValue(c_szLockTime, (char*)piLockTime))
+ && (pNdbRecAttrLockTimeUSec=pNdbOperation->getValue(c_szLockTimeUSec, (char*)piLockTimeUSec))
+ && (pNdbRecAttrContextData=pNdbOperation->getValue(c_szContextData, pchContextData)))
+ {
+ if(!pNdbConnection->execute(Commit))
+ iRes = 0;
+ else
+ err = pNdbConnection->getNdbError();
+ }
+ else
+ err = pNdbOperation->getNdbError();
+ }
+ else
+ err = pNdbConnection->getNdbError();
+
+ pNdb->closeTransaction(pNdbConnection);
+ }
+ else
+ err = pNdb->getNdbError();
+
+ return iRes;
+}
+
+
+int RetryQueryTransaction(Ndb* pNdb,
+ long iContextId,
+ long* piVersion,
+ long* piLockFlag,
+ long* piLockTime,
+ long* piLockTimeUSec,
+ char* pchContextData,
+ NdbError& err,
+ int& nRetry)
+{
+ int iRes = -1;
+ nRetry = 0;
+ bool bRetry = true;
+ while(bRetry && nRetry<g_nMaxRetry)
+ {
+ if(!QueryTransaction(pNdb, iContextId, piVersion, piLockFlag,
+ piLockTime, piLockTimeUSec, pchContextData, err))
+ {
+ iRes = 0;
+ bRetry = false;
+ }
+ else
+ {
+ switch(err.status)
+ {
+ case NdbError::TemporaryError:
+ case NdbError::UnknownResult:
+ SleepOneCall();
+ ++nRetry;
+ break;
+
+ case NdbError::PermanentError:
+ default:
+ bRetry = false;
+ break;
+ }
+ }
+ }
+ return iRes;
+}
+
+
+int DeleteTransaction(Ndb* pNdb, long iContextId, NdbError& err)
+{
+ int iRes = -1;
+ NdbConnection* pNdbConnection = pNdb->startTransaction(0, (const char*)&iContextId, 4);
+ if(pNdbConnection)
+ {
+ NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName);
+ if(pNdbOperation)
+ {
+ if(!pNdbOperation->deleteTuple()
+ && !pNdbOperation->equal(c_szContextId, (Int32)iContextId))
+ {
+ if(pNdbConnection->execute(Commit) == 0)
+ iRes = 0;
+ else
+ err = pNdbConnection->getNdbError();
+ }
+ else
+ err = pNdbOperation->getNdbError();
+ }
+ else
+ err = pNdbConnection->getNdbError();
+
+ pNdb->closeTransaction(pNdbConnection);
+ }
+ else
+ err = pNdb->getNdbError();
+
+ return iRes;
+}
+
+
+
+int RetryDeleteTransaction(Ndb* pNdb, long iContextId, NdbError& err, int& nRetry)
+{
+ int iRes = -1;
+ nRetry = 0;
+ bool bRetry = true;
+ bool bUnknown = false;
+ while(bRetry && nRetry<g_nMaxRetry)
+ {
+ if(!DeleteTransaction(pNdb, iContextId, err))
+ {
+ iRes = 0;
+ bRetry = false;
+ }
+ else
+ {
+ switch(err.status)
+ {
+ case NdbError::UnknownResult:
+ bUnknown = true;
+ ++nRetry;
+ break;
+
+ case NdbError::TemporaryError:
+ bUnknown = false;
+ SleepOneCall();
+ ++nRetry;
+ break;
+
+ case NdbError::PermanentError:
+ if(err.code==626 && bUnknown)
+ iRes = 0;
+ bRetry = false;
+ break;
+
+ default:
+ bRetry = false;
+ break;
+ }
+ }
+ }
+ return iRes;
+}
+
+
+
+int InsertTransaction(Ndb* pNdb,
+ long iContextID,
+ long iVersion,
+ long iLockFlag,
+ long iLockTime,
+ long iLockTimeUSec,
+ const char* pchContextData,
+ NdbError& err)
+{
+ int iRes = -1;
+ NdbConnection* pNdbConnection = pNdb->startTransaction(0, (const char*)&iContextID, 4);
+ if(pNdbConnection)
+ {
+ NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName);
+ if(pNdbOperation)
+ {
+ if(!(g_bWriteTuple ? pNdbOperation->writeTuple() : pNdbOperation->insertTuple())
+ && !pNdbOperation->equal(c_szContextId, (Int32)iContextID)
+ && !pNdbOperation->setValue(c_szVersion, (Int32)iVersion)
+ && !pNdbOperation->setValue(c_szLockFlag, (Int32)iLockFlag)
+ && !pNdbOperation->setValue(c_szLockTime, (Int32)iLockTime)
+ && !pNdbOperation->setValue(c_szLockTimeUSec, (Int32)iLockTimeUSec)
+ && !pNdbOperation->setValue(c_szContextData, pchContextData, g_nStatusDataSize))
+ {
+ if(!pNdbConnection->execute(Commit))
+ iRes = 0;
+ else
+ err = pNdbConnection->getNdbError();
+ }
+ else
+ err = pNdbOperation->getNdbError();
+ }
+ else
+ err = pNdbConnection->getNdbError();
+
+ pNdb->closeTransaction(pNdbConnection);
+ }
+ else
+ err = pNdb->getNdbError();
+
+ return iRes;
+}
+
+
+
+int RetryInsertTransaction(Ndb* pNdb,
+ long iContextId,
+ long iVersion,
+ long iLockFlag,
+ long iLockTime,
+ long iLockTimeUSec,
+ const char* pchContextData,
+ NdbError& err, int& nRetry)
+{
+ int iRes = -1;
+ nRetry = 0;
+ bool bRetry = true;
+ bool bUnknown = false;
+ while(bRetry && nRetry<g_nMaxRetry)
+ {
+ if(!InsertTransaction(pNdb, iContextId, iVersion, iLockFlag,
+ iLockTime, iLockTimeUSec, pchContextData, err))
+ {
+ iRes = 0;
+ bRetry = false;
+ }
+ else
+ {
+ switch(err.status)
+ {
+ case NdbError::UnknownResult:
+ bUnknown = true;
+ ++nRetry;
+ break;
+
+ case NdbError::TemporaryError:
+ bUnknown = false;
+ SleepOneCall();
+ ++nRetry;
+ break;
+
+ case NdbError::PermanentError:
+ if(err.code==630 && bUnknown)
+ iRes = 0;
+ bRetry = false;
+ break;
+
+ default:
+ bRetry = false;
+ break;
+ }
+ }
+ }
+ return iRes;
+}
+
+
+int UpdateTransaction(Ndb* pNdb, long iContextId, NdbError& err)
+{
+ int iRes = -1;
+ NdbConnection* pNdbConnection = pNdb->startTransaction(0, (const char*)&iContextId, 4);
+ if(pNdbConnection)
+ {
+ NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName);
+ if(pNdbOperation)
+ {
+ if(!pNdbOperation->updateTuple()
+ && !pNdbOperation->equal(c_szContextId, (Int32)iContextId)
+ && !pNdbOperation->setValue(c_szContextData, STATUS_DATA, g_nStatusDataSize))
+ {
+ if(!pNdbConnection->execute(Commit))
+ iRes = 0;
+ else
+ err = pNdbConnection->getNdbError();
+ }
+ else
+ err = pNdbOperation->getNdbError();
+ }
+ else
+ err = pNdbConnection->getNdbError();
+
+ pNdb->closeTransaction(pNdbConnection);
+ }
+ else
+ err = pNdb->getNdbError();
+
+ return iRes;
+}
+
+
+int RetryUpdateTransaction(Ndb* pNdb, long iContextId, NdbError& err, int& nRetry)
+{
+ int iRes = -1;
+ nRetry = 0;
+ bool bRetry = true;
+ while(bRetry && nRetry<g_nMaxRetry)
+ {
+ if(!UpdateTransaction(pNdb, iContextId, err))
+ {
+ iRes = 0;
+ bRetry = false;
+ }
+ else
+ {
+ switch(err.status)
+ {
+ case NdbError::TemporaryError:
+ case NdbError::UnknownResult:
+ SleepOneCall();
+ ++nRetry;
+ break;
+
+ case NdbError::PermanentError:
+ default:
+ bRetry = false;
+ break;
+ }
+ }
+ }
+ return iRes;
+}
+
+
+
+int InsertInitialRecords(Ndb* pNdb, long nInsert, long nSeed)
+{
+ int iRes = -1;
+ char szMsg[100];
+ for(long i=0; i<nInsert; ++i)
+ {
+ int iContextID = i+nSeed;
+ int nRetry = 0;
+ NdbError err;
+ memset(&err, 0, sizeof(err));
+ NDB_TICKS tStartTrans = NdbTick_CurrentMillisecond();
+ iRes = RetryInsertTransaction(pNdb, iContextID, nSeed, iContextID,
+ (long)(tStartTrans/1000), (long)((tStartTrans%1000)*1000),
+ STATUS_DATA, err, nRetry);
+ NDB_TICKS tEndTrans = NdbTick_CurrentMillisecond();
+ long lMillisecForThisTrans = (long)(tEndTrans-tStartTrans);
+ if(nRetry>0)
+ {
+ sprintf(szMsg, "insert retried %d times, time %ld msec.",
+ nRetry, lMillisecForThisTrans);
+ ReportNdbError(szMsg, err);
+ }
+ if(iRes)
+ {
+ ReportNdbError("Insert initial record failed", err);
+ return iRes;
+ }
+ InterlockedIncrement(&g_nNumberOfInitialInsert);
+ }
+ return iRes;
+}
+
+
+
+int VerifyInitialRecords(Ndb* pNdb, long nVerify, long nSeed)
+{
+ int iRes = -1;
+ char* pchContextData = new char[g_nStatusDataSize];
+ char szMsg[100];
+ long iPrevLockTime = -1;
+ long iPrevLockTimeUSec = -1;
+ for(long i=0; i<nVerify; ++i)
+ {
+ int iContextID = i+nSeed;
+ long iVersion = 0;
+ long iLockFlag = 0;
+ long iLockTime = 0;
+ long iLockTimeUSec = 0;
+ int nRetry = 0;
+ NdbError err;
+ memset(&err, 0, sizeof(err));
+ NDB_TICKS tStartTrans = NdbTick_CurrentMillisecond();
+ iRes = RetryQueryTransaction(pNdb, iContextID, &iVersion, &iLockFlag,
+ &iLockTime, &iLockTimeUSec, pchContextData, err, nRetry);
+ NDB_TICKS tEndTrans = NdbTick_CurrentMillisecond();
+ long lMillisecForThisTrans = (long)(tEndTrans-tStartTrans);
+ if(nRetry>0)
+ {
+ sprintf(szMsg, "verify retried %d times, time %ld msec.",
+ nRetry, lMillisecForThisTrans);
+ ReportNdbError(szMsg, err);
+ }
+ if(iRes)
+ {
+ ReportNdbError("Read initial record failed", err);
+ delete[] pchContextData;
+ return iRes;
+ }
+ if(memcmp(pchContextData, STATUS_DATA, g_nStatusDataSize))
+ {
+ sprintf(szMsg, "wrong context data in tuple %d", iContextID);
+ ReportNdbError(szMsg, err);
+ delete[] pchContextData;
+ return -1;
+ }
+ if(iVersion!=nSeed
+ || iLockFlag!=iContextID
+ || iLockTime<iPrevLockTime
+ || (iLockTime==iPrevLockTime && iLockTimeUSec<iPrevLockTimeUSec))
+ {
+ sprintf(szMsg, "wrong call data in tuple %d", iContextID);
+ ReportNdbError(szMsg, err);
+ delete[] pchContextData;
+ return -1;
+ }
+ iPrevLockTime = iLockTime;
+ iPrevLockTimeUSec = iLockTimeUSec;
+ InterlockedIncrement(&g_nNumberOfInitialVerify);
+ }
+ delete[] pchContextData;
+ return iRes;
+}
+
+
+
+
+
+void* RuntimeCallContext(void* lpParam)
+{
+ long nNumCallsProcessed = 0;
+ int nStartingRecordID = *(int*)lpParam;
+
+ Ndb* pNdb;
+ char* pchContextData = new char[g_nStatusDataSize];
+ char szMsg[100];
+
+ int iRes;
+ const char* szOp;
+ long iVersion;
+ long iLockFlag;
+ long iLockTime;
+ long iLockTimeUSec;
+
+ pNdb = new Ndb("TEST_DB");
+ if(!pNdb)
+ {
+ NdbMutex_Lock(g_pNdbMutexPrintf);
+ printf("new Ndb failed\n");
+ NdbMutex_Unlock(g_pNdbMutexPrintf);
+ delete[] pchContextData;
+ return 0;
+ }
+
+ if(pNdb->init(1) || pNdb->waitUntilReady())
+ {
+ ReportNdbError("init of Ndb failed", pNdb->getNdbError());
+ delete pNdb;
+ delete[] pchContextData;
+ return 0;
+ }
+
+ if(g_bInsertInitial)
+ {
+ if(InsertInitialRecords(pNdb, g_nMaxContextIdPerThread, -nStartingRecordID-g_nMaxContextIdPerThread))
+ {
+ delete pNdb;
+ delete[] pchContextData;
+ return 0;
+ }
+ }
+
+ if(g_bVerifyInitial)
+ {
+ NdbError err;
+ memset(&err, 0, sizeof(err));
+ if(VerifyInitialRecords(pNdb, g_nMaxContextIdPerThread, -nStartingRecordID-g_nMaxContextIdPerThread))
+ {
+ delete pNdb;
+ delete[] pchContextData;
+ return 0;
+ }
+ }
+ if(g_bInsertInitial || g_bVerifyInitial)
+ {
+ delete[] pchContextData;
+ return 0;
+ }
+
+ long nContextID = nStartingRecordID;
+#ifdef NDB_WIN32
+ while(WaitForSingleObject(hShutdownEvent,0) != WAIT_OBJECT_0)
+#else
+ while(!bShutdownEvent)
+#endif
+ {
+ ++nContextID;
+ nContextID %= g_nMaxContextIdPerThread;
+ nContextID += nStartingRecordID;
+
+ bool bTimeLatency = (nContextID==100);
+
+ NDB_TICKS tStartCall = NdbTick_CurrentMillisecond();
+ for (int i=0; i < 20; i++)
+ {
+ int nRetry = 0;
+ NdbError err;
+ memset(&err, 0, sizeof(err));
+ NDB_TICKS tStartTrans = NdbTick_CurrentMillisecond();
+ switch(i)
+ {
+ case 3:
+ case 6:
+ case 9:
+ case 11:
+ case 12:
+ case 15:
+ case 18: // Query Record
+ szOp = "Read";
+ iRes = RetryQueryTransaction(pNdb, nContextID, &iVersion, &iLockFlag,
+ &iLockTime, &iLockTimeUSec, pchContextData, err, nRetry);
+ break;
+
+ case 19: // Delete Record
+ szOp = "Delete";
+ iRes = RetryDeleteTransaction(pNdb, nContextID, err, nRetry);
+ break;
+
+ case 0: // Insert Record
+ szOp = "Insert";
+ iRes = RetryInsertTransaction(pNdb, nContextID, 1, 1, 1, 1, STATUS_DATA, err, nRetry);
+ break;
+
+ default: // Update Record
+ szOp = "Update";
+ iRes = RetryUpdateTransaction(pNdb, nContextID, err, nRetry);
+ break;
+ }
+ NDB_TICKS tEndTrans = NdbTick_CurrentMillisecond();
+ long lMillisecForThisTrans = (long)(tEndTrans-tStartTrans);
+
+ if(g_bReport)
+ {
+ assert(lMillisecForThisTrans>=0 && lMillisecForThisTrans<c_nMaxMillisecForAllTrans);
+ InterlockedIncrement(g_plCountMillisecForTrans+lMillisecForThisTrans);
+ }
+
+ if(nRetry>0)
+ {
+ sprintf(szMsg, "%s retried %d times, time %ld msec.",
+ szOp, nRetry, lMillisecForThisTrans);
+ ReportNdbError(szMsg, err);
+ }
+ else if(bTimeLatency)
+ {
+ NdbMutex_Lock(g_pNdbMutexPrintf);
+ printf("%s = %ld msec.\n", szOp, lMillisecForThisTrans);
+ NdbMutex_Unlock(g_pNdbMutexPrintf);
+ }
+
+ if(iRes)
+ {
+ sprintf(szMsg, "%s failed after %ld calls, terminating thread",
+ szOp, nNumCallsProcessed);
+ ReportNdbError(szMsg, err);
+ delete pNdb;
+ delete[] pchContextData;
+ return 0;
+ }
+ }
+ NDB_TICKS tEndCall = NdbTick_CurrentMillisecond();
+ long lMillisecForThisCall = (long)(tEndCall-tStartCall);
+
+ if(g_bReport)
+ {
+ assert(lMillisecForThisCall>=0 && lMillisecForThisCall<c_nMaxMillisecForAllCall);
+ InterlockedIncrement(g_plCountMillisecForCall+lMillisecForThisCall);
+ }
+
+ if(bTimeLatency)
+ {
+ NdbMutex_Lock(g_pNdbMutexPrintf);
+ printf("Total time for call is %ld msec.\n", (long)lMillisecForThisCall);
+ NdbMutex_Unlock(g_pNdbMutexPrintf);
+ }
+
+ nNumCallsProcessed++;
+ InterlockedIncrementAndReport();
+ if(g_nMaxCallsPerSecond>0)
+ {
+ int iMillisecToSleep = (1000*g_nNumThreads)/g_nMaxCallsPerSecond;
+ iMillisecToSleep -= lMillisecForThisCall;
+ if(iMillisecToSleep>0)
+ {
+ NdbSleep_MilliSleep(iMillisecToSleep);
+ }
+ }
+ }
+
+ NdbMutex_Lock(g_pNdbMutexPrintf);
+ printf("Terminating thread after %ld calls\n", nNumCallsProcessed);
+ NdbMutex_Unlock(g_pNdbMutexPrintf);
+
+ delete pNdb;
+ delete[] pchContextData;
+ return 0;
+}
+
+
+int CreateCallContextTable(Ndb* pNdb, const char* szTableName, bool bStored)
+{
+ int iRes = -1;
+ NdbError err;
+ memset(&err, 0, sizeof(err));
+
+ NdbSchemaCon* pNdbSchemaCon = NdbSchemaCon::startSchemaTrans(pNdb);
+ if(pNdbSchemaCon)
+ {
+ NdbSchemaOp* pNdbSchemaOp = pNdbSchemaCon->getNdbSchemaOp();
+ if(pNdbSchemaOp)
+ {
+ if(!pNdbSchemaOp->createTable(szTableName, 8, TupleKey, 2,
+ All, 6, 78, 80, 1, bStored)
+ && !pNdbSchemaOp->createAttribute(c_szContextId, TupleKey, 32, 1, Signed)
+ && !pNdbSchemaOp->createAttribute(c_szVersion, NoKey, 32, 1, Signed)
+ && !pNdbSchemaOp->createAttribute(c_szLockFlag, NoKey, 32, 1, Signed)
+ && !pNdbSchemaOp->createAttribute(c_szLockTime, NoKey, 32, 1, Signed)
+ && !pNdbSchemaOp->createAttribute(c_szLockTimeUSec, NoKey, 32, 1, Signed)
+ && !pNdbSchemaOp->createAttribute(c_szContextData, NoKey, 8, g_nStatusDataSize, String))
+ {
+ if(!pNdbSchemaCon->execute())
+ iRes = 0;
+ else
+ err = pNdbSchemaCon->getNdbError();
+ }
+ else
+ err = pNdbSchemaOp->getNdbError();
+ }
+ else
+ err = pNdbSchemaCon->getNdbError();
+
+ NdbSchemaCon::closeSchemaTrans(pNdbSchemaCon);
+ }
+ else
+ err = pNdb->getNdbError();
+
+ if(iRes)
+ {
+ ReportNdbError("create call context table failed", err);
+ }
+ return iRes;
+}
+
+
+
+void ReportResponseTimeStatistics(const char* szStat, long* plCount, const long lSize)
+{
+ long lCount = 0;
+ Int64 llSum = 0;
+ Int64 llSum2 = 0;
+ long lMin = -1;
+ long lMax = -1;
+
+ for(long l=0; l<lSize; ++l)
+ {
+ if(plCount[l]>0)
+ {
+ lCount += plCount[l];
+ llSum += (Int64)l*(Int64)plCount[l];
+ llSum2 += (Int64)l*(Int64)l*(Int64)plCount[l];
+ if(lMin==-1 || l<lMin)
+ {
+ lMin = l;
+ }
+ if(lMax==-1 || l>lMax)
+ {
+ lMax = l;
+ }
+ }
+ }
+
+ long lAvg = long(llSum/lCount);
+ double dblVar = ((double)lCount*(double)llSum2 - (double)llSum*(double)llSum)/((double)lCount*(double)(lCount-1));
+ long lStd = long(sqrt(dblVar));
+
+ long lMed = -1;
+ long l95 = -1;
+ long lSel = -1;
+ for(long l=lMin; l<=lMax; ++l)
+ {
+ if(plCount[l]>0)
+ {
+ lSel += plCount[l];
+ if(lMed==-1 && lSel>=(lCount/2))
+ {
+ lMed = l;
+ }
+ if(l95==-1 && lSel>=((lCount*95)/100))
+ {
+ l95 = l;
+ }
+ if(g_bReportPlus)
+ {
+ printf("%ld\t%ld\n", l, plCount[l]);
+ }
+ }
+ }
+
+ printf("%s: Count=%ld, Min=%ld, Max=%ld, Avg=%ld, Std=%ld, Med=%ld, 95%%=%ld\n",
+ szStat, lCount, lMin, lMax, lAvg, lStd, lMed, l95);
+}
+
+
+
+void ShowHelp(const char* szCmd)
+{
+ printf("%s -t<threads> [-s<seed>] [-b<batch>] [-c<maxcps>] [-m<size>] [-d] [-i] [-v] [-f] [-w] [-r[+]]\n", szCmd);
+ printf("%s -?\n", szCmd);
+ puts("-d\t\tcreate the table");
+ puts("-i\t\tinsert initial records");
+ puts("-v\t\tverify initial records");
+ puts("-t<threads>\tnumber of threads making calls");
+ puts("-s<seed>\toffset for primary key");
+ puts("-b<batch>\tbatch size per thread");
+ puts("-c<maxcps>\tmax number of calls per second for this process");
+ puts("-m<size>\tsize of context data");
+ puts("-f\t\tno checkpointing and no logging");
+ puts("-w\t\tuse writeTuple instead of insertTuple");
+ puts("-r\t\treport response time statistics");
+ puts("-r+\t\treport response time distribution");
+ puts("-?\t\thelp");
+}
+
+
+int main(int argc, char* argv[])
+{
+ int iRes = -1;
+ g_nNumThreads = 0;
+ g_nMaxCallsPerSecond = 0;
+ long nSeed = 0;
+ bool bStoredTable = true;
+ bool bCreateTable = false;
+ g_bWriteTuple = false;
+ g_bReport = false;
+ g_bReportPlus = false;
+
+ for(int i=1; i<argc; ++i)
+ {
+ if(argv[i][0]=='-' || argv[i][0]=='/')
+ {
+ switch(argv[i][1])
+ {
+ case 't':
+ g_nNumThreads = atol(argv[i]+2);
+ break;
+ case 's':
+ nSeed = atol(argv[i]+2);
+ break;
+ case 'b':
+ g_nMaxContextIdPerThread = atol(argv[i]+2);
+ break;
+ case 'm':
+ g_nStatusDataSize = atol(argv[i]+2);
+ if(g_nStatusDataSize>sizeof(STATUS_DATA))
+ {
+ g_nStatusDataSize = sizeof(STATUS_DATA);
+ }
+ break;
+ case 'i':
+ g_bInsertInitial = true;
+ break;
+ case 'v':
+ g_bVerifyInitial = true;
+ break;
+ case 'd':
+ bCreateTable = true;
+ break;
+ case 'f':
+ bStoredTable = false;
+ break;
+ case 'w':
+ g_bWriteTuple = true;
+ break;
+ case 'r':
+ g_bReport = true;
+ if(argv[i][2]=='+')
+ {
+ g_bReportPlus = true;
+ }
+ break;
+ case 'c':
+ g_nMaxCallsPerSecond = atol(argv[i]+2);
+ break;
+ case '?':
+ default:
+ ShowHelp(argv[0]);
+ return -1;
+ }
+ }
+ else
+ {
+ ShowHelp(argv[0]);
+ return -1;
+ }
+ }
+ if(bCreateTable)
+ puts("-d\tcreate the table");
+ if(g_bInsertInitial)
+ printf("-i\tinsert initial records\n");
+ if(g_bVerifyInitial)
+ printf("-v\tverify initial records\n");
+ if(g_nNumThreads>0)
+ printf("-t%ld\tnumber of threads making calls\n", g_nNumThreads);
+ if(g_nNumThreads>0)
+ {
+ printf("-s%ld\toffset for primary key\n", nSeed);
+ printf("-b%ld\tbatch size per thread\n", g_nMaxContextIdPerThread);
+ }
+ if(g_nMaxCallsPerSecond>0)
+ printf("-c%ld\tmax number of calls per second for this process\n", g_nMaxCallsPerSecond);
+ if(!bStoredTable)
+ puts("-f\tno checkpointing and no logging to disk");
+ if(g_bWriteTuple)
+ puts("-w\tuse writeTuple instead of insertTuple");
+ if(g_bReport)
+ puts("-r\treport response time statistics");
+ if(g_bReportPlus)
+ puts("-r+\treport response time distribution");
+
+ if(!bCreateTable && g_nNumThreads<=0)
+ {
+ ShowHelp(argv[0]);
+ return -1;
+ }
+ printf("-m%ld\tsize of context data\n", g_nStatusDataSize);
+
+ g_szTableName = (bStoredTable ? c_szTableNameStored : c_szTableNameTemp);
+
+#ifdef NDB_WIN32
+ SetConsoleCtrlHandler(ConsoleCtrlHandler, true);
+#else
+ signal(SIGINT, CtrlCHandler);
+#endif
+
+ if(g_bReport)
+ {
+ g_plCountMillisecForCall = new long[c_nMaxMillisecForAllCall];
+ memset(g_plCountMillisecForCall, 0, c_nMaxMillisecForAllCall*sizeof(long));
+ g_plCountMillisecForTrans = new long[c_nMaxMillisecForAllTrans];
+ memset(g_plCountMillisecForTrans, 0, c_nMaxMillisecForAllTrans*sizeof(long));
+ }
+
+ g_pNdbMutexIncrement = NdbMutex_Create();
+ g_pNdbMutexPrintf = NdbMutex_Create();
+#ifdef NDB_WIN32
+ hShutdownEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
+#endif
+
+ Ndb* pNdb = new Ndb(c_szDatabaseName);
+ if(!pNdb)
+ {
+ printf("could not construct ndb\n");
+ return 1;
+ }
+
+ if(pNdb->init(1) || pNdb->waitUntilReady())
+ {
+ ReportNdbError("could not initialize ndb\n", pNdb->getNdbError());
+ delete pNdb;
+ return 2;
+ }
+
+ if(bCreateTable)
+ {
+ printf("Create CallContext table\n");
+ if (bStoredTable)
+ {
+ if (CreateCallContextTable(pNdb, c_szTableNameStored, true))
+ {
+ printf("Create table failed\n");
+ delete pNdb;
+ return 3;
+ }
+ }
+ else
+ {
+ if (CreateCallContextTable(pNdb, c_szTableNameTemp, false))
+ {
+ printf("Create table failed\n");
+ delete pNdb;
+ return 3;
+ }
+ }
+ }
+
+ if(g_nNumThreads>0)
+ {
+ printf("creating %d threads\n", (int)g_nNumThreads);
+ if(g_bInsertInitial)
+ {
+ printf("each thread will insert %ld initial records, total %ld inserts\n",
+ g_nMaxContextIdPerThread, g_nNumThreads*g_nMaxContextIdPerThread);
+ }
+ if(g_bVerifyInitial)
+ {
+ printf("each thread will verify %ld initial records, total %ld reads\n",
+ g_nMaxContextIdPerThread, g_nNumThreads*g_nMaxContextIdPerThread);
+ }
+
+ g_nNumberOfInitialInsert = 0;
+ g_nNumberOfInitialVerify = 0;
+
+ NDB_TICKS tStartTime = NdbTick_CurrentMillisecond();
+ NdbThread* pThreads[256];
+ int pnStartingRecordNum[256];
+ int ij;
+ for(ij=0;ij<g_nNumThreads;ij++)
+ {
+ pnStartingRecordNum[ij] = (ij*g_nMaxContextIdPerThread) + nSeed;
+ }
+
+ for(ij=0;ij<g_nNumThreads;ij++)
+ {
+ pThreads[ij] = NdbThread_Create(RuntimeCallContext,
+ (void**)(pnStartingRecordNum+ij),
+ 0, "RuntimeCallContext", NDB_THREAD_PRIO_LOW);
+ }
+
+ //Wait for the threads to finish
+ for(ij=0;ij<g_nNumThreads;ij++)
+ {
+ void* status;
+ NdbThread_WaitFor(pThreads[ij], &status);
+ }
+ NDB_TICKS tEndTime = NdbTick_CurrentMillisecond();
+
+ //Print time taken
+ printf("Time Taken for %ld Calls is %ld msec (= %ld calls/sec)\n",
+ g_nNumCallsProcessed,
+ (long)(tEndTime-tStartTime),
+ (long)((1000*g_nNumCallsProcessed)/(tEndTime-tStartTime)));
+
+ if(g_bInsertInitial)
+ printf("successfully inserted %ld tuples\n", g_nNumberOfInitialInsert);
+ if(g_bVerifyInitial)
+ printf("successfully verified %ld tuples\n", g_nNumberOfInitialVerify);
+ }
+
+ delete pNdb;
+
+#ifdef NDB_WIN32
+ CloseHandle(hShutdownEvent);
+#endif
+ NdbMutex_Destroy(g_pNdbMutexIncrement);
+ NdbMutex_Destroy(g_pNdbMutexPrintf);
+
+ if(g_bReport)
+ {
+ ReportResponseTimeStatistics("Calls", g_plCountMillisecForCall, c_nMaxMillisecForAllCall);
+ ReportResponseTimeStatistics("Transactions", g_plCountMillisecForTrans, c_nMaxMillisecForAllTrans);
+
+ delete[] g_plCountMillisecForCall;
+ delete[] g_plCountMillisecForTrans;
+ }
+
+ return 0;
+}
+
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/user/ndb_async1.cpp b/ndb/test/ndbapi/ndb_async1.cpp
index 2a84f6b2aca..2a84f6b2aca 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/user/ndb_async1.cpp
+++ b/ndb/test/ndbapi/ndb_async1.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/user/ndb_async2.cpp b/ndb/test/ndbapi/ndb_async2.cpp
index 0c1d138defb..0c1d138defb 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/user/ndb_async2.cpp
+++ b/ndb/test/ndbapi/ndb_async2.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_populate.cpp b/ndb/test/ndbapi/ndb_user_populate.cpp
index ce3a76cdd59..ce3a76cdd59 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_populate.cpp
+++ b/ndb/test/ndbapi/ndb_user_populate.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction.cpp b/ndb/test/ndbapi/ndb_user_transaction.cpp
index 182f1f99586..182f1f99586 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction.cpp
+++ b/ndb/test/ndbapi/ndb_user_transaction.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction2.cpp b/ndb/test/ndbapi/ndb_user_transaction2.cpp
index df3c7a7989e..df3c7a7989e 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction2.cpp
+++ b/ndb/test/ndbapi/ndb_user_transaction2.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction3.cpp b/ndb/test/ndbapi/ndb_user_transaction3.cpp
index d2c92ecd424..d2c92ecd424 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction3.cpp
+++ b/ndb/test/ndbapi/ndb_user_transaction3.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction4.cpp b/ndb/test/ndbapi/ndb_user_transaction4.cpp
index e652c7bfed8..e652c7bfed8 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction4.cpp
+++ b/ndb/test/ndbapi/ndb_user_transaction4.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction5.cpp b/ndb/test/ndbapi/ndb_user_transaction5.cpp
index 86580008d10..86580008d10 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction5.cpp
+++ b/ndb/test/ndbapi/ndb_user_transaction5.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction6.cpp b/ndb/test/ndbapi/ndb_user_transaction6.cpp
index 262f38e9ffb..262f38e9ffb 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/ndb_user_transaction6.cpp
+++ b/ndb/test/ndbapi/ndb_user_transaction6.cpp
diff --git a/ndb/test/ndbapi/acid/Makefile b/ndb/test/ndbapi/old_dirs/acid/Makefile
index 33dc49fcdea..33dc49fcdea 100644
--- a/ndb/test/ndbapi/acid/Makefile
+++ b/ndb/test/ndbapi/old_dirs/acid/Makefile
diff --git a/ndb/test/ndbapi/acid2/Makefile b/ndb/test/ndbapi/old_dirs/acid2/Makefile
index 69c9d409b9e..69c9d409b9e 100644
--- a/ndb/test/ndbapi/acid2/Makefile
+++ b/ndb/test/ndbapi/old_dirs/acid2/Makefile
diff --git a/ndb/test/ndbapi/acid2/TraceNdbApi.hpp b/ndb/test/ndbapi/old_dirs/acid2/TraceNdbApi.hpp
index 2bd4eab6b70..2bd4eab6b70 100644
--- a/ndb/test/ndbapi/acid2/TraceNdbApi.hpp
+++ b/ndb/test/ndbapi/old_dirs/acid2/TraceNdbApi.hpp
diff --git a/ndb/test/ndbapi/acid2/VerifyNdbApi.hpp b/ndb/test/ndbapi/old_dirs/acid2/VerifyNdbApi.hpp
index 4a5b8cc8111..4a5b8cc8111 100644
--- a/ndb/test/ndbapi/acid2/VerifyNdbApi.hpp
+++ b/ndb/test/ndbapi/old_dirs/acid2/VerifyNdbApi.hpp
diff --git a/ndb/test/ndbapi/basicAsynch/Makefile b/ndb/test/ndbapi/old_dirs/basicAsynch/Makefile
index 802c5e5a2bd..802c5e5a2bd 100755
--- a/ndb/test/ndbapi/basicAsynch/Makefile
+++ b/ndb/test/ndbapi/old_dirs/basicAsynch/Makefile
diff --git a/ndb/test/ndbapi/bulk_copy/Makefile b/ndb/test/ndbapi/old_dirs/bulk_copy/Makefile
index 22c05b138b7..22c05b138b7 100644
--- a/ndb/test/ndbapi/bulk_copy/Makefile
+++ b/ndb/test/ndbapi/old_dirs/bulk_copy/Makefile
diff --git a/ndb/test/ndbapi/create_all_tabs/Makefile b/ndb/test/ndbapi/old_dirs/create_all_tabs/Makefile
index 58309807682..58309807682 100644
--- a/ndb/test/ndbapi/create_all_tabs/Makefile
+++ b/ndb/test/ndbapi/old_dirs/create_all_tabs/Makefile
diff --git a/ndb/test/ndbapi/create_tab/Makefile b/ndb/test/ndbapi/old_dirs/create_tab/Makefile
index c2ea0b52b15..c2ea0b52b15 100644
--- a/ndb/test/ndbapi/create_tab/Makefile
+++ b/ndb/test/ndbapi/old_dirs/create_tab/Makefile
diff --git a/ndb/test/ndbapi/drop_all_tabs/Makefile b/ndb/test/ndbapi/old_dirs/drop_all_tabs/Makefile
index 96db0781417..96db0781417 100644
--- a/ndb/test/ndbapi/drop_all_tabs/Makefile
+++ b/ndb/test/ndbapi/old_dirs/drop_all_tabs/Makefile
diff --git a/ndb/test/ndbapi/flexAsynch/Makefile b/ndb/test/ndbapi/old_dirs/flexAsynch/Makefile
index 2c77c8e21df..2c77c8e21df 100644
--- a/ndb/test/ndbapi/flexAsynch/Makefile
+++ b/ndb/test/ndbapi/old_dirs/flexAsynch/Makefile
diff --git a/ndb/test/ndbapi/old_dirs/flexBench/Makefile.am b/ndb/test/ndbapi/old_dirs/flexBench/Makefile.am
new file mode 100644
index 00000000000..d4de4b92b60
--- /dev/null
+++ b/ndb/test/ndbapi/old_dirs/flexBench/Makefile.am
@@ -0,0 +1,10 @@
+
+bin_PROGRAMS = flexBench
+
+flexBench_SOURCES = flexBench.cpp
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/test/ndbapi/flexBench/Makefile b/ndb/test/ndbapi/old_dirs/flexBench/Makefile_old
index bfff5cd161a..bfff5cd161a 100644
--- a/ndb/test/ndbapi/flexBench/Makefile
+++ b/ndb/test/ndbapi/old_dirs/flexBench/Makefile_old
diff --git a/ndb/test/ndbapi/flexBench/ndbplot.pl b/ndb/test/ndbapi/old_dirs/flexBench/ndbplot.pl
index b16f6d5897d..b16f6d5897d 100755
--- a/ndb/test/ndbapi/flexBench/ndbplot.pl
+++ b/ndb/test/ndbapi/old_dirs/flexBench/ndbplot.pl
diff --git a/ndb/test/ndbapi/flexHammer/Makefile b/ndb/test/ndbapi/old_dirs/flexHammer/Makefile
index c8e436fb7f5..c8e436fb7f5 100644
--- a/ndb/test/ndbapi/flexHammer/Makefile
+++ b/ndb/test/ndbapi/old_dirs/flexHammer/Makefile
diff --git a/ndb/test/ndbapi/flexHammer/README b/ndb/test/ndbapi/old_dirs/flexHammer/README
index 556582aab96..556582aab96 100644
--- a/ndb/test/ndbapi/flexHammer/README
+++ b/ndb/test/ndbapi/old_dirs/flexHammer/README
diff --git a/ndb/test/ndbapi/flexScan/Makefile b/ndb/test/ndbapi/old_dirs/flexScan/Makefile
index 78f9d481063..78f9d481063 100644
--- a/ndb/test/ndbapi/flexScan/Makefile
+++ b/ndb/test/ndbapi/old_dirs/flexScan/Makefile
diff --git a/ndb/test/ndbapi/flexScan/README b/ndb/test/ndbapi/old_dirs/flexScan/README
index cddbdea5336..cddbdea5336 100644
--- a/ndb/test/ndbapi/flexScan/README
+++ b/ndb/test/ndbapi/old_dirs/flexScan/README
diff --git a/ndb/test/ndbapi/flexTT/Makefile b/ndb/test/ndbapi/old_dirs/flexTT/Makefile
index a63bd803d95..a63bd803d95 100644
--- a/ndb/test/ndbapi/flexTT/Makefile
+++ b/ndb/test/ndbapi/old_dirs/flexTT/Makefile
diff --git a/ndb/test/ndbapi/flexTimedAsynch/Makefile b/ndb/test/ndbapi/old_dirs/flexTimedAsynch/Makefile
index e9995dbd16f..e9995dbd16f 100644
--- a/ndb/test/ndbapi/flexTimedAsynch/Makefile
+++ b/ndb/test/ndbapi/old_dirs/flexTimedAsynch/Makefile
diff --git a/ndb/test/ndbapi/flex_bench_mysql/Makefile b/ndb/test/ndbapi/old_dirs/flex_bench_mysql/Makefile
index d2608526cae..d2608526cae 100644
--- a/ndb/test/ndbapi/flex_bench_mysql/Makefile
+++ b/ndb/test/ndbapi/old_dirs/flex_bench_mysql/Makefile
diff --git a/ndb/test/ndbapi/indexTest/Makefile b/ndb/test/ndbapi/old_dirs/indexTest/Makefile
index d842e487ee5..d842e487ee5 100644
--- a/ndb/test/ndbapi/indexTest/Makefile
+++ b/ndb/test/ndbapi/old_dirs/indexTest/Makefile
diff --git a/ndb/test/ndbapi/indexTest2/Makefile b/ndb/test/ndbapi/old_dirs/indexTest2/Makefile
index ad78fd51986..ad78fd51986 100644
--- a/ndb/test/ndbapi/indexTest2/Makefile
+++ b/ndb/test/ndbapi/old_dirs/indexTest2/Makefile
diff --git a/ndb/test/ndbapi/interpreterInTup/Makefile b/ndb/test/ndbapi/old_dirs/interpreterInTup/Makefile
index 074adbf674a..074adbf674a 100644
--- a/ndb/test/ndbapi/interpreterInTup/Makefile
+++ b/ndb/test/ndbapi/old_dirs/interpreterInTup/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/Makefile
index af472b1589f..af472b1589f 100644
--- a/ndb/test/ndbapi/lmc-bench/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/Makefile
index 744d6171139..744d6171139 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/generator/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/generator/Makefile
index c1f84a3ef70..c1f84a3ef70 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/generator/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/generator/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/include/dbGenerator.h b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/dbGenerator.h
index 2256498e151..2256498e151 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/include/dbGenerator.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/dbGenerator.h
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/include/testData.h b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/testData.h
index 3db85e7342e..3db85e7342e 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/include/testData.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/testData.h
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/include/userInterface.h b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/userInterface.h
index 94bd1e80ab3..94bd1e80ab3 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/include/userInterface.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/userInterface.h
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/user/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/Makefile
index c0b532a8359..c0b532a8359 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/user/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/user/macros.h b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/macros.h
index 22b7f564490..22b7f564490 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/user/macros.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/macros.h
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/user/ndb_error.hpp b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/ndb_error.hpp
index 9e6c5e55e73..9e6c5e55e73 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/user/ndb_error.hpp
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/ndb_error.hpp
diff --git a/ndb/test/ndbapi/lmc-bench/bin/.empty b/ndb/test/ndbapi/old_dirs/lmc-bench/bin/.empty
index e69de29bb2d..e69de29bb2d 100644
--- a/ndb/test/ndbapi/lmc-bench/bin/.empty
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/bin/.empty
diff --git a/ndb/test/ndbapi/lmc-bench/include/ndb_schema.hpp b/ndb/test/ndbapi/old_dirs/lmc-bench/include/ndb_schema.hpp
index af08bc2eecd..af08bc2eecd 100644
--- a/ndb/test/ndbapi/lmc-bench/include/ndb_schema.hpp
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/include/ndb_schema.hpp
diff --git a/ndb/test/ndbapi/lmc-bench/include/testDefinitions.h b/ndb/test/ndbapi/old_dirs/lmc-bench/include/testDefinitions.h
index 2f4aeb30975..2f4aeb30975 100644
--- a/ndb/test/ndbapi/lmc-bench/include/testDefinitions.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/include/testDefinitions.h
diff --git a/ndb/test/ndbapi/lmc-bench/lib/.empty b/ndb/test/ndbapi/old_dirs/lmc-bench/lib/.empty
index e69de29bb2d..e69de29bb2d 100644
--- a/ndb/test/ndbapi/lmc-bench/lib/.empty
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/lib/.empty
diff --git a/ndb/test/ndbapi/lmc-bench/script/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/script/Makefile
index 240b5957573..240b5957573 100644
--- a/ndb/test/ndbapi/lmc-bench/script/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/script/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/script/async-lmc-bench-l-p10.sh b/ndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench-l-p10.sh
index 1ce3969f9fb..1ce3969f9fb 100755
--- a/ndb/test/ndbapi/lmc-bench/script/async-lmc-bench-l-p10.sh
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench-l-p10.sh
diff --git a/ndb/test/ndbapi/lmc-bench/script/async-lmc-bench-l.sh b/ndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench-l.sh
index a5de71395c4..a5de71395c4 100755
--- a/ndb/test/ndbapi/lmc-bench/script/async-lmc-bench-l.sh
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench-l.sh
diff --git a/ndb/test/ndbapi/lmc-bench/script/async-lmc-bench-p10.sh b/ndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench-p10.sh
index 92c853cdd86..92c853cdd86 100755
--- a/ndb/test/ndbapi/lmc-bench/script/async-lmc-bench-p10.sh
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench-p10.sh
diff --git a/ndb/test/ndbapi/lmc-bench/script/async-lmc-bench.sh b/ndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench.sh
index da8e9d9bf42..da8e9d9bf42 100755
--- a/ndb/test/ndbapi/lmc-bench/script/async-lmc-bench.sh
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/script/async-lmc-bench.sh
diff --git a/ndb/test/ndbapi/lmc-bench/src/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/src/Makefile
index ae7fac9c49b..ae7fac9c49b 100644
--- a/ndb/test/ndbapi/lmc-bench/src/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/src/README b/ndb/test/ndbapi/old_dirs/lmc-bench/src/README
index e81c8ba0051..e81c8ba0051 100644
--- a/ndb/test/ndbapi/lmc-bench/src/README
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/README
diff --git a/ndb/test/ndbapi/lmc-bench/src/generator/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/Makefile
index 143d9ba655e..143d9ba655e 100644
--- a/ndb/test/ndbapi/lmc-bench/src/generator/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/src/generator/dbGenerator.c b/ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/dbGenerator.c
index 7484c7647f5..7484c7647f5 100644
--- a/ndb/test/ndbapi/lmc-bench/src/generator/dbGenerator.c
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/dbGenerator.c
diff --git a/ndb/test/ndbapi/lmc-bench/src/generator/dbGenerator.h b/ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/dbGenerator.h
index 824688b6cf9..824688b6cf9 100644
--- a/ndb/test/ndbapi/lmc-bench/src/generator/dbGenerator.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/dbGenerator.h
diff --git a/ndb/test/ndbapi/lmc-bench/src/generator/mainGenerator.c b/ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/mainGenerator.c
index 4a31db0b4e9..4a31db0b4e9 100644
--- a/ndb/test/ndbapi/lmc-bench/src/generator/mainGenerator.c
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/mainGenerator.c
diff --git a/ndb/test/ndbapi/lmc-bench/src/include/testData.h b/ndb/test/ndbapi/old_dirs/lmc-bench/src/include/testData.h
index 863c230502b..863c230502b 100644
--- a/ndb/test/ndbapi/lmc-bench/src/include/testData.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/include/testData.h
diff --git a/ndb/test/ndbapi/lmc-bench/src/include/userInterface.h b/ndb/test/ndbapi/old_dirs/lmc-bench/src/include/userInterface.h
index b70ded87756..b70ded87756 100644
--- a/ndb/test/ndbapi/lmc-bench/src/include/userInterface.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/include/userInterface.h
diff --git a/ndb/test/ndbapi/lmc-bench/src/makevars.linux b/ndb/test/ndbapi/old_dirs/lmc-bench/src/makevars.linux
index a933669cfe7..a933669cfe7 100644
--- a/ndb/test/ndbapi/lmc-bench/src/makevars.linux
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/makevars.linux
diff --git a/ndb/test/ndbapi/lmc-bench/src/makevars.sparc b/ndb/test/ndbapi/old_dirs/lmc-bench/src/makevars.sparc
index 57ab8bf982f..57ab8bf982f 100644
--- a/ndb/test/ndbapi/lmc-bench/src/makevars.sparc
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/makevars.sparc
diff --git a/ndb/test/ndbapi/lmc-bench/src/populator/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/Makefile
index 2107c948843..2107c948843 100644
--- a/ndb/test/ndbapi/lmc-bench/src/populator/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/src/populator/dbPopulate.c b/ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/dbPopulate.c
index 42fbb52f3b2..42fbb52f3b2 100644
--- a/ndb/test/ndbapi/lmc-bench/src/populator/dbPopulate.c
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/dbPopulate.c
diff --git a/ndb/test/ndbapi/lmc-bench/src/populator/dbPopulate.h b/ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/dbPopulate.h
index 1916720e141..1916720e141 100644
--- a/ndb/test/ndbapi/lmc-bench/src/populator/dbPopulate.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/dbPopulate.h
diff --git a/ndb/test/ndbapi/lmc-bench/src/populator/mainPopulate.c b/ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/mainPopulate.c
index 838ac8a7196..838ac8a7196 100644
--- a/ndb/test/ndbapi/lmc-bench/src/populator/mainPopulate.c
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/mainPopulate.c
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/Makefile
index 9bf229ac84c..9bf229ac84c 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/localDbPrepare.c b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/localDbPrepare.c
index dd100507016..dd100507016 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/localDbPrepare.c
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/localDbPrepare.c
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/macros.h b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/macros.h
index 363f247b93f..363f247b93f 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/macros.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/macros.h
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/ndb_error.hpp b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/ndb_error.hpp
index b3aaeac822e..b3aaeac822e 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/ndb_error.hpp
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/ndb_error.hpp
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/old/Makefile b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/Makefile
index 9b1247d44af..9b1247d44af 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/old/Makefile
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/Makefile
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/old/userHandle.h b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userHandle.h
index 1de468d4dad..1de468d4dad 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/old/userHandle.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userHandle.h
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/old/userInterface.c b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userInterface.c
index bacf1861dde..bacf1861dde 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/old/userInterface.c
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userInterface.c
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/old/userTransaction.c b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userTransaction.c
index a2f4787bb0c..a2f4787bb0c 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/old/userTransaction.c
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userTransaction.c
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/userHandle.h b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userHandle.h
index 6da76fc2bff..6da76fc2bff 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/userHandle.h
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userHandle.h
diff --git a/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userInterface.cpp b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userInterface.cpp
new file mode 100644
index 00000000000..fe3c17acbf5
--- /dev/null
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userInterface.cpp
@@ -0,0 +1,739 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/***************************************************************
+* I N C L U D E D F I L E S *
+***************************************************************/
+
+#include <ndb_global.h>
+#ifndef NDB_WIN32
+#include <sys/time.h>
+#endif
+
+#include "ndb_error.hpp"
+#include "userHandle.h"
+#include "userInterface.h"
+#include <NdbThread.h>
+#include <NdbTick.h>
+#include <NdbMutex.h>
+#include <NdbSleep.h>
+#include "ndb_schema.hpp"
+#include <NDBT.hpp>
+#include <NdbSchemaCon.hpp>
+
+/***************************************************************
+* L O C A L C O N S T A N T S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L D A T A S T R U C T U R E S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L F U N C T I O N S *
+***************************************************************/
+
+extern int localDbPrepare(UserHandle *uh);
+
+static int dbCreate(UserHandle *uh);
+
+/***************************************************************
+* L O C A L D A T A *
+***************************************************************/
+
+/***************************************************************
+* P U B L I C D A T A *
+***************************************************************/
+
+
+/***************************************************************
+****************************************************************
+* L O C A L F U N C T I O N S C O D E S E C T I O N *
+****************************************************************
+***************************************************************/
+
+/***************************************************************
+****************************************************************
+* P U B L I C F U N C T I O N S C O D E S E C T I O N *
+****************************************************************
+***************************************************************/
+
+/*-----------------------------------*/
+/* Time related Functions */
+/* */
+/* Returns a double value in seconds */
+/*-----------------------------------*/
+double userGetTimeSync(void)
+{
+ static int initialized = 0;
+ static NDB_TICKS initSecs = 0;
+ static Uint32 initMicros = 0;
+ double timeValue = 0;
+
+ if ( !initialized ) {
+ initialized = 1;
+ NdbTick_CurrentMicrosecond(&initSecs, &initMicros);
+ timeValue = 0.0;
+ } else {
+ NDB_TICKS secs = 0;
+ Uint32 micros = 0;
+
+ NdbTick_CurrentMicrosecond(&secs, &micros);
+
+ double s = (double)secs - (double)initSecs;
+ double us = (double)secs - (double)initMicros;
+
+ timeValue = s + (us / 1000000.0);
+ }
+
+ return timeValue;
+}
+
+// 0 - OK
+// 1 - Retry transaction
+// 2 - Permanent
+int
+userDbCommit(UserHandle *uh){
+ if(uh->pCurrTrans != 0){
+ int check = uh->pCurrTrans->execute( Commit );
+ NdbError err = uh->pCurrTrans->getNdbError();
+ uh->pNDB->closeTransaction(uh->pCurrTrans);
+ uh->pCurrTrans = 0;
+
+ if(err.status != NdbError::Success)
+ ndbout << err << endl;
+
+ if(err.status == NdbError::TemporaryError &&
+ err.classification == NdbError::OverloadError){
+ NdbSleep_SecSleep(3);
+ }
+
+ return err.status;
+ }
+ return 2;
+}
+
+/**
+ * TRUE - Normal table
+ * FALSE - Table w.o. checkpoing and logging
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int useTableLogging;
+extern int useIndexTables;
+#ifdef __cplusplus
+}
+#endif
+
+
+int
+create_table_server(Ndb * pNdb){
+ int check;
+ NdbSchemaCon * MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if( MySchemaTransaction == NULL )
+ error_handler("startSchemaTransaction", pNdb->getNdbError(), 0);
+
+ NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( MySchemaOp == NULL )
+ error_handler("getNdbSchemaOp", MySchemaTransaction->getNdbError(), 0);
+
+ // Create table
+ check = MySchemaOp->createTable( SERVER_TABLE,
+ 8, // Table size
+ TupleKey, // Key Type
+ 1 // Nr of Pages
+ ,DistributionGroup,
+ 6,
+ 78,
+ 80,
+ 1,
+ useTableLogging
+ );
+ if( check == -1 )
+ error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute
+ ( SERVER_SUBSCRIBER_SUFFIX,
+ TupleKey,
+ sizeof(char) << 3,
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute,
+ NormalStorageAttribute,
+ 0,
+ 1,
+ 16);
+ if( check == -1 )
+ error_handler("createAttribute (subscriber suffix)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ // Create first column, primary key
+ check = MySchemaOp->createAttribute( SERVER_ID,
+ TupleKey,
+ sizeof(ServerId) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (serverid)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SERVER_NAME,
+ NoKey,
+ sizeof(char) << 3,
+ SERVER_NAME_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server name)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SERVER_READS,
+ NoKey,
+ sizeof(Counter) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server reads)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SERVER_INSERTS,
+ NoKey,
+ sizeof(Counter) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server inserts)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SERVER_DELETES,
+ NoKey,
+ sizeof(Counter) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server deletes)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ if( MySchemaTransaction->execute() == -1 ) {
+ error_handler("schemaTransaction->execute()",
+ MySchemaTransaction->getNdbError(), 0);
+ }
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return 0;
+}
+
+int
+create_table_group(Ndb * pNdb){
+ int check;
+
+ NdbSchemaCon * MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if( MySchemaTransaction == NULL )
+ error_handler("startSchemaTransaction", pNdb->getNdbError(), 0);
+
+ NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( MySchemaOp == NULL )
+ error_handler("getNdbSchemaOp", MySchemaTransaction->getNdbError(), 0);
+
+ // Create table
+ check = MySchemaOp->createTable( GROUP_TABLE,
+ 8, // Table size
+ TupleKey, // Key Type
+ 1 // Nr of Pages
+ ,All,
+ 6,
+ 78,
+ 80,
+ 1,
+ useTableLogging
+ );
+
+ if( check == -1 )
+ error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
+
+ // Create first column, primary key
+ check = MySchemaOp->createAttribute( GROUP_ID,
+ TupleKey,
+ sizeof(GroupId) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group id)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( GROUP_NAME,
+ NoKey,
+ sizeof(char) << 3,
+ GROUP_NAME_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group name)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( GROUP_ALLOW_READ,
+ NoKey,
+ sizeof(Permission) << 3,
+ 1,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group read)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( GROUP_ALLOW_INSERT,
+ NoKey,
+ sizeof(Permission) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group insert)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( GROUP_ALLOW_DELETE,
+ NoKey,
+ sizeof(Permission) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group delete)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ if( MySchemaTransaction->execute() == -1 ) {
+ error_handler("schemaTransaction->execute()",
+ MySchemaTransaction->getNdbError(), 0);
+ }
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return 0;
+}
+
+int
+create_table_subscriber(Ndb * pNdb){
+ int check;
+ NdbSchemaCon * MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if( MySchemaTransaction == NULL )
+ error_handler("startSchemaTransaction", pNdb->getNdbError(), 0);
+
+ NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( MySchemaOp == NULL )
+ error_handler("getNdbSchemaOp", MySchemaTransaction->getNdbError(), 0);
+
+ // Create table
+ check = MySchemaOp->createTable( SUBSCRIBER_TABLE,
+ 8, // Table size
+ TupleKey, // Key Type
+ 1 // Nr of Pages
+ ,DistributionGroup,
+ 6,
+ 78,
+ 80,
+ 1,
+ useTableLogging
+ );
+ if( check == -1 )
+ error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
+
+ // Create first column, primary key
+ check = MySchemaOp->createAttribute
+ ( SUBSCRIBER_NUMBER,
+ TupleKey,
+ sizeof(char) << 3,
+ SUBSCRIBER_NUMBER_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute,
+ (useIndexTables ? IndexStorageAttribute : NormalStorageAttribute),
+ 0,
+ 1,
+ 16);
+ if( check == -1 )
+ error_handler("createAttribute (subscriber number)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_NAME,
+ NoKey,
+ sizeof(char) << 3,
+ SUBSCRIBER_NAME_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber name)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_GROUP,
+ NoKey,
+ sizeof(GroupId) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber_group)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_LOCATION,
+ NoKey,
+ sizeof(Location) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server reads)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_SESSIONS,
+ NoKey,
+ sizeof(ActiveSessions) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber_sessions)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_CHANGED_BY,
+ NoKey,
+ sizeof(char) << 3,
+ CHANGED_BY_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber_changed_by)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_CHANGED_TIME,
+ NoKey,
+ sizeof(char) << 3,
+ CHANGED_TIME_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber_changed_time)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ if( MySchemaTransaction->execute() == -1 ) {
+ error_handler("schemaTransaction->execute()",
+ MySchemaTransaction->getNdbError(), 0);
+ }
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return 0;
+}
+
+int
+create_table_session(Ndb * pNdb){
+ int check;
+ NdbSchemaCon * MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if( MySchemaTransaction == NULL )
+ error_handler("startSchemaTransaction", pNdb->getNdbError(), 0);
+
+ NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( MySchemaOp == NULL )
+ error_handler("getNdbSchemaOp",
+ MySchemaTransaction->getNdbError(), 0);
+
+ // Create table
+ check = MySchemaOp->createTable( SESSION_TABLE,
+ 8, // Table size
+ TupleKey, // Key Type
+ 1 // Nr of Pages
+ ,DistributionGroup,
+ 6,
+ 78,
+ 80,
+ 1,
+ useTableLogging
+ );
+ if( check == -1 )
+ error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SESSION_SUBSCRIBER,
+ TupleKey,
+ sizeof(char) << 3,
+ SUBSCRIBER_NUMBER_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute,
+ NormalStorageAttribute,
+ 0,
+ 1,
+ 16);
+ if( check == -1 )
+ error_handler("createAttribute (session_subscriber)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ // Create first column, primary key
+ check = MySchemaOp->createAttribute( SESSION_SERVER,
+ TupleKey,
+ sizeof(ServerId) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (session_server)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SESSION_DATA,
+ NoKey,
+ sizeof(char) << 3,
+ SESSION_DETAILS_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (session_data)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ if( MySchemaTransaction->execute() == -1 ) {
+ error_handler("schemaTransaction->execute()",
+ MySchemaTransaction->getNdbError(), 0);
+ }
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return 0;
+}
+
+void
+create_table(const char * name, int (* function)(Ndb * pNdb), Ndb* pNdb){
+ printf("creating table %s...", name);
+ if(pNdb->getDictionary()->getTable(name) != 0){
+ printf(" it already exists\n");
+ return;
+ } else {
+ printf("\n");
+ }
+ function(pNdb);
+ printf("creating table %s... done\n", name);
+}
+
+static int dbCreate(Ndb * pNdb)
+{
+ create_table(SUBSCRIBER_TABLE, create_table_subscriber, pNdb);
+ create_table(GROUP_TABLE , create_table_group, pNdb);
+ create_table(SESSION_TABLE , create_table_session, pNdb);
+ create_table(SERVER_TABLE , create_table_server, pNdb);
+ return 0;
+}
+
+#ifndef NDB_WIN32
+#include <unistd.h>
+#endif
+
+static NdbMutex* startupMutex = NdbMutex_Create();
+
+UserHandle*
+userDbConnect(uint32 createDb, char *dbName)
+{
+ NdbMutex_Lock(startupMutex);
+
+ Ndb * pNdb = new Ndb("");
+
+ //printf("Initializing...\n");
+ pNdb->init();
+
+ //printf("Waiting...");
+ while(pNdb->waitUntilReady() != 0){
+ //printf("...");
+ }
+ // printf("done\n");
+
+ if( createDb )
+ dbCreate(pNdb);
+
+
+ UserHandle * uh = new UserHandle;
+ uh->pNDB = pNdb;
+ uh->pCurrTrans = 0;
+
+ NdbMutex_Unlock(startupMutex);
+
+ return uh;
+}
+
+void userDbDisconnect(UserHandle *uh)
+{
+ delete uh;
+}
+
+int userDbInsertServer(UserHandle *uh,
+ ServerId serverId,
+ SubscriberSuffix suffix,
+ ServerName name)
+{
+ int check;
+
+ uint32 noOfRead = 0;
+ uint32 noOfInsert = 0;
+ uint32 noOfDelete = 0;
+
+ NdbConnection * MyTransaction = 0;
+ if(uh->pCurrTrans != 0){
+ MyTransaction = uh->pCurrTrans;
+ } else {
+ uh->pCurrTrans = MyTransaction = uh->pNDB->startTransaction();
+ }
+ if (MyTransaction == NULL)
+ error_handler("startTranscation", uh->pNDB->getNdbError(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "getNdbOperation", MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "insert tuple", MyTransaction);
+
+ check = MyOperation->equal(SERVER_ID, (char*)&serverId);
+ CHECK_MINUS_ONE(check, "setValue id", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_SUBSCRIBER_SUFFIX, suffix);
+ CHECK_MINUS_ONE(check, "setValue suffix", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_NAME, name);
+ CHECK_MINUS_ONE(check, "setValue name", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_READS, (char*)&noOfRead);
+ CHECK_MINUS_ONE(check, "setValue reads", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_INSERTS, (char*)&noOfInsert);
+ CHECK_MINUS_ONE(check, "setValue inserts", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_DELETES, (char*)&noOfDelete);
+ CHECK_MINUS_ONE(check, "setValue deletes", MyTransaction);
+
+ return 0;
+}
+
+int userDbInsertSubscriber(UserHandle *uh,
+ SubscriberNumber number,
+ uint32 groupId,
+ SubscriberName name)
+{
+ int check;
+ uint32 activeSessions = 0;
+ Location l = 0;
+ ChangedBy changedBy; snprintf(changedBy, sizeof(changedBy), "ChangedBy");
+ ChangedTime changedTime; snprintf(changedTime, sizeof(changedTime), "ChangedTime");
+
+ NdbConnection * MyTransaction = 0;
+ if(uh->pCurrTrans != 0){
+ MyTransaction = uh->pCurrTrans;
+ } else {
+ uh->pCurrTrans = MyTransaction = uh->pNDB->startTransaction();
+ }
+ if (MyTransaction == NULL)
+ error_handler("startTranscation", uh->pNDB->getNdbError(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "getNdbOperation", MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "insertTuple", MyTransaction);
+
+ check = MyOperation->equal(SUBSCRIBER_NUMBER, number);
+ CHECK_MINUS_ONE(check, "equal", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_NAME, name);
+ CHECK_MINUS_ONE(check, "setValue name", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_GROUP, (char*)&groupId);
+ CHECK_MINUS_ONE(check, "setValue group", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_LOCATION, (char*)&l);
+ CHECK_MINUS_ONE(check, "setValue location", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_SESSIONS, (char*)&activeSessions);
+ CHECK_MINUS_ONE(check, "setValue sessions", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_CHANGED_BY, changedBy);
+ CHECK_MINUS_ONE(check, "setValue changedBy", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_CHANGED_TIME, changedTime);
+ CHECK_MINUS_ONE(check, "setValue changedTime", MyTransaction);
+
+ return 0;
+}
+
+int userDbInsertGroup(UserHandle *uh,
+ GroupId groupId,
+ GroupName name,
+ Permission allowRead,
+ Permission allowInsert,
+ Permission allowDelete)
+{
+ int check;
+
+ NdbConnection * MyTransaction = 0;
+ if(uh->pCurrTrans != 0){
+ MyTransaction = uh->pCurrTrans;
+ } else {
+ uh->pCurrTrans = MyTransaction = uh->pNDB->startTransaction();
+ }
+ if (MyTransaction == NULL)
+ error_handler("startTranscation", uh->pNDB->getNdbError(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "getNdbOperation", MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "insertTuple", MyTransaction);
+
+ check = MyOperation->equal(GROUP_ID, (char*)&groupId);
+ CHECK_MINUS_ONE(check, "equal", MyTransaction);
+
+ check = MyOperation->setValue(GROUP_NAME, name);
+ CHECK_MINUS_ONE(check, "setValue name", MyTransaction);
+
+ check = MyOperation->setValue(GROUP_ALLOW_READ, (char*)&allowRead);
+ CHECK_MINUS_ONE(check, "setValue allowRead", MyTransaction);
+
+ check = MyOperation->setValue(GROUP_ALLOW_INSERT, (char*)&allowInsert);
+ CHECK_MINUS_ONE(check, "setValue allowInsert", MyTransaction);
+
+ check = MyOperation->setValue(GROUP_ALLOW_DELETE, (char*)&allowDelete);
+ CHECK_MINUS_ONE(check, "setValue allowDelete", MyTransaction);
+
+ return 0;
+}
+
diff --git a/ndb/test/ndbapi/lmc-bench/src/user/userTransaction.c b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userTransaction.c
index a2f4787bb0c..a2f4787bb0c 100644
--- a/ndb/test/ndbapi/lmc-bench/src/user/userTransaction.c
+++ b/ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userTransaction.c
diff --git a/ndb/test/ndbapi/restarter/Makefile b/ndb/test/ndbapi/old_dirs/restarter/Makefile
index 041fbfd82ba..041fbfd82ba 100644
--- a/ndb/test/ndbapi/restarter/Makefile
+++ b/ndb/test/ndbapi/old_dirs/restarter/Makefile
diff --git a/ndb/test/ndbapi/restarter2/Makefile b/ndb/test/ndbapi/old_dirs/restarter2/Makefile
index ba33a2e21dc..ba33a2e21dc 100644
--- a/ndb/test/ndbapi/restarter2/Makefile
+++ b/ndb/test/ndbapi/old_dirs/restarter2/Makefile
diff --git a/ndb/test/ndbapi/restarts/Makefile b/ndb/test/ndbapi/old_dirs/restarts/Makefile
index 9f14b81fae5..9f14b81fae5 100644
--- a/ndb/test/ndbapi/restarts/Makefile
+++ b/ndb/test/ndbapi/old_dirs/restarts/Makefile
diff --git a/ndb/test/ndbapi/ronja/Makefile b/ndb/test/ndbapi/old_dirs/ronja/Makefile
index a11a27c5fd7..a11a27c5fd7 100644
--- a/ndb/test/ndbapi/ronja/Makefile
+++ b/ndb/test/ndbapi/old_dirs/ronja/Makefile
diff --git a/ndb/test/ndbapi/ronja/benchronja/Makefile b/ndb/test/ndbapi/old_dirs/ronja/benchronja/Makefile
index f0521c3ba77..f0521c3ba77 100644
--- a/ndb/test/ndbapi/ronja/benchronja/Makefile
+++ b/ndb/test/ndbapi/old_dirs/ronja/benchronja/Makefile
diff --git a/ndb/test/ndbapi/ronja/initronja/Makefile b/ndb/test/ndbapi/old_dirs/ronja/initronja/Makefile
index dd66dd813d1..dd66dd813d1 100644
--- a/ndb/test/ndbapi/ronja/initronja/Makefile
+++ b/ndb/test/ndbapi/old_dirs/ronja/initronja/Makefile
diff --git a/ndb/test/ndbapi/telco/Makefile b/ndb/test/ndbapi/old_dirs/telco/Makefile
index 8f82c714119..8f82c714119 100644
--- a/ndb/test/ndbapi/telco/Makefile
+++ b/ndb/test/ndbapi/old_dirs/telco/Makefile
diff --git a/ndb/test/ndbapi/telco/readme b/ndb/test/ndbapi/old_dirs/telco/readme
index 627b4256eef..627b4256eef 100644
--- a/ndb/test/ndbapi/telco/readme
+++ b/ndb/test/ndbapi/old_dirs/telco/readme
diff --git a/ndb/test/ndbapi/testBackup/Makefile b/ndb/test/ndbapi/old_dirs/testBackup/Makefile
index ce0e404803c..ce0e404803c 100644
--- a/ndb/test/ndbapi/testBackup/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testBackup/Makefile
diff --git a/ndb/test/ndbapi/testBasic/Makefile b/ndb/test/ndbapi/old_dirs/testBasic/Makefile
index 755b19939cb..755b19939cb 100644
--- a/ndb/test/ndbapi/testBasic/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testBasic/Makefile
diff --git a/ndb/test/ndbapi/testBlobs/Makefile b/ndb/test/ndbapi/old_dirs/testBlobs/Makefile
index cc5bb629c17..cc5bb629c17 100644
--- a/ndb/test/ndbapi/testBlobs/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testBlobs/Makefile
diff --git a/ndb/test/ndbapi/testDataBuffers/Makefile b/ndb/test/ndbapi/old_dirs/testDataBuffers/Makefile
index 181fbc829d4..181fbc829d4 100644
--- a/ndb/test/ndbapi/testDataBuffers/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testDataBuffers/Makefile
diff --git a/ndb/test/ndbapi/testDict/Makefile b/ndb/test/ndbapi/old_dirs/testDict/Makefile
index 75d493c3424..75d493c3424 100644
--- a/ndb/test/ndbapi/testDict/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testDict/Makefile
diff --git a/ndb/test/ndbapi/testGrep/Makefile b/ndb/test/ndbapi/old_dirs/testGrep/Makefile
index 34fdd7113d0..34fdd7113d0 100644
--- a/ndb/test/ndbapi/testGrep/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testGrep/Makefile
diff --git a/ndb/test/ndbapi/testGrep/verify/Makefile b/ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile
index 4e6182de6b2..4e6182de6b2 100644
--- a/ndb/test/ndbapi/testGrep/verify/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile
diff --git a/ndb/test/ndbapi/testIndex/Makefile b/ndb/test/ndbapi/old_dirs/testIndex/Makefile
index e5cd4542c9c..e5cd4542c9c 100644
--- a/ndb/test/ndbapi/testIndex/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testIndex/Makefile
diff --git a/ndb/test/ndbapi/testInterpreter/Makefile b/ndb/test/ndbapi/old_dirs/testInterpreter/Makefile
index e84287a1b16..e84287a1b16 100644
--- a/ndb/test/ndbapi/testInterpreter/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testInterpreter/Makefile
diff --git a/ndb/test/ndbapi/testMgm/Makefile b/ndb/test/ndbapi/old_dirs/testMgm/Makefile
index be50d3dae7e..be50d3dae7e 100644
--- a/ndb/test/ndbapi/testMgm/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testMgm/Makefile
diff --git a/ndb/test/ndbapi/testNdbApi/Makefile b/ndb/test/ndbapi/old_dirs/testNdbApi/Makefile
index 3bb3cba427e..3bb3cba427e 100644
--- a/ndb/test/ndbapi/testNdbApi/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testNdbApi/Makefile
diff --git a/ndb/test/ndbapi/testNodeRestart/Makefile b/ndb/test/ndbapi/old_dirs/testNodeRestart/Makefile
index 8c13ab3beb4..8c13ab3beb4 100644
--- a/ndb/test/ndbapi/testNodeRestart/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testNodeRestart/Makefile
diff --git a/ndb/test/ndbapi/testOIBasic/Makefile b/ndb/test/ndbapi/old_dirs/testOIBasic/Makefile
index 1bbbcf1d17e..1bbbcf1d17e 100644
--- a/ndb/test/ndbapi/testOIBasic/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testOIBasic/Makefile
diff --git a/ndb/test/ndbapi/testOIBasic/times.txt b/ndb/test/ndbapi/old_dirs/testOIBasic/times.txt
index 641e9ddb4bf..641e9ddb4bf 100644
--- a/ndb/test/ndbapi/testOIBasic/times.txt
+++ b/ndb/test/ndbapi/old_dirs/testOIBasic/times.txt
diff --git a/ndb/test/ndbapi/testOperations/Makefile b/ndb/test/ndbapi/old_dirs/testOperations/Makefile
index 25546ade639..25546ade639 100644
--- a/ndb/test/ndbapi/testOperations/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testOperations/Makefile
diff --git a/ndb/test/ndbapi/testOrderedIndex/Makefile b/ndb/test/ndbapi/old_dirs/testOrderedIndex/Makefile
index d8899a37895..d8899a37895 100644
--- a/ndb/test/ndbapi/testOrderedIndex/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testOrderedIndex/Makefile
diff --git a/ndb/test/ndbapi/testRestartGci/Makefile b/ndb/test/ndbapi/old_dirs/testRestartGci/Makefile
index 24f449b747d..24f449b747d 100644
--- a/ndb/test/ndbapi/testRestartGci/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testRestartGci/Makefile
diff --git a/ndb/test/ndbapi/testScan/Makefile b/ndb/test/ndbapi/old_dirs/testScan/Makefile
index fe48f5bc926..fe48f5bc926 100644
--- a/ndb/test/ndbapi/testScan/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testScan/Makefile
diff --git a/ndb/test/ndbapi/testScanInterpreter/Makefile b/ndb/test/ndbapi/old_dirs/testScanInterpreter/Makefile
index c7d96494148..c7d96494148 100644
--- a/ndb/test/ndbapi/testScanInterpreter/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testScanInterpreter/Makefile
diff --git a/ndb/test/ndbapi/testSystemRestart/Makefile b/ndb/test/ndbapi/old_dirs/testSystemRestart/Makefile
index 7a306eb313d..7a306eb313d 100644
--- a/ndb/test/ndbapi/testSystemRestart/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testSystemRestart/Makefile
diff --git a/ndb/test/ndbapi/testTimeout/Makefile b/ndb/test/ndbapi/old_dirs/testTimeout/Makefile
index 01a9df9887f..01a9df9887f 100644
--- a/ndb/test/ndbapi/testTimeout/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testTimeout/Makefile
diff --git a/ndb/test/ndbapi/testTransactions/Makefile b/ndb/test/ndbapi/old_dirs/testTransactions/Makefile
index 0279a526923..0279a526923 100644
--- a/ndb/test/ndbapi/testTransactions/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testTransactions/Makefile
diff --git a/ndb/test/ndbapi/test_event/Makefile b/ndb/test/ndbapi/old_dirs/test_event/Makefile
index 6299fa47845..6299fa47845 100644
--- a/ndb/test/ndbapi/test_event/Makefile
+++ b/ndb/test/ndbapi/old_dirs/test_event/Makefile
diff --git a/ndb/test/ndbapi/vw_test/Makefile b/ndb/test/ndbapi/old_dirs/vw_test/Makefile
index 144873dcc69..144873dcc69 100644
--- a/ndb/test/ndbapi/vw_test/Makefile
+++ b/ndb/test/ndbapi/old_dirs/vw_test/Makefile
diff --git a/ndb/test/ndbapi/vw_test/bcd.h b/ndb/test/ndbapi/old_dirs/vw_test/bcd.h
index d0aaffbd8b7..d0aaffbd8b7 100644
--- a/ndb/test/ndbapi/vw_test/bcd.h
+++ b/ndb/test/ndbapi/old_dirs/vw_test/bcd.h
diff --git a/ndb/test/ndbapi/vw_test/script/client_start b/ndb/test/ndbapi/old_dirs/vw_test/script/client_start
index 2965be6fbb5..2965be6fbb5 100644
--- a/ndb/test/ndbapi/vw_test/script/client_start
+++ b/ndb/test/ndbapi/old_dirs/vw_test/script/client_start
diff --git a/ndb/test/ndbapi/vw_test/utv.h b/ndb/test/ndbapi/old_dirs/vw_test/utv.h
index 6f378e5595b..6f378e5595b 100644
--- a/ndb/test/ndbapi/vw_test/utv.h
+++ b/ndb/test/ndbapi/old_dirs/vw_test/utv.h
diff --git a/ndb/test/ndbapi/vw_test/vcdrfunc.h b/ndb/test/ndbapi/old_dirs/vw_test/vcdrfunc.h
index 3c5444d733b..3c5444d733b 100644
--- a/ndb/test/ndbapi/vw_test/vcdrfunc.h
+++ b/ndb/test/ndbapi/old_dirs/vw_test/vcdrfunc.h
diff --git a/ndb/test/ndbapi/restarter/restarter.cpp b/ndb/test/ndbapi/restarter.cpp
index 9a522f5dcac..9a522f5dcac 100644
--- a/ndb/test/ndbapi/restarter/restarter.cpp
+++ b/ndb/test/ndbapi/restarter.cpp
diff --git a/ndb/test/ndbapi/restarter2/restarter2.cpp b/ndb/test/ndbapi/restarter2.cpp
index f2bcf6f8e7b..f2bcf6f8e7b 100644
--- a/ndb/test/ndbapi/restarter2/restarter2.cpp
+++ b/ndb/test/ndbapi/restarter2.cpp
diff --git a/ndb/test/ndbapi/restarts/restarts.cpp b/ndb/test/ndbapi/restarts.cpp
index 0ec2883d53c..0ec2883d53c 100644
--- a/ndb/test/ndbapi/restarts/restarts.cpp
+++ b/ndb/test/ndbapi/restarts.cpp
diff --git a/ndb/test/ndbapi/ronja/initronja/initronja.cpp b/ndb/test/ndbapi/ronja/initronja/initronja.cpp
deleted file mode 100644
index f3f4d9628e2..00000000000
--- a/ndb/test/ndbapi/ronja/initronja/initronja.cpp
+++ /dev/null
@@ -1,349 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-/* ***************************************************
- INITRONJA
- Initialise benchmark for Ronja Database
- * *************************************************** */
-
-#include "NdbApi.hpp"
-#include <NdbOut.hpp>
-#include <NdbMain.h>
-#include <NdbTest.hpp>
-#include <string.h>
-
-#define MAXSTRLEN 16
-#define MAXATTR 64
-#define MAXTABLES 64
-#define MAXTHREADS 256
-#define MAXATTRSIZE 8000
-
-static unsigned int tNoOfRecords;
-static unsigned int tNoOfLoops;
-static unsigned int tNoOfTables;
-static int tAttributeSize;
-static int tNodeId;
-static unsigned int tValue;
-static unsigned int tNoOfOperations;
-static char tableName[MAXTABLES][MAXSTRLEN];
-static char attrName[MAXATTR][MAXSTRLEN];
-
-inline int InsertRecords(Ndb*, int) ;
-
-NDB_COMMAND(initronja, "initronja", "initronja", "initronja", 65535){
-
- Ndb* pNdb = NULL ;
- NdbSchemaCon *MySchemaTransaction = NULL ;
- NdbSchemaOp *MySchemaOp = NULL ;
-
-
- int check, status, i, j, cont ;
- check = status = i = j = cont = 0 ;
- tNoOfRecords = 500 ;
- tNoOfLoops = tNoOfRecords / 10;
-
- i = 1;
- while (argc > 1){
-
- if (strcmp(argv[i], "-r") == 0){
- if( NULL == argv[i+1] ) goto error_input ;
- tNoOfRecords = atoi(argv[i+1]);
- tNoOfRecords = tNoOfRecords - (tNoOfRecords % 10);
- tNoOfLoops = tNoOfRecords / 10;
- if ((tNoOfRecords < 1) || (tNoOfRecords > 1000000000)) goto error_input;
- }else{
- goto error_input;
- }
-
- argc -= 2;
- i = i + 2; //
- }
-
- pNdb = new Ndb( "TEST_DB" ) ;
- ndbout << "Initialisation started. " << endl;
- pNdb->init();
- ndbout << "Initialisation completed. " << endl;
-
- tNodeId = pNdb->getNodeId();
- ndbout << endl << "Initial loading of Ronja Database" << endl;
- ndbout << " NdbAPI node with id = " << tNodeId << endl;
-
- if (pNdb->waitUntilReady(30) != 0) {
- ndbout << "Benchmark failed - NDB is not ready" << endl;
- delete pNdb ;
- return NDBT_ProgramExit(NDBT_FAILED) ;
- }//if
-
- ndbout << endl << "Creating the table SHORT_REC" << "..." << endl;
-
- MySchemaTransaction = pNdb->startSchemaTransaction();
- if(!MySchemaTransaction) goto error_handler;
- MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if(!MySchemaOp) goto error_handler;
-#if defined NDB_OSE || defined NDB_SOFTOSE
- check = MySchemaOp->createTable( "SHORT_REC"
- ,8 // Table Size
- ,TupleKey // Key Type
- ,40 // Nr of Pages
- ,All
- ,6
- ,78
- ,80
- ,1
- ,false);
-#else
- check = MySchemaOp->createTable( "SHORT_REC"
- ,8 // Table Size
- ,TupleKey // Key Type
- ,40 // Nr of Pages
- );
-#endif
- if (check == -1) goto error_handler;
-
- ndbout << "Key attribute..." ;
- check = MySchemaOp->createAttribute( (char*)"Key", TupleKey, 32, 1,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) goto error_handler;
- ndbout << "\t\tOK" << endl ;
-
- ndbout << "Flip attribute..." ;
- check = MySchemaOp->createAttribute("Flip", NoKey, 32, 1,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) goto error_handler;
- ndbout << "\t\tOK" << endl ;
-
- ndbout << "Count attribute..." ;
- check = MySchemaOp->createAttribute("Count", NoKey, 32, 1,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) goto error_handler;
- ndbout << "\t\tOK" << endl ;
-
- ndbout << "Placeholder attribute..." ;
- check = MySchemaOp->createAttribute("Placeholder", NoKey, 8, 90,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) goto error_handler;
- ndbout << "\tOK" << endl ;
-
- if (MySchemaTransaction->execute() == -1) {
- if(721 == MySchemaOp->getNdbError().code){
- ndbout << "Table SHORT_REC already exists" << endl ;
- }else{
- ndbout << MySchemaTransaction->getNdbError() << endl;
- }
- }else{
- ndbout << "SHORT_REC created " << endl;
- }// if
-
- pNdb->closeSchemaTransaction(MySchemaTransaction);
-
- ndbout << endl << "Creating the table LONG_REC..." << endl;
-
- MySchemaTransaction = pNdb->startSchemaTransaction();
- if(!MySchemaTransaction) goto error_handler;
-
- MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
- if(!MySchemaOp) goto error_handler;
-#if defined NDB_OSE || defined NDB_SOFTOSE
- check = MySchemaOp->createTable( "LONG_REC"
- ,8 // Table Size
- ,TupleKey // Key Type
- ,40 // Nr of Pages
- ,All
- ,6
- ,78
- ,80
- ,1
- ,false);
-#else
- check = MySchemaOp->createTable( "LONG_REC"
- ,8 // Table Size
- ,TupleKey // Key Type
- ,40 // Nr of Pages
- );
-#endif
-
- if (check == -1) goto error_handler;
-
- ndbout << "Key attribute..." ;
- check = MySchemaOp->createAttribute( (char*)"Key", TupleKey, 32, 1,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) goto error_handler;
- ndbout << "\t\tOK" << endl ;
-
- ndbout << "Flip attribute..." ;
- check = MySchemaOp->createAttribute("Flip", NoKey, 32, 1,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) goto error_handler;
- ndbout << "\t\tOK" << endl ;
-
- ndbout << "Count attribute..." ;
- check = MySchemaOp->createAttribute("Count", NoKey, 32, 1,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) goto error_handler;
- ndbout << "\t\tOK" << endl ;
-
- ndbout << "Placeholder attribute..." ;
- check = MySchemaOp->createAttribute("Placeholder", NoKey, 8, 1014,
- UnSigned, MMBased, NotNullAttribute );
- if (check == -1) goto error_handler;
- ndbout << "\tOK" << endl ;
-
- if (MySchemaTransaction->execute() == -1) {
- if(721 == MySchemaOp->getNdbError().code){
- ndbout << "Table LONG_REC already exists" << endl ;
- }else{
- ndbout << MySchemaTransaction->getNdbError() << endl;
- }
- }else{
- ndbout << "LONG_REC created" << endl;
- }// if
-
- pNdb->closeSchemaTransaction(MySchemaTransaction);
-
-
- check = InsertRecords(pNdb, tNoOfRecords);
-
- delete pNdb ;
-
- if(-1 == check){
- ndbout << endl << "Initial loading of Ronja Database failed" << endl;
- return NDBT_ProgramExit(NDBT_FAILED) ;
- }else{
- ndbout << endl << "Initial loading of Ronja Database completed" << endl;
- return NDBT_ProgramExit(NDBT_OK) ;
- }
-
-
-
-
-
-error_handler:
- ndbout << "SchemaTransaction returned error:" ;
- ndbout << MySchemaTransaction->getNdbError() << endl;
- pNdb->closeSchemaTransaction(MySchemaTransaction);
- delete pNdb ;
- NDBT_ProgramExit(NDBT_FAILED) ;
- exit(-1);
-
-error_input:
- ndbout << endl << " Ivalid parameter(s)" << endl;
- ndbout << " Usage: initronja [-r n] , where 'n' is the number of records to be inserted" << endl;
- ndbout << " If omitted, 500 records will be created by default" << endl;
- ndbout << " Note: use this number in combination with '-r' argument when running 'benchronja'" << endl << endl;
- NDBT_ProgramExit(NDBT_WRONGARGS) ;
- exit(1);
-}
-////////////////////////////////////////
-
-inline int InsertRecords(Ndb* pNdb, int nNoRecords){
-
- NdbConnection *MyTransaction = NULL ;
- NdbOperation* MyOperation[10];
-
- int Tsuccess = 0 ;
- int loop_count_ops = 2 * tNoOfLoops;
- int loop_count_tables = 10;
- int loop_count_attributes = 0 ;
- int check = 0;
- int count = 0 ;
- int count_tables = 0;
- int count_attributes = 0 ;
- int i = 0 ;
- int tType = 0 ;
- unsigned int attrValue[1000];
- unsigned int setAttrValue = 0;
- unsigned int keyValue[3];
-
- for (i = 0; i < 1000; i ++) attrValue[i] = 1;
-
- for (count=0 ; count < loop_count_ops ; count++){
- if ((((count / 100)* 100) == count) && (count != 0)){
- ndbout << "1000 records inserted again, " << (count/100) << "000 records now inserted" << endl;
- }
-
- MyTransaction = pNdb->startTransaction();
- if(!MyTransaction){
- ndbout << "startTransaction: " << pNdb->getNdbError();
- ndbout << " count = " << count << endl;
- return -1 ;
- }
-
- for (count_tables = 0; count_tables < loop_count_tables; count_tables++) {
- if (count < tNoOfLoops) {
- keyValue[0] = count*10 + count_tables ;
- MyOperation[count_tables] = MyTransaction->getNdbOperation("SHORT_REC") ;
- }else{
- keyValue[0] = (count - tNoOfLoops)*10 + count_tables;
- MyOperation[count_tables] = MyTransaction->getNdbOperation("LONG_REC");
- }//if
-
- if (!MyOperation[count_tables]) goto error_handler1;
-
- check = MyOperation[count_tables]->insertTuple();
- if (check == -1) goto error_handler2;
-
- check = MyOperation[count_tables]->equal("Key",(char*)&keyValue[0]);
- if (check == -1) goto error_handler4;
-
- check = MyOperation[count_tables]->setValue("Flip",(char*)&setAttrValue);
- if (check == -1) goto error_handler5;
-
- check = MyOperation[count_tables]->setValue("Count",(char*)&setAttrValue);
- if (check == -1) goto error_handler5;
-
- check = MyOperation[count_tables]->setValue("Placeholder",(char*)&attrValue[0]);
- if (check == -1) goto error_handler5;
- }//for
-
- if (MyTransaction->execute( Commit ) == -1){
- ndbout << MyTransaction->getNdbError()<< endl ;
- ndbout << "count = " << count << endl;
- }//if
-
- pNdb->closeTransaction(MyTransaction) ;
- }//for
- return 0;
-
-error_handler1:
- ndbout << "Error occured in getNdbOperation " << endl;
- ndbout << MyTransaction->getNdbError() << endl;
- pNdb->closeTransaction(MyTransaction);
- return -1 ;
-
-error_handler2:
- ndbout << "Error occured in defining operation " << endl;
- ndbout << MyOperation[count_tables]->getNdbError() << endl;
- pNdb->closeTransaction(MyTransaction);
- return -1 ;
-
-error_handler3:
- pNdb->closeTransaction(MyTransaction);
- return -1 ;
-
-error_handler4:
- ndbout << "Error occured in equal " << endl;
- ndbout << MyOperation[count_tables]->getNdbError() << endl;
- pNdb->closeTransaction(MyTransaction);
- return -1 ;
-
-error_handler5:
- ndbout << "Error occured in get/setValue " << endl;
- ndbout << MyOperation[count_tables]->getNdbError() << endl;
- pNdb->closeTransaction(MyTransaction);
- return -1 ;
-
-}
diff --git a/ndb/test/ndbapi/vw_test/size.cpp b/ndb/test/ndbapi/size.cpp
index c506771ebde..c506771ebde 100644
--- a/ndb/test/ndbapi/vw_test/size.cpp
+++ b/ndb/test/ndbapi/size.cpp
diff --git a/ndb/test/ndbapi/telco/msa.cpp b/ndb/test/ndbapi/telco/msa.cpp
deleted file mode 100644
index 39ddaac2019..00000000000
--- a/ndb/test/ndbapi/telco/msa.cpp
+++ /dev/null
@@ -1,1203 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <ndb_global.h>
-
-#include <NdbApi.hpp>
-#include <NdbCondition.h>
-#include <NdbMutex.h>
-#include <NdbSleep.h>
-#include <NdbThread.h>
-#include <NdbTick.h>
-
-const char* const c_szDatabaseName = "TEST_DB";
-
-const char* const c_szTableNameStored = "CCStored";
-const char* const c_szTableNameTemp = "CCTemp";
-
-const char* const c_szContextId = "ContextId";
-const char* const c_szVersion = "Version";
-const char* const c_szLockFlag = "LockFlag";
-const char* const c_szLockTime = "LockTime";
-const char* const c_szLockTimeUSec = "LockTimeUSec";
-const char* const c_szContextData = "ContextData";
-
-const char* g_szTableName = c_szTableNameStored;
-
-
-#ifdef NDB_WIN32
-HANDLE hShutdownEvent = 0;
-#else
-#include <signal.h>
-bool bShutdownEvent = false;
-#endif
-long g_nMaxContextIdPerThread = 5000;
-long g_nNumThreads = 0;
-long g_nMaxCallsPerSecond = 0;
-long g_nMaxRetry = 50;
-bool g_bWriteTuple = false;
-bool g_bInsertInitial = false;
-bool g_bVerifyInitial = false;
-
-NdbMutex* g_pNdbMutexPrintf = 0;
-NdbMutex* g_pNdbMutexIncrement = 0;
-long g_nNumCallsProcessed = 0;
-NDB_TICKS g_tStartTime = 0;
-NDB_TICKS g_tEndTime = 0;
-
-long g_nNumberOfInitialInsert = 0;
-long g_nNumberOfInitialVerify = 0;
-
-const long c_nMaxMillisecForAllCall = 5000;
-long* g_plCountMillisecForCall = 0;
-const long c_nMaxMillisecForAllTrans = 5000;
-long* g_plCountMillisecForTrans = 0;
-bool g_bReport = false;
-bool g_bReportPlus = false;
-
-
-// data for CALL_CONTEXT and GROUP_RESOURCE
-static char STATUS_DATA[]=
-"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
-"101112131415161718191A1B1C1D1E1F000102030405060708090A0B0C0D0E0F"
-"202122232425262728292A2B2C2D2E2F000102030405060708090A0B0C0D0E0F"
-"303132333435363738393A3B3C3D3E3F000102030405060708090A0B0C0D0E0F"
-"404142434445464748494A4B4C4D4E4F000102030405060708090A0B0C0D0E0F"
-"505152535455565758595A5B5C5D5E5F000102030405060708090A0B0C0D0E0F"
-"606162636465666768696A6B6C6D6E6F000102030405060708090A0B0C0D0E0F"
-"707172737475767778797A7B7C7D7E7F000102030405060708090A0B0C0D0E0F"
-"808182838485868788898A8B8C8D8E8F000102030405060708090A0B0C0D0E0F"
-"909192939495969798999A9B9C9D9E9F000102030405060708090A0B0C0D0E0F"
-"10010110210310410510610710810910A000102030405060708090A0B0C0D0EF"
-"10B10C10D10E10F110111112113114115000102030405060708090A0B0C0D0EF"
-"11611711811911A11B11C11D11E11F120000102030405060708090A0B0C0D0EF"
-"12112212312412512612712812912A12B000102030405060708090A0B0C0D0EF"
-"12C12D12E12F130131132134135136137000102030405060708090A0B0C0D0EF"
-"13813913A13B13C13D13E13F140141142000102030405060708090A0B0C0D0EF"
-"14314414514614714814914A14B14C14D000102030405060708090A0B0C0D0EF"
-"14E14F150151152153154155156157158000102030405060708090A0B0C0D0EF"
-"15915A15B15C15D15E15F160161162163000102030405060708090A0B0C0D0EF"
-"16416516616716816916A16B16C16D16E000102030405060708090A0B0C0D0EF"
-"16F170171172173174175176177178179000102030405060708090A0B0C0D0EF"
-"17A17B17C17D17E17F180181182183184000102030405060708090A0B0C0D0EF"
-"18518618718818918A18B18C18D18E18F000102030405060708090A0B0C0D0EF"
-"19019119219319419519619719819919A000102030405060708090A0B0C0D0EF"
-"19B19C19D19E19F200201202203204205000102030405060708090A0B0C0D0EF"
-"20620720820920A20B20C20D20F210211000102030405060708090A0B0C0D0EF"
-"21221321421521621721821921A21B21C000102030405060708090A0B0C0D0EF"
-"21D21E21F220221222223224225226227000102030405060708090A0B0C0D0EF"
-"22822922A22B22C22D22E22F230231232000102030405060708090A0B0C0D0EF"
-"23323423523623723823923A23B23C23D000102030405060708090A0B0C0D0EF"
-"23E23F240241242243244245246247248000102030405060708090A0B0C0D0EF"
-"24924A24B24C24D24E24F250251252253000102030405060708090A0B0C0D0EF"
-"101112131415161718191A1B1C1D1E1F000102030405060708090A0B0C0D0E0F"
-"202122232425262728292A2B2C2D2E2F000102030405060708090A0B0C0D0E0F"
-"303132333435363738393A3B3C3D3E3F000102030405060708090A0B0C0D0E0F"
-"404142434445464748494A4B4C4D4E4F000102030405060708090A0B0C0D0E0F"
-"505152535455565758595A5B5C5D5E5F000102030405060708090A0B0C0D0E0F"
-"606162636465666768696A6B6C6D6E6F000102030405060708090A0B0C0D0E0F"
-"707172737475767778797A7B7C7D7E7F000102030405060708090A0B0C0D0E0F"
-"808182838485868788898A8B8C8D8E8F000102030405060708090A0B0C0D0E0F"
-"909192939495969798999A9B9C9D9E9F000102030405060708090A0B0C0D0E0F"
-"10010110210310410510610710810910A000102030405060708090A0B0C0D0EF"
-"10B10C10D10E10F110111112113114115000102030405060708090A0B0C0D0EF"
-"11611711811911A11B11C11D11E11F120000102030405060708090A0B0C0D0EF"
-"12112212312412512612712812912A12B000102030405060708090A0B0C0D0EF"
-"12C12D12E12F130131132134135136137000102030405060708090A0B0C0D0EF"
-"13813913A13B13C13D13E13F140141142000102030405060708090A0B0C0D0EF"
-"14314414514614714814914A14B14C14D000102030405060708090A0B0C0D0EF"
-"14E14F150151152153154155156157158000102030405060708090A0B0C0D0EF"
-"15915A15B15C15D15E15F160161162163000102030405060708090A0B0C0D0EF"
-"16416516616716816916A16B16C16D16E000102030405060708090A0B0C0D0EF"
-"16F170171172173174175176177178179000102030405060708090A0B0C0D0EF"
-"17A17B17C17D17E17F180181182183184000102030405060708090A0B0C0D0EF"
-"18518618718818918A18B18C18D18E18F000102030405060708090A0B0C0D0EF"
-"19019119219319419519619719819919A000102030405060708090A0B0C0D0EF"
-"19B19C19D19E19F200201202203204205000102030405060708090A0B0C0D0EF"
-"20620720820920A20B20C20D20F210211000102030405060708090A0B0C0D0EF"
-"21221321421521621721821921A21B21C000102030405060708090A0B0C0D0EF"
-"21D21E21F220221222223224225226227000102030405060708090A0B0C0D0EF"
-"22822922A22B22C22D22E22F230231232000102030405060708090A0B0C0D0EF"
-"23323423523623723823923A23B23C23D000102030405060708090A0B0C0D0EF"
-"2366890FE1438751097E7F6325DC0E6326F"
-"25425525625725825925A25B25C25D25E25F000102030405060708090A0B0C0F";
-
-long g_nStatusDataSize = sizeof(STATUS_DATA);
-
-
-// Thread function for Call Context Inserts
-
-
-#ifdef NDB_WIN32
-
-BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
-{
- if(CTRL_C_EVENT == dwCtrlType)
- {
- SetEvent(hShutdownEvent);
- return TRUE;
- }
- return FALSE;
-}
-
-#else
-
-void CtrlCHandler(int)
-{
- bShutdownEvent = true;
-}
-
-#endif
-
-
-
-void ReportNdbError(const char* szMsg, const NdbError& err)
-{
- NdbMutex_Lock(g_pNdbMutexPrintf);
- printf("%s: %d: %s\n", szMsg, err.code, (err.message ? err.message : ""));
- NdbMutex_Unlock(g_pNdbMutexPrintf);
-}
-
-
-void
-ReportCallsPerSecond(long nNumCallsProcessed,
- NDB_TICKS tStartTime,
- NDB_TICKS tEndTime)
-{
- NDB_TICKS tElapsed = tEndTime - tStartTime;
- long lCallsPerSec;
- if(tElapsed>0)
- lCallsPerSec = (long)((1000*nNumCallsProcessed)/tElapsed);
- else
- lCallsPerSec = 0;
-
- NdbMutex_Lock(g_pNdbMutexPrintf);
- printf("Time Taken for %ld Calls is %ld msec (= %ld calls/sec)\n",
- nNumCallsProcessed, (long)tElapsed, lCallsPerSec);
- NdbMutex_Unlock(g_pNdbMutexPrintf);
-}
-
-
-#ifndef NDB_WIN32
-void InterlockedIncrement(long* lp) // expensive
-{
- NdbMutex_Lock(g_pNdbMutexIncrement);
- (*lp)++;
- NdbMutex_Unlock(g_pNdbMutexIncrement);
-}
-#endif
-
-
-void InterlockedIncrementAndReport(void)
-{
- NdbMutex_Lock(g_pNdbMutexIncrement);
- ++g_nNumCallsProcessed;
- if((g_nNumCallsProcessed%1000)==0)
- {
- g_tEndTime = NdbTick_CurrentMillisecond();
- if(g_tStartTime)
- ReportCallsPerSecond(1000, g_tStartTime, g_tEndTime);
-
- g_tStartTime = g_tEndTime;
- }
- NdbMutex_Unlock(g_pNdbMutexIncrement);
-}
-
-
-void SleepOneCall(void)
-{
- int iMillisecToSleep;
- if(g_nMaxCallsPerSecond>0)
- iMillisecToSleep = (1000*g_nNumThreads)/g_nMaxCallsPerSecond;
- else
- iMillisecToSleep = 50;
-
- if(iMillisecToSleep>0)
- NdbSleep_MilliSleep(iMillisecToSleep);
-
-}
-
-
-
-int QueryTransaction(Ndb* pNdb,
- long iContextId,
- long* piVersion,
- long* piLockFlag,
- long* piLockTime,
- long* piLockTimeUSec,
- char* pchContextData,
- NdbError& err)
-{
- int iRes = -1;
- NdbConnection* pNdbConnection = pNdb->startTransaction(0, (const char*)&iContextId, 4);
- if(pNdbConnection)
- {
- NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName);
- if(pNdbOperation)
- {
- NdbRecAttr* pNdbRecAttrVersion;
- NdbRecAttr* pNdbRecAttrLockFlag;
- NdbRecAttr* pNdbRecAttrLockTime;
- NdbRecAttr* pNdbRecAttrLockTimeUSec;
- NdbRecAttr* pNdbRecAttrContextData;
- if(!pNdbOperation->readTuple()
- && !pNdbOperation->equal(c_szContextId, (Int32)iContextId)
- && (pNdbRecAttrVersion=pNdbOperation->getValue(c_szVersion, (char*)piVersion))
- && (pNdbRecAttrLockFlag=pNdbOperation->getValue(c_szLockFlag, (char*)piLockFlag))
- && (pNdbRecAttrLockTime=pNdbOperation->getValue(c_szLockTime, (char*)piLockTime))
- && (pNdbRecAttrLockTimeUSec=pNdbOperation->getValue(c_szLockTimeUSec, (char*)piLockTimeUSec))
- && (pNdbRecAttrContextData=pNdbOperation->getValue(c_szContextData, pchContextData)))
- {
- if(!pNdbConnection->execute(Commit))
- iRes = 0;
- else
- err = pNdbConnection->getNdbError();
- }
- else
- err = pNdbOperation->getNdbError();
- }
- else
- err = pNdbConnection->getNdbError();
-
- pNdb->closeTransaction(pNdbConnection);
- }
- else
- err = pNdb->getNdbError();
-
- return iRes;
-}
-
-
-int RetryQueryTransaction(Ndb* pNdb,
- long iContextId,
- long* piVersion,
- long* piLockFlag,
- long* piLockTime,
- long* piLockTimeUSec,
- char* pchContextData,
- NdbError& err,
- int& nRetry)
-{
- int iRes = -1;
- nRetry = 0;
- bool bRetry = true;
- while(bRetry && nRetry<g_nMaxRetry)
- {
- if(!QueryTransaction(pNdb, iContextId, piVersion, piLockFlag,
- piLockTime, piLockTimeUSec, pchContextData, err))
- {
- iRes = 0;
- bRetry = false;
- }
- else
- {
- switch(err.status)
- {
- case NdbError::TemporaryError:
- case NdbError::UnknownResult:
- SleepOneCall();
- ++nRetry;
- break;
-
- case NdbError::PermanentError:
- default:
- bRetry = false;
- break;
- }
- }
- }
- return iRes;
-}
-
-
-int DeleteTransaction(Ndb* pNdb, long iContextId, NdbError& err)
-{
- int iRes = -1;
- NdbConnection* pNdbConnection = pNdb->startTransaction(0, (const char*)&iContextId, 4);
- if(pNdbConnection)
- {
- NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName);
- if(pNdbOperation)
- {
- if(!pNdbOperation->deleteTuple()
- && !pNdbOperation->equal(c_szContextId, (Int32)iContextId))
- {
- if(pNdbConnection->execute(Commit) == 0)
- iRes = 0;
- else
- err = pNdbConnection->getNdbError();
- }
- else
- err = pNdbOperation->getNdbError();
- }
- else
- err = pNdbConnection->getNdbError();
-
- pNdb->closeTransaction(pNdbConnection);
- }
- else
- err = pNdb->getNdbError();
-
- return iRes;
-}
-
-
-
-int RetryDeleteTransaction(Ndb* pNdb, long iContextId, NdbError& err, int& nRetry)
-{
- int iRes = -1;
- nRetry = 0;
- bool bRetry = true;
- bool bUnknown = false;
- while(bRetry && nRetry<g_nMaxRetry)
- {
- if(!DeleteTransaction(pNdb, iContextId, err))
- {
- iRes = 0;
- bRetry = false;
- }
- else
- {
- switch(err.status)
- {
- case NdbError::UnknownResult:
- bUnknown = true;
- ++nRetry;
- break;
-
- case NdbError::TemporaryError:
- bUnknown = false;
- SleepOneCall();
- ++nRetry;
- break;
-
- case NdbError::PermanentError:
- if(err.code==626 && bUnknown)
- iRes = 0;
- bRetry = false;
- break;
-
- default:
- bRetry = false;
- break;
- }
- }
- }
- return iRes;
-}
-
-
-
-int InsertTransaction(Ndb* pNdb,
- long iContextID,
- long iVersion,
- long iLockFlag,
- long iLockTime,
- long iLockTimeUSec,
- const char* pchContextData,
- NdbError& err)
-{
- int iRes = -1;
- NdbConnection* pNdbConnection = pNdb->startTransaction(0, (const char*)&iContextID, 4);
- if(pNdbConnection)
- {
- NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName);
- if(pNdbOperation)
- {
- if(!(g_bWriteTuple ? pNdbOperation->writeTuple() : pNdbOperation->insertTuple())
- && !pNdbOperation->equal(c_szContextId, (Int32)iContextID)
- && !pNdbOperation->setValue(c_szVersion, (Int32)iVersion)
- && !pNdbOperation->setValue(c_szLockFlag, (Int32)iLockFlag)
- && !pNdbOperation->setValue(c_szLockTime, (Int32)iLockTime)
- && !pNdbOperation->setValue(c_szLockTimeUSec, (Int32)iLockTimeUSec)
- && !pNdbOperation->setValue(c_szContextData, pchContextData, g_nStatusDataSize))
- {
- if(!pNdbConnection->execute(Commit))
- iRes = 0;
- else
- err = pNdbConnection->getNdbError();
- }
- else
- err = pNdbOperation->getNdbError();
- }
- else
- err = pNdbConnection->getNdbError();
-
- pNdb->closeTransaction(pNdbConnection);
- }
- else
- err = pNdb->getNdbError();
-
- return iRes;
-}
-
-
-
-int RetryInsertTransaction(Ndb* pNdb,
- long iContextId,
- long iVersion,
- long iLockFlag,
- long iLockTime,
- long iLockTimeUSec,
- const char* pchContextData,
- NdbError& err, int& nRetry)
-{
- int iRes = -1;
- nRetry = 0;
- bool bRetry = true;
- bool bUnknown = false;
- while(bRetry && nRetry<g_nMaxRetry)
- {
- if(!InsertTransaction(pNdb, iContextId, iVersion, iLockFlag,
- iLockTime, iLockTimeUSec, pchContextData, err))
- {
- iRes = 0;
- bRetry = false;
- }
- else
- {
- switch(err.status)
- {
- case NdbError::UnknownResult:
- bUnknown = true;
- ++nRetry;
- break;
-
- case NdbError::TemporaryError:
- bUnknown = false;
- SleepOneCall();
- ++nRetry;
- break;
-
- case NdbError::PermanentError:
- if(err.code==630 && bUnknown)
- iRes = 0;
- bRetry = false;
- break;
-
- default:
- bRetry = false;
- break;
- }
- }
- }
- return iRes;
-}
-
-
-int UpdateTransaction(Ndb* pNdb, long iContextId, NdbError& err)
-{
- int iRes = -1;
- NdbConnection* pNdbConnection = pNdb->startTransaction(0, (const char*)&iContextId, 4);
- if(pNdbConnection)
- {
- NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTableName);
- if(pNdbOperation)
- {
- if(!pNdbOperation->updateTuple()
- && !pNdbOperation->equal(c_szContextId, (Int32)iContextId)
- && !pNdbOperation->setValue(c_szContextData, STATUS_DATA, g_nStatusDataSize))
- {
- if(!pNdbConnection->execute(Commit))
- iRes = 0;
- else
- err = pNdbConnection->getNdbError();
- }
- else
- err = pNdbOperation->getNdbError();
- }
- else
- err = pNdbConnection->getNdbError();
-
- pNdb->closeTransaction(pNdbConnection);
- }
- else
- err = pNdb->getNdbError();
-
- return iRes;
-}
-
-
-int RetryUpdateTransaction(Ndb* pNdb, long iContextId, NdbError& err, int& nRetry)
-{
- int iRes = -1;
- nRetry = 0;
- bool bRetry = true;
- while(bRetry && nRetry<g_nMaxRetry)
- {
- if(!UpdateTransaction(pNdb, iContextId, err))
- {
- iRes = 0;
- bRetry = false;
- }
- else
- {
- switch(err.status)
- {
- case NdbError::TemporaryError:
- case NdbError::UnknownResult:
- SleepOneCall();
- ++nRetry;
- break;
-
- case NdbError::PermanentError:
- default:
- bRetry = false;
- break;
- }
- }
- }
- return iRes;
-}
-
-
-
-int InsertInitialRecords(Ndb* pNdb, long nInsert, long nSeed)
-{
- int iRes = -1;
- char szMsg[100];
- for(long i=0; i<nInsert; ++i)
- {
- int iContextID = i+nSeed;
- int nRetry = 0;
- NdbError err;
- memset(&err, 0, sizeof(err));
- NDB_TICKS tStartTrans = NdbTick_CurrentMillisecond();
- iRes = RetryInsertTransaction(pNdb, iContextID, nSeed, iContextID,
- (long)(tStartTrans/1000), (long)((tStartTrans%1000)*1000),
- STATUS_DATA, err, nRetry);
- NDB_TICKS tEndTrans = NdbTick_CurrentMillisecond();
- long lMillisecForThisTrans = (long)(tEndTrans-tStartTrans);
- if(nRetry>0)
- {
- sprintf(szMsg, "insert retried %d times, time %ld msec.",
- nRetry, lMillisecForThisTrans);
- ReportNdbError(szMsg, err);
- }
- if(iRes)
- {
- ReportNdbError("Insert initial record failed", err);
- return iRes;
- }
- InterlockedIncrement(&g_nNumberOfInitialInsert);
- }
- return iRes;
-}
-
-
-
-int VerifyInitialRecords(Ndb* pNdb, long nVerify, long nSeed)
-{
- int iRes = -1;
- char* pchContextData = new char[g_nStatusDataSize];
- char szMsg[100];
- long iPrevLockTime = -1;
- long iPrevLockTimeUSec = -1;
- for(long i=0; i<nVerify; ++i)
- {
- int iContextID = i+nSeed;
- long iVersion = 0;
- long iLockFlag = 0;
- long iLockTime = 0;
- long iLockTimeUSec = 0;
- int nRetry = 0;
- NdbError err;
- memset(&err, 0, sizeof(err));
- NDB_TICKS tStartTrans = NdbTick_CurrentMillisecond();
- iRes = RetryQueryTransaction(pNdb, iContextID, &iVersion, &iLockFlag,
- &iLockTime, &iLockTimeUSec, pchContextData, err, nRetry);
- NDB_TICKS tEndTrans = NdbTick_CurrentMillisecond();
- long lMillisecForThisTrans = (long)(tEndTrans-tStartTrans);
- if(nRetry>0)
- {
- sprintf(szMsg, "verify retried %d times, time %ld msec.",
- nRetry, lMillisecForThisTrans);
- ReportNdbError(szMsg, err);
- }
- if(iRes)
- {
- ReportNdbError("Read initial record failed", err);
- delete[] pchContextData;
- return iRes;
- }
- if(memcmp(pchContextData, STATUS_DATA, g_nStatusDataSize))
- {
- sprintf(szMsg, "wrong context data in tuple %d", iContextID);
- ReportNdbError(szMsg, err);
- delete[] pchContextData;
- return -1;
- }
- if(iVersion!=nSeed
- || iLockFlag!=iContextID
- || iLockTime<iPrevLockTime
- || (iLockTime==iPrevLockTime && iLockTimeUSec<iPrevLockTimeUSec))
- {
- sprintf(szMsg, "wrong call data in tuple %d", iContextID);
- ReportNdbError(szMsg, err);
- delete[] pchContextData;
- return -1;
- }
- iPrevLockTime = iLockTime;
- iPrevLockTimeUSec = iLockTimeUSec;
- InterlockedIncrement(&g_nNumberOfInitialVerify);
- }
- delete[] pchContextData;
- return iRes;
-}
-
-
-
-
-
-void* RuntimeCallContext(void* lpParam)
-{
- long nNumCallsProcessed = 0;
- int nStartingRecordID = *(int*)lpParam;
-
- Ndb* pNdb;
- char* pchContextData = new char[g_nStatusDataSize];
- char szMsg[100];
-
- int iRes;
- const char* szOp;
- long iVersion;
- long iLockFlag;
- long iLockTime;
- long iLockTimeUSec;
-
- pNdb = new Ndb("TEST_DB");
- if(!pNdb)
- {
- NdbMutex_Lock(g_pNdbMutexPrintf);
- printf("new Ndb failed\n");
- NdbMutex_Unlock(g_pNdbMutexPrintf);
- delete[] pchContextData;
- return 0;
- }
-
- if(pNdb->init(1) || pNdb->waitUntilReady())
- {
- ReportNdbError("init of Ndb failed", pNdb->getNdbError());
- delete pNdb;
- delete[] pchContextData;
- return 0;
- }
-
- if(g_bInsertInitial)
- {
- if(InsertInitialRecords(pNdb, g_nMaxContextIdPerThread, -nStartingRecordID-g_nMaxContextIdPerThread))
- {
- delete pNdb;
- delete[] pchContextData;
- return 0;
- }
- }
-
- if(g_bVerifyInitial)
- {
- NdbError err;
- memset(&err, 0, sizeof(err));
- if(VerifyInitialRecords(pNdb, g_nMaxContextIdPerThread, -nStartingRecordID-g_nMaxContextIdPerThread))
- {
- delete pNdb;
- delete[] pchContextData;
- return 0;
- }
- }
- if(g_bInsertInitial || g_bVerifyInitial)
- {
- delete[] pchContextData;
- return 0;
- }
-
- long nContextID = nStartingRecordID;
-#ifdef NDB_WIN32
- while(WaitForSingleObject(hShutdownEvent,0) != WAIT_OBJECT_0)
-#else
- while(!bShutdownEvent)
-#endif
- {
- ++nContextID;
- nContextID %= g_nMaxContextIdPerThread;
- nContextID += nStartingRecordID;
-
- bool bTimeLatency = (nContextID==100);
-
- NDB_TICKS tStartCall = NdbTick_CurrentMillisecond();
- for (int i=0; i < 20; i++)
- {
- int nRetry = 0;
- NdbError err;
- memset(&err, 0, sizeof(err));
- NDB_TICKS tStartTrans = NdbTick_CurrentMillisecond();
- switch(i)
- {
- case 3:
- case 6:
- case 9:
- case 11:
- case 12:
- case 15:
- case 18: // Query Record
- szOp = "Read";
- iRes = RetryQueryTransaction(pNdb, nContextID, &iVersion, &iLockFlag,
- &iLockTime, &iLockTimeUSec, pchContextData, err, nRetry);
- break;
-
- case 19: // Delete Record
- szOp = "Delete";
- iRes = RetryDeleteTransaction(pNdb, nContextID, err, nRetry);
- break;
-
- case 0: // Insert Record
- szOp = "Insert";
- iRes = RetryInsertTransaction(pNdb, nContextID, 1, 1, 1, 1, STATUS_DATA, err, nRetry);
- break;
-
- default: // Update Record
- szOp = "Update";
- iRes = RetryUpdateTransaction(pNdb, nContextID, err, nRetry);
- break;
- }
- NDB_TICKS tEndTrans = NdbTick_CurrentMillisecond();
- long lMillisecForThisTrans = (long)(tEndTrans-tStartTrans);
-
- if(g_bReport)
- {
- assert(lMillisecForThisTrans>=0 && lMillisecForThisTrans<c_nMaxMillisecForAllTrans);
- InterlockedIncrement(g_plCountMillisecForTrans+lMillisecForThisTrans);
- }
-
- if(nRetry>0)
- {
- sprintf(szMsg, "%s retried %d times, time %ld msec.",
- szOp, nRetry, lMillisecForThisTrans);
- ReportNdbError(szMsg, err);
- }
- else if(bTimeLatency)
- {
- NdbMutex_Lock(g_pNdbMutexPrintf);
- printf("%s = %ld msec.\n", szOp, lMillisecForThisTrans);
- NdbMutex_Unlock(g_pNdbMutexPrintf);
- }
-
- if(iRes)
- {
- sprintf(szMsg, "%s failed after %ld calls, terminating thread",
- szOp, nNumCallsProcessed);
- ReportNdbError(szMsg, err);
- delete pNdb;
- delete[] pchContextData;
- return 0;
- }
- }
- NDB_TICKS tEndCall = NdbTick_CurrentMillisecond();
- long lMillisecForThisCall = (long)(tEndCall-tStartCall);
-
- if(g_bReport)
- {
- assert(lMillisecForThisCall>=0 && lMillisecForThisCall<c_nMaxMillisecForAllCall);
- InterlockedIncrement(g_plCountMillisecForCall+lMillisecForThisCall);
- }
-
- if(bTimeLatency)
- {
- NdbMutex_Lock(g_pNdbMutexPrintf);
- printf("Total time for call is %ld msec.\n", (long)lMillisecForThisCall);
- NdbMutex_Unlock(g_pNdbMutexPrintf);
- }
-
- nNumCallsProcessed++;
- InterlockedIncrementAndReport();
- if(g_nMaxCallsPerSecond>0)
- {
- int iMillisecToSleep = (1000*g_nNumThreads)/g_nMaxCallsPerSecond;
- iMillisecToSleep -= lMillisecForThisCall;
- if(iMillisecToSleep>0)
- {
- NdbSleep_MilliSleep(iMillisecToSleep);
- }
- }
- }
-
- NdbMutex_Lock(g_pNdbMutexPrintf);
- printf("Terminating thread after %ld calls\n", nNumCallsProcessed);
- NdbMutex_Unlock(g_pNdbMutexPrintf);
-
- delete pNdb;
- delete[] pchContextData;
- return 0;
-}
-
-
-int CreateCallContextTable(Ndb* pNdb, const char* szTableName, bool bStored)
-{
- int iRes = -1;
- NdbError err;
- memset(&err, 0, sizeof(err));
-
- NdbSchemaCon* pNdbSchemaCon = pNdb->startSchemaTransaction();
- if(pNdbSchemaCon)
- {
- NdbSchemaOp* pNdbSchemaOp = pNdbSchemaCon->getNdbSchemaOp();
- if(pNdbSchemaOp)
- {
- if(!pNdbSchemaOp->createTable(szTableName, 8, TupleKey, 2,
- All, 6, 78, 80, 1, bStored)
- && !pNdbSchemaOp->createAttribute(c_szContextId, TupleKey, 32, 1, Signed)
- && !pNdbSchemaOp->createAttribute(c_szVersion, NoKey, 32, 1, Signed)
- && !pNdbSchemaOp->createAttribute(c_szLockFlag, NoKey, 32, 1, Signed)
- && !pNdbSchemaOp->createAttribute(c_szLockTime, NoKey, 32, 1, Signed)
- && !pNdbSchemaOp->createAttribute(c_szLockTimeUSec, NoKey, 32, 1, Signed)
- && !pNdbSchemaOp->createAttribute(c_szContextData, NoKey, 8, g_nStatusDataSize, String))
- {
- if(!pNdbSchemaCon->execute())
- iRes = 0;
- else
- err = pNdbSchemaCon->getNdbError();
- }
- else
- err = pNdbSchemaOp->getNdbError();
- }
- else
- err = pNdbSchemaCon->getNdbError();
- pNdb->closeSchemaTransaction(pNdbSchemaCon);
- }
- else
- err = pNdb->getNdbError();
-
- if(iRes)
- {
- ReportNdbError("create call context table failed", err);
- }
- return iRes;
-}
-
-
-
-void ReportResponseTimeStatistics(const char* szStat, long* plCount, const long lSize)
-{
- long lCount = 0;
- Int64 llSum = 0;
- Int64 llSum2 = 0;
- long lMin = -1;
- long lMax = -1;
-
- for(long l=0; l<lSize; ++l)
- {
- if(plCount[l]>0)
- {
- lCount += plCount[l];
- llSum += (Int64)l*(Int64)plCount[l];
- llSum2 += (Int64)l*(Int64)l*(Int64)plCount[l];
- if(lMin==-1 || l<lMin)
- {
- lMin = l;
- }
- if(lMax==-1 || l>lMax)
- {
- lMax = l;
- }
- }
- }
-
- long lAvg = long(llSum/lCount);
- double dblVar = ((double)lCount*(double)llSum2 - (double)llSum*(double)llSum)/((double)lCount*(double)(lCount-1));
- long lStd = long(sqrt(dblVar));
-
- long lMed = -1;
- long l95 = -1;
- long lSel = -1;
- for(long l=lMin; l<=lMax; ++l)
- {
- if(plCount[l]>0)
- {
- lSel += plCount[l];
- if(lMed==-1 && lSel>=(lCount/2))
- {
- lMed = l;
- }
- if(l95==-1 && lSel>=((lCount*95)/100))
- {
- l95 = l;
- }
- if(g_bReportPlus)
- {
- printf("%ld\t%ld\n", l, plCount[l]);
- }
- }
- }
-
- printf("%s: Count=%ld, Min=%ld, Max=%ld, Avg=%ld, Std=%ld, Med=%ld, 95%%=%ld\n",
- szStat, lCount, lMin, lMax, lAvg, lStd, lMed, l95);
-}
-
-
-
-void ShowHelp(const char* szCmd)
-{
- printf("%s -t<threads> [-s<seed>] [-b<batch>] [-c<maxcps>] [-m<size>] [-d] [-i] [-v] [-f] [-w] [-r[+]]\n", szCmd);
- printf("%s -?\n", szCmd);
- puts("-d\t\tcreate the table");
- puts("-i\t\tinsert initial records");
- puts("-v\t\tverify initial records");
- puts("-t<threads>\tnumber of threads making calls");
- puts("-s<seed>\toffset for primary key");
- puts("-b<batch>\tbatch size per thread");
- puts("-c<maxcps>\tmax number of calls per second for this process");
- puts("-m<size>\tsize of context data");
- puts("-f\t\tno checkpointing and no logging");
- puts("-w\t\tuse writeTuple instead of insertTuple");
- puts("-r\t\treport response time statistics");
- puts("-r+\t\treport response time distribution");
- puts("-?\t\thelp");
-}
-
-
-int main(int argc, char* argv[])
-{
- int iRes = -1;
- g_nNumThreads = 0;
- g_nMaxCallsPerSecond = 0;
- long nSeed = 0;
- bool bStoredTable = true;
- bool bCreateTable = false;
- g_bWriteTuple = false;
- g_bReport = false;
- g_bReportPlus = false;
-
- for(int i=1; i<argc; ++i)
- {
- if(argv[i][0]=='-' || argv[i][0]=='/')
- {
- switch(argv[i][1])
- {
- case 't':
- g_nNumThreads = atol(argv[i]+2);
- break;
- case 's':
- nSeed = atol(argv[i]+2);
- break;
- case 'b':
- g_nMaxContextIdPerThread = atol(argv[i]+2);
- break;
- case 'm':
- g_nStatusDataSize = atol(argv[i]+2);
- if(g_nStatusDataSize>sizeof(STATUS_DATA))
- {
- g_nStatusDataSize = sizeof(STATUS_DATA);
- }
- break;
- case 'i':
- g_bInsertInitial = true;
- break;
- case 'v':
- g_bVerifyInitial = true;
- break;
- case 'd':
- bCreateTable = true;
- break;
- case 'f':
- bStoredTable = false;
- break;
- case 'w':
- g_bWriteTuple = true;
- break;
- case 'r':
- g_bReport = true;
- if(argv[i][2]=='+')
- {
- g_bReportPlus = true;
- }
- break;
- case 'c':
- g_nMaxCallsPerSecond = atol(argv[i]+2);
- break;
- case '?':
- default:
- ShowHelp(argv[0]);
- return -1;
- }
- }
- else
- {
- ShowHelp(argv[0]);
- return -1;
- }
- }
- if(bCreateTable)
- puts("-d\tcreate the table");
- if(g_bInsertInitial)
- printf("-i\tinsert initial records\n");
- if(g_bVerifyInitial)
- printf("-v\tverify initial records\n");
- if(g_nNumThreads>0)
- printf("-t%ld\tnumber of threads making calls\n", g_nNumThreads);
- if(g_nNumThreads>0)
- {
- printf("-s%ld\toffset for primary key\n", nSeed);
- printf("-b%ld\tbatch size per thread\n", g_nMaxContextIdPerThread);
- }
- if(g_nMaxCallsPerSecond>0)
- printf("-c%ld\tmax number of calls per second for this process\n", g_nMaxCallsPerSecond);
- if(!bStoredTable)
- puts("-f\tno checkpointing and no logging to disk");
- if(g_bWriteTuple)
- puts("-w\tuse writeTuple instead of insertTuple");
- if(g_bReport)
- puts("-r\treport response time statistics");
- if(g_bReportPlus)
- puts("-r+\treport response time distribution");
-
- if(!bCreateTable && g_nNumThreads<=0)
- {
- ShowHelp(argv[0]);
- return -1;
- }
- printf("-m%ld\tsize of context data\n", g_nStatusDataSize);
-
- g_szTableName = (bStoredTable ? c_szTableNameStored : c_szTableNameTemp);
-
-#ifdef NDB_WIN32
- SetConsoleCtrlHandler(ConsoleCtrlHandler, true);
-#else
- signal(SIGINT, CtrlCHandler);
-#endif
-
- if(g_bReport)
- {
- g_plCountMillisecForCall = new long[c_nMaxMillisecForAllCall];
- memset(g_plCountMillisecForCall, 0, c_nMaxMillisecForAllCall*sizeof(long));
- g_plCountMillisecForTrans = new long[c_nMaxMillisecForAllTrans];
- memset(g_plCountMillisecForTrans, 0, c_nMaxMillisecForAllTrans*sizeof(long));
- }
-
- g_pNdbMutexIncrement = NdbMutex_Create();
- g_pNdbMutexPrintf = NdbMutex_Create();
-#ifdef NDB_WIN32
- hShutdownEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
-#endif
-
- Ndb* pNdb = new Ndb(c_szDatabaseName);
- if(!pNdb)
- {
- printf("could not construct ndb\n");
- return 1;
- }
-
- if(pNdb->init(1) || pNdb->waitUntilReady())
- {
- ReportNdbError("could not initialize ndb\n", pNdb->getNdbError());
- delete pNdb;
- return 2;
- }
-
- if(bCreateTable)
- {
- printf("Create CallContext table\n");
- if (bStoredTable)
- {
- if (CreateCallContextTable(pNdb, c_szTableNameStored, true))
- {
- printf("Create table failed\n");
- delete pNdb;
- return 3;
- }
- }
- else
- {
- if (CreateCallContextTable(pNdb, c_szTableNameTemp, false))
- {
- printf("Create table failed\n");
- delete pNdb;
- return 3;
- }
- }
- }
-
- if(g_nNumThreads>0)
- {
- printf("creating %d threads\n", (int)g_nNumThreads);
- if(g_bInsertInitial)
- {
- printf("each thread will insert %ld initial records, total %ld inserts\n",
- g_nMaxContextIdPerThread, g_nNumThreads*g_nMaxContextIdPerThread);
- }
- if(g_bVerifyInitial)
- {
- printf("each thread will verify %ld initial records, total %ld reads\n",
- g_nMaxContextIdPerThread, g_nNumThreads*g_nMaxContextIdPerThread);
- }
-
- g_nNumberOfInitialInsert = 0;
- g_nNumberOfInitialVerify = 0;
-
- NDB_TICKS tStartTime = NdbTick_CurrentMillisecond();
- NdbThread* pThreads[256];
- int pnStartingRecordNum[256];
- int ij;
- for(ij=0;ij<g_nNumThreads;ij++)
- {
- pnStartingRecordNum[ij] = (ij*g_nMaxContextIdPerThread) + nSeed;
- }
-
- for(ij=0;ij<g_nNumThreads;ij++)
- {
- pThreads[ij] = NdbThread_Create(RuntimeCallContext,
- (void**)(pnStartingRecordNum+ij),
- 0, "RuntimeCallContext", NDB_THREAD_PRIO_LOW);
- }
-
- //Wait for the threads to finish
- for(ij=0;ij<g_nNumThreads;ij++)
- {
- void* status;
- NdbThread_WaitFor(pThreads[ij], &status);
- }
- NDB_TICKS tEndTime = NdbTick_CurrentMillisecond();
-
- //Print time taken
- printf("Time Taken for %ld Calls is %ld msec (= %ld calls/sec)\n",
- g_nNumCallsProcessed,
- (long)(tEndTime-tStartTime),
- (long)((1000*g_nNumCallsProcessed)/(tEndTime-tStartTime)));
-
- if(g_bInsertInitial)
- printf("successfully inserted %ld tuples\n", g_nNumberOfInitialInsert);
- if(g_bVerifyInitial)
- printf("successfully verified %ld tuples\n", g_nNumberOfInitialVerify);
- }
-
- delete pNdb;
-
-#ifdef NDB_WIN32
- CloseHandle(hShutdownEvent);
-#endif
- NdbMutex_Destroy(g_pNdbMutexIncrement);
- NdbMutex_Destroy(g_pNdbMutexPrintf);
-
- if(g_bReport)
- {
- ReportResponseTimeStatistics("Calls", g_plCountMillisecForCall, c_nMaxMillisecForAllCall);
- ReportResponseTimeStatistics("Transactions", g_plCountMillisecForTrans, c_nMaxMillisecForAllTrans);
-
- delete[] g_plCountMillisecForCall;
- delete[] g_plCountMillisecForTrans;
- }
-
- return 0;
-}
-
diff --git a/ndb/test/ndbapi/testBackup.cpp b/ndb/test/ndbapi/testBackup.cpp
new file mode 100644
index 00000000000..129eced54b0
--- /dev/null
+++ b/ndb/test/ndbapi/testBackup.cpp
@@ -0,0 +1,475 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbBackup.hpp>
+
+
+#define CHECK(b) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ continue; }
+
+
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+bool testMaster = true;
+bool testSlave = false;
+
+int setMaster(NDBT_Context* ctx, NDBT_Step* step){
+ testMaster = true;
+ testSlave = false;
+ return NDBT_OK;
+}
+int setMasterAsSlave(NDBT_Context* ctx, NDBT_Step* step){
+ testMaster = true;
+ testSlave = true;
+ return NDBT_OK;
+}
+int setSlave(NDBT_Context* ctx, NDBT_Step* step){
+ testMaster = false;
+ testSlave = true;
+ return NDBT_OK;
+}
+
+int runAbort(NDBT_Context* ctx, NDBT_Step* step){
+ NdbBackup backup(GETNDB(step)->getNodeId()+1);
+
+ NdbRestarter restarter;
+
+ if (restarter.getNumDbNodes() < 2){
+ ctx->stopTest();
+ return NDBT_OK;
+ }
+
+ if(restarter.waitClusterStarted(60) != 0){
+ g_err << "Cluster failed to start" << endl;
+ return NDBT_FAILED;
+ }
+
+ if (testMaster) {
+ if (testSlave) {
+ if (backup.NFMasterAsSlave(restarter) == -1){
+ return NDBT_FAILED;
+ }
+ } else {
+ if (backup.NFMaster(restarter) == -1){
+ return NDBT_FAILED;
+ }
+ }
+ } else {
+ if (backup.NFSlave(restarter) == -1){
+ return NDBT_FAILED;
+ }
+ }
+
+ return NDBT_OK;
+}
+
+int runFail(NDBT_Context* ctx, NDBT_Step* step){
+ NdbBackup backup(GETNDB(step)->getNodeId()+1);
+
+ NdbRestarter restarter;
+
+ if (restarter.getNumDbNodes() < 2){
+ ctx->stopTest();
+ return NDBT_OK;
+ }
+
+ if(restarter.waitClusterStarted(60) != 0){
+ g_err << "Cluster failed to start" << endl;
+ return NDBT_FAILED;
+ }
+
+ if (testMaster) {
+ if (testSlave) {
+ if (backup.FailMasterAsSlave(restarter) == -1){
+ return NDBT_FAILED;
+ }
+ } else {
+ if (backup.FailMaster(restarter) == -1){
+ return NDBT_FAILED;
+ }
+ }
+ } else {
+ if (backup.FailSlave(restarter) == -1){
+ return NDBT_FAILED;
+ }
+ }
+
+ return NDBT_OK;
+}
+
+int runBackupOne(NDBT_Context* ctx, NDBT_Step* step){
+ NdbBackup backup(GETNDB(step)->getNodeId()+1);
+ unsigned backupId = 0;
+
+ if (backup.start(backupId) == -1){
+ return NDBT_FAILED;
+ }
+ ndbout << "Started backup " << backupId << endl;
+ ctx->setProperty("BackupId", backupId);
+
+ return NDBT_OK;
+}
+
+int runRestartInitial(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+
+ Ndb* pNdb = GETNDB(step);
+
+ const NdbDictionary::Table *tab = ctx->getTab();
+ pNdb->getDictionary()->dropTable(tab->getName());
+
+ if (restarter.restartAll(true) != 0)
+ return NDBT_FAILED;
+
+ return NDBT_OK;
+}
+
+int runRestoreOne(NDBT_Context* ctx, NDBT_Step* step){
+ NdbBackup backup(GETNDB(step)->getNodeId()+1);
+ unsigned backupId = ctx->getProperty("BackupId");
+
+ ndbout << "Restoring backup " << backupId << endl;
+
+ if (backup.restore(backupId) == -1){
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+int runVerifyOne(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ int count = 0;
+
+ ndbout << *(const NDBT_Table*)ctx->getTab() << endl;
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ do{
+
+ // Check that there are as many records as we expected
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+
+ g_err << "count = " << count;
+ g_err << " records = " << records;
+ g_err << endl;
+
+ CHECK(count == records);
+
+ // Read and verify every record
+ CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
+
+ } while (false);
+
+ return result;
+}
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable2(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+#include "bank/Bank.hpp"
+
+int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int overWriteExisting = true;
+ if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int wait = 30; // Max seconds between each "day"
+ int yield = 1; // Loops before bank returns
+
+ while (ctx->isTestStopped() == false) {
+ bank.performIncreaseTime(wait, yield);
+ }
+ return NDBT_OK;
+}
+
+int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int wait = 10; // Max ms between each transaction
+ int yield = 100; // Loops before bank returns
+
+ while (ctx->isTestStopped() == false) {
+ bank.performTransactions(wait, yield);
+ }
+ return NDBT_OK;
+}
+
+int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int yield = 20; // Loops before bank returns
+ int result = NDBT_OK;
+
+ while (ctx->isTestStopped() == false) {
+ if (bank.performMakeGLs(yield) != NDBT_OK){
+ ndbout << "bank.performMakeGLs FAILED" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+ return NDBT_OK;
+}
+
+int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int wait = 2000; // Max ms between each sum of accounts
+ int yield = 1; // Loops before bank returns
+ int result = NDBT_OK;
+
+ while (ctx->isTestStopped() == false) {
+ if (bank.performSumAccounts(wait, yield) != NDBT_OK){
+ ndbout << "bank.performSumAccounts FAILED" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+ return result ;
+}
+
+int runDropBank(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ if (bank.dropBank() != NDBT_OK)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+int runBackupBank(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int l = 0;
+ int maxSleep = 30; // Max seconds between each backup
+ Ndb* pNdb = GETNDB(step);
+ NdbBackup backup(GETNDB(step)->getNodeId()+1);
+ unsigned minBackupId = ~0;
+ unsigned maxBackupId = 0;
+ unsigned backupId = 0;
+ int result = NDBT_OK;
+
+ while (l < loops && result != NDBT_FAILED){
+
+ if (pNdb->waitUntilReady() != 0){
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ // Sleep for a while
+ NdbSleep_SecSleep(maxSleep);
+
+ // Perform backup
+ if (backup.start(backupId) != 0){
+ ndbout << "backup.start failed" << endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+ ndbout << "Started backup " << backupId << endl;
+
+ // Remember min and max backupid
+ if (backupId < minBackupId)
+ minBackupId = backupId;
+
+ if (backupId > maxBackupId)
+ maxBackupId = backupId;
+
+ ndbout << " maxBackupId = " << maxBackupId
+ << ", minBackupId = " << minBackupId << endl;
+ ctx->setProperty("MinBackupId", minBackupId);
+ ctx->setProperty("MaxBackupId", maxBackupId);
+
+ l++;
+ }
+
+ ctx->stopTest();
+
+ return result;
+}
+
+int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+ NdbBackup backup(GETNDB(step)->getNodeId()+1);
+ unsigned minBackupId = ctx->getProperty("MinBackupId");
+ unsigned maxBackupId = ctx->getProperty("MaxBackupId");
+ unsigned backupId = minBackupId;
+ int result = NDBT_OK;
+ int errSumAccounts = 0;
+ int errValidateGL = 0;
+
+ ndbout << " maxBackupId = " << maxBackupId << endl;
+ ndbout << " minBackupId = " << minBackupId << endl;
+
+ while (backupId <= maxBackupId){
+
+ // TEMPORARY FIX
+ // To erase all tables from cache(s)
+ // To be removed, maybe replaced by ndb.invalidate();
+ {
+ Bank bank;
+
+ if (bank.dropBank() != NDBT_OK){
+ result = NDBT_FAILED;
+ break;
+ }
+ }
+ // END TEMPORARY FIX
+
+ ndbout << "Performing initial restart" << endl;
+ if (restarter.restartAll(true) != 0)
+ return NDBT_FAILED;
+
+ if (restarter.waitClusterStarted() != 0)
+ return NDBT_FAILED;
+
+ ndbout << "Restoring backup " << backupId << endl;
+ if (backup.restore(backupId) == -1){
+ return NDBT_FAILED;
+ }
+ ndbout << "Backup " << backupId << " restored" << endl;
+
+ // Let bank verify
+ Bank bank;
+
+ int wait = 0;
+ int yield = 1;
+ if (bank.performSumAccounts(wait, yield) != 0){
+ ndbout << "bank.performSumAccounts FAILED" << endl;
+ ndbout << " backupId = " << backupId << endl << endl;
+ result = NDBT_FAILED;
+ errSumAccounts++;
+ }
+
+ if (bank.performValidateAllGLs() != 0){
+ ndbout << "bank.performValidateAllGLs FAILED" << endl;
+ ndbout << " backupId = " << backupId << endl << endl;
+ result = NDBT_FAILED;
+ errValidateGL++;
+ }
+
+ backupId++;
+ }
+
+ if (result != NDBT_OK){
+ ndbout << "Verification of backup failed" << endl
+ << " errValidateGL="<<errValidateGL<<endl
+ << " errSumAccounts="<<errSumAccounts<<endl << endl;
+ }
+
+ return result;
+}
+
+NDBT_TESTSUITE(testBackup);
+TESTCASE("BackupOne",
+ "Test that backup and restore works on one table \n"
+ "1. Load table\n"
+ "2. Backup\n"
+ "3. Restart -i\n"
+ "4. Restore\n"
+ "5. Verify count and content of table\n"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runBackupOne);
+ INITIALIZER(runRestartInitial);
+ INITIALIZER(runRestoreOne);
+ VERIFIER(runVerifyOne);
+ FINALIZER(runClearTable);
+
+}
+TESTCASE("BackupBank",
+ "Test that backup and restore works during transaction load\n"
+ " by backing up the bank"
+ "1. Create bank\n"
+ "2a. Start bank and let it run\n"
+ "2b. Perform loop number of backups of the bank\n"
+ " when backups are finished tell bank to close\n"
+ "3. Restart ndb -i and reload each backup\n"
+ " let bank verify that the backup is consistent\n"
+ "4. Drop bank\n"){
+ INITIALIZER(runCreateBank);
+ STEP(runBankTimer);
+ STEP(runBankTransactions);
+ STEP(runBankGL);
+ // TODO STEP(runBankSum);
+ STEP(runBackupBank);
+ VERIFIER(runRestoreBankAndVerify);
+ // FINALIZER(runDropBank);
+
+}
+TESTCASE("NFMaster",
+ "Test that backup behaves during node failiure\n"){
+ INITIALIZER(setMaster);
+ STEP(runAbort);
+
+}
+TESTCASE("NFMasterAsSlave",
+ "Test that backup behaves during node failiure\n"){
+ INITIALIZER(setMasterAsSlave);
+ STEP(runAbort);
+
+}
+TESTCASE("NFSlave",
+ "Test that backup behaves during node failiure\n"){
+ INITIALIZER(setSlave);
+ STEP(runAbort);
+
+}
+TESTCASE("FailMaster",
+ "Test that backup behaves during node failiure\n"){
+ INITIALIZER(setMaster);
+ STEP(runFail);
+
+}
+TESTCASE("FailMasterAsSlave",
+ "Test that backup behaves during node failiure\n"){
+ INITIALIZER(setMasterAsSlave);
+ STEP(runFail);
+
+}
+TESTCASE("FailSlave",
+ "Test that backup behaves during node failiure\n"){
+ INITIALIZER(setSlave);
+ STEP(runFail);
+
+}
+NDBT_TESTSUITE_END(testBackup);
+
+int main(int argc, const char** argv){
+ return testBackup.execute(argc, argv);
+}
+
+
diff --git a/ndb/test/ndbapi/testBackup/testBackup.cpp b/ndb/test/ndbapi/testBackup/testBackup.cpp
deleted file mode 100644
index f9ae7ffcbbc..00000000000
--- a/ndb/test/ndbapi/testBackup/testBackup.cpp
+++ /dev/null
@@ -1,476 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NDBT.hpp>
-#include <NDBT_Test.hpp>
-#include <HugoTransactions.hpp>
-#include <UtilTransactions.hpp>
-#include <NdbBackup.hpp>
-
-
-#define CHECK(b) if (!(b)) { \
- g_err << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- continue; }
-
-
-int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
-
- int records = ctx->getNumRecords();
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-bool testMaster = true;
-bool testSlave = false;
-
-int setMaster(NDBT_Context* ctx, NDBT_Step* step){
- testMaster = true;
- testSlave = false;
- return NDBT_OK;
-}
-int setMasterAsSlave(NDBT_Context* ctx, NDBT_Step* step){
- testMaster = true;
- testSlave = true;
- return NDBT_OK;
-}
-int setSlave(NDBT_Context* ctx, NDBT_Step* step){
- testMaster = false;
- testSlave = true;
- return NDBT_OK;
-}
-
-int runAbort(NDBT_Context* ctx, NDBT_Step* step){
- NdbBackup backup(GETNDB(step)->getNodeId()+1);
-
- NdbRestarter restarter;
-
- if (restarter.getNumDbNodes() < 2){
- ctx->stopTest();
- return NDBT_OK;
- }
-
- if(restarter.waitClusterStarted(60) != 0){
- g_err << "Cluster failed to start" << endl;
- return NDBT_FAILED;
- }
-
- if (testMaster) {
- if (testSlave) {
- if (backup.NFMasterAsSlave(restarter) == -1){
- return NDBT_FAILED;
- }
- } else {
- if (backup.NFMaster(restarter) == -1){
- return NDBT_FAILED;
- }
- }
- } else {
- if (backup.NFSlave(restarter) == -1){
- return NDBT_FAILED;
- }
- }
-
- return NDBT_OK;
-}
-
-int runFail(NDBT_Context* ctx, NDBT_Step* step){
- NdbBackup backup(GETNDB(step)->getNodeId()+1);
-
- NdbRestarter restarter;
-
- if (restarter.getNumDbNodes() < 2){
- ctx->stopTest();
- return NDBT_OK;
- }
-
- if(restarter.waitClusterStarted(60) != 0){
- g_err << "Cluster failed to start" << endl;
- return NDBT_FAILED;
- }
-
- if (testMaster) {
- if (testSlave) {
- if (backup.FailMasterAsSlave(restarter) == -1){
- return NDBT_FAILED;
- }
- } else {
- if (backup.FailMaster(restarter) == -1){
- return NDBT_FAILED;
- }
- }
- } else {
- if (backup.FailSlave(restarter) == -1){
- return NDBT_FAILED;
- }
- }
-
- return NDBT_OK;
-}
-
-int runBackupOne(NDBT_Context* ctx, NDBT_Step* step){
- NdbBackup backup(GETNDB(step)->getNodeId()+1);
- unsigned backupId = 0;
-
- if (backup.start(backupId) == -1){
- return NDBT_FAILED;
- }
- ndbout << "Started backup " << backupId << endl;
- ctx->setProperty("BackupId", backupId);
-
- return NDBT_OK;
-}
-
-int runRestartInitial(NDBT_Context* ctx, NDBT_Step* step){
- NdbRestarter restarter;
-
- Ndb* pNdb = GETNDB(step);
-
- const NdbDictionary::Table *tab = ctx->getTab();
- pNdb->getDictionary()->dropTable(tab->getName());
-
- if (restarter.restartAll(true) != 0)
- return NDBT_FAILED;
-
- return NDBT_OK;
-}
-
-int runRestoreOne(NDBT_Context* ctx, NDBT_Step* step){
- NdbBackup backup(GETNDB(step)->getNodeId()+1);
- unsigned backupId = ctx->getProperty("BackupId");
-
- ndbout << "Restoring backup " << backupId << endl;
-
- if (backup.restore(backupId) == -1){
- return NDBT_FAILED;
- }
-
- return NDBT_OK;
-}
-
-int runVerifyOne(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- int count = 0;
-
- ndbout << *(const NDBT_Table*)ctx->getTab() << endl;
-
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
-
- do{
-
- // Check that there are as many records as we expected
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
-
- g_err << "count = " << count;
- g_err << " records = " << records;
- g_err << endl;
-
- CHECK(count == records);
-
- // Read and verify every record
- CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
-
- } while (false);
-
- return result;
-}
-
-int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
-
- UtilTransactions utilTrans(*ctx->getTab());
- if (utilTrans.clearTable2(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-
-#include "../bank/Bank.hpp"
-
-int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int overWriteExisting = true;
- if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK)
- return NDBT_FAILED;
- return NDBT_OK;
-}
-
-int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int wait = 30; // Max seconds between each "day"
- int yield = 1; // Loops before bank returns
-
- while (ctx->isTestStopped() == false) {
- bank.performIncreaseTime(wait, yield);
- }
- return NDBT_OK;
-}
-
-int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int wait = 10; // Max ms between each transaction
- int yield = 100; // Loops before bank returns
-
- while (ctx->isTestStopped() == false) {
- bank.performTransactions(wait, yield);
- }
- return NDBT_OK;
-}
-
-int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int yield = 20; // Loops before bank returns
- int result = NDBT_OK;
-
- while (ctx->isTestStopped() == false) {
- if (bank.performMakeGLs(yield) != NDBT_OK){
- ndbout << "bank.performMakeGLs FAILED" << endl;
- result = NDBT_FAILED;
- }
- }
- return NDBT_OK;
-}
-
-int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- int wait = 2000; // Max ms between each sum of accounts
- int yield = 1; // Loops before bank returns
- int result = NDBT_OK;
-
- while (ctx->isTestStopped() == false) {
- if (bank.performSumAccounts(wait, yield) != NDBT_OK){
- ndbout << "bank.performSumAccounts FAILED" << endl;
- result = NDBT_FAILED;
- }
- }
- return result ;
-}
-
-int runDropBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
- if (bank.dropBank() != NDBT_OK)
- return NDBT_FAILED;
- return NDBT_OK;
-}
-
-int runBackupBank(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int l = 0;
- int maxSleep = 30; // Max seconds between each backup
- Ndb* pNdb = GETNDB(step);
- NdbBackup backup(GETNDB(step)->getNodeId()+1);
- unsigned minBackupId = ~0;
- unsigned maxBackupId = 0;
- unsigned backupId = 0;
- int result = NDBT_OK;
-
- while (l < loops && result != NDBT_FAILED){
-
- if (pNdb->waitUntilReady() != 0){
- result = NDBT_FAILED;
- continue;
- }
-
- // Sleep for a while
- NdbSleep_SecSleep(maxSleep);
-
- // Perform backup
- if (backup.start(backupId) != 0){
- ndbout << "backup.start failed" << endl;
- result = NDBT_FAILED;
- continue;
- }
- ndbout << "Started backup " << backupId << endl;
-
- // Remember min and max backupid
- if (backupId < minBackupId)
- minBackupId = backupId;
-
- if (backupId > maxBackupId)
- maxBackupId = backupId;
-
- ndbout << " maxBackupId = " << maxBackupId
- << ", minBackupId = " << minBackupId << endl;
- ctx->setProperty("MinBackupId", minBackupId);
- ctx->setProperty("MaxBackupId", maxBackupId);
-
- l++;
- }
-
- ctx->stopTest();
-
- return result;
-}
-
-int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){
- NdbRestarter restarter;
- NdbBackup backup(GETNDB(step)->getNodeId()+1);
- unsigned minBackupId = ctx->getProperty("MinBackupId");
- unsigned maxBackupId = ctx->getProperty("MaxBackupId");
- unsigned backupId = minBackupId;
- int result = NDBT_OK;
- int errSumAccounts = 0;
- int errValidateGL = 0;
-
- ndbout << " maxBackupId = " << maxBackupId << endl;
- ndbout << " minBackupId = " << minBackupId << endl;
-
- while (backupId <= maxBackupId){
-
- // TEMPORARY FIX
- // To erase all tables from cache(s)
- // To be removed, maybe replaced by ndb.invalidate();
- {
- Bank bank;
-
- if (bank.dropBank() != NDBT_OK){
- result = NDBT_FAILED;
- break;
- }
- }
- // END TEMPORARY FIX
-
- ndbout << "Performing initial restart" << endl;
- if (restarter.restartAll(true) != 0)
- return NDBT_FAILED;
-
- if (restarter.waitClusterStarted() != 0)
- return NDBT_FAILED;
-
- ndbout << "Restoring backup " << backupId << endl;
- if (backup.restore(backupId) == -1){
- return NDBT_FAILED;
- }
- ndbout << "Backup " << backupId << " restored" << endl;
-
- // Let bank verify
- Bank bank;
-
- int wait = 0;
- int yield = 1;
- if (bank.performSumAccounts(wait, yield) != 0){
- ndbout << "bank.performSumAccounts FAILED" << endl;
- ndbout << " backupId = " << backupId << endl << endl;
- result = NDBT_FAILED;
- errSumAccounts++;
- }
-
- if (bank.performValidateAllGLs() != 0){
- ndbout << "bank.performValidateAllGLs FAILED" << endl;
- ndbout << " backupId = " << backupId << endl << endl;
- result = NDBT_FAILED;
- errValidateGL++;
- }
-
- backupId++;
- }
-
- if (result != NDBT_OK){
- ndbout << "Verification of backup failed" << endl
- << " errValidateGL="<<errValidateGL<<endl
- << " errSumAccounts="<<errSumAccounts<<endl << endl;
- }
-
- return result;
-}
-
-NDBT_TESTSUITE(testBackup);
-TESTCASE("BackupOne",
- "Test that backup and restore works on one table \n"
- "1. Load table\n"
- "2. Backup\n"
- "3. Restart -i\n"
- "4. Restore\n"
- "5. Verify count and content of table\n"){
- INITIALIZER(runLoadTable);
- INITIALIZER(runBackupOne);
- INITIALIZER(runRestartInitial);
- INITIALIZER(runRestoreOne);
- VERIFIER(runVerifyOne);
- FINALIZER(runClearTable);
-
-}
-TESTCASE("BackupBank",
- "Test that backup and restore works during transaction load\n"
- " by backing up the bank"
- "1. Create bank\n"
- "2a. Start bank and let it run\n"
- "2b. Perform loop number of backups of the bank\n"
- " when backups are finished tell bank to close\n"
- "3. Restart ndb -i and reload each backup\n"
- " let bank verify that the backup is consistent\n"
- "4. Drop bank\n"){
- INITIALIZER(runCreateBank);
- STEP(runBankTimer);
- STEP(runBankTransactions);
- STEP(runBankGL);
- // TODO STEP(runBankSum);
- STEP(runBackupBank);
- VERIFIER(runRestoreBankAndVerify);
- // FINALIZER(runDropBank);
-
-}
-TESTCASE("NFMaster",
- "Test that backup behaves during node failiure\n"){
- INITIALIZER(setMaster);
- STEP(runAbort);
-
-}
-TESTCASE("NFMasterAsSlave",
- "Test that backup behaves during node failiure\n"){
- INITIALIZER(setMasterAsSlave);
- STEP(runAbort);
-
-}
-TESTCASE("NFSlave",
- "Test that backup behaves during node failiure\n"){
- INITIALIZER(setSlave);
- STEP(runAbort);
-
-}
-TESTCASE("FailMaster",
- "Test that backup behaves during node failiure\n"){
- INITIALIZER(setMaster);
- STEP(runFail);
-
-}
-TESTCASE("FailMasterAsSlave",
- "Test that backup behaves during node failiure\n"){
- INITIALIZER(setMasterAsSlave);
- STEP(runFail);
-
-}
-TESTCASE("FailSlave",
- "Test that backup behaves during node failiure\n"){
- INITIALIZER(setSlave);
- STEP(runFail);
-
-}
-NDBT_TESTSUITE_END(testBackup);
-
-int main(int argc, const char** argv){
- return testBackup.execute(argc, argv);
-}
-
-
diff --git a/ndb/test/ndbapi/testBasic/testBasic.cpp b/ndb/test/ndbapi/testBasic.cpp
index 64dfe492c2c..64dfe492c2c 100644
--- a/ndb/test/ndbapi/testBasic/testBasic.cpp
+++ b/ndb/test/ndbapi/testBasic.cpp
diff --git a/ndb/test/ndbapi/basicAsynch/testBasicAsynch.cpp b/ndb/test/ndbapi/testBasicAsynch.cpp
index a97920e53da..a97920e53da 100755..100644
--- a/ndb/test/ndbapi/basicAsynch/testBasicAsynch.cpp
+++ b/ndb/test/ndbapi/testBasicAsynch.cpp
diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp
new file mode 100644
index 00000000000..001ec83630a
--- /dev/null
+++ b/ndb/test/ndbapi/testBlobs.cpp
@@ -0,0 +1,1213 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ * testBlobs
+ */
+
+#include <ndb_global.h>
+#include <NdbMain.h>
+#include <NdbOut.hpp>
+#include <NdbTest.hpp>
+
+struct Bcol {
+ bool m_nullable;
+ unsigned m_inline;
+ unsigned m_partsize;
+ unsigned m_stripe;
+ char m_btname[NdbBlob::BlobTableNameSize];
+ Bcol(bool a, unsigned b, unsigned c, unsigned d) :
+ m_nullable(a),
+ m_inline(b),
+ m_partsize(c),
+ m_stripe(d)
+ {}
+};
+
+struct Opt {
+ bool m_core;
+ bool m_dbg;
+ bool m_dbgall;
+ bool m_full;
+ unsigned m_loop;
+ unsigned m_parts;
+ unsigned m_rows;
+ unsigned m_seed;
+ char m_skip[255];
+ // metadata
+ const char* m_tname;
+ const char* m_x1name; // hash index
+ const char* m_x2name; // ordered index
+ unsigned m_pk1off;
+ unsigned m_pk2len;
+ bool m_oneblob;
+ Bcol m_blob1;
+ Bcol m_blob2;
+ // bugs
+ int m_bug;
+ int (*m_bugtest)();
+ Opt() :
+ m_core(false),
+ m_dbg(false),
+ m_dbgall(false),
+ m_full(false),
+ m_loop(1),
+ m_parts(10),
+ m_rows(100),
+ m_seed(0),
+ // metadata
+ m_tname("TBLOB1"),
+ m_x1name("TBLOB1X1"),
+ m_x2name("TBLOB1X2"),
+ m_pk1off(0x12340000),
+ m_pk2len(55),
+ m_oneblob(false),
+ m_blob1(false, 7, 1137, 10),
+ m_blob2(true, 99, 55, 1),
+ // bugs
+ m_bug(0),
+ m_bugtest(0) {
+ memset(m_skip, false, sizeof(m_skip));
+ }
+};
+
+static const unsigned g_max_pk2len = 256;
+
+static void
+printusage()
+{
+ Opt d;
+ ndbout
+ << "usage: testBlobs options [default/max]" << endl
+ << " -core dump core on error" << endl
+ << " -dbg print debug" << endl
+ << " -dbgall print also NDB API debug (if compiled in)" << endl
+ << " -full read/write only full blob values" << endl
+ << " -inline read/write only blobs which fit inline" << endl
+ << " -loop N loop N times 0=forever [" << d.m_loop << "]" << endl
+ << " -parts N max parts in blob value [" << d.m_parts << "]" << endl
+ << " -rows N number of rows [" << d.m_rows << "]" << endl
+ << " -seed N random seed 0=loop number [" << d.m_seed << "]" << endl
+ << " -skip xxx skip these tests (see list)" << endl
+ << "metadata" << endl
+ << " -pk2len N length of PK2 [" << d.m_pk2len << "/" << g_max_pk2len <<"]" << endl
+ << " -oneblob only 1 blob attribute [default 2]" << endl
+ << "testcases for -skip" << endl
+ << " k primary key ops" << endl
+ << " i hash index ops" << endl
+ << " s table scans" << endl
+ << " r ordered index scans" << endl
+ << " u update blob value" << endl
+ << " v getValue / setValue" << endl
+ << " w readData / writeData" << endl
+ << "bug tests (no blob test)" << endl
+ << " -bug 4088 ndb api hang with mixed ops on index table" << endl
+ << " -bug 2222 delete + write gives 626" << endl
+ << " -bug 3333 acc crash on delete and long key" << endl
+ ;
+}
+
+static Opt g_opt;
+
+static char&
+skip(unsigned x)
+{
+ assert(x < sizeof(g_opt.m_skip));
+ return g_opt.m_skip[x];
+}
+
+static Ndb* g_ndb = 0;
+static NdbDictionary::Dictionary* g_dic = 0;
+static NdbConnection* g_con = 0;
+static NdbOperation* g_opr = 0;
+static NdbIndexOperation* g_opx = 0;
+static NdbScanOperation* g_ops = 0;
+static NdbBlob* g_bh1 = 0;
+static NdbBlob* g_bh2 = 0;
+static bool g_printerror = true;
+
+static void
+printerror(int line, const char* msg)
+{
+ ndbout << "line " << line << ": " << msg << " failed" << endl;
+ if (! g_printerror) {
+ return;
+ }
+ if (g_ndb != 0 && g_ndb->getNdbError().code != 0) {
+ ndbout << "ndb: " << g_ndb->getNdbError() << endl;
+ }
+ if (g_dic != 0 && g_dic->getNdbError().code != 0) {
+ ndbout << "dic: " << g_dic->getNdbError() << endl;
+ }
+ if (g_con != 0 && g_con->getNdbError().code != 0) {
+ ndbout << "con: " << g_con->getNdbError() << endl;
+ if (g_opr != 0 && g_opr->getNdbError().code != 0) {
+ ndbout << "opr: table=" << g_opr->getTableName() << " " << g_opr->getNdbError() << endl;
+ }
+ if (g_opx != 0 && g_opx->getNdbError().code != 0) {
+ ndbout << "opx: table=" << g_opx->getTableName() << " " << g_opx->getNdbError() << endl;
+ }
+ if (g_ops != 0 && g_ops->getNdbError().code != 0) {
+ ndbout << "ops: table=" << g_ops->getTableName() << " " << g_ops->getNdbError() << endl;
+ }
+ NdbOperation* ope = g_con->getNdbErrorOperation();
+ if (ope != 0 && ope->getNdbError().code != 0) {
+ if (ope != g_opr && ope != g_opx && ope != g_ops)
+ ndbout << "ope: table=" << ope->getTableName() << " " << ope->getNdbError() << endl;
+ }
+ }
+ if (g_bh1 != 0 && g_bh1->getNdbError().code != 0) {
+ ndbout << "bh1: " << g_bh1->getNdbError() << endl;
+ }
+ if (g_bh2 != 0 && g_bh2->getNdbError().code != 0) {
+ ndbout << "bh2: " << g_bh2->getNdbError() << endl;
+ }
+ if (g_opt.m_core) {
+ abort();
+ }
+ g_printerror = false;
+}
+
+#define CHK(x) \
+ do { \
+ if (x) break; \
+ printerror(__LINE__, #x); return -1; \
+ } while (0)
+#define DBG(x) \
+ do { \
+ if (! g_opt.m_dbg) break; \
+ ndbout << "line " << __LINE__ << " " << x << endl; \
+ } while (0)
+
+static int
+dropTable()
+{
+ NdbDictionary::Table tab(g_opt.m_tname);
+ if (g_dic->getTable(g_opt.m_tname) != 0)
+ CHK(g_dic->dropTable(tab) == 0);
+ return 0;
+}
+
+static int
+createTable()
+{
+ NdbDictionary::Table tab(g_opt.m_tname);
+ // col PK1 - Uint32
+ { NdbDictionary::Column col("PK1");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ tab.addColumn(col);
+ }
+ // col BL1 - Blob not-nullable
+ { NdbDictionary::Column col("BL1");
+ const Bcol& b = g_opt.m_blob1;
+ col.setType(NdbDictionary::Column::Blob);
+ col.setInlineSize(b.m_inline);
+ col.setPartSize(b.m_partsize);
+ col.setStripeSize(b.m_stripe);
+ tab.addColumn(col);
+ }
+ // col PK2 - Char[55]
+ if (g_opt.m_pk2len != 0)
+ { NdbDictionary::Column col("PK2");
+ col.setType(NdbDictionary::Column::Char);
+ col.setLength(g_opt.m_pk2len);
+ col.setPrimaryKey(true);
+ tab.addColumn(col);
+ }
+ // col BL2 - Clob nullable
+ if (! g_opt.m_oneblob)
+ { NdbDictionary::Column col("BL2");
+ const Bcol& b = g_opt.m_blob2;
+ col.setType(NdbDictionary::Column::Clob);
+ col.setNullable(true);
+ col.setInlineSize(b.m_inline);
+ col.setPartSize(b.m_partsize);
+ col.setStripeSize(b.m_stripe);
+ tab.addColumn(col);
+ }
+ // create table
+ CHK(g_dic->createTable(tab) == 0);
+ // unique hash index on PK2
+ if (g_opt.m_pk2len != 0)
+ { NdbDictionary::Index idx(g_opt.m_x1name);
+ idx.setType(NdbDictionary::Index::UniqueHashIndex);
+ idx.setTable(g_opt.m_tname);
+ idx.addColumnName("PK2");
+ CHK(g_dic->createIndex(idx) == 0);
+ }
+ // ordered index on PK2
+ if (g_opt.m_pk2len != 0)
+ { NdbDictionary::Index idx(g_opt.m_x2name);
+ idx.setType(NdbDictionary::Index::OrderedIndex);
+ idx.setLogging(false);
+ idx.setTable(g_opt.m_tname);
+ idx.addColumnName("PK2");
+ CHK(g_dic->createIndex(idx) == 0);
+ }
+ return 0;
+}
+
+// tuples
+
+struct Bval {
+ char* m_val;
+ unsigned m_len;
+ char* m_buf;
+ unsigned m_buflen;
+ Bval() :
+ m_val(0),
+ m_len(0),
+ m_buf(0), // read/write buffer
+ m_buflen(0)
+ {}
+ ~Bval() { delete [] m_val; delete [] m_buf; }
+ void alloc(unsigned buflen) {
+ m_buflen = buflen;
+ delete [] m_buf;
+ m_buf = new char [m_buflen];
+ trash();
+ }
+ void copy(const Bval& v) {
+ m_len = v.m_len;
+ delete [] m_val;
+ if (v.m_val == 0)
+ m_val = 0;
+ else
+ m_val = (char*)memcpy(new char [m_len], v.m_val, m_len);
+ }
+ void trash() const {
+ assert(m_buf != 0);
+ memset(m_buf, 'x', m_buflen);
+ }
+private:
+ Bval(const Bval&);
+ Bval& operator=(const Bval&);
+};
+
+struct Tup {
+ bool m_exists; // exists in table
+ Uint32 m_pk1; // primary keys concatenated like keyinfo
+ char m_pk2[g_max_pk2len + 1];
+ Bval m_blob1;
+ Bval m_blob2;
+ Tup() :
+ m_exists(false)
+ {}
+ ~Tup() { }
+ // alloc buffers of max size
+ void alloc() {
+ m_blob1.alloc(g_opt.m_blob1.m_inline + g_opt.m_blob1.m_partsize * g_opt.m_parts);
+ m_blob2.alloc(g_opt.m_blob2.m_inline + g_opt.m_blob2.m_partsize * g_opt.m_parts);
+ }
+ void copy(const Tup& tup) {
+ assert(m_pk1 == tup.m_pk1);
+ m_blob1.copy(tup.m_blob1);
+ m_blob2.copy(tup.m_blob2);
+ }
+private:
+ Tup(const Tup&);
+ Tup& operator=(const Tup&);
+};
+
+static Tup* g_tups;
+
+static unsigned
+urandom(unsigned n)
+{
+ return n == 0 ? 0 : random() % n;
+}
+
+static void
+calcBval(const Bcol& b, Bval& v, bool keepsize)
+{
+ if (b.m_nullable && urandom(10) == 0) {
+ v.m_len = 0;
+ delete v.m_val;
+ v.m_val = 0;
+ v.m_buf = new char [1];
+ } else {
+ if (keepsize && v.m_val != 0)
+ ;
+ else if (urandom(10) == 0)
+ v.m_len = urandom(b.m_inline);
+ else
+ v.m_len = urandom(b.m_inline + g_opt.m_parts * b.m_partsize + 1);
+ delete v.m_val;
+ v.m_val = new char [v.m_len + 1];
+ for (unsigned i = 0; i < v.m_len; i++)
+ v.m_val[i] = 'a' + urandom(25);
+ v.m_val[v.m_len] = 0;
+ v.m_buf = new char [v.m_len];
+ }
+ v.m_buflen = v.m_len;
+ v.trash();
+}
+
+static void
+calcTups(bool keepsize)
+{
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ tup.m_pk1 = g_opt.m_pk1off + k;
+ for (unsigned i = 0, n = k; i < g_opt.m_pk2len; i++) {
+ if (n != 0) {
+ tup.m_pk2[i] = '0' + n % 10;
+ n = n / 10;
+ } else {
+ tup.m_pk2[i] = 'a' + i % 26;
+ }
+ }
+ calcBval(g_opt.m_blob1, tup.m_blob1, keepsize);
+ if (! g_opt.m_oneblob)
+ calcBval(g_opt.m_blob2, tup.m_blob2, keepsize);
+ }
+}
+
+// blob handle ops
+
+static int
+getBlobLength(NdbBlob* h, unsigned& len)
+{
+ Uint64 len2 = (unsigned)-1;
+ CHK(h->getLength(len2) == 0);
+ len = (unsigned)len2;
+ assert(len == len2);
+ return 0;
+}
+
+static int
+setBlobValue(NdbBlob* h, const Bval& v)
+{
+ bool null = (v.m_val == 0);
+ bool isNull;
+ unsigned len;
+ DBG("set " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null);
+ if (null) {
+ CHK(h->setNull() == 0);
+ isNull = false;
+ CHK(h->getNull(isNull) == 0 && isNull == true);
+ CHK(getBlobLength(h, len) == 0 && len == 0);
+ } else {
+ CHK(h->setValue(v.m_val, v.m_len) == 0);
+ CHK(h->getNull(isNull) == 0 && isNull == false);
+ CHK(getBlobLength(h, len) == 0 && len == v.m_len);
+ }
+ return 0;
+}
+
+static int
+getBlobValue(NdbBlob* h, const Bval& v)
+{
+ bool null = (v.m_val == 0);
+ DBG("get " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null);
+ CHK(h->getValue(v.m_buf, v.m_buflen) == 0);
+ return 0;
+}
+
+static int
+getBlobValue(const Tup& tup)
+{
+ CHK(getBlobValue(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(getBlobValue(g_bh2, tup.m_blob2) == 0);
+ return 0;
+}
+
+static int
+verifyBlobValue(NdbBlob* h, const Bval& v)
+{
+ bool null = (v.m_val == 0);
+ bool isNull;
+ unsigned len;
+ if (null) {
+ isNull = false;
+ CHK(h->getNull(isNull) == 0 && isNull == true);
+ CHK(getBlobLength(h, len) == 0 && len == 0);
+ } else {
+ isNull = true;
+ CHK(h->getNull(isNull) == 0 && isNull == false);
+ CHK(getBlobLength(h, len) == 0 && len == v.m_len);
+ for (unsigned i = 0; i < v.m_len; i++)
+ CHK(v.m_val[i] == v.m_buf[i]);
+ }
+ return 0;
+}
+
+static int
+verifyBlobValue(const Tup& tup)
+{
+ CHK(verifyBlobValue(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(verifyBlobValue(g_bh2, tup.m_blob2) == 0);
+ return 0;
+}
+
+static int
+writeBlobData(NdbBlob* h, const Bval& v)
+{
+ bool null = (v.m_val == 0);
+ bool isNull;
+ unsigned len;
+ DBG("write " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null);
+ if (null) {
+ CHK(h->setNull() == 0);
+ isNull = false;
+ CHK(h->getNull(isNull) == 0 && isNull == true);
+ CHK(getBlobLength(h, len) == 0 && len == 0);
+ } else {
+ unsigned n = 0;
+ do {
+ unsigned m = g_opt.m_full ? v.m_len : urandom(v.m_len + 1);
+ if (m > v.m_len - n)
+ m = v.m_len - n;
+ DBG("write pos=" << n << " cnt=" << m);
+ CHK(h->writeData(v.m_val + n, m) == 0);
+ n += m;
+ } while (n < v.m_len);
+ assert(n == v.m_len);
+ isNull = true;
+ CHK(h->getNull(isNull) == 0 && isNull == false);
+ CHK(getBlobLength(h, len) == 0 && len == v.m_len);
+ }
+ return 0;
+}
+
+static int
+readBlobData(NdbBlob* h, const Bval& v)
+{
+ bool null = (v.m_val == 0);
+ bool isNull;
+ unsigned len;
+ DBG("read " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null);
+ if (null) {
+ isNull = false;
+ CHK(h->getNull(isNull) == 0 && isNull == true);
+ CHK(getBlobLength(h, len) == 0 && len == 0);
+ } else {
+ isNull = true;
+ CHK(h->getNull(isNull) == 0 && isNull == false);
+ CHK(getBlobLength(h, len) == 0 && len == v.m_len);
+ v.trash();
+ unsigned n = 0;
+ while (n < v.m_len) {
+ unsigned m = g_opt.m_full ? v.m_len : urandom(v.m_len + 1);
+ if (m > v.m_len - n)
+ m = v.m_len - n;
+ DBG("read pos=" << n << " cnt=" << m);
+ const unsigned m2 = m;
+ CHK(h->readData(v.m_buf + n, m) == 0);
+ CHK(m2 == m);
+ n += m;
+ }
+ assert(n == v.m_len);
+ // need to execute to see the data
+ CHK(g_con->execute(NoCommit) == 0);
+ for (unsigned i = 0; i < v.m_len; i++)
+ CHK(v.m_val[i] == v.m_buf[i]);
+ }
+ return 0;
+}
+
+static int
+readBlobData(const Tup& tup)
+{
+ CHK(readBlobData(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(readBlobData(g_bh2, tup.m_blob2) == 0);
+ return 0;
+}
+
+// verify blob data
+
+static int
+verifyHeadInline(const Bcol& c, const Bval& v, NdbRecAttr* ra)
+{
+ if (v.m_val == 0) {
+ CHK(ra->isNULL() == 1);
+ } else {
+ CHK(ra->isNULL() == 0);
+ CHK(ra->u_64_value() == v.m_len);
+ }
+ return 0;
+}
+
+static int
+verifyHeadInline(const Tup& tup)
+{
+ DBG("verifyHeadInline pk1=" << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHK(g_opr->readTuple() == 0);
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ NdbRecAttr* ra1;
+ NdbRecAttr* ra2;
+ CHK((ra1 = g_opr->getValue("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((ra2 = g_opr->getValue("BL2")) != 0);
+ if (tup.m_exists) {
+ CHK(g_con->execute(Commit) == 0);
+ DBG("verifyHeadInline BL1");
+ CHK(verifyHeadInline(g_opt.m_blob1, tup.m_blob1, ra1) == 0);
+ if (! g_opt.m_oneblob) {
+ DBG("verifyHeadInline BL2");
+ CHK(verifyHeadInline(g_opt.m_blob2, tup.m_blob2, ra2) == 0);
+ }
+ } else {
+ CHK(g_con->execute(Commit) == -1 && g_con->getNdbError().code == 626);
+ }
+ g_ndb->closeTransaction(g_con);
+ g_opr = 0;
+ g_con = 0;
+ return 0;
+}
+
+static int
+verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists)
+{
+ DBG("verify " << b.m_btname << " pk1=" << pk1);
+ NdbRecAttr* ra_pk;
+ NdbRecAttr* ra_part;
+ NdbRecAttr* ra_data;
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opr = g_con->getNdbOperation(b.m_btname)) != 0);
+ CHK(g_opr->openScanRead() == 0);
+ CHK((ra_pk = g_opr->getValue("PK")) != 0);
+ CHK((ra_part = g_opr->getValue("PART")) != 0);
+ CHK((ra_data = g_opr->getValue("DATA")) != 0);
+ CHK(g_con->executeScan() == 0);
+ unsigned partcount;
+ if (! exists || v.m_len <= b.m_inline)
+ partcount = 0;
+ else
+ partcount = (v.m_len - b.m_inline + b.m_partsize - 1) / b.m_partsize;
+ char* seen = new char [partcount];
+ memset(seen, 0, partcount);
+ while (1) {
+ int ret;
+ CHK((ret = g_con->nextScanResult()) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ if (pk1 != ra_pk->u_32_value())
+ continue;
+ Uint32 part = ra_part->u_32_value();
+ DBG("part " << part << " of " << partcount);
+ const char* data = ra_data->aRef();
+ CHK(part < partcount && ! seen[part]);
+ seen[part] = 1;
+ unsigned n = b.m_inline + part * b.m_partsize;
+ assert(exists && v.m_val != 0 && n < v.m_len);
+ unsigned m = v.m_len - n;
+ if (m > b.m_partsize)
+ m = b.m_partsize;
+ CHK(memcmp(data, v.m_val + n, m) == 0);
+ }
+ for (unsigned i = 0; i < partcount; i++)
+ CHK(seen[i] == 1);
+ g_ndb->closeTransaction(g_con);
+ g_opr = 0;
+ g_con = 0;
+ return 0;
+}
+
+static int
+verifyBlobTable(const Tup& tup)
+{
+ CHK(verifyBlobTable(g_opt.m_blob1, tup.m_blob1, tup.m_pk1, tup.m_exists) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(verifyBlobTable(g_opt.m_blob2, tup.m_blob2, tup.m_pk1, tup.m_exists) == 0);
+ return 0;
+}
+
+static int
+verifyBlob()
+{
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ const Tup& tup = g_tups[k];
+ DBG("verifyBlob pk1=" << tup.m_pk1);
+ CHK(verifyHeadInline(tup) == 0);
+ CHK(verifyBlobTable(tup) == 0);
+ }
+ return 0;
+}
+
+// operations
+
+static int
+insertPk(bool rw)
+{
+ DBG("--- insertPk ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("insertPk pk1=" << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHK(g_opr->insertTuple() == 0);
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK((g_bh1 = g_opr->getBlobHandle("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((g_bh2 = g_opr->getBlobHandle("BL2")) != 0);
+ if (! rw) {
+ CHK(setBlobValue(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(setBlobValue(g_bh2, tup.m_blob2) == 0);
+ } else {
+ // non-nullable must be set
+ CHK(g_bh1->setValue("", 0) == 0);
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(writeBlobData(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(writeBlobData(g_bh2, tup.m_blob2) == 0);
+ }
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_opr = 0;
+ g_con = 0;
+ tup.m_exists = true;
+ }
+ return 0;
+}
+
+static int
+updatePk(bool rw)
+{
+ DBG("--- updatePk ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("updatePk pk1=" << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHK(g_opr->updateTuple() == 0);
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK((g_bh1 = g_opr->getBlobHandle("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((g_bh2 = g_opr->getBlobHandle("BL2")) != 0);
+ if (! rw) {
+ CHK(setBlobValue(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(setBlobValue(g_bh2, tup.m_blob2) == 0);
+ } else {
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(writeBlobData(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(writeBlobData(g_bh2, tup.m_blob2) == 0);
+ }
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_opr = 0;
+ g_con = 0;
+ tup.m_exists = true;
+ }
+ return 0;
+}
+
+static int
+updateIdx(bool rw)
+{
+ DBG("--- updateIdx ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("updateIdx pk1=" << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
+ CHK(g_opx->updateTuple() == 0);
+ CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
+ CHK((g_bh1 = g_opx->getBlobHandle("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((g_bh2 = g_opx->getBlobHandle("BL2")) != 0);
+ if (! rw) {
+ CHK(setBlobValue(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(setBlobValue(g_bh2, tup.m_blob2) == 0);
+ } else {
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(writeBlobData(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(writeBlobData(g_bh2, tup.m_blob2) == 0);
+ }
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_opx = 0;
+ g_con = 0;
+ tup.m_exists = true;
+ }
+ return 0;
+}
+
+static int
+readPk(bool rw)
+{
+ DBG("--- readPk ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("readPk pk1=" << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHK(g_opr->readTuple() == 0);
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK((g_bh1 = g_opr->getBlobHandle("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((g_bh2 = g_opr->getBlobHandle("BL2")) != 0);
+ if (! rw) {
+ CHK(getBlobValue(tup) == 0);
+ } else {
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(readBlobData(tup) == 0);
+ }
+ CHK(g_con->execute(Commit) == 0);
+ if (! rw) {
+ CHK(verifyBlobValue(tup) == 0);
+ }
+ g_ndb->closeTransaction(g_con);
+ g_opr = 0;
+ g_con = 0;
+ }
+ return 0;
+}
+
+static int
+readIdx(bool rw)
+{
+ DBG("--- readIdx ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("readIdx pk1=" << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
+ CHK(g_opx->readTuple() == 0);
+ CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
+ CHK((g_bh1 = g_opx->getBlobHandle("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((g_bh2 = g_opx->getBlobHandle("BL2")) != 0);
+ if (! rw) {
+ CHK(getBlobValue(tup) == 0);
+ } else {
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(readBlobData(tup) == 0);
+ }
+ CHK(g_con->execute(Commit) == 0);
+ if (! rw) {
+ CHK(verifyBlobValue(tup) == 0);
+ }
+ g_ndb->closeTransaction(g_con);
+ g_opx = 0;
+ g_con = 0;
+ }
+ return 0;
+}
+
+static int
+readScan(bool rw, bool idx)
+{
+ const char* func = ! idx ? "scan read table" : "scan read index";
+ DBG("--- " << func << " ---");
+ Tup tup;
+ tup.alloc(); // allocate buffers
+ NdbResultSet* rs;
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ if (! idx) {
+ CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_tname)) != 0);
+ } else {
+ CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
+ }
+ CHK((rs = g_ops->readTuples(240, NdbScanOperation::LM_Exclusive)) != 0);
+ CHK(g_ops->getValue("PK1", (char*)&tup.m_pk1) != 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
+ CHK((g_bh1 = g_ops->getBlobHandle("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((g_bh2 = g_ops->getBlobHandle("BL2")) != 0);
+ if (! rw) {
+ CHK(getBlobValue(tup) == 0);
+ }
+ CHK(g_con->execute(NoCommit) == 0);
+ unsigned rows = 0;
+ while (1) {
+ int ret;
+ tup.m_pk1 = (Uint32)-1;
+ memset(tup.m_pk2, 'x', g_opt.m_pk2len);
+ CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ DBG(func << " pk1=" << tup.m_pk1);
+ Uint32 k = tup.m_pk1 - g_opt.m_pk1off;
+ CHK(k < g_opt.m_rows && g_tups[k].m_exists);
+ tup.copy(g_tups[k]);
+ if (! rw) {
+ CHK(verifyBlobValue(tup) == 0);
+ } else {
+ CHK(readBlobData(tup) == 0);
+ }
+ rows++;
+ }
+ g_ndb->closeTransaction(g_con);
+ g_con = 0;
+ g_ops = 0;
+ CHK(g_opt.m_rows == rows);
+ return 0;
+}
+
+static int
+deletePk()
+{
+ DBG("--- deletePk ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("deletePk pk1=" << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHK(g_opr->deleteTuple() == 0);
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_opr = 0;
+ g_con = 0;
+ tup.m_exists = false;
+ }
+ return 0;
+}
+
+static int
+deleteIdx()
+{
+ DBG("--- deleteIdx ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("deleteIdx pk1=" << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
+ CHK(g_opx->deleteTuple() == 0);
+ CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_opx = 0;
+ g_con = 0;
+ tup.m_exists = false;
+ }
+ return 0;
+}
+
+static int
+deleteScan(bool idx)
+{
+ const char* func = ! idx ? "scan delete table" : "scan delete index";
+ DBG("--- " << func << " ---");
+ Tup tup;
+ NdbResultSet* rs;
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ if (! idx) {
+ CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_tname)) != 0);
+ } else {
+ CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
+ }
+ CHK((rs = g_ops->readTuples(240, NdbScanOperation::LM_Exclusive)) != 0);
+ CHK(g_ops->getValue("PK1", (char*)&tup.m_pk1) != 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
+ CHK(g_con->execute(NoCommit) == 0);
+ unsigned rows = 0;
+ while (1) {
+ int ret;
+ tup.m_pk1 = (Uint32)-1;
+ memset(tup.m_pk2, 'x', g_opt.m_pk2len);
+ CHK((ret = rs->nextResult()) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ DBG(func << " pk1=" << tup.m_pk1);
+ CHK(rs->deleteTuple() == 0);
+ CHK(g_con->execute(NoCommit) == 0);
+ Uint32 k = tup.m_pk1 - g_opt.m_pk1off;
+ CHK(k < g_opt.m_rows && g_tups[k].m_exists);
+ g_tups[k].m_exists = false;
+ rows++;
+ }
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_con = 0;
+ g_opr = 0;
+ g_ops = 0;
+ CHK(g_opt.m_rows == rows);
+ return 0;
+}
+
+// main
+
+static int
+testmain()
+{
+ g_ndb = new Ndb("TEST_DB");
+ CHK(g_ndb->init() == 0);
+ CHK(g_ndb->waitUntilReady() == 0);
+ g_dic = g_ndb->getDictionary();
+ g_tups = new Tup [g_opt.m_rows];
+ CHK(dropTable() == 0);
+ CHK(createTable() == 0);
+ if (g_opt.m_bugtest != 0) {
+ // test a general bug instead of blobs
+ CHK((*g_opt.m_bugtest)() == 0);
+ return 0;
+ }
+ Bcol& b1 = g_opt.m_blob1;
+ CHK(NdbBlob::getBlobTableName(b1.m_btname, g_ndb, g_opt.m_tname, "BL1") == 0);
+ DBG("BL1: inline=" << b1.m_inline << " part=" << b1.m_partsize << " table=" << b1.m_btname);
+ if (! g_opt.m_oneblob) {
+ Bcol& b2 = g_opt.m_blob2;
+ CHK(NdbBlob::getBlobTableName(b2.m_btname, g_ndb, g_opt.m_tname, "BL2") == 0);
+ DBG("BL2: inline=" << b2.m_inline << " part=" << b2.m_partsize << " table=" << b2.m_btname);
+ }
+ if (g_opt.m_seed != 0)
+ srandom(g_opt.m_seed);
+ for (unsigned loop = 0; g_opt.m_loop == 0 || loop < g_opt.m_loop; loop++) {
+ DBG("=== loop " << loop << " ===");
+ if (g_opt.m_seed == 0)
+ srandom(loop);
+ bool llim = skip('v') ? true : false;
+ bool ulim = skip('w') ? false : true;
+ // pk
+ for (int rw = llim; rw <= ulim; rw++) {
+ if (skip('k'))
+ continue;
+ DBG("--- pk ops " << (! rw ? "get/set" : "read/write") << " ---");
+ calcTups(false);
+ CHK(insertPk(rw) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readPk(rw) == 0);
+ if (! skip('u')) {
+ calcTups(rw);
+ CHK(updatePk(rw) == 0);
+ CHK(verifyBlob() == 0);
+ }
+ CHK(readPk(rw) == 0);
+ CHK(deletePk() == 0);
+ CHK(verifyBlob() == 0);
+ }
+ // hash index
+ for (int rw = llim; rw <= ulim; rw++) {
+ if (skip('i'))
+ continue;
+ DBG("--- idx ops " << (! rw ? "get/set" : "read/write") << " ---");
+ calcTups(false);
+ CHK(insertPk(rw) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readIdx(rw) == 0);
+ calcTups(rw);
+ if (! skip('u')) {
+ CHK(updateIdx(rw) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readIdx(rw) == 0);
+ }
+ CHK(deleteIdx() == 0);
+ CHK(verifyBlob() == 0);
+ }
+ // scan table
+ for (int rw = llim; rw <= ulim; rw++) {
+ if (skip('s'))
+ continue;
+ DBG("--- table scan " << (! rw ? "get/set" : "read/write") << " ---");
+ calcTups(false);
+ CHK(insertPk(rw) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readScan(rw, false) == 0);
+ CHK(deleteScan(false) == 0);
+ CHK(verifyBlob() == 0);
+ }
+ // scan index
+ for (int rw = llim; rw <= ulim; rw++) {
+ if (skip('r'))
+ continue;
+ DBG("--- index scan " << (! rw ? "get/set" : "read/write") << " ---");
+ calcTups(false);
+ CHK(insertPk(rw) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readScan(rw, true) == 0);
+ CHK(deleteScan(true) == 0);
+ CHK(verifyBlob() == 0);
+ }
+ }
+ delete g_ndb;
+ return 0;
+}
+
+// bug tests
+
+static int
+bugtest_4088()
+{
+ DBG("bug test 4088 - ndb api hang with mixed ops on index table");
+ // insert rows
+ calcTups(false);
+ CHK(insertPk(false) == 0);
+ // new trans
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ // read table pk via index as a table
+ const unsigned pkcnt = 2;
+ Tup pktup[pkcnt];
+ for (unsigned i = 0; i < pkcnt; i++) {
+ char name[20];
+ // XXX guess table id
+ sprintf(name, "%d/%s", 4, g_opt.m_x1name);
+ CHK((g_opr = g_con->getNdbOperation(name)) != 0);
+ CHK(g_opr->readTuple() == 0);
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK(g_opr->getValue("NDB$PK", (char*)&pktup[i].m_pk1) != 0);
+ }
+ // read blob inline via index as an index
+ CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
+ CHK(g_opx->readTuple() == 0);
+ CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
+ assert(tup.m_blob1.m_buf != 0);
+ CHK(g_opx->getValue("BL1", (char*)tup.m_blob1.m_buf) != 0);
+ // execute
+ // BUG 4088: gets 1 tckeyconf, 1 tcindxconf, then hangs
+ CHK(g_con->execute(Commit) == 0);
+ // verify
+ for (unsigned i = 0; i < pkcnt; i++) {
+ CHK(pktup[i].m_pk1 == tup.m_pk1);
+ CHK(memcmp(pktup[i].m_pk2, tup.m_pk2, g_opt.m_pk2len) == 0);
+ }
+ CHK(memcmp(tup.m_blob1.m_val, tup.m_blob1.m_buf, 8 + g_opt.m_blob1.m_inline) == 0);
+ }
+ return 0;
+}
+
+static int
+bugtest_2222()
+{
+ return 0;
+}
+
+static int
+bugtest_3333()
+{
+ return 0;
+}
+
+static struct {
+ int m_bug;
+ int (*m_test)();
+} g_bugtest[] = {
+ { 4088, bugtest_4088 },
+ { 2222, bugtest_2222 },
+ { 3333, bugtest_3333 }
+};
+
+NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
+{
+ while (++argv, --argc > 0) {
+ const char* arg = argv[0];
+ if (strcmp(arg, "-core") == 0) {
+ g_opt.m_core = true;
+ continue;
+ }
+ if (strcmp(arg, "-dbg") == 0) {
+ g_opt.m_dbg = true;
+ continue;
+ }
+ if (strcmp(arg, "-dbgall") == 0) {
+ g_opt.m_dbg = true;
+ g_opt.m_dbgall = true;
+ putenv("NDB_BLOB_DEBUG=1");
+ continue;
+ }
+ if (strcmp(arg, "-full") == 0) {
+ g_opt.m_full = true;
+ continue;
+ }
+ if (strcmp(arg, "-loop") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_loop = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-parts") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_parts = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-rows") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_rows = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-seed") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_seed = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-skip") == 0) {
+ if (++argv, --argc > 0) {
+ for (const char* p = argv[0]; *p != 0; p++) {
+ skip(*p) = true;
+ }
+ continue;
+ }
+ }
+ // metadata
+ if (strcmp(arg, "-pk2len") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_pk2len = atoi(argv[0]);
+ if (g_opt.m_pk2len == 0) {
+ skip('i') = true;
+ skip('r') = true;
+ }
+ if (g_opt.m_pk2len <= g_max_pk2len)
+ continue;
+ }
+ }
+ if (strcmp(arg, "-oneblob") == 0) {
+ g_opt.m_oneblob = true;
+ continue;
+ }
+ // bugs
+ if (strcmp(arg, "-bug") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_bug = atoi(argv[0]);
+ for (unsigned i = 0; i < sizeof(g_bugtest)/sizeof(g_bugtest[0]); i++) {
+ if (g_opt.m_bug == g_bugtest[i].m_bug) {
+ g_opt.m_bugtest = g_bugtest[i].m_test;
+ break;
+ }
+ }
+ if (g_opt.m_bugtest != 0)
+ continue;
+ }
+ }
+ ndbout << "testOIBasic: unknown option " << arg << endl;
+ printusage();
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ if (testmain() == -1) {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ return NDBT_ProgramExit(NDBT_OK);
+}
+
+// vim: set sw=2 et:
diff --git a/ndb/test/ndbapi/testBlobs/testBlobs.cpp b/ndb/test/ndbapi/testBlobs/testBlobs.cpp
deleted file mode 100644
index 9f959702402..00000000000
--- a/ndb/test/ndbapi/testBlobs/testBlobs.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- * testBlobs
- */
-
-#include <ndb_global.h>
-
-#include <NdbMain.h>
-#include <NdbOut.hpp>
-#include <NdbThread.h>
-#include <NdbMutex.h>
-#include <NdbCondition.h>
-#include <NdbTest.hpp>
-#include <NdbTick.h>
-#include <ndb_limits.h>
-
-struct Opt {
- bool m_core;
- const char* m_table;
- Opt() :
- m_core(false),
- m_table("TB1")
- {
- }
-};
-
-static Opt opt;
-
-static void printusage()
-{
- Opt d;
- ndbout
- << "usage: testBlobs [options]" << endl
- << "-core dump core on error - default " << d.m_core << endl
- ;
-}
-
-static Ndb* myNdb = 0;
-static NdbDictionary::Dictionary* myDic = 0;
-static NdbConnection* myCon = 0;
-static NdbOperation* myOp = 0;
-static NdbBlob* myBlob = 0;
-
-static void
-fatal(const char* fmt, ...)
-{
- va_list ap;
- char buf[200];
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
- ndbout << "fatal: " << buf << endl;
- if (myNdb != 0 && myNdb->getNdbError().code != 0)
- ndbout << "ndb - " << myNdb->getNdbError() << endl;
- if (myDic != 0 && myDic->getNdbError().code != 0)
- ndbout << "dic - " << myDic->getNdbError() << endl;
- if (opt.m_core)
- abort();
- NDBT_ProgramExit(NDBT_FAILED);
- exit(1);
-}
-
-static void
-dropBlobsTable()
-{
- NdbDictionary::Table tab(NDB_BLOB_TABLE_NAME);
- if (myDic->dropTable(tab) == -1)
- if (myDic->getNdbError().code != 709)
- fatal("dropTable");
-}
-
-static void
-createBlobsTable()
-{
- NdbDictionary::Table tab(NDB_BLOB_TABLE_NAME);
- // col 0
- NdbDictionary::Column col0("BLOBID");
- col0.setPrimaryKey(true);
- col0.setType(NdbDictionary::Column::Bigunsigned);
- tab.addColumn(col0);
- // col 1
- NdbDictionary::Column col1("DATA");
- col1.setPrimaryKey(false);
- col1.setType(NdbDictionary::Column::Binary);
- col1.setLength(NDB_BLOB_PIECE_SIZE);
- tab.addColumn(col1);
- // create
- if (myDic->createTable(tab) == -1)
- fatal("createTable");
-}
-
-static void
-dropTable()
-{
- NdbDictionary::Table tab(opt.m_table);
- if (myDic->dropTable(tab) == -1)
- if (myDic->getNdbError().code != 709)
- fatal("dropTable");
-}
-
-static void
-createTable()
-{
- NdbDictionary::Table tab(opt.m_table);
- // col 0
- NdbDictionary::Column col0("A");
- col0.setPrimaryKey(true);
- col0.setType(NdbDictionary::Column::Unsigned);
- tab.addColumn(col0);
- // col 1
- NdbDictionary::Column col1("B");
- col1.setPrimaryKey(false);
- col1.setType(NdbDictionary::Column::Blob);
- tab.addColumn(col1);
- // create
- if (myDic->createTable(tab) == -1)
- fatal("createTable");
-}
-
-static void
-insertData(Uint32 key)
-{
-}
-
-static void
-insertTuples()
-{
- for (Uint32 key = 0; key <= 99; key++) {
- if ((myCon = myNdb->startTransaction()) == 0)
- fatal("startTransaction");
- if ((myOp = myCon->getNdbOperation(opt.m_table)) == 0)
- fatal("getNdbOperation");
- if (myOp->insertTuple() == -1)
- fatal("insertTuple");
- if (myOp->setValue((unsigned)0, key) == -1)
- fatal("setValue %u", (unsigned)key);
- if ((myBlob = myOp->setBlob(1)) == 0)
- fatal("setBlob");
- if (myCon->execute(NoCommit) == -1)
- fatal("execute NoCommit");
- insertData(key);
- if (myCon->execute(Commit) == -1)
- fatal("execute Commit");
- myNdb->closeTransaction(myCon);
- myOp = 0;
- myBlob = 0;
- myCon = 0;
- }
-}
-
-static void
-testMain()
-{
- myNdb = new Ndb("TEST_DB");
- if (myNdb->init() != 0)
- fatal("init");
- if (myNdb->waitUntilReady() < 0)
- fatal("waitUntilReady");
- myDic = myNdb->getDictionary();
- dropBlobsTable();
- createBlobsTable(); // until moved to Ndbcntr
- dropTable();
- createTable();
- insertTuples();
-}
-
-NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
-{
- while (++argv, --argc > 0) {
- const char* arg = argv[0];
- if (strcmp(arg, "-core") == 0) {
- opt.m_core = true;
- continue;
- }
- }
- testMain();
- return NDBT_ProgramExit(NDBT_OK);
-}
-
-// vim: set sw=4:
diff --git a/ndb/test/ndbapi/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers.cpp
new file mode 100644
index 00000000000..75773040113
--- /dev/null
+++ b/ndb/test/ndbapi/testDataBuffers.cpp
@@ -0,0 +1,616 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ * testDataBuffers
+ *
+ * Test getValue() of byte arrays:
+ * - using application buffers of different alignments and sizes
+ * - using NdbApi allocated small (<32) and big (>=32) buffers
+ *
+ * Verifies fixes to tickets 189 and 206.
+ *
+ * Options: see printusage() below.
+ *
+ * Creates tables TB00 to TB15
+ */
+
+#include <ndb_global.h>
+
+#include <NdbMain.h>
+#include <NdbOut.hpp>
+#include <NdbApi.hpp>
+#include <NdbTest.hpp>
+#include <NdbSchemaCon.hpp>
+// limits
+static int const MaxAttr = 64;
+static int const MaxOper = 1000;
+static int const MaxSize = 10000;
+static int const MaxOff = 64; // max offset to add to data buffer
+static int const MaxData = MaxSize + MaxOff + 100;
+
+// options
+static int attrcnt = 25;
+static int existok = 0;
+static bool kontinue = false;
+static int loopcnt = 1;
+static int opercnt = 100; // also does this many scans
+static int randomizer = 171317;
+static int sizelim = 500;
+static int xverbose = 0;
+
+static void printusage() {
+ ndbout
+ << "usage: testDataBuffers options [default/max]"
+ << endl
+ << "NOTE: too large combinations result in NDB error"
+ << endl
+ << "-a N number of attributes (including the key) [25/64]"
+ << endl
+ << "-e no error if table exists (assumed to have same structure)"
+ << endl
+ << "-k on error continue with next test case"
+ << endl
+ << "-l N number of loops to run, 0 means infinite [1]"
+ << endl
+ << "-o N number of operations (rows in each table) [100/1000]"
+ << endl
+ << "-r N source of randomness (big number (prime)) [171317]"
+ << endl
+ << "-s N array size limit (rounded up in some tests) [500/10000]"
+ << endl
+ << "-x extremely verbose"
+ << endl
+ << "Tables: TB00 .. TB15"
+ << endl
+ ;
+}
+
+static Ndb* ndb = 0;
+static NdbSchemaCon* tcon = 0;
+static NdbSchemaOp* top = 0;
+static NdbConnection* con = 0;
+static NdbOperation* op = 0;
+
+static int
+ndberror(char const* fmt, ...)
+{
+ va_list ap;
+ char buf[200];
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ ndbout << buf << " --" << endl;
+ if (ndb)
+ ndbout << "ndb : " << ndb->getNdbError() << endl;
+ if (tcon)
+ ndbout << "tcon: " << tcon->getNdbError() << endl;
+ if (top)
+ ndbout << "top: " << top->getNdbError() << endl;
+ if (con)
+ ndbout << "con : " << con->getNdbError() << endl;
+ if (op)
+ ndbout << "op : " << op->getNdbError() << endl;
+ return -1;
+}
+
+static int
+chkerror(char const* fmt, ...)
+{
+ va_list ap;
+ char buf[200];
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ ndbout << "*** check failed: " << buf << " ***" << endl;
+ return -1;
+}
+
+// alignment of addresses and data sizes
+
+static bool isAligned(unsigned x)
+{
+ return ((x & 3) == 0);
+}
+static bool isAligned(char* p)
+{
+ return isAligned(unsigned(p));
+}
+static unsigned toAligned(unsigned x)
+{
+ while (! isAligned(x))
+ x++;
+ return x;
+}
+static char* toAligned(char* p)
+{
+ while (! isAligned(p))
+ p++;
+ return p;
+}
+
+// byte value for key k column i byte j
+static int byteVal(int k, int i, int j)
+{
+ return '0' + (k + i + j) % 10;
+}
+
+// tables
+
+static char tab[20] = "";
+
+static struct col {
+ char aAttrName[20];
+ AttrType aAttrType;
+ int aAttrSize;
+ int aArraySize;
+ KeyType aTupleKey;
+ bool nullable;
+ NdbRecAttr* aRa;
+ char* buf;
+ int bufsiz;
+ char data[MaxData];
+} ccol[MaxAttr];
+
+static int key = 0;
+
+// independent test bits
+static bool alignAddr; // align our buffer addresses to 4x
+static bool alignSize; // align data sizes to 4x
+static bool useBuf; // use our buffers for output
+static bool noRandom; // do not randomize sizes and offsets
+static int testbits = 4;
+
+static int
+makeSize(int i)
+{
+ int n;
+ if (noRandom)
+ n = i;
+ else
+ n = i * randomizer;
+ n %= sizelim;
+ if (n <= 0)
+ n = 1;
+ if (alignSize)
+ n = toAligned(n);
+ return n;
+}
+
+static int
+makeOff(int k)
+{
+ int n;
+ if (alignAddr)
+ n = 0;
+ else if (noRandom)
+ n = k;
+ else
+ n = k * randomizer;
+ n %= MaxOff;
+ if (n < 0)
+ n = -n;
+ return n;
+}
+
+static int
+testcase(int flag)
+{
+ ndbout << "--- case " << flag << " ---" << endl;
+ sprintf(tab, "TB%02d", flag);
+
+ alignAddr = ! (flag & 1);
+ ndbout << (alignAddr ? "align addresses" : "mis-align addresses") << endl;
+ alignSize = ! (flag & 2);
+ ndbout << (alignSize ? "align data sizes" : "mis-align data sizes") << endl;
+ useBuf = ! (flag & 4);
+ ndbout << (useBuf ? "use our buffers" : "use ndbapi buffers") << endl;
+ noRandom = ! (flag & 8);
+ ndbout << (noRandom ? "simple sizes" : "randomize sizes") << endl;
+
+ int smax = 0, stot = 0;
+ if (xverbose)
+ ndbout << "- define table " << tab << endl;
+ for (int i = 0; i < attrcnt; i++) {
+ col& c = ccol[i];
+ memset(&c, 0, sizeof(c));
+ sprintf(c.aAttrName, "C%d", i);
+ if (i == 0) {
+ c.aAttrType = UnSigned;
+ c.aAttrSize = 32;
+ c.aArraySize = 1;
+ c.aTupleKey = TupleKey;
+ c.nullable = false;
+ } else {
+ c.aAttrType = String;
+ c.aAttrSize = 8;
+ c.aArraySize = makeSize(i);
+ if (smax < c.aArraySize)
+ smax = c.aArraySize;
+ stot += c.aArraySize;
+ c.aTupleKey = NoKey;
+ c.nullable = true;
+ if (xverbose)
+ ndbout << "-- column " << i << " size=" << c.aArraySize << endl;
+ }
+ c.buf = toAligned(c.data);
+ c.bufsiz = sizeof(c.data) - (c.buf - c.data);
+ }
+ ndbout << "tab=" << tab << " cols=" << attrcnt
+ << " size max=" << smax << " tot=" << stot << endl;
+
+ ndb = new Ndb("TEST_DB");
+ if (ndb->init() != 0)
+ return ndberror("init");
+ if (ndb->waitUntilReady(30) < 0)
+ return ndberror("waitUntilReady");
+
+ if ((tcon = NdbSchemaCon::startSchemaTrans(ndb)) == 0)
+ return ndberror("startSchemaTransaction");
+ if ((top = tcon->getNdbSchemaOp()) == 0)
+ return ndberror("getNdbSchemaOp");
+ if (top->createTable(tab) < 0)
+ return ndberror("createTable");
+ for (int i = 0; i < attrcnt; i++) {
+ col& c = ccol[i];
+ if (top->createAttribute(
+ c.aAttrName,
+ c.aTupleKey,
+ c.aAttrSize,
+ c.aArraySize,
+ c.aAttrType,
+ MMBased,
+ c.nullable
+ ) < 0)
+ return ndberror("createAttribute col=%d", i);
+ }
+ if (tcon->execute() < 0) {
+ if (! (tcon->getNdbError().code == 721 && existok))
+ return ndberror("execute");
+ ndbout << "using " << tab << endl;
+ } else {
+ ndbout << "created " << tab << endl;
+ }
+ top = 0;
+ tcon = 0;
+
+ if (xverbose)
+ ndbout << "- delete" << endl;
+ int delcnt = 0;
+ for (key = 0; key < opercnt; key++) {
+ if ((con = ndb->startTransaction()) == 0)
+ return ndberror("startTransaction key=%d", key);
+ if ((op = con->getNdbOperation(tab)) == 0)
+ return ndberror("getNdbOperation key=%d", key);
+ if (op->deleteTuple() < 0)
+ return ndberror("deleteTuple key=%d", key);
+ for (int i = 0; i < attrcnt; i++) {
+ col& c = ccol[i];
+ if (i == 0) {
+ if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
+ return ndberror("equal key=%d", key);
+ } else {
+ }
+ }
+ if (con->execute(Commit) < 0) {
+ if (con->getNdbError().code != 626)
+ return ndberror("execute key=%d", key);
+ } else {
+ delcnt++;
+ }
+ ndb->closeTransaction(con);
+ }
+ con = 0;
+ op = 0;
+ ndbout << "deleted " << delcnt << endl;
+
+ if (xverbose)
+ ndbout << "- insert" << endl;
+ for (key = 0; key < opercnt; key++) {
+ int off = makeOff(key);
+ if ((con = ndb->startTransaction()) == 0)
+ return ndberror("startTransaction key=%d", key);
+ if ((op = con->getNdbOperation(tab)) == 0)
+ return ndberror("getNdbOperation key=%d", key);
+ if (op->insertTuple() < 0)
+ return ndberror("insertTuple key=%d", key);
+ for (int i = 0; i < attrcnt; i++) {
+ col& c = ccol[i];
+ if (i == 0) {
+ if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
+ return ndberror("equal key=%d", key);
+ } else {
+ memset(c.buf, 'A', c.bufsiz);
+ for (int j = 0; j < c.aArraySize; j++)
+ c.buf[j + off] = byteVal(key, i, j);
+ if (op->setValue(c.aAttrName, c.buf + off, c.aArraySize) < 0)
+ return ndberror("setValue key=%d col=%d", key, i);
+ }
+ }
+ if (con->execute(Commit) < 0)
+ return ndberror("execute key=%d", key);
+ ndb->closeTransaction(con);
+ }
+ con = 0;
+ op = 0;
+ ndbout << "inserted " << key << endl;
+
+ if (xverbose)
+ ndbout << "- select" << endl;
+ for (key = 0; key < opercnt; key++) {
+ int off = makeOff(key);
+ if (xverbose)
+ ndbout << "-- key " << key << " off=" << off << endl;
+ if ((con = ndb->startTransaction()) == 0)
+ return ndberror("startTransaction key=%d", key);
+ if ((op = con->getNdbOperation(tab)) == 0)
+ return ndberror("getNdbOperation key=%d", key);
+ if (op->readTuple() < 0)
+ return ndberror("readTuple key=%d", key);
+ for (int i = 0; i < attrcnt; i++) {
+ col& c = ccol[i];
+ if (i == 0) {
+ if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
+ return ndberror("equal key=%d", key);
+ } else {
+ if (xverbose) {
+ char tmp[20];
+ if (useBuf)
+ sprintf(tmp, "0x%x", int(c.buf + off));
+ else
+ strcpy(tmp, "ndbapi");
+ ndbout << "--- column " << i << " addr=" << tmp << endl;
+ }
+ memset(c.buf, 'B', c.bufsiz);
+ if (useBuf) {
+ if (op->getValue(c.aAttrName, c.buf + off) < 0)
+ return ndberror("getValue key=%d col=%d", key, i);
+ } else {
+ if ((c.aRa = op->getValue(c.aAttrName)) == 0)
+ return ndberror("getValue key=%d col=%d", key, i);
+ }
+ }
+ }
+ if (con->execute(Commit) != 0)
+ return ndberror("execute key=%d", key);
+ for (int i = 0; i < attrcnt; i++) {
+ col& c = ccol[i];
+ if (i == 0) {
+ } else if (useBuf) {
+ for (int j = 0; j < off; j++) {
+ if (c.buf[j] != 'B') {
+ return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
+ key, i, j, 'B', c.buf[j]);
+ }
+ }
+ for (int j = 0; j < c.aArraySize; j++) {
+ if (c.buf[j + off] != byteVal(key, i, j)) {
+ return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
+ key, i, j, byteVal(key, i, j), c.buf[j]);
+ }
+ }
+ for (int j = c.aArraySize + off; j < c.bufsiz; j++) {
+ if (c.buf[j] != 'B') {
+ return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
+ key, i, j, 'B', c.buf[j]);
+ }
+ }
+ } else {
+ char* buf = c.aRa->aRef();
+ if (buf == 0)
+ return ndberror("null aRef key=%d col%d", key, i);
+ for (int j = 0; j < c.aArraySize; j++) {
+ if (buf[j] != byteVal(key, i, j)) {
+ return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
+ key, i, j, byteVal(key, i, j), buf[j]);
+ }
+ }
+ }
+ }
+ ndb->closeTransaction(con);
+ }
+ con = 0;
+ op = 0;
+ ndbout << "selected " << key << endl;
+
+ if (xverbose)
+ ndbout << "- scan" << endl;
+ char found[MaxOper];
+ for (int k = 0; k < opercnt; k++)
+ found[k] = 0;
+ for (key = 0; key < opercnt; key++) {
+ int off = makeOff(key);
+ if (xverbose)
+ ndbout << "-- key " << key << " off=" << off << endl;
+ int newkey = 0;
+ if ((con = ndb->startTransaction()) == 0)
+ return ndberror("startTransaction key=%d", key);
+ if ((op = con->getNdbOperation(tab)) == 0)
+ return ndberror("getNdbOperation key=%d", key);
+ if (op->openScanRead(1) < 0)
+ return ndberror("openScanRead key=%d", key);
+ {
+ col& c = ccol[0];
+ if (op->load_const_u32(1, key) < 0)
+ return ndberror("load_const_u32");
+ if (op->read_attr(c.aAttrName, 2) < 0)
+ return ndberror("read_attr");
+ if (op->branch_eq(1, 2, 0) < 0)
+ return ndberror("branch_eq");
+ if (op->interpret_exit_nok() < 0)
+ return ndberror("interpret_exit_nok");
+ if (op->def_label(0) < 0)
+ return ndberror("def_label");
+ if (op->interpret_exit_ok() < 0)
+ return ndberror("interpret_exit_ok");
+ }
+ for (int i = 0; i < attrcnt; i++) {
+ col& c = ccol[i];
+ if (i == 0) {
+ if (op->getValue(c.aAttrName, (char*)&newkey) < 0)
+ return ndberror("getValue key=%d col=%d", key, i);
+ } else {
+ if (xverbose) {
+ char tmp[20];
+ if (useBuf)
+ sprintf(tmp, "0x%x", int(c.buf + off));
+ else
+ strcpy(tmp, "ndbapi");
+ ndbout << "--- column " << i << " addr=" << tmp << endl;
+ }
+ memset(c.buf, 'C', c.bufsiz);
+ if (useBuf) {
+ if (op->getValue(c.aAttrName, c.buf + off) < 0)
+ return ndberror("getValue key=%d col=%d", key, i);
+ } else {
+ if ((c.aRa = op->getValue(c.aAttrName)) == 0)
+ return ndberror("getValue key=%d col=%d", key, i);
+ }
+ }
+ }
+ if (con->executeScan() < 0)
+ return ndberror("executeScan key=%d", key);
+ int ret, cnt = 0;
+ while ((ret = con->nextScanResult()) == 0) {
+ if (key != newkey)
+ return ndberror("unexpected key=%d newkey=%d", key, newkey);
+ for (int i = 1; i < attrcnt; i++) {
+ col& c = ccol[i];
+ if (useBuf) {
+ for (int j = 0; j < off; j++) {
+ if (c.buf[j] != 'C') {
+ return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
+ key, i, j, 'C', c.buf[j]);
+ }
+ }
+ for (int j = 0; j < c.aArraySize; j++) {
+ if (c.buf[j + off] != byteVal(key, i, j)) {
+ return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
+ key, i, j, byteVal(key, i, j), c.buf[j]);
+ }
+ }
+ for (int j = c.aArraySize + off; j < c.bufsiz; j++) {
+ if (c.buf[j] != 'C') {
+ return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
+ key, i, j, 'C', c.buf[j]);
+ }
+ }
+ } else {
+ char* buf = c.aRa->aRef();
+ if (buf == 0)
+ return ndberror("null aRef key=%d col%d", key, i);
+ for (int j = 0; j < c.aArraySize; j++) {
+ if (buf[j] != byteVal(key, i, j)) {
+ return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
+ key, i, j, byteVal(key, i, j), buf[j]);
+ }
+ }
+ }
+ }
+ cnt++;
+ }
+ if (ret < 0)
+ return ndberror("nextScanResult key=%d", key);
+ if (cnt != 1)
+ return ndberror("scan key=%d found %d", key, cnt);
+ found[key] = 1;
+ ndb->closeTransaction(con);
+ }
+ con = 0;
+ op = 0;
+ for (int k = 0; k < opercnt; k++)
+ if (! found[k])
+ return ndberror("key %d not found", k);
+ ndbout << "scanned " << key << endl;
+
+ ndb = 0;
+ ndbout << "done" << endl;
+ return 0;
+}
+
+NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuffers", 65535)
+{
+ while (++argv, --argc > 0) {
+ char const* p = argv[0];
+ if (*p++ != '-' || strlen(p) != 1)
+ goto wrongargs;
+ switch (*p) {
+ case 'a':
+ if (++argv, --argc > 0) {
+ attrcnt = atoi(argv[0]);
+ if (1 <= attrcnt && attrcnt <= MaxAttr)
+ break;
+ }
+ goto wrongargs;
+ case 'e':
+ existok = 1;
+ break;
+ case 'k':
+ kontinue = true;
+ break;
+ case 'l':
+ if (++argv, --argc > 0) {
+ loopcnt = atoi(argv[0]);
+ if (0 <= loopcnt)
+ break;
+ }
+ goto wrongargs;
+ case 'o':
+ if (++argv, --argc > 0) {
+ opercnt = atoi(argv[0]);
+ if (0 <= opercnt && opercnt <= MaxOper)
+ break;
+ }
+ goto wrongargs;
+ case 'r':
+ if (++argv, --argc > 0) {
+ randomizer = atoi(argv[0]);
+ if (1 <= randomizer)
+ break;
+ }
+ goto wrongargs;
+ case 's':
+ if (++argv, --argc > 0) {
+ sizelim = atoi(argv[0]);
+ if (1 <= sizelim && sizelim <= MaxSize)
+ break;
+ }
+ goto wrongargs;
+ case 'x':
+ xverbose = 1;
+ break;
+ default:
+ wrongargs:
+ printusage();
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ }
+ unsigned ok = true;
+ for (int i = 1; 0 == loopcnt || i <= loopcnt; i++) {
+ ndbout << "=== loop " << i << " ===" << endl;
+ for (int flag = 0; flag < (1<<testbits); flag++) {
+ if (testcase(flag) < 0) {
+ ok = false;
+ if (! kontinue)
+ goto out;
+ }
+ }
+ }
+out:
+ return NDBT_ProgramExit(ok ? NDBT_OK : NDBT_FAILED);
+}
+
+// vim: set sw=4:
diff --git a/ndb/test/ndbapi/testDataBuffers/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers/testDataBuffers.cpp
deleted file mode 100644
index b8e0fef6cef..00000000000
--- a/ndb/test/ndbapi/testDataBuffers/testDataBuffers.cpp
+++ /dev/null
@@ -1,616 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- * testDataBuffers
- *
- * Test getValue() of byte arrays:
- * - using application buffers of different alignments and sizes
- * - using NdbApi allocated small (<32) and big (>=32) buffers
- *
- * Verifies fixes to tickets 189 and 206.
- *
- * Options: see printusage() below.
- *
- * Creates tables TB00 to TB15
- */
-
-#include <ndb_global.h>
-
-#include <NdbMain.h>
-#include <NdbOut.hpp>
-#include <NdbApi.hpp>
-#include <NdbTest.hpp>
-
-// limits
-static int const MaxAttr = 64;
-static int const MaxOper = 1000;
-static int const MaxSize = 10000;
-static int const MaxOff = 64; // max offset to add to data buffer
-static int const MaxData = MaxSize + MaxOff + 100;
-
-// options
-static int attrcnt = 25;
-static int existok = 0;
-static bool kontinue = false;
-static int loopcnt = 1;
-static int opercnt = 100; // also does this many scans
-static int randomizer = 171317;
-static int sizelim = 500;
-static int xverbose = 0;
-
-static void printusage() {
- ndbout
- << "usage: testDataBuffers options [default/max]"
- << endl
- << "NOTE: too large combinations result in NDB error"
- << endl
- << "-a N number of attributes (including the key) [25/64]"
- << endl
- << "-e no error if table exists (assumed to have same structure)"
- << endl
- << "-k on error continue with next test case"
- << endl
- << "-l N number of loops to run, 0 means infinite [1]"
- << endl
- << "-o N number of operations (rows in each table) [100/1000]"
- << endl
- << "-r N source of randomness (big number (prime)) [171317]"
- << endl
- << "-s N array size limit (rounded up in some tests) [500/10000]"
- << endl
- << "-x extremely verbose"
- << endl
- << "Tables: TB00 .. TB15"
- << endl
- ;
-}
-
-static Ndb* ndb = 0;
-static NdbSchemaCon* tcon = 0;
-static NdbSchemaOp* top = 0;
-static NdbConnection* con = 0;
-static NdbOperation* op = 0;
-
-static int
-ndberror(char const* fmt, ...)
-{
- va_list ap;
- char buf[200];
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
- ndbout << buf << " --" << endl;
- if (ndb)
- ndbout << "ndb : " << ndb->getNdbError() << endl;
- if (tcon)
- ndbout << "tcon: " << tcon->getNdbError() << endl;
- if (top)
- ndbout << "top : " << top->getNdbError() << endl;
- if (con)
- ndbout << "con : " << con->getNdbError() << endl;
- if (op)
- ndbout << "op : " << op->getNdbError() << endl;
- return -1;
-}
-
-static int
-chkerror(char const* fmt, ...)
-{
- va_list ap;
- char buf[200];
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
- ndbout << "*** check failed: " << buf << " ***" << endl;
- return -1;
-}
-
-// alignment of addresses and data sizes
-
-static bool isAligned(unsigned x)
-{
- return ((x & 3) == 0);
-}
-static bool isAligned(char* p)
-{
- return isAligned(unsigned(p));
-}
-static unsigned toAligned(unsigned x)
-{
- while (! isAligned(x))
- x++;
- return x;
-}
-static char* toAligned(char* p)
-{
- while (! isAligned(p))
- p++;
- return p;
-}
-
-// byte value for key k column i byte j
-static int byteVal(int k, int i, int j)
-{
- return '0' + (k + i + j) % 10;
-}
-
-// tables
-
-static char tab[20] = "";
-
-static struct col {
- char aAttrName[20];
- AttrType aAttrType;
- int aAttrSize;
- int aArraySize;
- KeyType aTupleKey;
- bool nullable;
- NdbRecAttr* aRa;
- char* buf;
- int bufsiz;
- char data[MaxData];
-} ccol[MaxAttr];
-
-static int key = 0;
-
-// independent test bits
-static bool alignAddr; // align our buffer addresses to 4x
-static bool alignSize; // align data sizes to 4x
-static bool useBuf; // use our buffers for output
-static bool noRandom; // do not randomize sizes and offsets
-static int testbits = 4;
-
-static int
-makeSize(int i)
-{
- int n;
- if (noRandom)
- n = i;
- else
- n = i * randomizer;
- n %= sizelim;
- if (n <= 0)
- n = 1;
- if (alignSize)
- n = toAligned(n);
- return n;
-}
-
-static int
-makeOff(int k)
-{
- int n;
- if (alignAddr)
- n = 0;
- else if (noRandom)
- n = k;
- else
- n = k * randomizer;
- n %= MaxOff;
- if (n < 0)
- n = -n;
- return n;
-}
-
-static int
-testcase(int flag)
-{
- ndbout << "--- case " << flag << " ---" << endl;
- sprintf(tab, "TB%02d", flag);
-
- alignAddr = ! (flag & 1);
- ndbout << (alignAddr ? "align addresses" : "mis-align addresses") << endl;
- alignSize = ! (flag & 2);
- ndbout << (alignSize ? "align data sizes" : "mis-align data sizes") << endl;
- useBuf = ! (flag & 4);
- ndbout << (useBuf ? "use our buffers" : "use ndbapi buffers") << endl;
- noRandom = ! (flag & 8);
- ndbout << (noRandom ? "simple sizes" : "randomize sizes") << endl;
-
- int smax = 0, stot = 0;
- if (xverbose)
- ndbout << "- define table " << tab << endl;
- for (int i = 0; i < attrcnt; i++) {
- col& c = ccol[i];
- memset(&c, 0, sizeof(c));
- sprintf(c.aAttrName, "C%d", i);
- if (i == 0) {
- c.aAttrType = UnSigned;
- c.aAttrSize = 32;
- c.aArraySize = 1;
- c.aTupleKey = TupleKey;
- c.nullable = false;
- } else {
- c.aAttrType = String;
- c.aAttrSize = 8;
- c.aArraySize = makeSize(i);
- if (smax < c.aArraySize)
- smax = c.aArraySize;
- stot += c.aArraySize;
- c.aTupleKey = NoKey;
- c.nullable = true;
- if (xverbose)
- ndbout << "-- column " << i << " size=" << c.aArraySize << endl;
- }
- c.buf = toAligned(c.data);
- c.bufsiz = sizeof(c.data) - (c.buf - c.data);
- }
- ndbout << "tab=" << tab << " cols=" << attrcnt
- << " size max=" << smax << " tot=" << stot << endl;
-
- ndb = new Ndb("TEST_DB");
- if (ndb->init() != 0)
- return ndberror("init");
- if (ndb->waitUntilReady(30) < 0)
- return ndberror("waitUntilReady");
-
- if ((tcon = ndb->startSchemaTransaction()) == 0)
- return ndberror("startSchemaTransaction");
- if ((top = tcon->getNdbSchemaOp()) == 0)
- return ndberror("getNdbSchemaOp");
- if (top->createTable(tab) < 0)
- return ndberror("createTable");
- for (int i = 0; i < attrcnt; i++) {
- col& c = ccol[i];
- if (top->createAttribute(
- c.aAttrName,
- c.aTupleKey,
- c.aAttrSize,
- c.aArraySize,
- c.aAttrType,
- MMBased,
- c.nullable
- ) < 0)
- return ndberror("createAttribute col=%d", i);
- }
- if (tcon->execute() < 0) {
- if (! (tcon->getNdbError().code == 721 && existok))
- return ndberror("execute");
- ndbout << "using " << tab << endl;
- } else {
- ndbout << "created " << tab << endl;
- }
- top = 0;
- tcon = 0;
-
- if (xverbose)
- ndbout << "- delete" << endl;
- int delcnt = 0;
- for (key = 0; key < opercnt; key++) {
- if ((con = ndb->startTransaction()) == 0)
- return ndberror("startTransaction key=%d", key);
- if ((op = con->getNdbOperation(tab)) == 0)
- return ndberror("getNdbOperation key=%d", key);
- if (op->deleteTuple() < 0)
- return ndberror("deleteTuple key=%d", key);
- for (int i = 0; i < attrcnt; i++) {
- col& c = ccol[i];
- if (i == 0) {
- if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
- return ndberror("equal key=%d", key);
- } else {
- }
- }
- if (con->execute(Commit) < 0) {
- if (con->getNdbError().code != 626)
- return ndberror("execute key=%d", key);
- } else {
- delcnt++;
- }
- ndb->closeTransaction(con);
- }
- con = 0;
- op = 0;
- ndbout << "deleted " << delcnt << endl;
-
- if (xverbose)
- ndbout << "- insert" << endl;
- for (key = 0; key < opercnt; key++) {
- int off = makeOff(key);
- if ((con = ndb->startTransaction()) == 0)
- return ndberror("startTransaction key=%d", key);
- if ((op = con->getNdbOperation(tab)) == 0)
- return ndberror("getNdbOperation key=%d", key);
- if (op->insertTuple() < 0)
- return ndberror("insertTuple key=%d", key);
- for (int i = 0; i < attrcnt; i++) {
- col& c = ccol[i];
- if (i == 0) {
- if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
- return ndberror("equal key=%d", key);
- } else {
- memset(c.buf, 'A', c.bufsiz);
- for (int j = 0; j < c.aArraySize; j++)
- c.buf[j + off] = byteVal(key, i, j);
- if (op->setValue(c.aAttrName, c.buf + off, c.aArraySize) < 0)
- return ndberror("setValue key=%d col=%d", key, i);
- }
- }
- if (con->execute(Commit) < 0)
- return ndberror("execute key=%d", key);
- ndb->closeTransaction(con);
- }
- con = 0;
- op = 0;
- ndbout << "inserted " << key << endl;
-
- if (xverbose)
- ndbout << "- select" << endl;
- for (key = 0; key < opercnt; key++) {
- int off = makeOff(key);
- if (xverbose)
- ndbout << "-- key " << key << " off=" << off << endl;
- if ((con = ndb->startTransaction()) == 0)
- return ndberror("startTransaction key=%d", key);
- if ((op = con->getNdbOperation(tab)) == 0)
- return ndberror("getNdbOperation key=%d", key);
- if (op->readTuple() < 0)
- return ndberror("readTuple key=%d", key);
- for (int i = 0; i < attrcnt; i++) {
- col& c = ccol[i];
- if (i == 0) {
- if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
- return ndberror("equal key=%d", key);
- } else {
- if (xverbose) {
- char tmp[20];
- if (useBuf)
- sprintf(tmp, "0x%x", int(c.buf + off));
- else
- strcpy(tmp, "ndbapi");
- ndbout << "--- column " << i << " addr=" << tmp << endl;
- }
- memset(c.buf, 'B', c.bufsiz);
- if (useBuf) {
- if (op->getValue(c.aAttrName, c.buf + off) < 0)
- return ndberror("getValue key=%d col=%d", key, i);
- } else {
- if ((c.aRa = op->getValue(c.aAttrName)) == 0)
- return ndberror("getValue key=%d col=%d", key, i);
- }
- }
- }
- if (con->execute(Commit) != 0)
- return ndberror("execute key=%d", key);
- for (int i = 0; i < attrcnt; i++) {
- col& c = ccol[i];
- if (i == 0) {
- } else if (useBuf) {
- for (int j = 0; j < off; j++) {
- if (c.buf[j] != 'B') {
- return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
- key, i, j, 'B', c.buf[j]);
- }
- }
- for (int j = 0; j < c.aArraySize; j++) {
- if (c.buf[j + off] != byteVal(key, i, j)) {
- return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
- key, i, j, byteVal(key, i, j), c.buf[j]);
- }
- }
- for (int j = c.aArraySize + off; j < c.bufsiz; j++) {
- if (c.buf[j] != 'B') {
- return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
- key, i, j, 'B', c.buf[j]);
- }
- }
- } else {
- char* buf = c.aRa->aRef();
- if (buf == 0)
- return ndberror("null aRef key=%d col%d", key, i);
- for (int j = 0; j < c.aArraySize; j++) {
- if (buf[j] != byteVal(key, i, j)) {
- return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
- key, i, j, byteVal(key, i, j), buf[j]);
- }
- }
- }
- }
- ndb->closeTransaction(con);
- }
- con = 0;
- op = 0;
- ndbout << "selected " << key << endl;
-
- if (xverbose)
- ndbout << "- scan" << endl;
- char found[MaxOper];
- for (int k = 0; k < opercnt; k++)
- found[k] = 0;
- for (key = 0; key < opercnt; key++) {
- int off = makeOff(key);
- if (xverbose)
- ndbout << "-- key " << key << " off=" << off << endl;
- int newkey = 0;
- if ((con = ndb->startTransaction()) == 0)
- return ndberror("startTransaction key=%d", key);
- if ((op = con->getNdbOperation(tab)) == 0)
- return ndberror("getNdbOperation key=%d", key);
- if (op->openScanRead(1) < 0)
- return ndberror("openScanRead key=%d", key);
- {
- col& c = ccol[0];
- if (op->load_const_u32(1, key) < 0)
- return ndberror("load_const_u32");
- if (op->read_attr(c.aAttrName, 2) < 0)
- return ndberror("read_attr");
- if (op->branch_eq(1, 2, 0) < 0)
- return ndberror("branch_eq");
- if (op->interpret_exit_nok() < 0)
- return ndberror("interpret_exit_nok");
- if (op->def_label(0) < 0)
- return ndberror("def_label");
- if (op->interpret_exit_ok() < 0)
- return ndberror("interpret_exit_ok");
- }
- for (int i = 0; i < attrcnt; i++) {
- col& c = ccol[i];
- if (i == 0) {
- if (op->getValue(c.aAttrName, (char*)&newkey) < 0)
- return ndberror("getValue key=%d col=%d", key, i);
- } else {
- if (xverbose) {
- char tmp[20];
- if (useBuf)
- sprintf(tmp, "0x%x", int(c.buf + off));
- else
- strcpy(tmp, "ndbapi");
- ndbout << "--- column " << i << " addr=" << tmp << endl;
- }
- memset(c.buf, 'C', c.bufsiz);
- if (useBuf) {
- if (op->getValue(c.aAttrName, c.buf + off) < 0)
- return ndberror("getValue key=%d col=%d", key, i);
- } else {
- if ((c.aRa = op->getValue(c.aAttrName)) == 0)
- return ndberror("getValue key=%d col=%d", key, i);
- }
- }
- }
- if (con->executeScan() < 0)
- return ndberror("executeScan key=%d", key);
- int ret, cnt = 0;
- while ((ret = con->nextScanResult()) == 0) {
- if (key != newkey)
- return ndberror("unexpected key=%d newkey=%d", key, newkey);
- for (int i = 1; i < attrcnt; i++) {
- col& c = ccol[i];
- if (useBuf) {
- for (int j = 0; j < off; j++) {
- if (c.buf[j] != 'C') {
- return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
- key, i, j, 'C', c.buf[j]);
- }
- }
- for (int j = 0; j < c.aArraySize; j++) {
- if (c.buf[j + off] != byteVal(key, i, j)) {
- return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
- key, i, j, byteVal(key, i, j), c.buf[j]);
- }
- }
- for (int j = c.aArraySize + off; j < c.bufsiz; j++) {
- if (c.buf[j] != 'C') {
- return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
- key, i, j, 'C', c.buf[j]);
- }
- }
- } else {
- char* buf = c.aRa->aRef();
- if (buf == 0)
- return ndberror("null aRef key=%d col%d", key, i);
- for (int j = 0; j < c.aArraySize; j++) {
- if (buf[j] != byteVal(key, i, j)) {
- return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
- key, i, j, byteVal(key, i, j), buf[j]);
- }
- }
- }
- }
- cnt++;
- }
- if (ret < 0)
- return ndberror("nextScanResult key=%d", key);
- if (cnt != 1)
- return ndberror("scan key=%d found %d", key, cnt);
- found[key] = 1;
- ndb->closeTransaction(con);
- }
- con = 0;
- op = 0;
- for (int k = 0; k < opercnt; k++)
- if (! found[k])
- return ndberror("key %d not found", k);
- ndbout << "scanned " << key << endl;
-
- ndb = 0;
- ndbout << "done" << endl;
- return 0;
-}
-
-NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuffers", 65535)
-{
- while (++argv, --argc > 0) {
- char const* p = argv[0];
- if (*p++ != '-' || strlen(p) != 1)
- goto wrongargs;
- switch (*p) {
- case 'a':
- if (++argv, --argc > 0) {
- attrcnt = atoi(argv[0]);
- if (1 <= attrcnt && attrcnt <= MaxAttr)
- break;
- }
- goto wrongargs;
- case 'e':
- existok = 1;
- break;
- case 'k':
- kontinue = true;
- break;
- case 'l':
- if (++argv, --argc > 0) {
- loopcnt = atoi(argv[0]);
- if (0 <= loopcnt)
- break;
- }
- goto wrongargs;
- case 'o':
- if (++argv, --argc > 0) {
- opercnt = atoi(argv[0]);
- if (0 <= opercnt && opercnt <= MaxOper)
- break;
- }
- goto wrongargs;
- case 'r':
- if (++argv, --argc > 0) {
- randomizer = atoi(argv[0]);
- if (1 <= randomizer)
- break;
- }
- goto wrongargs;
- case 's':
- if (++argv, --argc > 0) {
- sizelim = atoi(argv[0]);
- if (1 <= sizelim && sizelim <= MaxSize)
- break;
- }
- goto wrongargs;
- case 'x':
- xverbose = 1;
- break;
- default:
- wrongargs:
- printusage();
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
- }
- unsigned ok = true;
- for (int i = 1; 0 == loopcnt || i <= loopcnt; i++) {
- ndbout << "=== loop " << i << " ===" << endl;
- for (int flag = 0; flag < (1<<testbits); flag++) {
- if (testcase(flag) < 0) {
- ok = false;
- if (! kontinue)
- goto out;
- }
- }
- }
-out:
- return NDBT_ProgramExit(ok ? NDBT_OK : NDBT_FAILED);
-}
-
-// vim: set sw=4:
diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp
new file mode 100644
index 00000000000..1451c942362
--- /dev/null
+++ b/ndb/test/ndbapi/testDict.cpp
@@ -0,0 +1,1578 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbRestarter.hpp>
+#include <Vector.hpp>
+#include <signaldata/DumpStateOrd.hpp>
+#include <../../include/kernel/ndb_limits.h>
+#include <random.h>
+#include <NdbAutoPtr.hpp>
+
+#define CHECK(b) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ break; }
+
+#define CHECK2(b, c) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << ": " << c << endl; \
+ result = NDBT_FAILED; \
+ goto end; }
+
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+
+int runCreateInvalidTables(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+
+ char failTabName[256];
+
+ for (int i = 0; i < 10; i++){
+ snprintf(failTabName, 256, "F%d", i);
+
+ const NdbDictionary::Table* pFailTab = NDBT_Tables::getTable(failTabName);
+ if (pFailTab != NULL){
+ ndbout << "|- " << failTabName << endl;
+
+ // Try to create table in db
+ if (pFailTab->createTableInDb(pNdb) == 0){
+ ndbout << failTabName << " created, this was not expected"<< endl;
+ result = NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, failTabName) ;
+ if (pTab2 != NULL){
+ ndbout << failTabName << " was found in DB, this was not expected"<< endl;
+ result = NDBT_FAILED;
+ if (pFailTab->equal(*pTab2) == true){
+ ndbout << "It was equal" << endl;
+ } else {
+ ndbout << "It was not equal" << endl;
+ }
+ int records = 1000;
+ HugoTransactions hugoTrans(*pTab2);
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ ndbout << "It can NOT be loaded" << endl;
+ } else{
+ ndbout << "It can be loaded" << endl;
+
+ UtilTransactions utilTrans(*pTab2);
+ if (utilTrans.clearTable(pNdb, records, 64) != 0){
+ ndbout << "It can NOT be cleared" << endl;
+ } else{
+ ndbout << "It can be cleared" << endl;
+ }
+ }
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) == -1){
+ ndbout << "It can NOT be dropped" << endl;
+ } else {
+ ndbout << "It can be dropped" << endl;
+ }
+ }
+ }
+ }
+ return result;
+}
+
+int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ ctx->setTab(pTab2);
+
+ return NDBT_OK;
+}
+
+int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ const char* tabName = "TRANSACTION"; //Use a util table
+
+ const NdbDictionary::Table* pTab = NDBT_Tables::getTable(tabName);
+ if (pTab != NULL){
+ ndbout << "|- " << tabName << endl;
+
+ // Verify that table is not in db
+ if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
+ ndbout << tabName << " was found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) == 0){
+ result = NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
+ ndbout << tabName << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ }
+ }
+
+ return result;
+}
+
+int runDropTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ const char* tabName = "TRANSACTION"; //Use a util table
+
+ const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(pNdb, tabName);
+ if (pTab != NULL){
+ ndbout << "|- TRANSACTION" << endl;
+
+ // Try to drop table in db
+ if (pNdb->getDictionary()->dropTable(pTab->getName()) == -1){
+ result = NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
+ ndbout << tabName << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ }
+ }
+
+ return result;
+
+}
+
+
+int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int loops = ctx->getNumLoops();
+ int i = 0;
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+
+ while (i < loops){
+
+ ndbout << i << ": ";
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName())){
+ ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 != NULL){
+ ndbout << pTab3->getName() << " was found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+
+ return NDBT_OK;
+}
+
+int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int i = 0;
+
+ NdbRestarter restarter;
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ int result;
+ do { CHECK(0); } while (0);
+ g_err << "Unable to change timebetween LCP" << endl;
+ return NDBT_FAILED;
+ }
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+
+ while (i < loops){
+ ndbout << i << ": ";
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ HugoTransactions hugoTrans(*pTab2);
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+
+ int count = 0;
+ UtilTransactions utilTrans(*pTab2);
+ if (utilTrans.selectCount(pNdb, 64, &count) != 0){
+ return NDBT_FAILED;
+ }
+ if (count != records){
+ ndbout << count <<" != "<<records << endl;
+ return NDBT_FAILED;
+ }
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 != NULL){
+ ndbout << pTab3->getName() << " was found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+
+ i++;
+ }
+
+ return NDBT_OK;
+}
+
+int runFillTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.fillTable(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int records = ctx->getNumRecords();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int i = 0;
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+
+ while (i < loops && result == NDBT_OK){
+ ndbout << i << ": " << endl;
+ // Try to create table in db
+
+ Ndb* pNdb = GETNDB(step);
+ g_debug << "Creating table" << endl;
+
+ if (pTab->createTableInDb(pNdb) != 0){
+ g_err << "createTableInDb failed" << endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ g_debug << "Verifying creation of table" << endl;
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ g_err << pTab->getName() << " was not found in DB"<< endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ NdbSleep_MilliSleep(3000);
+
+ g_debug << "Dropping table" << endl;
+
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ g_err << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ g_debug << "Verifying dropping of table" << endl;
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 != NULL){
+ g_err << pTab3->getName() << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+ i++;
+ }
+ ctx->stopTest();
+
+ return result;
+}
+
+
+int runUseTableUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ while (ctx->isTestStopped() == false) {
+ // g_info << i++ << ": ";
+
+
+ // Delete and recreate Ndb object
+ // Otherwise you always get Invalid Schema Version
+ // It would be a nice feature to remove this two lines
+ //step->tearDown();
+ //step->setUp();
+
+ Ndb* pNdb = GETNDB(step);
+
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL)
+ continue;
+
+ int res;
+ HugoTransactions hugoTrans(*pTab2);
+ if ((res = hugoTrans.loadTable(pNdb, records)) != 0){
+ NdbError err = pNdb->getNdbError(res);
+ if(err.classification == NdbError::SchemaError){
+ pNdb->getDictionary()->invalidateTable(pTab->getName());
+ }
+ continue;
+ }
+
+ UtilTransactions utilTrans(*pTab2);
+ if ((res = utilTrans.clearTable(pNdb, records)) != 0){
+ NdbError err = pNdb->getNdbError(res);
+ if(err.classification == NdbError::SchemaError){
+ pNdb->getDictionary()->invalidateTable(pTab->getName());
+ }
+ continue;
+ }
+ }
+ g_info << endl;
+ return NDBT_OK;
+}
+
+
+int runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step){
+ int failures = 0;
+ char tabName[256];
+ int numTables = ctx->getProperty("tables", 1000);
+ Ndb* pNdb = GETNDB(step);
+
+ for (int i = 0; i < numTables && failures < 5; i++){
+ snprintf(tabName, 256, "MAXTAB%d", i);
+
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << tabName << endl;
+
+ // Set new name for T1
+ NdbDictionary::Table newTab(* pTab);
+ newTab.setName(tabName);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) != 0){
+ ndbout << tabName << " coult not be created"<< endl;
+ failures++;
+ continue;
+ }
+
+ // Verify that table exists in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
+ if (pTab3 == NULL){
+ ndbout << tabName << " was not found in DB"<< endl;
+ failures++;
+ continue;
+ }
+
+ if (pTab->equal(*pTab3) == false){
+ ndbout << "It was not equal" << endl;
+ failures++;
+ }
+
+ int records = 1000;
+ HugoTransactions hugoTrans(*pTab3);
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ ndbout << "It can NOT be loaded" << endl;
+ } else{
+ ndbout << "It can be loaded" << endl;
+
+ UtilTransactions utilTrans(*pTab3);
+ if (utilTrans.clearTable(pNdb, records, 64) != 0){
+ ndbout << "It can NOT be cleared" << endl;
+ } else{
+ ndbout << "It can be cleared" << endl;
+ }
+ }
+
+ }
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+ // HURRAAA!
+ return NDBT_OK;
+}
+
+int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ char tabName[256];
+ int numTables = ctx->getProperty("tables", 1000);
+ Ndb* pNdb = GETNDB(step);
+
+ for (int i = 0; i < numTables; i++){
+ snprintf(tabName, 256, "MAXTAB%d", i);
+
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+
+ // Verify that table exists in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
+ if (pTab3 == NULL){
+ ndbout << tabName << " was not found in DB"<< endl;
+ continue;
+ }
+
+
+ // Try to drop table in db
+ if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
+ ndbout << tabName << " coult not be dropped"<< endl;
+ result = NDBT_FAILED;
+ }
+
+ }
+ return result;
+}
+
+int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ int fragTtype = ctx->getProperty("FragmentType");
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ NdbRestarter restarter;
+
+ // enum FragmentType {
+ // Unknown = 0,
+ // Single = 1, ///< Only one fragment
+ // All = 2, ///< Default value. One fragment per node group
+ // AllLarge = 3 ///< Sixten fragments per node group.
+ // };
+
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ NdbDictionary::Table newTab(* pTab);
+ // Set fragment type for table
+ newTab.setFragmentType((NdbDictionary::Object::FragmentType)fragTtype);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) != 0){
+ ndbout << newTab.getName() << " could not be created"
+ << ", fragmentType = "<<fragTtype <<endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table exists in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName()) ;
+ if (pTab3 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+
+ }
+
+ if (pTab3->getFragmentType() != fragTtype){
+ ndbout << pTab->getName() << " fragmentType error "<< endl;
+ result = NDBT_FAILED;
+ goto drop_the_tab;
+ }
+
+ if (newTab.equal(*pTab3) == false){
+ ndbout << "It was not equal" << endl;
+ result = NDBT_FAILED;
+ goto drop_the_tab;
+ }
+
+ do {
+
+ HugoTransactions hugoTrans(*pTab3);
+ UtilTransactions utilTrans(*pTab3);
+ int count;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+ CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+
+ // restart all
+ ndbout << "Restarting cluster" << endl;
+ CHECK(restarter.restartAll() == 0);
+ int timeout = 120;
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ // Verify content
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records, 64) == 0);
+
+ } while(false);
+
+ drop_the_tab:
+
+ // Try to drop table in db
+ if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
+ ndbout << pTab3->getName() << " could not be dropped"<< endl;
+ result = NDBT_FAILED;
+ }
+
+ return result;
+}
+
+
+int runTestTemporaryTables(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ Ndb* pNdb = GETNDB(step);
+ int i = 0;
+ NdbRestarter restarter;
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+
+ NdbDictionary::Table newTab(* pTab);
+ // Set table as temporary
+ newTab.setStoredTable(false);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ if (pTab2->getStoredTable() != false){
+ ndbout << pTab->getName() << " was not temporary in DB"<< endl;
+ result = NDBT_FAILED;
+ goto drop_the_tab;
+ }
+
+
+ while (i < loops && result == NDBT_OK){
+ ndbout << i << ": ";
+
+ HugoTransactions hugoTrans(*pTab2);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+
+ int count = 0;
+ UtilTransactions utilTrans(*pTab2);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+
+ // restart all
+ ndbout << "Restarting cluster" << endl;
+ CHECK(restarter.restartAll() == 0);
+ int timeout = 120;
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+
+ i++;
+ }
+
+ drop_the_tab:
+
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ result = NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 != NULL){
+ ndbout << pTab3->getName() << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ }
+
+ return result;
+}
+
+int runPkSizes(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ char tabName[256];
+ int minPkSize = 1;
+ ndbout << "minPkSize=" <<minPkSize<<endl;
+ int maxPkSize = MAX_KEY_SIZE_IN_WORDS * 4;
+ ndbout << "maxPkSize=" <<maxPkSize<<endl;
+ Ndb* pNdb = GETNDB(step);
+ int numRecords = ctx->getNumRecords();
+
+ for (int i = minPkSize; i < maxPkSize; i++){
+ snprintf(tabName, 256, "TPK_%d", i);
+
+ int records = numRecords;
+ int max = ~0;
+ // Limit num records for small PKs
+ if (i == 1)
+ max = 99;
+ if (i == 2)
+ max = 999;
+ if (i == 3)
+ max = 9999;
+ if (records > max)
+ records = max;
+ ndbout << "records =" << records << endl;
+
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+
+ ndbout << "|- " << tabName << endl;
+
+ if (NDBT_Tables::createTable(pNdb, tabName) != 0){
+ ndbout << tabName << " could not be created"<< endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table exists in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
+ if (pTab3 == NULL){
+ g_err << tabName << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ // ndbout << *pTab3 << endl;
+
+ if (pTab3->equal(*NDBT_Tables::getTable(tabName)) == false){
+ g_err << "It was not equal" << endl;
+ return NDBT_FAILED;
+ }
+
+ do {
+ // Do it all
+ HugoTransactions hugoTrans(*pTab3);
+ UtilTransactions utilTrans(*pTab3);
+ int count;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+ CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+
+#if 0
+ // Fill table
+ CHECK(hugoTrans.fillTable(pNdb) == 0);
+ CHECK(utilTrans.clearTable2(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+#endif
+ } while(false);
+
+ // Drop table
+ if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
+ ndbout << "Failed to drop "<<pTab3->getName()<<" in db" << endl;
+ return NDBT_FAILED;
+ }
+ }
+ return result;
+}
+
+int runStoreFrm(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+
+ Uint32 dataLen = (Uint32)myRandom48(MAX_FRM_DATA_SIZE);
+ // size_t dataLen = 10;
+ unsigned char data[MAX_FRM_DATA_SIZE];
+
+ char start = l + 248;
+ for(Uint32 i = 0; i < dataLen; i++){
+ data[i] = start;
+ start++;
+ }
+#if 0
+ ndbout << "dataLen="<<dataLen<<endl;
+ for (Uint32 i = 0; i < dataLen; i++){
+ unsigned char c = data[i];
+ ndbout << hex << c << ", ";
+ }
+ ndbout << endl;
+#endif
+
+ NdbDictionary::Table newTab(* pTab);
+ void* pData = &data;
+ newTab.setFrm(pData, dataLen);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) != 0){
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ g_err << pTab->getName() << " was not found in DB"<< endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ const void* pData2 = pTab2->getFrmData();
+ Uint32 resultLen = pTab2->getFrmLength();
+ if (dataLen != resultLen){
+ g_err << "Length of data failure" << endl
+ << " expected = " << dataLen << endl
+ << " got = " << resultLen << endl;
+ result = NDBT_FAILED;
+ }
+
+ // Verfiy the frm data
+ if (memcmp(pData, pData2, resultLen) != 0){
+ g_err << "Wrong data recieved" << endl;
+ for (size_t i = 0; i < dataLen; i++){
+ unsigned char c = ((unsigned char*)pData2)[i];
+ g_err << hex << c << ", ";
+ }
+ g_err << endl;
+ result = NDBT_FAILED;
+ }
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ g_err << "It can NOT be dropped" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+
+ return result;
+}
+
+int runStoreFrmError(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+
+ const Uint32 dataLen = MAX_FRM_DATA_SIZE + 10;
+ unsigned char data[dataLen];
+
+ char start = l + 248;
+ for(Uint32 i = 0; i < dataLen; i++){
+ data[i] = start;
+ start++;
+ }
+#if 0
+ ndbout << "dataLen="<<dataLen<<endl;
+ for (Uint32 i = 0; i < dataLen; i++){
+ unsigned char c = data[i];
+ ndbout << hex << c << ", ";
+ }
+ ndbout << endl;
+#endif
+
+ NdbDictionary::Table newTab(* pTab);
+
+ void* pData = &data;
+ newTab.setFrm(pData, dataLen);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) == 0){
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 != NULL){
+ g_err << pTab->getName() << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ g_err << "It can NOT be dropped" << endl;
+ result = NDBT_FAILED;
+ }
+
+ continue;
+ }
+
+ }
+
+ return result;
+}
+
+int verifyTablesAreEqual(const NdbDictionary::Table* pTab, const NdbDictionary::Table* pTab2){
+ // Verify that getPrimaryKey only returned true for primary keys
+ for (int i = 0; i < pTab2->getNoOfColumns(); i++){
+ const NdbDictionary::Column* col = pTab->getColumn(i);
+ const NdbDictionary::Column* col2 = pTab2->getColumn(i);
+ if (col->getPrimaryKey() != col2->getPrimaryKey()){
+ g_err << "col->getPrimaryKey() != col2->getPrimaryKey()" << endl;
+ return NDBT_FAILED;
+ }
+ }
+
+ if (!pTab->equal(*pTab2)){
+ g_err << "equal failed" << endl;
+ g_info << *pTab;
+ g_info << *pTab2;
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+ g_info << *pTab;
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ int result = NDBT_OK;
+ if (verifyTablesAreEqual(pTab, pTab2) != NDBT_OK)
+ result = NDBT_FAILED;
+
+
+#if 0
+ // Create an index on the table and see what
+ // the function returns now
+ char name[200];
+ sprintf(name, "%s_X007", pTab->getName());
+ NDBT_Index* pInd = new NDBT_Index(name);
+ pInd->setTable(pTab->getName());
+ pInd->setType(NdbDictionary::Index::UniqueHashIndex);
+ // pInd->setLogging(false);
+ for (int i = 0; i < 2; i++){
+ const NDBT_Attribute* pAttr = pTab->getAttribute(i);
+ pInd->addAttribute(*pAttr);
+ }
+ g_info << "Create index:" << endl << *pInd;
+ if (pInd->createIndexInDb(pNdb, false) != 0){
+ result = NDBT_FAILED;
+ }
+ delete pInd;
+
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ if (verifyTablesAreEqual(pTab, pTab3) != NDBT_OK)
+ result = NDBT_FAILED;
+ if (verifyTablesAreEqual(pTab2, pTab3) != NDBT_OK)
+ result = NDBT_FAILED;
+#endif
+
+#if 0
+ if (pTab2->getDictionary()->dropTable(pNdb) != 0){
+ ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab4 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab4 != NULL){
+ ndbout << pTab4->getName() << " was found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+#endif
+
+ return result;
+}
+
+int
+NF_codes[] = {
+ 6003
+ ,6004
+ //,6005
+};
+
+int
+runNF1(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+ if(restarter.getNumDbNodes() < 2)
+ return NDBT_OK;
+
+ myRandom48Init(NdbTick_CurrentMillisecond());
+
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+ dict->dropTable(pTab->getName());
+
+ int result = NDBT_OK;
+
+ /**
+ * Need to run LCP at high rate otherwise
+ * packed replicas become "to many"
+ */
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ do { CHECK(0); } while(0);
+ g_err << "Failed to set LCP to min value" << endl;
+ return NDBT_FAILED;
+ }
+
+ const int loops = ctx->getNumLoops();
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+ const int sz = sizeof(NF_codes)/sizeof(NF_codes[0]);
+ for(int i = 0; i<sz; i++){
+ int rand = myRandom48(restarter.getNumDbNodes());
+ int nodeId = restarter.getRandomNotMasterNodeId(rand);
+ int error = NF_codes[i];
+
+ g_info << "NF1: node = " << nodeId << " error code = " << error << endl;
+
+ int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 3};
+
+ CHECK2(restarter.dumpStateOneNode(nodeId, val2, 2) == 0,
+ "failed to set RestartOnErrorInsert");
+
+ CHECK2(restarter.insertErrorInNode(nodeId, error) == 0,
+ "failed to set error insert");
+
+ CHECK2(dict->createTable(* pTab) == 0,
+ "failed to create table");
+
+ CHECK2(restarter.waitNodesNoStart(&nodeId, 1) == 0,
+ "waitNodesNoStart failed");
+
+ if(myRandom48(100) > 50){
+ CHECK2(restarter.startNodes(&nodeId, 1) == 0,
+ "failed to start node");
+
+ CHECK2(restarter.waitClusterStarted() == 0,
+ "waitClusterStarted failed");
+
+ CHECK2(dict->dropTable(pTab->getName()) == 0,
+ "drop table failed");
+ } else {
+ CHECK2(dict->dropTable(pTab->getName()) == 0,
+ "drop table failed");
+
+ CHECK2(restarter.startNodes(&nodeId, 1) == 0,
+ "failed to start node");
+
+ CHECK2(restarter.waitClusterStarted() == 0,
+ "waitClusterStarted failed");
+ }
+
+ CHECK2(restarter.dumpStateOneNode(nodeId, &val, 1) == 0,
+ "Failed to set LCP to min value");
+ }
+ }
+ end:
+ dict->dropTable(pTab->getName());
+
+ return result;
+}
+
+#define APIERROR(error) \
+ { g_err << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
+ << error.code << ", msg: " << error.message << "." << endl; \
+ }
+
+int
+runCreateAutoincrementTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ Uint32 startvalues[5] = {256-2, 0, 256*256-2, ~0, 256*256*256-2};
+
+ int ret = NDBT_OK;
+
+ for (int jj = 0; jj < 5 && ret == NDBT_OK; jj++) {
+ char tabname[] = "AUTOINCTAB";
+ Uint32 startvalue = startvalues[jj];
+
+ NdbDictionary::Table myTable;
+ NdbDictionary::Column myColumn;
+
+ Ndb* myNdb = GETNDB(step);
+ NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
+
+
+ if (myDict->getTable(tabname) != NULL) {
+ g_err << "NDB already has example table: " << tabname << endl;
+ APIERROR(myNdb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ myTable.setName(tabname);
+
+ myColumn.setName("ATTR1");
+ myColumn.setPrimaryKey(true);
+ myColumn.setType(NdbDictionary::Column::Unsigned);
+ myColumn.setLength(1);
+ myColumn.setNullable(false);
+ myColumn.setAutoIncrement(true);
+ if (startvalue != ~0) // check that default value starts with 1
+ myColumn.setAutoIncrementInitialValue(startvalue);
+ myTable.addColumn(myColumn);
+
+ if (myDict->createTable(myTable) == -1) {
+ g_err << "Failed to create table " << tabname << endl;
+ APIERROR(myNdb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+
+ if (startvalue == ~0) // check that default value starts with 1
+ startvalue = 1;
+
+ for (int i = 0; i < 16; i++) {
+
+ Uint64 value = myNdb->getAutoIncrementValue(tabname, 1);
+
+ if (value != (startvalue+i)) {
+ g_err << "value = " << value << " expected " << startvalue+i << endl;;
+ APIERROR(myNdb->getNdbError());
+ // ret = NDBT_FAILED;
+ // break;
+ }
+ }
+
+ if (myDict->dropTable(tabname) == -1) {
+ g_err << "Failed to drop table " << tabname << endl;
+ APIERROR(myNdb->getNdbError());
+ ret = NDBT_FAILED;
+ }
+ }
+
+ return ret;
+}
+
+int
+runTableRename(NDBT_Context* ctx, NDBT_Step* step){
+
+ int result = NDBT_OK;
+
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+ int records = ctx->getNumRecords();
+ const int loops = ctx->getNumLoops();
+
+ ndbout << "|- " << ctx->getTab()->getName() << endl;
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ ctx->setTab(pTab2);
+
+ // Load table
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Rename table
+ BaseString pTabName(pTab->getName());
+ BaseString pTabNewName(pTabName);
+ pTabNewName.append("xx");
+
+ const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
+ if (oldTable) {
+ NdbDictionary::Table newTable = dict->getTableForAlteration(pTabName.c_str());
+ newTable.setName(pTabNewName.c_str());
+ CHECK2(dict->alterTable(newTable) == 0,
+ "TableRename failed");
+ }
+ else {
+ result = NDBT_FAILED;
+ }
+
+ // Verify table contents
+ NdbDictionary::Table pNewTab(pTabNewName.c_str());
+
+ UtilTransactions utilTrans(pNewTab);
+ if (utilTrans.clearTable(pNdb, records) != 0){
+ continue;
+ }
+
+ // Drop table
+ dict->dropTable(pNewTab.getName());
+ }
+ end:
+
+ return result;
+}
+
+int
+runTableRenameNF(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+ if(restarter.getNumDbNodes() < 2)
+ return NDBT_OK;
+
+ int result = NDBT_OK;
+
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+ int records = ctx->getNumRecords();
+ const int loops = ctx->getNumLoops();
+
+ ndbout << "|- " << ctx->getTab()->getName() << endl;
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ ctx->setTab(pTab2);
+
+ // Load table
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+
+ BaseString pTabName(pTab->getName());
+ BaseString pTabNewName(pTabName);
+ pTabNewName.append("xx");
+
+ const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
+ if (oldTable) {
+ NdbDictionary::Table newTable = dict->getTableForAlteration(pTabName.c_str());
+ newTable.setName(pTabNewName.c_str());
+ CHECK2(dict->alterTable(newTable) == 0,
+ "TableRename failed");
+ }
+ else {
+ result = NDBT_FAILED;
+ }
+
+ // Restart one node at a time
+
+ /**
+ * Need to run LCP at high rate otherwise
+ * packed replicas become "to many"
+ */
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ do { CHECK(0); } while(0);
+ g_err << "Failed to set LCP to min value" << endl;
+ return NDBT_FAILED;
+ }
+
+ const int numNodes = restarter.getNumDbNodes();
+ for(int i = 0; i<numNodes; i++){
+ int nodeId = restarter.getDbNodeId(i);
+ int error = NF_codes[i];
+
+ g_info << "NF1: node = " << nodeId << " error code = " << error << endl;
+
+ CHECK2(restarter.restartOneDbNode(nodeId) == 0,
+ "failed to set restartOneDbNode");
+
+ CHECK2(restarter.waitClusterStarted() == 0,
+ "waitClusterStarted failed");
+
+ }
+
+ // Verify table contents
+ NdbDictionary::Table pNewTab(pTabNewName.c_str());
+
+ UtilTransactions utilTrans(pNewTab);
+ if (utilTrans.clearTable(pNdb, records) != 0){
+ continue;
+ }
+
+ // Drop table
+ dict->dropTable(pTabNewName.c_str());
+ }
+ end:
+ return result;
+}
+
+int
+runTableRenameSR(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+ if(restarter.getNumDbNodes() < 2)
+ return NDBT_OK;
+
+ int result = NDBT_OK;
+
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+ int records = ctx->getNumRecords();
+ const int loops = ctx->getNumLoops();
+
+ ndbout << "|- " << ctx->getTab()->getName() << endl;
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+ // Rename table
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ ctx->setTab(pTab2);
+
+ // Load table
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+
+ BaseString pTabName(pTab->getName());
+ BaseString pTabNewName(pTabName);
+ pTabNewName.append("xx");
+
+ const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
+ if (oldTable) {
+ NdbDictionary::Table newTable = dict->getTableForAlteration(pTabName.c_str());
+ newTable.setName(pTabNewName.c_str());
+ CHECK2(dict->alterTable(newTable) == 0,
+ "TableRename failed");
+ }
+ else {
+ result = NDBT_FAILED;
+ }
+
+ // Restart cluster
+
+ /**
+ * Need to run LCP at high rate otherwise
+ * packed replicas become "to many"
+ */
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ do { CHECK(0); } while(0);
+ g_err << "Failed to set LCP to min value" << endl;
+ return NDBT_FAILED;
+ }
+
+ CHECK2(restarter.restartAll() == 0,
+ "failed to set restartOneDbNode");
+
+ CHECK2(restarter.waitClusterStarted() == 0,
+ "waitClusterStarted failed");
+
+ // Verify table contents
+ NdbDictionary::Table pNewTab(pTabNewName.c_str());
+
+ UtilTransactions utilTrans(pNewTab);
+ if (utilTrans.clearTable(pNdb, records) != 0){
+ continue;
+ }
+
+ // Drop table
+ dict->dropTable(pTabNewName.c_str());
+ }
+ end:
+ return result;
+}
+
+static void
+f(const NdbDictionary::Column * col){
+ if(col == 0){
+ abort();
+ }
+}
+
+int
+runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
+ Vector<char*> cols;
+ Vector<const NdbDictionary::Table*> tabs;
+
+ Ndb* pNdb = GETNDB(step);
+
+ const Uint32 count = NDBT_Tables::getNumTables();
+ for (int i=0; i < count; i++){
+ const NdbDictionary::Table * tab = NDBT_Tables::getTable(i);
+ pNdb->getDictionary()->createTable(* tab);
+
+ const NdbDictionary::Table * tab2 = pNdb->getDictionary()->getTable(tab->getName());
+
+ for(size_t j = 0; j<tab->getNoOfColumns(); j++){
+ cols.push_back((char*)tab2);
+ cols.push_back(strdup(tab->getColumn(j)->getName()));
+ }
+ }
+
+ const Uint32 times = 10000000;
+
+ ndbout_c("%d tables and %d columns",
+ NDBT_Tables::getNumTables(), cols.size()/2);
+
+ char ** tcols = cols.getBase();
+
+ srand(time(0));
+ Uint32 size = cols.size() / 2;
+ char ** columns = &cols[0];
+ Uint64 start = NdbTick_CurrentMillisecond();
+ for(int i = 0; i<times; i++){
+ int j = 2 * (rand() % size);
+ const NdbDictionary::Table* tab = (const NdbDictionary::Table*)tcols[j];
+ const char * col = tcols[j+1];
+ const NdbDictionary::Column* column = tab->getColumn(col);
+ f(column);
+ }
+ Uint64 stop = NdbTick_CurrentMillisecond();
+ stop -= start;
+
+ Uint64 per = stop;
+ per *= 1000;
+ per /= times;
+
+ ndbout_c("%d random getColumn(name) in %Ld ms -> %d us/get",
+ times, stop, per);
+
+ return NDBT_OK;
+}
+
+NDBT_TESTSUITE(testDict);
+TESTCASE("CreateAndDrop",
+ "Try to create and drop the table loop number of times\n"){
+ INITIALIZER(runCreateAndDrop);
+}
+TESTCASE("CreateAndDropWithData",
+ "Try to create and drop the table when it's filled with data\n"
+ "do this loop number of times\n"){
+ INITIALIZER(runCreateAndDropWithData);
+}
+TESTCASE("CreateAndDropDuring",
+ "Try to create and drop the table when other thread is using it\n"
+ "do this loop number of times\n"){
+ STEP(runCreateAndDropDuring);
+ STEP(runUseTableUntilStopped);
+}
+TESTCASE("CreateInvalidTables",
+ "Try to create the invalid tables we have defined\n"){
+ INITIALIZER(runCreateInvalidTables);
+}
+TESTCASE("CreateTableWhenDbIsFull",
+ "Try to create a new table when db already is full\n"){
+ INITIALIZER(runCreateTheTable);
+ INITIALIZER(runFillTable);
+ INITIALIZER(runCreateTableWhenDbIsFull);
+ INITIALIZER(runDropTableWhenDbIsFull);
+ FINALIZER(runClearTable);
+}
+TESTCASE("FragmentTypeSingle",
+ "Create the table with fragment type Single\n"){
+ TC_PROPERTY("FragmentType", 1);
+ INITIALIZER(runTestFragmentTypes);
+}
+TESTCASE("FragmentTypeAll",
+ "Create the table with fragment type All\n"){
+ TC_PROPERTY("FragmentType", 2);
+ INITIALIZER(runTestFragmentTypes);
+}
+TESTCASE("FragmentTypeAllLarge",
+ "Create the table with fragment type AllLarge\n"){
+ TC_PROPERTY("FragmentType", 3);
+ INITIALIZER(runTestFragmentTypes);
+}
+TESTCASE("TemporaryTables",
+ "Create the table as temporary and make sure it doesn't\n"
+ "contain any data when system is restarted\n"){
+ INITIALIZER(runTestTemporaryTables);
+}
+TESTCASE("CreateMaxTables",
+ "Create tables until db says that it can't create any more\n"){
+ TC_PROPERTY("tables", 1000);
+ INITIALIZER(runCreateMaxTables);
+ FINALIZER(runDropMaxTables);
+}
+TESTCASE("PkSizes",
+ "Create tables with all different primary key sizes.\n"\
+ "Test all data operations insert, update, delete etc.\n"\
+ "Drop table."){
+ INITIALIZER(runPkSizes);
+}
+TESTCASE("StoreFrm",
+ "Test that a frm file can be properly stored as part of the\n"
+ "data in Dict."){
+ INITIALIZER(runStoreFrm);
+}
+TESTCASE("GetPrimaryKey",
+ "Test the function NdbDictionary::Column::getPrimaryKey\n"
+ "It should return true only if the column is part of \n"
+ "the primary key in the table"){
+ INITIALIZER(runGetPrimaryKey);
+}
+TESTCASE("StoreFrmError",
+ "Test that a frm file with too long length can't be stored."){
+ INITIALIZER(runStoreFrmError);
+}
+TESTCASE("NF1",
+ "Test that create table can handle NF (not master)"){
+ INITIALIZER(runNF1);
+}
+TESTCASE("TableRename",
+ "Test basic table rename"){
+ INITIALIZER(runTableRename);
+}
+TESTCASE("TableRenameNF",
+ "Test that table rename can handle node failure"){
+ INITIALIZER(runTableRenameNF);
+}
+TESTCASE("TableRenameSR",
+ "Test that table rename can handle system restart"){
+ INITIALIZER(runTableRenameSR);
+}
+TESTCASE("DictionaryPerf",
+ ""){
+ INITIALIZER(runTestDictionaryPerf);
+}
+NDBT_TESTSUITE_END(testDict);
+
+int main(int argc, const char** argv){
+ // Tables should not be auto created
+ testDict.setCreateTable(false);
+ myRandom48Init(NdbTick_CurrentMillisecond());
+ return testDict.execute(argc, argv);
+}
+
+
diff --git a/ndb/test/ndbapi/testDict/testDict.cpp b/ndb/test/ndbapi/testDict/testDict.cpp
deleted file mode 100644
index 06614690b8d..00000000000
--- a/ndb/test/ndbapi/testDict/testDict.cpp
+++ /dev/null
@@ -1,1578 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NDBT.hpp>
-#include <NDBT_Test.hpp>
-#include <HugoTransactions.hpp>
-#include <UtilTransactions.hpp>
-#include <NdbRestarter.hpp>
-#include <Vector.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-#include <../../include/kernel/ndb_limits.h>
-#include <random.h>
-#include <NdbAutoPtr.hpp>
-
-#define CHECK(b) if (!(b)) { \
- g_err << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- break; }
-
-#define CHECK2(b, c) if (!(b)) { \
- g_err << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << ": " << c << endl; \
- result = NDBT_FAILED; \
- goto end; }
-
-int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int records = ctx->getNumRecords();
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(pNdb, records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-
-int runCreateInvalidTables(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
-
- char failTabName[256];
-
- for (int i = 0; i < 10; i++){
- snprintf(failTabName, 256, "F%d", i);
-
- const NdbDictionary::Table* pFailTab = NDBT_Tables::getTable(failTabName);
- if (pFailTab != NULL){
- ndbout << "|- " << failTabName << endl;
-
- // Try to create table in db
- if (pFailTab->createTableInDb(pNdb) == 0){
- ndbout << failTabName << " created, this was not expected"<< endl;
- result = NDBT_FAILED;
- }
-
- // Verify that table is not in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, failTabName) ;
- if (pTab2 != NULL){
- ndbout << failTabName << " was found in DB, this was not expected"<< endl;
- result = NDBT_FAILED;
- if (pFailTab->equal(*pTab2) == true){
- ndbout << "It was equal" << endl;
- } else {
- ndbout << "It was not equal" << endl;
- }
- int records = 1000;
- HugoTransactions hugoTrans(*pTab2);
- if (hugoTrans.loadTable(pNdb, records) != 0){
- ndbout << "It can NOT be loaded" << endl;
- } else{
- ndbout << "It can be loaded" << endl;
-
- UtilTransactions utilTrans(*pTab2);
- if (utilTrans.clearTable(pNdb, records, 64) != 0){
- ndbout << "It can NOT be cleared" << endl;
- } else{
- ndbout << "It can be cleared" << endl;
- }
- }
-
- if (pNdb->getDictionary()->dropTable(pTab2->getName()) == -1){
- ndbout << "It can NOT be dropped" << endl;
- } else {
- ndbout << "It can be dropped" << endl;
- }
- }
- }
- }
- return result;
-}
-
-int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- // Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
- return NDBT_FAILED;
- }
-
- // Verify that table is in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
- ctx->setTab(pTab2);
-
- return NDBT_OK;
-}
-
-int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- const char* tabName = "TRANSACTION"; //Use a util table
-
- const NdbDictionary::Table* pTab = NDBT_Tables::getTable(tabName);
- if (pTab != NULL){
- ndbout << "|- " << tabName << endl;
-
- // Verify that table is not in db
- if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
- ndbout << tabName << " was found in DB"<< endl;
- return NDBT_FAILED;
- }
-
- // Try to create table in db
- if (pTab->createTableInDb(pNdb) == 0){
- result = NDBT_FAILED;
- }
-
- // Verify that table is in db
- if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
- ndbout << tabName << " was found in DB"<< endl;
- result = NDBT_FAILED;
- }
- }
-
- return result;
-}
-
-int runDropTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- const char* tabName = "TRANSACTION"; //Use a util table
-
- const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(pNdb, tabName);
- if (pTab != NULL){
- ndbout << "|- TRANSACTION" << endl;
-
- // Try to drop table in db
- if (pNdb->getDictionary()->dropTable(pTab->getName()) == -1){
- result = NDBT_FAILED;
- }
-
- // Verify that table is not in db
- if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
- ndbout << tabName << " was found in DB"<< endl;
- result = NDBT_FAILED;
- }
- }
-
- return result;
-
-}
-
-
-int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int loops = ctx->getNumLoops();
- int i = 0;
-
- const NdbDictionary::Table* pTab = ctx->getTab();
- ndbout << "|- " << pTab->getName() << endl;
-
- while (i < loops){
-
- ndbout << i << ": ";
- // Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
- return NDBT_FAILED;
- }
-
- // Verify that table is in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
-
- if (pNdb->getDictionary()->dropTable(pTab2->getName())){
- ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
- return NDBT_FAILED;
- }
-
- // Verify that table is not in db
- const NdbDictionary::Table* pTab3 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab3 != NULL){
- ndbout << pTab3->getName() << " was found in DB"<< endl;
- return NDBT_FAILED;
- }
- i++;
- }
-
- return NDBT_OK;
-}
-
-int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int i = 0;
-
- NdbRestarter restarter;
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- if(restarter.dumpStateAllNodes(&val, 1) != 0){
- int result;
- do { CHECK(0); } while (0);
- g_err << "Unable to change timebetween LCP" << endl;
- return NDBT_FAILED;
- }
-
- const NdbDictionary::Table* pTab = ctx->getTab();
- ndbout << "|- " << pTab->getName() << endl;
-
- while (i < loops){
- ndbout << i << ": ";
- // Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
- return NDBT_FAILED;
- }
-
- // Verify that table is in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
-
- HugoTransactions hugoTrans(*pTab2);
- if (hugoTrans.loadTable(pNdb, records) != 0){
- return NDBT_FAILED;
- }
-
- int count = 0;
- UtilTransactions utilTrans(*pTab2);
- if (utilTrans.selectCount(pNdb, 64, &count) != 0){
- return NDBT_FAILED;
- }
- if (count != records){
- ndbout << count <<" != "<<records << endl;
- return NDBT_FAILED;
- }
-
- if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
- ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
- return NDBT_FAILED;
- }
-
- // Verify that table is not in db
- const NdbDictionary::Table* pTab3 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab3 != NULL){
- ndbout << pTab3->getName() << " was found in DB"<< endl;
- return NDBT_FAILED;
- }
-
-
- i++;
- }
-
- return NDBT_OK;
-}
-
-int runFillTable(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.fillTable(pNdb) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int records = ctx->getNumRecords();
-
- UtilTransactions utilTrans(*ctx->getTab());
- if (utilTrans.clearTable(pNdb, records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
- int i = 0;
-
- const NdbDictionary::Table* pTab = ctx->getTab();
- ndbout << "|- " << pTab->getName() << endl;
-
- while (i < loops && result == NDBT_OK){
- ndbout << i << ": " << endl;
- // Try to create table in db
-
- Ndb* pNdb = GETNDB(step);
- g_debug << "Creating table" << endl;
-
- if (pTab->createTableInDb(pNdb) != 0){
- g_err << "createTableInDb failed" << endl;
- result = NDBT_FAILED;
- continue;
- }
-
- g_debug << "Verifying creation of table" << endl;
-
- // Verify that table is in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- g_err << pTab->getName() << " was not found in DB"<< endl;
- result = NDBT_FAILED;
- continue;
- }
-
- NdbSleep_MilliSleep(3000);
-
- g_debug << "Dropping table" << endl;
-
-
- if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
- g_err << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
- result = NDBT_FAILED;
- continue;
- }
-
- g_debug << "Verifying dropping of table" << endl;
-
- // Verify that table is not in db
- const NdbDictionary::Table* pTab3 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab3 != NULL){
- g_err << pTab3->getName() << " was found in DB"<< endl;
- result = NDBT_FAILED;
- continue;
- }
- i++;
- }
- ctx->stopTest();
-
- return result;
-}
-
-
-int runUseTableUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
-
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- while (ctx->isTestStopped() == false) {
- // g_info << i++ << ": ";
-
-
- // Delete and recreate Ndb object
- // Otherwise you always get Invalid Schema Version
- // It would be a nice feature to remove this two lines
- //step->tearDown();
- //step->setUp();
-
- Ndb* pNdb = GETNDB(step);
-
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL)
- continue;
-
- int res;
- HugoTransactions hugoTrans(*pTab2);
- if ((res = hugoTrans.loadTable(pNdb, records)) != 0){
- NdbError err = pNdb->getNdbError(res);
- if(err.classification == NdbError::SchemaError){
- pNdb->getDictionary()->invalidateTable(pTab->getName());
- }
- continue;
- }
-
- UtilTransactions utilTrans(*pTab2);
- if ((res = utilTrans.clearTable(pNdb, records)) != 0){
- NdbError err = pNdb->getNdbError(res);
- if(err.classification == NdbError::SchemaError){
- pNdb->getDictionary()->invalidateTable(pTab->getName());
- }
- continue;
- }
- }
- g_info << endl;
- return NDBT_OK;
-}
-
-
-int runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step){
- int failures = 0;
- char tabName[256];
- int numTables = ctx->getProperty("tables", 1000);
- Ndb* pNdb = GETNDB(step);
-
- for (int i = 0; i < numTables && failures < 5; i++){
- snprintf(tabName, 256, "MAXTAB%d", i);
-
- if (pNdb->waitUntilReady(30) != 0){
- // Db is not ready, return with failure
- return NDBT_FAILED;
- }
-
- const NdbDictionary::Table* pTab = ctx->getTab();
- ndbout << "|- " << tabName << endl;
-
- // Set new name for T1
- NdbDictionary::Table newTab(* pTab);
- newTab.setName(tabName);
-
- // Try to create table in db
- if (newTab.createTableInDb(pNdb) != 0){
- ndbout << tabName << " coult not be created"<< endl;
- failures++;
- continue;
- }
-
- // Verify that table exists in db
- const NdbDictionary::Table* pTab3 =
- NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
- if (pTab3 == NULL){
- ndbout << tabName << " was not found in DB"<< endl;
- failures++;
- continue;
- }
-
- if (pTab->equal(*pTab3) == false){
- ndbout << "It was not equal" << endl;
- failures++;
- }
-
- int records = 1000;
- HugoTransactions hugoTrans(*pTab3);
- if (hugoTrans.loadTable(pNdb, records) != 0){
- ndbout << "It can NOT be loaded" << endl;
- } else{
- ndbout << "It can be loaded" << endl;
-
- UtilTransactions utilTrans(*pTab3);
- if (utilTrans.clearTable(pNdb, records, 64) != 0){
- ndbout << "It can NOT be cleared" << endl;
- } else{
- ndbout << "It can be cleared" << endl;
- }
- }
-
- }
- if (pNdb->waitUntilReady(30) != 0){
- // Db is not ready, return with failure
- return NDBT_FAILED;
- }
- // HURRAAA!
- return NDBT_OK;
-}
-
-int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- char tabName[256];
- int numTables = ctx->getProperty("tables", 1000);
- Ndb* pNdb = GETNDB(step);
-
- for (int i = 0; i < numTables; i++){
- snprintf(tabName, 256, "MAXTAB%d", i);
-
- if (pNdb->waitUntilReady(30) != 0){
- // Db is not ready, return with failure
- return NDBT_FAILED;
- }
-
- // Verify that table exists in db
- const NdbDictionary::Table* pTab3 =
- NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
- if (pTab3 == NULL){
- ndbout << tabName << " was not found in DB"<< endl;
- continue;
- }
-
-
- // Try to drop table in db
- if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
- ndbout << tabName << " coult not be dropped"<< endl;
- result = NDBT_FAILED;
- }
-
- }
- return result;
-}
-
-int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- int fragTtype = ctx->getProperty("FragmentType");
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- NdbRestarter restarter;
-
- // enum FragmentType {
- // Unknown = 0,
- // Single = 1, ///< Only one fragment
- // All = 2, ///< Default value. One fragment per node group
- // AllLarge = 3 ///< Sixten fragments per node group.
- // };
-
- if (pNdb->waitUntilReady(30) != 0){
- // Db is not ready, return with failure
- return NDBT_FAILED;
- }
-
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- NdbDictionary::Table newTab(* pTab);
- // Set fragment type for table
- newTab.setFragmentType((NdbDictionary::Object::FragmentType)fragTtype);
-
- // Try to create table in db
- if (newTab.createTableInDb(pNdb) != 0){
- ndbout << newTab.getName() << " could not be created"
- << ", fragmentType = "<<fragTtype <<endl;
- return NDBT_FAILED;
- }
-
- // Verify that table exists in db
- const NdbDictionary::Table* pTab3 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName()) ;
- if (pTab3 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
-
- }
-
- if (pTab3->getFragmentType() != fragTtype){
- ndbout << pTab->getName() << " fragmentType error "<< endl;
- result = NDBT_FAILED;
- goto drop_the_tab;
- }
-
- if (newTab.equal(*pTab3) == false){
- ndbout << "It was not equal" << endl;
- result = NDBT_FAILED;
- goto drop_the_tab;
- }
-
- do {
-
- HugoTransactions hugoTrans(*pTab3);
- UtilTransactions utilTrans(*pTab3);
- int count;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == records);
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
- CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == (records/2));
-
- // restart all
- ndbout << "Restarting cluster" << endl;
- CHECK(restarter.restartAll() == 0);
- int timeout = 120;
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- // Verify content
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == (records/2));
-
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records, 64) == 0);
-
- } while(false);
-
- drop_the_tab:
-
- // Try to drop table in db
- if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
- ndbout << pTab3->getName() << " could not be dropped"<< endl;
- result = NDBT_FAILED;
- }
-
- return result;
-}
-
-
-int runTestTemporaryTables(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- Ndb* pNdb = GETNDB(step);
- int i = 0;
- NdbRestarter restarter;
-
- const NdbDictionary::Table* pTab = ctx->getTab();
- ndbout << "|- " << pTab->getName() << endl;
-
- NdbDictionary::Table newTab(* pTab);
- // Set table as temporary
- newTab.setStoredTable(false);
-
- // Try to create table in db
- if (newTab.createTableInDb(pNdb) != 0){
- return NDBT_FAILED;
- }
-
- // Verify that table is in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
-
- if (pTab2->getStoredTable() != false){
- ndbout << pTab->getName() << " was not temporary in DB"<< endl;
- result = NDBT_FAILED;
- goto drop_the_tab;
- }
-
-
- while (i < loops && result == NDBT_OK){
- ndbout << i << ": ";
-
- HugoTransactions hugoTrans(*pTab2);
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
-
- int count = 0;
- UtilTransactions utilTrans(*pTab2);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == records);
-
- // restart all
- ndbout << "Restarting cluster" << endl;
- CHECK(restarter.restartAll() == 0);
- int timeout = 120;
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == 0);
-
- i++;
- }
-
- drop_the_tab:
-
-
- if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
- ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
- result = NDBT_FAILED;
- }
-
- // Verify that table is not in db
- const NdbDictionary::Table* pTab3 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab3 != NULL){
- ndbout << pTab3->getName() << " was found in DB"<< endl;
- result = NDBT_FAILED;
- }
-
- return result;
-}
-
-int runPkSizes(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- char tabName[256];
- int minPkSize = 1;
- ndbout << "minPkSize=" <<minPkSize<<endl;
- int maxPkSize = MAX_KEY_SIZE_IN_WORDS * 4;
- ndbout << "maxPkSize=" <<maxPkSize<<endl;
- Ndb* pNdb = GETNDB(step);
- int numRecords = ctx->getNumRecords();
-
- for (int i = minPkSize; i < maxPkSize; i++){
- snprintf(tabName, 256, "TPK_%d", i);
-
- int records = numRecords;
- int max = ~0;
- // Limit num records for small PKs
- if (i == 1)
- max = 99;
- if (i == 2)
- max = 999;
- if (i == 3)
- max = 9999;
- if (records > max)
- records = max;
- ndbout << "records =" << records << endl;
-
- if (pNdb->waitUntilReady(30) != 0){
- // Db is not ready, return with failure
- return NDBT_FAILED;
- }
-
- ndbout << "|- " << tabName << endl;
-
- if (NDBT_Tables::createTable(pNdb, tabName) != 0){
- ndbout << tabName << " could not be created"<< endl;
- return NDBT_FAILED;
- }
-
- // Verify that table exists in db
- const NdbDictionary::Table* pTab3 =
- NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
- if (pTab3 == NULL){
- g_err << tabName << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
-
- // ndbout << *pTab3 << endl;
-
- if (pTab3->equal(*NDBT_Tables::getTable(tabName)) == false){
- g_err << "It was not equal" << endl;
- return NDBT_FAILED;
- }
-
- do {
- // Do it all
- HugoTransactions hugoTrans(*pTab3);
- UtilTransactions utilTrans(*pTab3);
- int count;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == records);
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
- CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == (records/2));
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
-
-#if 0
- // Fill table
- CHECK(hugoTrans.fillTable(pNdb) == 0);
- CHECK(utilTrans.clearTable2(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == 0);
-#endif
- } while(false);
-
- // Drop table
- if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
- ndbout << "Failed to drop "<<pTab3->getName()<<" in db" << endl;
- return NDBT_FAILED;
- }
- }
- return result;
-}
-
-int runStoreFrm(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- const NdbDictionary::Table* pTab = ctx->getTab();
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
-
- for (int l = 0; l < loops && result == NDBT_OK ; l++){
-
- Uint32 dataLen = (Uint32)myRandom48(MAX_FRM_DATA_SIZE);
- // size_t dataLen = 10;
- unsigned char data[MAX_FRM_DATA_SIZE];
-
- char start = l + 248;
- for(Uint32 i = 0; i < dataLen; i++){
- data[i] = start;
- start++;
- }
-#if 0
- ndbout << "dataLen="<<dataLen<<endl;
- for (Uint32 i = 0; i < dataLen; i++){
- unsigned char c = data[i];
- ndbout << hex << c << ", ";
- }
- ndbout << endl;
-#endif
-
- NdbDictionary::Table newTab(* pTab);
- void* pData = &data;
- newTab.setFrm(pData, dataLen);
-
- // Try to create table in db
- if (newTab.createTableInDb(pNdb) != 0){
- result = NDBT_FAILED;
- continue;
- }
-
- // Verify that table is in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- g_err << pTab->getName() << " was not found in DB"<< endl;
- result = NDBT_FAILED;
- continue;
- }
-
- const void* pData2 = pTab2->getFrmData();
- Uint32 resultLen = pTab2->getFrmLength();
- if (dataLen != resultLen){
- g_err << "Length of data failure" << endl
- << " expected = " << dataLen << endl
- << " got = " << resultLen << endl;
- result = NDBT_FAILED;
- }
-
- // Verfiy the frm data
- if (memcmp(pData, pData2, resultLen) != 0){
- g_err << "Wrong data recieved" << endl;
- for (size_t i = 0; i < dataLen; i++){
- unsigned char c = ((unsigned char*)pData2)[i];
- g_err << hex << c << ", ";
- }
- g_err << endl;
- result = NDBT_FAILED;
- }
-
- if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
- g_err << "It can NOT be dropped" << endl;
- result = NDBT_FAILED;
- }
- }
-
- return result;
-}
-
-int runStoreFrmError(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- const NdbDictionary::Table* pTab = ctx->getTab();
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
-
- for (int l = 0; l < loops && result == NDBT_OK ; l++){
-
- const Uint32 dataLen = MAX_FRM_DATA_SIZE + 10;
- unsigned char data[dataLen];
-
- char start = l + 248;
- for(Uint32 i = 0; i < dataLen; i++){
- data[i] = start;
- start++;
- }
-#if 0
- ndbout << "dataLen="<<dataLen<<endl;
- for (Uint32 i = 0; i < dataLen; i++){
- unsigned char c = data[i];
- ndbout << hex << c << ", ";
- }
- ndbout << endl;
-#endif
-
- NdbDictionary::Table newTab(* pTab);
-
- void* pData = &data;
- newTab.setFrm(pData, dataLen);
-
- // Try to create table in db
- if (newTab.createTableInDb(pNdb) == 0){
- result = NDBT_FAILED;
- continue;
- }
-
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 != NULL){
- g_err << pTab->getName() << " was found in DB"<< endl;
- result = NDBT_FAILED;
- if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
- g_err << "It can NOT be dropped" << endl;
- result = NDBT_FAILED;
- }
-
- continue;
- }
-
- }
-
- return result;
-}
-
-int verifyTablesAreEqual(const NdbDictionary::Table* pTab, const NdbDictionary::Table* pTab2){
- // Verify that getPrimaryKey only returned true for primary keys
- for (int i = 0; i < pTab2->getNoOfColumns(); i++){
- const NdbDictionary::Column* col = pTab->getColumn(i);
- const NdbDictionary::Column* col2 = pTab2->getColumn(i);
- if (col->getPrimaryKey() != col2->getPrimaryKey()){
- g_err << "col->getPrimaryKey() != col2->getPrimaryKey()" << endl;
- return NDBT_FAILED;
- }
- }
-
- if (!pTab->equal(*pTab2)){
- g_err << "equal failed" << endl;
- g_info << *pTab;
- g_info << *pTab2;
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- const NdbDictionary::Table* pTab = ctx->getTab();
- ndbout << "|- " << pTab->getName() << endl;
- g_info << *pTab;
- // Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
- return NDBT_FAILED;
- }
-
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
-
- int result = NDBT_OK;
- if (verifyTablesAreEqual(pTab, pTab2) != NDBT_OK)
- result = NDBT_FAILED;
-
-
-#if 0
- // Create an index on the table and see what
- // the function returns now
- char name[200];
- sprintf(name, "%s_X007", pTab->getName());
- NDBT_Index* pInd = new NDBT_Index(name);
- pInd->setTable(pTab->getName());
- pInd->setType(NdbDictionary::Index::UniqueHashIndex);
- // pInd->setLogging(false);
- for (int i = 0; i < 2; i++){
- const NDBT_Attribute* pAttr = pTab->getAttribute(i);
- pInd->addAttribute(*pAttr);
- }
- g_info << "Create index:" << endl << *pInd;
- if (pInd->createIndexInDb(pNdb, false) != 0){
- result = NDBT_FAILED;
- }
- delete pInd;
-
- const NdbDictionary::Table* pTab3 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab3 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
-
- if (verifyTablesAreEqual(pTab, pTab3) != NDBT_OK)
- result = NDBT_FAILED;
- if (verifyTablesAreEqual(pTab2, pTab3) != NDBT_OK)
- result = NDBT_FAILED;
-#endif
-
-#if 0
- if (pTab2->getDictionary()->dropTable(pNdb) != 0){
- ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
- return NDBT_FAILED;
- }
-
- // Verify that table is not in db
- const NdbDictionary::Table* pTab4 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab4 != NULL){
- ndbout << pTab4->getName() << " was found in DB"<< endl;
- return NDBT_FAILED;
- }
-#endif
-
- return result;
-}
-
-int
-NF_codes[] = {
- 14000
- ,14001
- //,14002
-};
-
-int
-runNF1(NDBT_Context* ctx, NDBT_Step* step){
- NdbRestarter restarter;
- if(restarter.getNumDbNodes() < 2)
- return NDBT_OK;
-
- myRandom48Init(NdbTick_CurrentMillisecond());
-
- Ndb* pNdb = GETNDB(step);
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- NdbDictionary::Dictionary* dict = pNdb->getDictionary();
- dict->dropTable(pTab->getName());
-
- int result = NDBT_OK;
-
- /**
- * Need to run LCP at high rate otherwise
- * packed replicas become "to many"
- */
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- if(restarter.dumpStateAllNodes(&val, 1) != 0){
- do { CHECK(0); } while(0);
- g_err << "Failed to set LCP to min value" << endl;
- return NDBT_FAILED;
- }
-
- const int loops = ctx->getNumLoops();
- for (int l = 0; l < loops && result == NDBT_OK ; l++){
- const int sz = sizeof(NF_codes)/sizeof(NF_codes[0]);
- for(int i = 0; i<sz; i++){
- int rand = myRandom48(restarter.getNumDbNodes());
- int nodeId = restarter.getRandomNotMasterNodeId(rand);
- int error = NF_codes[i];
-
- g_info << "NF1: node = " << nodeId << " error code = " << error << endl;
-
- int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 3};
-
- CHECK2(restarter.dumpStateOneNode(nodeId, val2, 2) == 0,
- "failed to set RestartOnErrorInsert");
-
- CHECK2(restarter.insertErrorInNode(nodeId, error) == 0,
- "failed to set error insert");
-
- CHECK2(dict->createTable(* pTab) == 0,
- "failed to create table");
-
- CHECK2(restarter.waitNodesNoStart(&nodeId, 1) == 0,
- "waitNodesNoStart failed");
-
- if(myRandom48(100) > 50){
- CHECK2(restarter.startNodes(&nodeId, 1) == 0,
- "failed to start node");
-
- CHECK2(restarter.waitClusterStarted() == 0,
- "waitClusterStarted failed");
-
- CHECK2(dict->dropTable(pTab->getName()) == 0,
- "drop table failed");
- } else {
- CHECK2(dict->dropTable(pTab->getName()) == 0,
- "drop table failed");
-
- CHECK2(restarter.startNodes(&nodeId, 1) == 0,
- "failed to start node");
-
- CHECK2(restarter.waitClusterStarted() == 0,
- "waitClusterStarted failed");
- }
-
- CHECK2(restarter.dumpStateOneNode(nodeId, &val, 1) == 0,
- "Failed to set LCP to min value");
- }
- }
- end:
- dict->dropTable(pTab->getName());
-
- return result;
-}
-
-#define APIERROR(error) \
- { g_err << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
- << error.code << ", msg: " << error.message << "." << endl; \
- }
-
-int
-runCreateAutoincrementTable(NDBT_Context* ctx, NDBT_Step* step){
-
- Uint32 startvalues[5] = {256-2, 0, 256*256-2, ~0, 256*256*256-2};
-
- int ret = NDBT_OK;
-
- for (int jj = 0; jj < 5 && ret == NDBT_OK; jj++) {
- char tabname[] = "AUTOINCTAB";
- Uint32 startvalue = startvalues[jj];
-
- NdbDictionary::Table myTable;
- NdbDictionary::Column myColumn;
-
- Ndb* myNdb = GETNDB(step);
- NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
-
-
- if (myDict->getTable(tabname) != NULL) {
- g_err << "NDB already has example table: " << tabname << endl;
- APIERROR(myNdb->getNdbError());
- return NDBT_FAILED;
- }
-
- myTable.setName(tabname);
-
- myColumn.setName("ATTR1");
- myColumn.setPrimaryKey(true);
- myColumn.setType(NdbDictionary::Column::Unsigned);
- myColumn.setLength(1);
- myColumn.setNullable(false);
- myColumn.setAutoIncrement(true);
- if (startvalue != ~0) // check that default value starts with 1
- myColumn.setAutoIncrementInitialValue(startvalue);
- myTable.addColumn(myColumn);
-
- if (myDict->createTable(myTable) == -1) {
- g_err << "Failed to create table " << tabname << endl;
- APIERROR(myNdb->getNdbError());
- return NDBT_FAILED;
- }
-
-
- if (startvalue == ~0) // check that default value starts with 1
- startvalue = 1;
-
- for (int i = 0; i < 16; i++) {
-
- Uint64 value = myNdb->getAutoIncrementValue(tabname, 1);
-
- if (value != (startvalue+i)) {
- g_err << "value = " << value << " expected " << startvalue+i << endl;;
- APIERROR(myNdb->getNdbError());
- // ret = NDBT_FAILED;
- // break;
- }
- }
-
- if (myDict->dropTable(tabname) == -1) {
- g_err << "Failed to drop table " << tabname << endl;
- APIERROR(myNdb->getNdbError());
- ret = NDBT_FAILED;
- }
- }
-
- return ret;
-}
-
-int
-runTableRename(NDBT_Context* ctx, NDBT_Step* step){
-
- int result = NDBT_OK;
-
- Ndb* pNdb = GETNDB(step);
- NdbDictionary::Dictionary* dict = pNdb->getDictionary();
- int records = ctx->getNumRecords();
- const int loops = ctx->getNumLoops();
-
- ndbout << "|- " << ctx->getTab()->getName() << endl;
-
- for (int l = 0; l < loops && result == NDBT_OK ; l++){
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- // Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
- return NDBT_FAILED;
- }
-
- // Verify that table is in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
- ctx->setTab(pTab2);
-
- // Load table
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(pNdb, records) != 0){
- return NDBT_FAILED;
- }
-
- // Rename table
- BaseString pTabName(pTab->getName());
- BaseString pTabNewName(pTabName);
- pTabNewName.append("xx");
-
- const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
- if (oldTable) {
- NdbDictionary::Table newTable = dict->getTableForAlteration(pTabName.c_str());
- newTable.setName(pTabNewName.c_str());
- CHECK2(dict->alterTable(newTable) == 0,
- "TableRename failed");
- }
- else {
- result = NDBT_FAILED;
- }
-
- // Verify table contents
- NdbDictionary::Table pNewTab(pTabNewName.c_str());
-
- UtilTransactions utilTrans(pNewTab);
- if (utilTrans.clearTable(pNdb, records) != 0){
- continue;
- }
-
- // Drop table
- dict->dropTable(pNewTab.getName());
- }
- end:
-
- return result;
-}
-
-int
-runTableRenameNF(NDBT_Context* ctx, NDBT_Step* step){
- NdbRestarter restarter;
- if(restarter.getNumDbNodes() < 2)
- return NDBT_OK;
-
- int result = NDBT_OK;
-
- Ndb* pNdb = GETNDB(step);
- NdbDictionary::Dictionary* dict = pNdb->getDictionary();
- int records = ctx->getNumRecords();
- const int loops = ctx->getNumLoops();
-
- ndbout << "|- " << ctx->getTab()->getName() << endl;
-
- for (int l = 0; l < loops && result == NDBT_OK ; l++){
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- // Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
- return NDBT_FAILED;
- }
-
- // Verify that table is in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
- ctx->setTab(pTab2);
-
- // Load table
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(pNdb, records) != 0){
- return NDBT_FAILED;
- }
-
- BaseString pTabName(pTab->getName());
- BaseString pTabNewName(pTabName);
- pTabNewName.append("xx");
-
- const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
- if (oldTable) {
- NdbDictionary::Table newTable = dict->getTableForAlteration(pTabName.c_str());
- newTable.setName(pTabNewName.c_str());
- CHECK2(dict->alterTable(newTable) == 0,
- "TableRename failed");
- }
- else {
- result = NDBT_FAILED;
- }
-
- // Restart one node at a time
-
- /**
- * Need to run LCP at high rate otherwise
- * packed replicas become "to many"
- */
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- if(restarter.dumpStateAllNodes(&val, 1) != 0){
- do { CHECK(0); } while(0);
- g_err << "Failed to set LCP to min value" << endl;
- return NDBT_FAILED;
- }
-
- const int numNodes = restarter.getNumDbNodes();
- for(int i = 0; i<numNodes; i++){
- int nodeId = restarter.getDbNodeId(i);
- int error = NF_codes[i];
-
- g_info << "NF1: node = " << nodeId << " error code = " << error << endl;
-
- CHECK2(restarter.restartOneDbNode(nodeId) == 0,
- "failed to set restartOneDbNode");
-
- CHECK2(restarter.waitClusterStarted() == 0,
- "waitClusterStarted failed");
-
- }
-
- // Verify table contents
- NdbDictionary::Table pNewTab(pTabNewName.c_str());
-
- UtilTransactions utilTrans(pNewTab);
- if (utilTrans.clearTable(pNdb, records) != 0){
- continue;
- }
-
- // Drop table
- dict->dropTable(pTabNewName.c_str());
- }
- end:
- return result;
-}
-
-int
-runTableRenameSR(NDBT_Context* ctx, NDBT_Step* step){
- NdbRestarter restarter;
- if(restarter.getNumDbNodes() < 2)
- return NDBT_OK;
-
- int result = NDBT_OK;
-
- Ndb* pNdb = GETNDB(step);
- NdbDictionary::Dictionary* dict = pNdb->getDictionary();
- int records = ctx->getNumRecords();
- const int loops = ctx->getNumLoops();
-
- ndbout << "|- " << ctx->getTab()->getName() << endl;
-
- for (int l = 0; l < loops && result == NDBT_OK ; l++){
- // Rename table
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- // Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
- return NDBT_FAILED;
- }
-
- // Verify that table is in db
- const NdbDictionary::Table* pTab2 =
- NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
- if (pTab2 == NULL){
- ndbout << pTab->getName() << " was not found in DB"<< endl;
- return NDBT_FAILED;
- }
- ctx->setTab(pTab2);
-
- // Load table
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(pNdb, records) != 0){
- return NDBT_FAILED;
- }
-
- BaseString pTabName(pTab->getName());
- BaseString pTabNewName(pTabName);
- pTabNewName.append("xx");
-
- const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
- if (oldTable) {
- NdbDictionary::Table newTable = dict->getTableForAlteration(pTabName.c_str());
- newTable.setName(pTabNewName.c_str());
- CHECK2(dict->alterTable(newTable) == 0,
- "TableRename failed");
- }
- else {
- result = NDBT_FAILED;
- }
-
- // Restart cluster
-
- /**
- * Need to run LCP at high rate otherwise
- * packed replicas become "to many"
- */
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- if(restarter.dumpStateAllNodes(&val, 1) != 0){
- do { CHECK(0); } while(0);
- g_err << "Failed to set LCP to min value" << endl;
- return NDBT_FAILED;
- }
-
- CHECK2(restarter.restartAll() == 0,
- "failed to set restartOneDbNode");
-
- CHECK2(restarter.waitClusterStarted() == 0,
- "waitClusterStarted failed");
-
- // Verify table contents
- NdbDictionary::Table pNewTab(pTabNewName.c_str());
-
- UtilTransactions utilTrans(pNewTab);
- if (utilTrans.clearTable(pNdb, records) != 0){
- continue;
- }
-
- // Drop table
- dict->dropTable(pTabNewName.c_str());
- }
- end:
- return result;
-}
-
-static void
-f(const NdbDictionary::Column * col){
- if(col == 0){
- abort();
- }
-}
-
-int
-runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
- Vector<char*> cols;
- Vector<const NdbDictionary::Table*> tabs;
-
- Ndb* pNdb = GETNDB(step);
-
- const Uint32 count = NDBT_Tables::getNumTables();
- for (int i=0; i < count; i++){
- const NdbDictionary::Table * tab = NDBT_Tables::getTable(i);
- pNdb->getDictionary()->createTable(* tab);
-
- const NdbDictionary::Table * tab2 = pNdb->getDictionary()->getTable(tab->getName());
-
- for(size_t j = 0; j<tab->getNoOfColumns(); j++){
- cols.push_back((char*)tab2);
- cols.push_back(strdup(tab->getColumn(j)->getName()));
- }
- }
-
- const Uint32 times = 10000000;
-
- ndbout_c("%d tables and %d columns",
- NDBT_Tables::getNumTables(), cols.size()/2);
-
- char ** tcols = cols.getBase();
-
- srand(time(0));
- Uint32 size = cols.size() / 2;
- char ** columns = &cols[0];
- Uint64 start = NdbTick_CurrentMillisecond();
- for(int i = 0; i<times; i++){
- int j = 2 * (rand() % size);
- const NdbDictionary::Table* tab = (const NdbDictionary::Table*)tcols[j];
- const char * col = tcols[j+1];
- const NdbDictionary::Column* column = tab->getColumn(col);
- f(column);
- }
- Uint64 stop = NdbTick_CurrentMillisecond();
- stop -= start;
-
- Uint64 per = stop;
- per *= 1000;
- per /= times;
-
- ndbout_c("%d random getColumn(name) in %Ld ms -> %d us/get",
- times, stop, per);
-
- return NDBT_OK;
-}
-
-NDBT_TESTSUITE(testDict);
-TESTCASE("CreateAndDrop",
- "Try to create and drop the table loop number of times\n"){
- INITIALIZER(runCreateAndDrop);
-}
-TESTCASE("CreateAndDropWithData",
- "Try to create and drop the table when it's filled with data\n"
- "do this loop number of times\n"){
- INITIALIZER(runCreateAndDropWithData);
-}
-TESTCASE("CreateAndDropDuring",
- "Try to create and drop the table when other thread is using it\n"
- "do this loop number of times\n"){
- STEP(runCreateAndDropDuring);
- STEP(runUseTableUntilStopped);
-}
-TESTCASE("CreateInvalidTables",
- "Try to create the invalid tables we have defined\n"){
- INITIALIZER(runCreateInvalidTables);
-}
-TESTCASE("CreateTableWhenDbIsFull",
- "Try to create a new table when db already is full\n"){
- INITIALIZER(runCreateTheTable);
- INITIALIZER(runFillTable);
- INITIALIZER(runCreateTableWhenDbIsFull);
- INITIALIZER(runDropTableWhenDbIsFull);
- FINALIZER(runClearTable);
-}
-TESTCASE("FragmentTypeSingle",
- "Create the table with fragment type Single\n"){
- TC_PROPERTY("FragmentType", 1);
- INITIALIZER(runTestFragmentTypes);
-}
-TESTCASE("FragmentTypeAll",
- "Create the table with fragment type All\n"){
- TC_PROPERTY("FragmentType", 2);
- INITIALIZER(runTestFragmentTypes);
-}
-TESTCASE("FragmentTypeAllLarge",
- "Create the table with fragment type AllLarge\n"){
- TC_PROPERTY("FragmentType", 3);
- INITIALIZER(runTestFragmentTypes);
-}
-TESTCASE("TemporaryTables",
- "Create the table as temporary and make sure it doesn't\n"
- "contain any data when system is restarted\n"){
- INITIALIZER(runTestTemporaryTables);
-}
-TESTCASE("CreateMaxTables",
- "Create tables until db says that it can't create any more\n"){
- TC_PROPERTY("tables", 1000);
- INITIALIZER(runCreateMaxTables);
- FINALIZER(runDropMaxTables);
-}
-TESTCASE("PkSizes",
- "Create tables with all different primary key sizes.\n"\
- "Test all data operations insert, update, delete etc.\n"\
- "Drop table."){
- INITIALIZER(runPkSizes);
-}
-TESTCASE("StoreFrm",
- "Test that a frm file can be properly stored as part of the\n"
- "data in Dict."){
- INITIALIZER(runStoreFrm);
-}
-TESTCASE("GetPrimaryKey",
- "Test the function NdbDictionary::Column::getPrimaryKey\n"
- "It should return true only if the column is part of \n"
- "the primary key in the table"){
- INITIALIZER(runGetPrimaryKey);
-}
-TESTCASE("StoreFrmError",
- "Test that a frm file with too long length can't be stored."){
- INITIALIZER(runStoreFrmError);
-}
-TESTCASE("NF1",
- "Test that create table can handle NF (not master)"){
- INITIALIZER(runNF1);
-}
-TESTCASE("TableRename",
- "Test basic table rename"){
- INITIALIZER(runTableRename);
-}
-TESTCASE("TableRenameNF",
- "Test that table rename can handle node failure"){
- INITIALIZER(runTableRenameNF);
-}
-TESTCASE("TableRenameSR",
- "Test that table rename can handle system restart"){
- INITIALIZER(runTableRenameSR);
-}
-TESTCASE("DictionaryPerf",
- ""){
- INITIALIZER(runTestDictionaryPerf);
-}
-NDBT_TESTSUITE_END(testDict);
-
-int main(int argc, const char** argv){
- // Tables should not be auto created
- testDict.setCreateTable(false);
- myRandom48Init(NdbTick_CurrentMillisecond());
- return testDict.execute(argc, argv);
-}
-
-
diff --git a/ndb/test/ndbapi/testGrep/testGrep.cpp b/ndb/test/ndbapi/testGrep.cpp
index 4b870f6f9a9..4b870f6f9a9 100644
--- a/ndb/test/ndbapi/testGrep/testGrep.cpp
+++ b/ndb/test/ndbapi/testGrep.cpp
diff --git a/ndb/test/ndbapi/testGrep/verify/testGrepVerify.cpp b/ndb/test/ndbapi/testGrep/verify/testGrepVerify.cpp
deleted file mode 100644
index 7fd2c19d9f7..00000000000
--- a/ndb/test/ndbapi/testGrep/verify/testGrepVerify.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include "mgmapi.h"
-#include <string.h>
-#include <NdbMain.h>
-#include <OutputStream.hpp>
-#include <NdbOut.hpp>
-#include <NdbSleep.h>
-#include <getarg.h>
-
-#include <NdbApi.hpp>
-#include <NDBT.hpp>
-
-#include <NDBT_Test.hpp>
-#include <HugoTransactions.hpp>
-#include <UtilTransactions.hpp>
-#include <ConfigRetriever.hpp>
-#include <ndb_version.h>
-
-
-#define CHECK(b) if (!(b)) { \
- g_err << "ERR: "<< "getStep" \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- continue; }
-
-int main(int argc, const char** argv){
-
-
- const char * connectString = NULL;
- const char * table = NULL;
- int records = 0;
- int _help = 0;
-
- struct getargs args[] = {
- { "connectString", 'c', arg_string, &connectString,
- "ConnectString", "nodeid=<api id>;host=<hostname:port>" },
- { "tableName", 't', arg_string, &table,
- "table", "Table" },
- { "records", 'r', arg_integer, &records, "Number of records", "recs"},
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "hostname:port\n"\
- "This program will connect to the mgmsrv of a NDB cluster.\n"\
- "It will then wait for all nodes to be started, then restart node(s)\n"\
- "and wait for all to restart inbetween. It will do this \n"\
- "loop number of times\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
- ndbout_c("table %s connectStirng %s", table, connectString);
- if(connectString == 0)
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- if(table == 0)
- return NDBT_ProgramExit(NDBT_WRONGARGS);
-
- Ndb::useFullyQualifiedNames(false);
-
- Ndb * m_ndb = new Ndb("");
- m_ndb->setConnectString(connectString);
- Ndb::useFullyQualifiedNames(false);
- /**
- * @todo Set proper max no of transactions?? needed?? Default 12??
- */
- m_ndb->init(2048);
- Ndb::useFullyQualifiedNames(false);
- if (m_ndb->waitUntilReady() != 0){
- ndbout_c("NDB Cluster not ready for connections");
- }
-
- int count = 0;
- int result = NDBT_OK;
-
-
- const NdbDictionary::Table * tab = NDBT_Table::discoverTableFromDb( m_ndb, table);
-// ndbout << *tab << endl;
-
- UtilTransactions utilTrans(*tab);
- HugoTransactions hugoTrans(*tab);
-
- do{
-
- // Check that there are as many records as we expected
- CHECK(utilTrans.selectCount(m_ndb, 64, &count) == 0);
-
- g_err << "count = " << count;
- g_err << " records = " << records;
- g_err << endl;
-
- CHECK(count == records);
-
- // Read and verify every record
- CHECK(hugoTrans.pkReadRecords(m_ndb, records) == 0);
-
- } while (false);
-
-
- return NDBT_ProgramExit(result);
-
-}
diff --git a/ndb/test/ndbapi/testGrepVerify.cpp b/ndb/test/ndbapi/testGrepVerify.cpp
new file mode 100644
index 00000000000..05445c1ba1b
--- /dev/null
+++ b/ndb/test/ndbapi/testGrepVerify.cpp
@@ -0,0 +1,117 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include "mgmapi.h"
+#include <string.h>
+#include <NdbMain.h>
+#include <OutputStream.hpp>
+#include <NdbOut.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+
+#include <NdbApi.hpp>
+#include <NDBT.hpp>
+
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <ConfigRetriever.hpp>
+#include <ndb_version.h>
+
+
+#define CHECK(b) if (!(b)) { \
+ g_err << "ERR: "<< "getStep" \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ continue; }
+
+int main(int argc, const char** argv){
+
+
+ const char * connectString = NULL;
+ const char * table = NULL;
+ int records = 0;
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "connectString", 'c', arg_string, &connectString,
+ "ConnectString", "nodeid=<api id>;host=<hostname:port>" },
+ { "tableName", 't', arg_string, &table,
+ "table", "Table" },
+ { "records", 'r', arg_integer, &records, "Number of records", "recs"},
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "hostname:port\n"\
+ "This program will connect to the mgmsrv of a NDB cluster.\n"\
+ "It will then wait for all nodes to be started, then restart node(s)\n"\
+ "and wait for all to restart inbetween. It will do this \n"\
+ "loop number of times\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ ndbout_c("table %s connectStirng %s", table, connectString);
+ if(connectString == 0)
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ if(table == 0)
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+
+ Ndb * m_ndb = new Ndb("");
+ m_ndb->useFullyQualifiedNames(false);
+ m_ndb->setConnectString(connectString);
+ /**
+ * @todo Set proper max no of transactions?? needed?? Default 12??
+ */
+ m_ndb->init(2048);
+ if (m_ndb->waitUntilReady() != 0){
+ ndbout_c("NDB Cluster not ready for connections");
+ }
+
+ int count = 0;
+ int result = NDBT_OK;
+
+
+ const NdbDictionary::Table * tab = NDBT_Table::discoverTableFromDb( m_ndb, table);
+// ndbout << *tab << endl;
+
+ UtilTransactions utilTrans(*tab);
+ HugoTransactions hugoTrans(*tab);
+
+ do{
+
+ // Check that there are as many records as we expected
+ CHECK(utilTrans.selectCount(m_ndb, 64, &count) == 0);
+
+ g_err << "count = " << count;
+ g_err << " records = " << records;
+ g_err << endl;
+
+ CHECK(count == records);
+
+ // Read and verify every record
+ CHECK(hugoTrans.pkReadRecords(m_ndb, records) == 0);
+
+ } while (false);
+
+
+ return NDBT_ProgramExit(result);
+
+}
diff --git a/ndb/test/ndbapi/testIndex/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp
index 47db0b3cff7..47db0b3cff7 100644
--- a/ndb/test/ndbapi/testIndex/testIndex.cpp
+++ b/ndb/test/ndbapi/testIndex.cpp
diff --git a/ndb/test/ndbapi/testInterpreter/testInterpreter.cpp b/ndb/test/ndbapi/testInterpreter.cpp
index 9c584d6f581..9c584d6f581 100644
--- a/ndb/test/ndbapi/testInterpreter/testInterpreter.cpp
+++ b/ndb/test/ndbapi/testInterpreter.cpp
diff --git a/ndb/test/ndbapi/testMgm/testMgm.cpp b/ndb/test/ndbapi/testMgm.cpp
index d5b9372cc9b..d5b9372cc9b 100644
--- a/ndb/test/ndbapi/testMgm/testMgm.cpp
+++ b/ndb/test/ndbapi/testMgm.cpp
diff --git a/ndb/test/ndbapi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi.cpp
new file mode 100644
index 00000000000..2e08ebbed4e
--- /dev/null
+++ b/ndb/test/ndbapi/testNdbApi.cpp
@@ -0,0 +1,1013 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbRestarter.hpp>
+#include <NdbRestarts.hpp>
+#include <Vector.hpp>
+#include <random.h>
+#include <NdbTick.h>
+
+#define MAX_NDB_OBJECTS 32678
+
+#define CHECK(b) if (!(b)) { \
+ ndbout << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ continue; }
+
+#define CHECKE(b) if (!(b)) { \
+ errors++; \
+ ndbout << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ continue; }
+
+
+int runTestMaxNdb(NDBT_Context* ctx, NDBT_Step* step){
+ Uint32 loops = ctx->getNumLoops();
+ Uint32 l = 0;
+ int oldi = 0;
+ int result = NDBT_OK;
+
+ while (l < loops && result == NDBT_OK){
+ ndbout_c("loop %d", l + 1);
+ int errors = 0;
+ int maxErrors = 5;
+
+ Vector<Ndb*> ndbVector;
+ int i = 0;
+ int init = 0;
+ do {
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ errors++;
+ continue;
+
+ }
+ i++;
+
+ ndbVector.push_back(pNdb);
+
+ if (pNdb->init()){
+ ERR(pNdb->getNdbError());
+ errors++;
+ continue;
+ }
+
+ init++;
+
+ } while (errors == 0);
+
+ ndbout << i << " ndb objects created" << endl;
+
+ if (l > 0 && i != oldi && init != MAX_NDB_OBJECTS){
+ ndbout << l << ": not as manyNdb objects created" << endl
+ << i << " != " << oldi << endl;
+ result = NDBT_FAILED;
+ }
+
+ oldi = i;
+
+
+ for(size_t i = 0; i < ndbVector.size(); i++){
+ delete ndbVector[i];
+ if(((i+1) % 250) == 0){
+ ndbout << "Deleted " << (Uint64) i << " ndb objects " << endl;
+ }
+ }
+ ndbVector.clear();
+
+ l++;
+ }
+
+ return result;
+}
+
+int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){
+ Uint32 loops = ctx->getNumLoops();
+ Uint32 l = 0;
+ int oldi = 0;
+ int result = NDBT_OK;
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init(2048)){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ while (l < loops && result == NDBT_OK){
+ int errors = 0;
+ int maxErrors = 5;
+
+ Vector<NdbConnection*> conVector;
+
+
+ int i = 0;
+ do {
+
+ NdbConnection* pCon;
+
+ int type = i%4;
+ switch (type){
+ case 0:
+ pCon = pNdb->startTransaction();
+ break;
+ case 1:
+ pCon = pNdb->startTransaction(2,
+ "DATA",
+ 4);
+ break;
+ case 2:
+ pCon = pNdb->startTransactionDGroup(1,
+ "TEST",
+ 0);
+ break;
+ case 3:
+ pCon = pNdb->startTransactionDGroup(2,
+ "TEST",
+ 1);
+ break;
+
+ default:
+ abort();
+ }
+
+ if (pCon == NULL){
+ ERR(pNdb->getNdbError());
+ errors++;
+ continue;
+ }
+
+ conVector.push_back(pCon);
+
+ i++;
+ } while (errors < maxErrors);
+
+ ndbout << i << " connections created" << endl;
+
+ if (l > 0 && i != oldi){
+ ndbout << l << ": not as many transactions created" << endl
+ << i << " != " << oldi << endl;
+ result = NDBT_FAILED;
+ }
+
+ oldi = i;
+
+
+ for(size_t i = 0; i < conVector.size(); i++){
+ pNdb->closeTransaction(conVector[i]);
+ }
+ conVector.clear();
+ l++;
+
+ }
+
+ // BONUS Test closeTransaction with null trans
+ pNdb->closeTransaction(NULL);
+
+ delete pNdb;
+
+
+ return result;
+}
+
+int runTestMaxOperations(NDBT_Context* ctx, NDBT_Step* step){
+ Uint32 l = 1;
+ int result = NDBT_OK;
+ int maxOpsLimit = 1;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init(2048)){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ HugoOperations hugoOps(*pTab);
+
+ bool endTest = false;
+ while (!endTest && result == NDBT_OK){
+ int errors = 0;
+ int maxErrors = 5;
+
+ maxOpsLimit = l*1000;
+
+ if (hugoOps.startTransaction(pNdb) != NDBT_OK){
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ int i = 0;
+ while (errors < maxErrors){
+
+ if(hugoOps.pkReadRecord(pNdb,1, false, 1) != NDBT_OK){
+ errors++;
+ continue;
+ }
+
+ i++;
+
+ if (i >= maxOpsLimit){
+ errors = maxErrors;
+ }
+
+ }
+
+ ndbout << i << " operations used" << endl;
+
+ int execResult = hugoOps.execute_Commit(pNdb);
+ switch(execResult){
+ case NDBT_OK:
+ break;
+ case 233: // Out of operation records in transaction coordinator
+ // OK - end test
+ endTest = true;
+ break;
+ default:
+ result = NDBT_FAILED;
+ break;
+ }
+
+ hugoOps.closeTransaction(pNdb);
+
+ l++;
+
+ }
+
+ delete pNdb;
+
+ return result;
+}
+
+int runTestGetValue(NDBT_Context* ctx, NDBT_Step* step){
+
+ int result = NDBT_OK;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init(2048)){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ HugoOperations hugoOps(*pTab);
+
+ for (int m = 1; m < 100; m++){
+ int errors = 0;
+ int maxErrors = 5;
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
+ if (pOp == NULL){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ if (pOp->readTuple() != 0){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ if (pTab->getColumn(a)->getPrimaryKey() == true){
+ if(hugoOps.equalForAttr(pOp, a, 1) != 0){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+ }
+ }
+
+ int i = 0;
+ int maxLimit = 1000*m;
+ do {
+
+ if (pOp->getValue(pTab->getColumn(1)->getName()) == NULL) {
+ const NdbError err = pCon->getNdbError();
+ ERR(err);
+ if (err.code == 0)
+ result = NDBT_FAILED;
+ errors++;
+ continue;
+ }
+
+ i++;
+
+ } while (errors < maxErrors && i < maxLimit);
+
+ ndbout << i << " getValues called" << endl;
+
+
+ if (pCon->execute(Commit) != 0){
+ const NdbError err = pCon->getNdbError();
+ switch(err.code){
+ case 880: // TUP - Read too much
+ case 823: // TUP - Too much AI
+ case 4257: // NDBAPI - Too much AI
+ // OK errors
+ ERR(pCon->getNdbError());
+ break;
+ default:
+ ERR(pCon->getNdbError());
+ ndbout << "Illegal error" << endl;
+ result= NDBT_FAILED;
+ break;
+ }
+ }
+
+ pNdb->closeTransaction(pCon);
+
+ }// m
+
+
+ delete pNdb;
+
+ return result;
+}
+
+int runTestEqual(NDBT_Context* ctx, NDBT_Step* step){
+ Uint32 loops = ctx->getNumLoops();
+ Uint32 l = 0;
+ int result = NDBT_OK;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init(2048)){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ HugoOperations hugoOps(*pTab);
+
+ while (l < loops){
+ for(int m = 1; m < 10; m++){
+ int errors = 0;
+ int maxErrors = 5;
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ ndbout << "Could not start transaction" << endl;
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
+ if (pOp == NULL){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ if (pOp->readTuple() != 0){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ int i = 0;
+ int maxLimit = 1000*m;
+ do {
+
+ if ((l%2)!=0){
+ // Forward
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ if (pTab->getColumn(a)->getPrimaryKey() == true){
+ if(hugoOps.equalForAttr(pOp, a, 1) != 0){
+ const NdbError err = pCon->getNdbError();
+ ERR(err);
+ if (err.code == 0)
+ result = NDBT_FAILED;
+ errors++;
+ }
+ }
+ }
+ } else {
+ // Backward
+ for(int a = pTab->getNoOfColumns()-1; a>=0; a--){
+ if (pTab->getColumn(a)->getPrimaryKey() == true){
+ if(hugoOps.equalForAttr(pOp, a, 1) != 0){
+ const NdbError err = pCon->getNdbError();
+ ERR(err);
+ if (err.code == 0)
+ result = NDBT_FAILED;
+ errors++;
+ }
+ }
+ }
+ }
+
+ i++;
+
+ } while (errors < maxErrors && i < maxLimit);
+
+ if (pOp->getValue(pTab->getColumn(1)->getName()) == NULL) {
+ const NdbError err = pCon->getNdbError();
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ if (err.code == 4225) {
+ return NDBT_OK;
+ } else {
+ return NDBT_FAILED;
+ }//if
+ }
+
+ ndbout << i << " equal called" << endl;
+
+
+ int check = pCon->execute(Commit);
+ if (check != 0){
+ ERR(pCon->getNdbError());
+ }
+
+ pNdb->closeTransaction(pCon);
+
+ }// m
+ l++;
+
+ }// l
+
+ delete pNdb;
+ return result;
+}
+
+int runTestDeleteNdb(NDBT_Context* ctx, NDBT_Step* step){
+ Uint32 loops = ctx->getNumLoops();
+ Uint32 l = 0;
+ int result = NDBT_OK;
+ NdbRestarts restarts;
+ Vector<Ndb*> ndbVector;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ HugoTransactions hugoTrans(*pTab);
+ int records = ctx->getNumRecords();
+
+ while (l < loops && result == NDBT_OK){
+
+ // Create 5 ndb objects
+ for( int i = 0; i < 5; i++){
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ result = NDBT_FAILED;
+ goto end_test;
+ }
+ ndbVector.push_back(pNdb);
+
+ if (pNdb->init()){
+ ERR(pNdb->getNdbError());
+ result = NDBT_FAILED;
+ goto end_test;
+ }
+ if (pNdb->waitUntilReady() != 0){
+ ERR(pNdb->getNdbError());
+ result = NDBT_FAILED;
+ goto end_test;
+ }
+ if (hugoTrans.pkReadRecords(pNdb, records) != 0){
+ result = NDBT_FAILED;
+ goto end_test;
+ }
+ }
+
+ if ((l % 2) == 0){
+ // Restart random node
+ ndbout << "Restart random node " << endl;
+ if(restarts.executeRestart("RestartRandomNodeAbort", 120) != 0){
+ g_err << "Failed to executeRestart(RestartRandomNode)"<<endl;
+ result = NDBT_FAILED;
+ goto end_test;
+ }
+ } else {
+ // Restart all nodes
+ ndbout << "Restart all nodes " << endl;
+ if(restarts.executeRestart("RestartAllNodesAbort", 120) != 0){
+ g_err << "Failed to executeRestart(RestartAllNodes)"<<endl;
+ result = NDBT_FAILED;
+ goto end_test;
+ }
+ }
+
+ // Delete the ndb objects
+ for(size_t i = 0; i < ndbVector.size(); i++)
+ delete ndbVector[i];
+ ndbVector.clear();
+ l++;
+ }
+
+
+ end_test:
+
+ for(size_t i = 0; i < ndbVector.size(); i++)
+ delete ndbVector[i];
+ ndbVector.clear();
+
+ return result;
+}
+
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable2(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runTestWaitUntilReady(NDBT_Context* ctx, NDBT_Step* step){
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+
+ // Forget about calling pNdb->init();
+
+ if (pNdb->waitUntilReady() == 0){
+ ndbout << "waitUntilReady returned OK" << endl;
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+ const NdbError err = pNdb->getNdbError();
+ delete pNdb;
+
+ ERR(err);
+ if (err.code != 4256)
+ return NDBT_FAILED;
+
+ return NDBT_OK;
+}
+
+int runGetNdbOperationNoTab(NDBT_Context* ctx, NDBT_Step* step){
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init()){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // Call getNdbOperation on an unknown table
+ NdbOperation* pOp = pCon->getNdbOperation("HUPP76");
+ if (pOp == NULL){
+ NdbError err = pCon->getNdbError();
+ ERR(err);
+ if (err.code == 0){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+ }
+
+ pNdb->closeTransaction(pCon);
+
+ delete pNdb;
+
+ return NDBT_OK;
+}
+
+int runMissingOperation(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init()){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
+ if (pOp == NULL){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // Forget about calling pOp->insertTuple();
+
+ // Call getValue should not work
+ if (pOp->getValue(pTab->getColumn(1)->getName()) == NULL) {
+ const NdbError err = pCon->getNdbError();
+ ERR(err);
+ if (err.code == 0){
+ ndbout << "hupp" << endl;
+ result = NDBT_FAILED;
+ }
+ } else {
+ ndbout << "hupp2" << endl;
+ result = NDBT_FAILED;
+ }
+
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+
+ return result;
+}
+
+int runGetValueInUpdate(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init()){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
+ if (pOp == NULL){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ if (pOp->updateTuple() != 0){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // Call getValue should not work
+ if (pOp->getValue(pTab->getColumn(1)->getName()) == NULL) {
+ // It didn't work
+ const NdbError err = pCon->getNdbError();
+ ERR(err);
+ if (err.code == 0){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+ } else {
+ // It worked, not good!
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ int check = pCon->execute(Commit);
+ if (check != 0){
+ ERR(pCon->getNdbError());
+ }
+
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+
+ return NDBT_OK;
+}
+
+int runUpdateWithoutValues(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ HugoOperations hugoOps(*pTab);
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init()){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
+ if (pOp == NULL){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ if (pOp->updateTuple() != 0){
+ pNdb->closeTransaction(pCon);
+ ERR(pOp->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ if (pTab->getColumn(a)->getPrimaryKey() == true){
+ if(hugoOps.equalForAttr(pOp, a, 1) != 0){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+ }
+ }
+
+ // Dont' call any setValues
+
+ // Execute should not work
+ int check = pCon->execute(Commit);
+ if (check == 0){
+ ndbout << "execute worked" << endl;
+ result = NDBT_FAILED;
+ } else {
+ ERR(pCon->getNdbError());
+ }
+
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+
+ return result;
+}
+
+int runUpdateWithoutKeys(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init()){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
+ if (pOp == NULL){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ if (pOp->updateTuple() != 0){
+ pNdb->closeTransaction(pCon);
+ ERR(pOp->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // Dont' call any equal or setValues
+
+ // Execute should not work
+ int check = pCon->execute(Commit);
+ if (check == 0){
+ ndbout << "execute worked" << endl;
+ result = NDBT_FAILED;
+ } else {
+ ERR(pCon->getNdbError());
+ }
+
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+
+ return result;
+}
+
+int runCheckGetNdbErrorOperation(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ Ndb* pNdb = new Ndb("TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init(2048)){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ HugoOperations hugoOps(*pTab);
+
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ ndbout << "Could not start transaction" << endl;
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
+ if (pOp == NULL){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // Dont call readTuple here
+ // That's the error!
+
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ if (pTab->getColumn(a)->getPrimaryKey() == true){
+ if(hugoOps.equalForAttr(pOp, a, 1) != 0){
+ // An error has occured, check that
+ // it's possible to get the NdbErrorOperation
+ const NdbError err = pCon->getNdbError();
+ ERR(err);
+ if (err.code == 0)
+ result = NDBT_FAILED;
+
+ NdbOperation* pOp2 = pCon->getNdbErrorOperation();
+ if (pOp2 == NULL)
+ result = NDBT_FAILED;
+ else {
+ const NdbError err2 = pOp2->getNdbError();
+ ERR(err2);
+ if (err.code == 0)
+ result = NDBT_FAILED;
+ }
+ }
+ }
+ }
+
+ pNdb->closeTransaction(pCon);
+
+ delete pNdb;
+ return result;
+}
+
+
+NDBT_TESTSUITE(testNdbApi);
+TESTCASE("MaxNdb",
+ "Create Ndb objects until no more can be created\n"){
+ INITIALIZER(runTestMaxNdb);
+}
+TESTCASE("MaxTransactions",
+ "Start transactions until no more can be created\n"){
+ INITIALIZER(runTestMaxTransaction);
+}
+TESTCASE("MaxOperations",
+ "Get operations until no more can be created\n"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runTestMaxOperations);
+ FINALIZER(runClearTable);
+}
+TESTCASE("MaxGetValue",
+ "Call getValue loads of time\n"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runTestGetValue);
+ FINALIZER(runClearTable);
+}
+TESTCASE("MaxEqual",
+ "Call equal loads of time\n"){
+ INITIALIZER(runTestEqual);
+}
+TESTCASE("DeleteNdb",
+ "Make sure that a deleted Ndb object is properly deleted\n"
+ "and removed from transporter\n"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runTestDeleteNdb);
+ FINALIZER(runClearTable);
+}
+TESTCASE("WaitUntilReady",
+ "Make sure you get an error message when calling waitUntilReady\n"
+ "without an init'ed Ndb\n"){
+ INITIALIZER(runTestWaitUntilReady);
+}
+TESTCASE("GetOperationNoTab",
+ "Call getNdbOperation on a table that does not exist\n"){
+ INITIALIZER(runGetNdbOperationNoTab);
+}
+TESTCASE("MissingOperation",
+ "Missing operation request(insertTuple) should give an error code\n"){
+ INITIALIZER(runMissingOperation);
+}
+TESTCASE("GetValueInUpdate",
+ "Test that it's not possible to perform getValue in an update\n"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runGetValueInUpdate);
+ FINALIZER(runClearTable);
+}
+TESTCASE("UpdateWithoutKeys",
+ "Test that it's not possible to perform update without setting\n"
+ "PKs"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runUpdateWithoutKeys);
+ FINALIZER(runClearTable);
+}
+TESTCASE("UpdateWithoutValues",
+ "Test that it's not possible to perform update without setValues\n"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runUpdateWithoutValues);
+ FINALIZER(runClearTable);
+}
+TESTCASE("NdbErrorOperation",
+ "Test that NdbErrorOperation is properly set"){
+ INITIALIZER(runCheckGetNdbErrorOperation);
+}
+NDBT_TESTSUITE_END(testNdbApi);
+
+int main(int argc, const char** argv){
+ // TABLE("T1");
+ return testNdbApi.execute(argc, argv);
+}
+
+
diff --git a/ndb/test/ndbapi/testNdbApi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi/testNdbApi.cpp
deleted file mode 100644
index c0e262f590f..00000000000
--- a/ndb/test/ndbapi/testNdbApi/testNdbApi.cpp
+++ /dev/null
@@ -1,1013 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NDBT.hpp>
-#include <NDBT_Test.hpp>
-#include <HugoTransactions.hpp>
-#include <UtilTransactions.hpp>
-#include <NdbRestarter.hpp>
-#include <NdbRestarts.hpp>
-#include <Vector.hpp>
-#include <random.h>
-#include <NdbTick.h>
-#include <AttrType.hpp>
-
-
-#define CHECK(b) if (!(b)) { \
- ndbout << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- continue; }
-
-#define CHECKE(b) if (!(b)) { \
- errors++; \
- ndbout << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- continue; }
-
-
-int runTestMaxNdb(NDBT_Context* ctx, NDBT_Step* step){
- Uint32 loops = ctx->getNumLoops();
- Uint32 l = 0;
- int oldi = 0;
- int result = NDBT_OK;
-
- while (l < loops && result == NDBT_OK){
- ndbout_c("loop %d", l + 1);
- int errors = 0;
- int maxErrors = 5;
-
- Vector<Ndb*> ndbVector;
- int i = 0;
- int init = 0;
- do {
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- errors++;
- continue;
-
- }
- i++;
-
- ndbVector.push_back(pNdb);
-
- if (pNdb->init()){
- ERR(pNdb->getNdbError());
- errors++;
- continue;
- }
-
- init++;
-
- } while (errors == 0);
-
- ndbout << i << " ndb objects created" << endl;
-
- if (l > 0 && i != oldi && init != MAX_NO_THREADS){
- ndbout << l << ": not as manyNdb objects created" << endl
- << i << " != " << oldi << endl;
- result = NDBT_FAILED;
- }
-
- oldi = i;
-
-
- for(size_t i = 0; i < ndbVector.size(); i++){
- delete ndbVector[i];
- if(((i+1) % 250) == 0){
- ndbout << "Deleted " << (Uint64) i << " ndb objects " << endl;
- }
- }
- ndbVector.clear();
-
- l++;
- }
-
- return result;
-}
-
-int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){
- Uint32 loops = ctx->getNumLoops();
- Uint32 l = 0;
- int oldi = 0;
- int result = NDBT_OK;
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init(2048)){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- while (l < loops && result == NDBT_OK){
- int errors = 0;
- int maxErrors = 5;
-
- Vector<NdbConnection*> conVector;
-
-
- int i = 0;
- do {
-
- NdbConnection* pCon;
-
- int type = i%4;
- switch (type){
- case 0:
- pCon = pNdb->startTransaction();
- break;
- case 1:
- pCon = pNdb->startTransaction(2,
- "DATA",
- 4);
- break;
- case 2:
- pCon = pNdb->startTransactionDGroup(1,
- "TEST",
- 0);
- break;
- case 3:
- pCon = pNdb->startTransactionDGroup(2,
- "TEST",
- 1);
- break;
-
- default:
- abort();
- }
-
- if (pCon == NULL){
- ERR(pNdb->getNdbError());
- errors++;
- continue;
- }
-
- conVector.push_back(pCon);
-
- i++;
- } while (errors < maxErrors);
-
- ndbout << i << " connections created" << endl;
-
- if (l > 0 && i != oldi){
- ndbout << l << ": not as many transactions created" << endl
- << i << " != " << oldi << endl;
- result = NDBT_FAILED;
- }
-
- oldi = i;
-
-
- for(size_t i = 0; i < conVector.size(); i++){
- pNdb->closeTransaction(conVector[i]);
- }
- conVector.clear();
- l++;
-
- }
-
- // BONUS Test closeTransaction with null trans
- pNdb->closeTransaction(NULL);
-
- delete pNdb;
-
-
- return result;
-}
-
-int runTestMaxOperations(NDBT_Context* ctx, NDBT_Step* step){
- Uint32 l = 1;
- int result = NDBT_OK;
- int maxOpsLimit = 1;
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init(2048)){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- HugoOperations hugoOps(*pTab);
-
- bool endTest = false;
- while (!endTest && result == NDBT_OK){
- int errors = 0;
- int maxErrors = 5;
-
- maxOpsLimit = l*1000;
-
- if (hugoOps.startTransaction(pNdb) != NDBT_OK){
- delete pNdb;
- return NDBT_FAILED;
- }
-
- int i = 0;
- while (errors < maxErrors){
-
- if(hugoOps.pkReadRecord(pNdb,1, false, 1) != NDBT_OK){
- errors++;
- continue;
- }
-
- i++;
-
- if (i >= maxOpsLimit){
- errors = maxErrors;
- }
-
- }
-
- ndbout << i << " operations used" << endl;
-
- int execResult = hugoOps.execute_Commit(pNdb);
- switch(execResult){
- case NDBT_OK:
- break;
- case 233: // Out of operation records in transaction coordinator
- // OK - end test
- endTest = true;
- break;
- default:
- result = NDBT_FAILED;
- break;
- }
-
- hugoOps.closeTransaction(pNdb);
-
- l++;
-
- }
-
- delete pNdb;
-
- return result;
-}
-
-int runTestGetValue(NDBT_Context* ctx, NDBT_Step* step){
-
- int result = NDBT_OK;
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init(2048)){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- HugoOperations hugoOps(*pTab);
-
- for (int m = 1; m < 100; m++){
- int errors = 0;
- int maxErrors = 5;
-
- NdbConnection* pCon = pNdb->startTransaction();
- if (pCon == NULL){
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
- if (pOp == NULL){
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- if (pOp->readTuple() != 0){
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- for(int a = 0; a<pTab->getNoOfColumns(); a++){
- if (pTab->getColumn(a)->getPrimaryKey() == true){
- if(hugoOps.equalForAttr(pOp, a, 1) != 0){
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
- }
- }
-
- int i = 0;
- int maxLimit = 1000*m;
- do {
-
- if (pOp->getValue(pTab->getColumn(1)->getName()) == NULL) {
- const NdbError err = pCon->getNdbError();
- ERR(err);
- if (err.code == 0)
- result = NDBT_FAILED;
- errors++;
- continue;
- }
-
- i++;
-
- } while (errors < maxErrors && i < maxLimit);
-
- ndbout << i << " getValues called" << endl;
-
-
- if (pCon->execute(Commit) != 0){
- const NdbError err = pCon->getNdbError();
- switch(err.code){
- case 880: // TUP - Read too much
- case 823: // TUP - Too much AI
- case 4257: // NDBAPI - Too much AI
- // OK errors
- ERR(pCon->getNdbError());
- break;
- default:
- ERR(pCon->getNdbError());
- ndbout << "Illegal error" << endl;
- result= NDBT_FAILED;
- break;
- }
- }
-
- pNdb->closeTransaction(pCon);
-
- }// m
-
-
- delete pNdb;
-
- return result;
-}
-
-int runTestEqual(NDBT_Context* ctx, NDBT_Step* step){
- Uint32 loops = ctx->getNumLoops();
- Uint32 l = 0;
- int result = NDBT_OK;
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init(2048)){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- HugoOperations hugoOps(*pTab);
-
- while (l < loops){
- for(int m = 1; m < 10; m++){
- int errors = 0;
- int maxErrors = 5;
-
- NdbConnection* pCon = pNdb->startTransaction();
- if (pCon == NULL){
- ndbout << "Could not start transaction" << endl;
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
- if (pOp == NULL){
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- if (pOp->readTuple() != 0){
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- int i = 0;
- int maxLimit = 1000*m;
- do {
-
- if ((l%2)!=0){
- // Forward
- for(int a = 0; a<pTab->getNoOfColumns(); a++){
- if (pTab->getColumn(a)->getPrimaryKey() == true){
- if(hugoOps.equalForAttr(pOp, a, 1) != 0){
- const NdbError err = pCon->getNdbError();
- ERR(err);
- if (err.code == 0)
- result = NDBT_FAILED;
- errors++;
- }
- }
- }
- } else {
- // Backward
- for(int a = pTab->getNoOfColumns()-1; a>=0; a--){
- if (pTab->getColumn(a)->getPrimaryKey() == true){
- if(hugoOps.equalForAttr(pOp, a, 1) != 0){
- const NdbError err = pCon->getNdbError();
- ERR(err);
- if (err.code == 0)
- result = NDBT_FAILED;
- errors++;
- }
- }
- }
- }
-
- i++;
-
- } while (errors < maxErrors && i < maxLimit);
-
- if (pOp->getValue(pTab->getColumn(1)->getName()) == NULL) {
- const NdbError err = pCon->getNdbError();
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- if (err.code == 4225) {
- return NDBT_OK;
- } else {
- return NDBT_FAILED;
- }//if
- }
-
- ndbout << i << " equal called" << endl;
-
-
- int check = pCon->execute(Commit);
- if (check != 0){
- ERR(pCon->getNdbError());
- }
-
- pNdb->closeTransaction(pCon);
-
- }// m
- l++;
-
- }// l
-
- delete pNdb;
- return result;
-}
-
-int runTestDeleteNdb(NDBT_Context* ctx, NDBT_Step* step){
- Uint32 loops = ctx->getNumLoops();
- Uint32 l = 0;
- int result = NDBT_OK;
- NdbRestarts restarts;
- Vector<Ndb*> ndbVector;
- const NdbDictionary::Table* pTab = ctx->getTab();
- HugoTransactions hugoTrans(*pTab);
- int records = ctx->getNumRecords();
-
- while (l < loops && result == NDBT_OK){
-
- // Create 5 ndb objects
- for( int i = 0; i < 5; i++){
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- result = NDBT_FAILED;
- goto end_test;
- }
- ndbVector.push_back(pNdb);
-
- if (pNdb->init()){
- ERR(pNdb->getNdbError());
- result = NDBT_FAILED;
- goto end_test;
- }
- if (pNdb->waitUntilReady() != 0){
- ERR(pNdb->getNdbError());
- result = NDBT_FAILED;
- goto end_test;
- }
- if (hugoTrans.pkReadRecords(pNdb, records) != 0){
- result = NDBT_FAILED;
- goto end_test;
- }
- }
-
- if ((l % 2) == 0){
- // Restart random node
- ndbout << "Restart random node " << endl;
- if(restarts.executeRestart("RestartRandomNodeAbort", 120) != 0){
- g_err << "Failed to executeRestart(RestartRandomNode)"<<endl;
- result = NDBT_FAILED;
- goto end_test;
- }
- } else {
- // Restart all nodes
- ndbout << "Restart all nodes " << endl;
- if(restarts.executeRestart("RestartAllNodesAbort", 120) != 0){
- g_err << "Failed to executeRestart(RestartAllNodes)"<<endl;
- result = NDBT_FAILED;
- goto end_test;
- }
- }
-
- // Delete the ndb objects
- for(size_t i = 0; i < ndbVector.size(); i++)
- delete ndbVector[i];
- ndbVector.clear();
- l++;
- }
-
-
- end_test:
-
- for(size_t i = 0; i < ndbVector.size(); i++)
- delete ndbVector[i];
- ndbVector.clear();
-
- return result;
-}
-
-
-int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
-
- UtilTransactions utilTrans(*ctx->getTab());
- if (utilTrans.clearTable2(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
-
- int records = ctx->getNumRecords();
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runTestWaitUntilReady(NDBT_Context* ctx, NDBT_Step* step){
-
- Ndb* pNdb = new Ndb("TEST_DB");
-
- // Forget about calling pNdb->init();
-
- if (pNdb->waitUntilReady() == 0){
- ndbout << "waitUntilReady returned OK" << endl;
- delete pNdb;
- return NDBT_FAILED;
- }
- const NdbError err = pNdb->getNdbError();
- delete pNdb;
-
- ERR(err);
- if (err.code != 4256)
- return NDBT_FAILED;
-
- return NDBT_OK;
-}
-
-int runGetNdbOperationNoTab(NDBT_Context* ctx, NDBT_Step* step){
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init()){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbConnection* pCon = pNdb->startTransaction();
- if (pCon == NULL){
- delete pNdb;
- return NDBT_FAILED;
- }
-
- // Call getNdbOperation on an unknown table
- NdbOperation* pOp = pCon->getNdbOperation("HUPP76");
- if (pOp == NULL){
- NdbError err = pCon->getNdbError();
- ERR(err);
- if (err.code == 0){
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
- }
-
- pNdb->closeTransaction(pCon);
-
- delete pNdb;
-
- return NDBT_OK;
-}
-
-int runMissingOperation(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- const NdbDictionary::Table* pTab = ctx->getTab();
-
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init()){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbConnection* pCon = pNdb->startTransaction();
- if (pCon == NULL){
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
- if (pOp == NULL){
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- // Forget about calling pOp->insertTuple();
-
- // Call getValue should not work
- if (pOp->getValue(pTab->getColumn(1)->getName()) == NULL) {
- const NdbError err = pCon->getNdbError();
- ERR(err);
- if (err.code == 0){
- ndbout << "hupp" << endl;
- result = NDBT_FAILED;
- }
- } else {
- ndbout << "hupp2" << endl;
- result = NDBT_FAILED;
- }
-
- pNdb->closeTransaction(pCon);
- delete pNdb;
-
- return result;
-}
-
-int runGetValueInUpdate(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init()){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbConnection* pCon = pNdb->startTransaction();
- if (pCon == NULL){
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
- if (pOp == NULL){
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- if (pOp->updateTuple() != 0){
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- // Call getValue should not work
- if (pOp->getValue(pTab->getColumn(1)->getName()) == NULL) {
- // It didn't work
- const NdbError err = pCon->getNdbError();
- ERR(err);
- if (err.code == 0){
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
- } else {
- // It worked, not good!
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- int check = pCon->execute(Commit);
- if (check != 0){
- ERR(pCon->getNdbError());
- }
-
- pNdb->closeTransaction(pCon);
- delete pNdb;
-
- return NDBT_OK;
-}
-
-int runUpdateWithoutValues(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- HugoOperations hugoOps(*pTab);
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init()){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbConnection* pCon = pNdb->startTransaction();
- if (pCon == NULL){
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
- if (pOp == NULL){
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- if (pOp->updateTuple() != 0){
- pNdb->closeTransaction(pCon);
- ERR(pOp->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- for(int a = 0; a<pTab->getNoOfColumns(); a++){
- if (pTab->getColumn(a)->getPrimaryKey() == true){
- if(hugoOps.equalForAttr(pOp, a, 1) != 0){
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
- }
- }
-
- // Dont' call any setValues
-
- // Execute should not work
- int check = pCon->execute(Commit);
- if (check == 0){
- ndbout << "execute worked" << endl;
- result = NDBT_FAILED;
- } else {
- ERR(pCon->getNdbError());
- }
-
- pNdb->closeTransaction(pCon);
- delete pNdb;
-
- return result;
-}
-
-int runUpdateWithoutKeys(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- const NdbDictionary::Table* pTab = ctx->getTab();
-
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init()){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbConnection* pCon = pNdb->startTransaction();
- if (pCon == NULL){
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
- if (pOp == NULL){
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- if (pOp->updateTuple() != 0){
- pNdb->closeTransaction(pCon);
- ERR(pOp->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- // Dont' call any equal or setValues
-
- // Execute should not work
- int check = pCon->execute(Commit);
- if (check == 0){
- ndbout << "execute worked" << endl;
- result = NDBT_FAILED;
- } else {
- ERR(pCon->getNdbError());
- }
-
- pNdb->closeTransaction(pCon);
- delete pNdb;
-
- return result;
-}
-
-int runCheckGetNdbErrorOperation(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- const NdbDictionary::Table* pTab = ctx->getTab();
-
- Ndb* pNdb = new Ndb("TEST_DB");
- if (pNdb == NULL){
- ndbout << "pNdb == NULL" << endl;
- return NDBT_FAILED;
- }
- if (pNdb->init(2048)){
- ERR(pNdb->getNdbError());
- delete pNdb;
- return NDBT_FAILED;
- }
-
- HugoOperations hugoOps(*pTab);
-
-
- NdbConnection* pCon = pNdb->startTransaction();
- if (pCon == NULL){
- ndbout << "Could not start transaction" << endl;
- delete pNdb;
- return NDBT_FAILED;
- }
-
- NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
- if (pOp == NULL){
- ERR(pCon->getNdbError());
- pNdb->closeTransaction(pCon);
- delete pNdb;
- return NDBT_FAILED;
- }
-
- // Dont call readTuple here
- // That's the error!
-
- for(int a = 0; a<pTab->getNoOfColumns(); a++){
- if (pTab->getColumn(a)->getPrimaryKey() == true){
- if(hugoOps.equalForAttr(pOp, a, 1) != 0){
- // An error has occured, check that
- // it's possible to get the NdbErrorOperation
- const NdbError err = pCon->getNdbError();
- ERR(err);
- if (err.code == 0)
- result = NDBT_FAILED;
-
- NdbOperation* pOp2 = pCon->getNdbErrorOperation();
- if (pOp2 == NULL)
- result = NDBT_FAILED;
- else {
- const NdbError err2 = pOp2->getNdbError();
- ERR(err2);
- if (err.code == 0)
- result = NDBT_FAILED;
- }
- }
- }
- }
-
- pNdb->closeTransaction(pCon);
-
- delete pNdb;
- return result;
-}
-
-
-NDBT_TESTSUITE(testNdbApi);
-TESTCASE("MaxNdb",
- "Create Ndb objects until no more can be created\n"){
- INITIALIZER(runTestMaxNdb);
-}
-TESTCASE("MaxTransactions",
- "Start transactions until no more can be created\n"){
- INITIALIZER(runTestMaxTransaction);
-}
-TESTCASE("MaxOperations",
- "Get operations until no more can be created\n"){
- INITIALIZER(runLoadTable);
- INITIALIZER(runTestMaxOperations);
- FINALIZER(runClearTable);
-}
-TESTCASE("MaxGetValue",
- "Call getValue loads of time\n"){
- INITIALIZER(runLoadTable);
- INITIALIZER(runTestGetValue);
- FINALIZER(runClearTable);
-}
-TESTCASE("MaxEqual",
- "Call equal loads of time\n"){
- INITIALIZER(runTestEqual);
-}
-TESTCASE("DeleteNdb",
- "Make sure that a deleted Ndb object is properly deleted\n"
- "and removed from transporter\n"){
- INITIALIZER(runLoadTable);
- INITIALIZER(runTestDeleteNdb);
- FINALIZER(runClearTable);
-}
-TESTCASE("WaitUntilReady",
- "Make sure you get an error message when calling waitUntilReady\n"
- "without an init'ed Ndb\n"){
- INITIALIZER(runTestWaitUntilReady);
-}
-TESTCASE("GetOperationNoTab",
- "Call getNdbOperation on a table that does not exist\n"){
- INITIALIZER(runGetNdbOperationNoTab);
-}
-TESTCASE("MissingOperation",
- "Missing operation request(insertTuple) should give an error code\n"){
- INITIALIZER(runMissingOperation);
-}
-TESTCASE("GetValueInUpdate",
- "Test that it's not possible to perform getValue in an update\n"){
- INITIALIZER(runLoadTable);
- INITIALIZER(runGetValueInUpdate);
- FINALIZER(runClearTable);
-}
-TESTCASE("UpdateWithoutKeys",
- "Test that it's not possible to perform update without setting\n"
- "PKs"){
- INITIALIZER(runLoadTable);
- INITIALIZER(runUpdateWithoutKeys);
- FINALIZER(runClearTable);
-}
-TESTCASE("UpdateWithoutValues",
- "Test that it's not possible to perform update without setValues\n"){
- INITIALIZER(runLoadTable);
- INITIALIZER(runUpdateWithoutValues);
- FINALIZER(runClearTable);
-}
-TESTCASE("NdbErrorOperation",
- "Test that NdbErrorOperation is properly set"){
- INITIALIZER(runCheckGetNdbErrorOperation);
-}
-NDBT_TESTSUITE_END(testNdbApi);
-
-int main(int argc, const char** argv){
- // TABLE("T1");
- return testNdbApi.execute(argc, argv);
-}
-
-
diff --git a/ndb/test/ndbapi/testNodeRestart/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp
index fd591f04c69..fd591f04c69 100644
--- a/ndb/test/ndbapi/testNodeRestart/testNodeRestart.cpp
+++ b/ndb/test/ndbapi/testNodeRestart.cpp
diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp
new file mode 100644
index 00000000000..0ca8ce79e2e
--- /dev/null
+++ b/ndb/test/ndbapi/testOIBasic.cpp
@@ -0,0 +1,2808 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ * testOIBasic - ordered index test
+ */
+
+#include <ndb_global.h>
+
+#include <NdbMain.h>
+#include <NdbOut.hpp>
+#include <NdbApi.hpp>
+#include <NdbTest.hpp>
+#include <NdbMutex.h>
+#include <NdbCondition.h>
+#include <NdbThread.h>
+#include <NdbTick.h>
+
+// options
+
+struct Opt {
+ // common options
+ const char* m_case;
+ bool m_core;
+ bool m_dups;
+ NdbDictionary::Object::FragmentType m_fragtype;
+ const char* m_index;
+ unsigned m_loop;
+ bool m_nologging;
+ unsigned m_rows;
+ unsigned m_scanrd;
+ unsigned m_scanex;
+ unsigned m_seed;
+ unsigned m_subloop;
+ const char* m_table;
+ unsigned m_threads;
+ unsigned m_v;
+ Opt() :
+ m_case(0),
+ m_core(false),
+ m_dups(false),
+ m_fragtype(NdbDictionary::Object::FragUndefined),
+ m_index(0),
+ m_loop(1),
+ m_nologging(false),
+ m_rows(1000),
+ m_scanrd(240),
+ m_scanex(240),
+ m_seed(1),
+ m_subloop(4),
+ m_table(0),
+ m_threads(4),
+ m_v(1) {
+ }
+};
+
+static Opt g_opt;
+
+static void printcases();
+static void printtables();
+
+static void
+printhelp()
+{
+ Opt d;
+ ndbout
+ << "usage: testOIbasic [options]" << endl
+ << " -case abc only given test cases (letters a-z)" << endl
+ << " -core core dump on error [" << d.m_core << "]" << endl
+ << " -dups allow duplicate tuples from index scan [" << d.m_dups << "]" << endl
+ << " -fragtype T fragment type single/small/medium/large" << endl
+ << " -index xyz only given index numbers (digits 1-9)" << endl
+ << " -loop N loop count full suite forever=0 [" << d.m_loop << "]" << endl
+ << " -nologging create tables in no-logging mode" << endl
+ << " -rows N rows per thread [" << d.m_rows << "]" << endl
+ << " -scanrd N scan read parallelism [" << d.m_scanrd << "]" << endl
+ << " -scanex N scan exclusive parallelism [" << d.m_scanex << "]" << endl
+ << " -seed N srandom seed [" << d.m_seed << "]" << endl
+ << " -subloop N subtest loop count [" << d.m_subloop << "]" << endl
+ << " -table xyz only given table numbers (digits 1-9)" << endl
+ << " -threads N number of threads [" << d.m_threads << "]" << endl
+ << " -vN verbosity [" << d.m_v << "]" << endl
+ << " -h or -help print this help text" << endl
+ ;
+ printcases();
+ printtables();
+}
+
+// log and error macros
+
+static NdbMutex ndbout_mutex = NDB_MUTEX_INITIALIZER;
+
+static unsigned getthrno();
+
+static const char*
+getthrstr()
+{
+ static char buf[20];
+ unsigned n = getthrno();
+ if (n == (unsigned)-1)
+ strcpy(buf, "");
+ else {
+ unsigned m =
+ g_opt.m_threads < 10 ? 1 :
+ g_opt.m_threads < 100 ? 2 : 3;
+ sprintf(buf, "[%0*u] ", m, n);
+ }
+ return buf;
+}
+
+#define LLN(n, s) \
+ do { \
+ if ((n) > g_opt.m_v) break; \
+ NdbMutex_Lock(&ndbout_mutex); \
+ ndbout << getthrstr() << s << endl; \
+ NdbMutex_Unlock(&ndbout_mutex); \
+ } while(0)
+
+#define LL0(s) LLN(0, s)
+#define LL1(s) LLN(1, s)
+#define LL2(s) LLN(2, s)
+#define LL3(s) LLN(3, s)
+#define LL4(s) LLN(4, s)
+#define LL5(s) LLN(5, s)
+
+// following check a condition and return -1 on failure
+
+#undef CHK // simple check
+#undef CHKTRY // execute action (try-catch) on failure
+#undef CHKMSG // print extra message on failure
+#undef CHKCON // print NDB API errors on failure
+
+#define CHK(x) CHKTRY(x, ;)
+
+#define CHKTRY(x, act) \
+ do { \
+ if (x) break; \
+ LL0("line " << __LINE__ << ": " << #x << " failed"); \
+ if (g_opt.m_core) abort(); \
+ act; \
+ return -1; \
+ } while (0)
+
+#define CHKMSG(x, msg) \
+ do { \
+ if (x) break; \
+ LL0("line " << __LINE__ << ": " << #x << " failed: " << msg); \
+ if (g_opt.m_core) abort(); \
+ return -1; \
+ } while (0)
+
+#define CHKCON(x, con) \
+ do { \
+ if (x) break; \
+ LL0("line " << __LINE__ << ": " << #x << " failed"); \
+ (con).printerror(ndbout); \
+ if (g_opt.m_core) abort(); \
+ return -1; \
+ } while (0)
+
+// method parameters base class
+
+class Thr;
+class Con;
+class Tab;
+class Set;
+
+struct Par : public Opt {
+ unsigned m_no;
+ Con* m_con;
+ Con& con() const { assert(m_con != 0); return *m_con; }
+ const Tab* m_tab;
+ const Tab& tab() const { assert(m_tab != 0); return *m_tab; }
+ Set* m_set;
+ Set& set() const { assert(m_set != 0); return *m_set; }
+ unsigned m_totrows;
+ unsigned m_batch;
+ // value calculation
+ unsigned m_pctnull;
+ unsigned m_range;
+ unsigned m_pctrange;
+ // do verify after read
+ bool m_verify;
+ // timer location
+ Par(const Opt& opt) :
+ Opt(opt),
+ m_no(0),
+ m_con(0),
+ m_tab(0),
+ m_set(0),
+ m_totrows(m_threads * m_rows),
+ m_batch(32),
+ m_pctnull(10),
+ m_range(m_rows),
+ m_pctrange(0),
+ m_verify(false) {
+ }
+};
+
+static bool
+usetable(unsigned i)
+{
+ return g_opt.m_table == 0 || strchr(g_opt.m_table, '1' + i) != 0;
+}
+
+static bool
+useindex(unsigned i)
+{
+ return g_opt.m_index == 0 || strchr(g_opt.m_index, '1' + i) != 0;
+}
+
+static unsigned
+thrrow(Par par, unsigned j)
+{
+ return par.m_threads * j + par.m_no;
+}
+
+static bool
+isthrrow(Par par, unsigned i)
+{
+ return i % par.m_threads == par.m_no;
+}
+
+// timer
+
+struct Tmr {
+ void clr();
+ void on();
+ void off(unsigned cnt = 0);
+ const char* time();
+ const char* over(const Tmr& t1);
+ NDB_TICKS m_on;
+ unsigned m_ms;
+ unsigned m_cnt;
+ char m_time[100];
+ char m_over[100];
+ Tmr() { clr(); }
+};
+
+void
+Tmr::clr()
+{
+ m_on = m_ms = m_cnt = m_time[0] = m_over[0] = 0;
+}
+
+void
+Tmr::on()
+{
+ assert(m_on == 0);
+ m_on = NdbTick_CurrentMillisecond();
+}
+
+void
+Tmr::off(unsigned cnt)
+{
+ NDB_TICKS off = NdbTick_CurrentMillisecond();
+ assert(m_on != 0 && off >= m_on);
+ m_ms += off - m_on;
+ m_cnt += cnt;
+ m_on = 0;
+}
+
+const char*
+Tmr::time()
+{
+ if (m_cnt == 0) {
+ sprintf(m_time, "%u ms", m_ms);
+ } else {
+ sprintf(m_time, "%u ms per %u ( %u ms per 1000 )", m_ms, m_cnt, (1000 * m_ms) / m_cnt);
+ }
+ return m_time;
+}
+
+const char*
+Tmr::over(const Tmr& t1)
+{
+ if (0 < t1.m_ms && t1.m_ms < m_ms) {
+ sprintf(m_over, "%u pct", (100 * (m_ms - t1.m_ms)) / t1.m_ms);
+ } else {
+ sprintf(m_over, "[cannot measure]");
+ }
+ return m_over;
+}
+
+// tables and indexes
+
+// Col - table column
+
+struct Col {
+ unsigned m_num;
+ const char* m_name;
+ bool m_pk;
+ NdbDictionary::Column::Type m_type;
+ unsigned m_length;
+ bool m_nullable;
+ void verify(const void* addr) const;
+};
+
+void
+Col::verify(const void* addr) const
+{
+ switch (m_type) {
+ case NdbDictionary::Column::Unsigned:
+ break;
+ case NdbDictionary::Column::Varchar:
+ {
+ const unsigned char* p = (const unsigned char*)addr;
+ unsigned n = (p[0] << 8) | p[1];
+ assert(n <= m_length);
+ for (unsigned i = 0; i < n; i++) {
+ assert(p[2 + i] != 0);
+ }
+ for (unsigned i = n; i < m_length; i++) {
+ assert(p[2 + i] == 0);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ break;
+ }
+}
+
+static NdbOut&
+operator<<(NdbOut& out, const Col& col)
+{
+ out << "col " << col.m_num;
+ out << " " << col.m_name;
+ switch (col.m_type) {
+ case NdbDictionary::Column::Unsigned:
+ out << " unsigned";
+ break;
+ case NdbDictionary::Column::Varchar:
+ out << " varchar(" << col.m_length << ")";
+ break;
+ default:
+ out << "type" << (int)col.m_type;
+ assert(false);
+ break;
+ }
+ out << (col.m_pk ? " pk" : "");
+ out << (col.m_nullable ? " nullable" : "");
+ return out;
+}
+
+// ICol - index column
+
+struct ICol {
+ unsigned m_num;
+ struct Col m_col;
+};
+
+// ITab - index
+
+struct ITab {
+ const char* m_name;
+ unsigned m_icols;
+ const ICol* m_icol;
+};
+
+static NdbOut&
+operator<<(NdbOut& out, const ITab& itab)
+{
+ out << "itab " << itab.m_name << " " << itab.m_icols;
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ out << endl;
+ out << "icol " << k << " " << itab.m_icol[k].m_col;
+ }
+ return out;
+}
+
+// Tab - table
+
+struct Tab {
+ const char* m_name;
+ unsigned m_cols;
+ const Col* m_col;
+ unsigned m_itabs;
+ const ITab* m_itab;
+};
+
+static NdbOut&
+operator<<(NdbOut& out, const Tab& tab)
+{
+ out << "tab " << tab.m_name << " " << tab.m_cols;
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ out << endl;
+ out << tab.m_col[k];
+ }
+ for (unsigned i = 0; i < tab.m_itabs; i++) {
+ if (! useindex(i))
+ continue;
+ out << endl;
+ out << tab.m_itab[i];
+ }
+ return out;
+}
+
+// tt1 + tt1x1 tt1x2 tt1x3 tt1x4
+
+static const Col
+tt1col[] = {
+ { 0, "A", 1, NdbDictionary::Column::Unsigned, 1, 0 },
+ { 1, "B", 0, NdbDictionary::Column::Unsigned, 1, 1 },
+ { 2, "C", 0, NdbDictionary::Column::Unsigned, 1, 1 },
+ { 3, "D", 0, NdbDictionary::Column::Unsigned, 1, 1 },
+ { 4, "E", 0, NdbDictionary::Column::Unsigned, 1, 1 }
+};
+
+static const ICol
+tt1x1col[] = {
+ { 0, tt1col[1] }
+};
+
+static const ICol
+tt1x2col[] = {
+ { 0, tt1col[1] },
+ { 1, tt1col[2] }
+};
+
+static const ICol
+tt1x3col[] = {
+ { 0, tt1col[3] },
+ { 1, tt1col[2] },
+ { 2, tt1col[1] }
+};
+
+static const ICol
+tt1x4col[] = {
+ { 0, tt1col[1] },
+ { 1, tt1col[4] },
+ { 2, tt1col[2] },
+ { 3, tt1col[3] }
+};
+
+static const ITab
+tt1x1 = {
+ "TT1X1", 1, tt1x1col
+};
+
+static const ITab
+tt1x2 = {
+ "TT1X2", 2, tt1x2col
+};
+
+static const ITab
+tt1x3 = {
+ "TT1X3", 3, tt1x3col
+};
+
+static const ITab
+tt1x4 = {
+ "TT1X4", 4, tt1x4col
+};
+
+static const ITab
+tt1itab[] = {
+ tt1x1,
+ tt1x2,
+ tt1x3,
+ tt1x4
+};
+
+static const Tab
+tt1 = {
+ "TT1", 5, tt1col, 4, tt1itab
+};
+
+// tt2 + tt2x1 tt2x2 tt2x3 tt2x4
+
+static const Col
+tt2col[] = {
+ { 0, "A", 1, NdbDictionary::Column::Unsigned, 1, 0 },
+ { 1, "B", 0, NdbDictionary::Column::Unsigned, 1, 1 },
+ { 2, "C", 0, NdbDictionary::Column::Varchar, 20, 1 },
+ { 3, "D", 0, NdbDictionary::Column::Varchar, 5, 1 },
+ { 4, "E", 0, NdbDictionary::Column::Varchar, 5, 1 }
+};
+
+static const ICol
+tt2x1col[] = {
+ { 0, tt2col[1] },
+ { 1, tt2col[2] }
+};
+
+static const ICol
+tt2x2col[] = {
+ { 0, tt2col[2] },
+ { 1, tt2col[1] }
+};
+
+static const ICol
+tt2x3col[] = {
+ { 0, tt2col[3] },
+ { 1, tt2col[4] }
+};
+
+static const ICol
+tt2x4col[] = {
+ { 0, tt2col[4] },
+ { 1, tt2col[3] },
+ { 2, tt2col[2] },
+ { 3, tt2col[1] }
+};
+
+static const ITab
+tt2x1 = {
+ "TT2X1", 2, tt2x1col
+};
+
+static const ITab
+tt2x2 = {
+ "TT2X2", 2, tt2x2col
+};
+
+static const ITab
+tt2x3 = {
+ "TT2X3", 2, tt2x3col
+};
+
+static const ITab
+tt2x4 = {
+ "TT2X4", 4, tt2x4col
+};
+
+static const ITab
+tt2itab[] = {
+ tt2x1,
+ tt2x2,
+ tt2x3,
+ tt2x4
+};
+
+static const Tab
+tt2 = {
+ "TT2", 5, tt2col, 4, tt2itab
+};
+
+// all tables
+
+static const Tab
+tablist[] = {
+ tt1,
+ tt2
+};
+
+static const unsigned
+tabcount = sizeof(tablist) / sizeof(tablist[0]);
+
+// connections
+
+struct Con {
+ Ndb* m_ndb;
+ NdbDictionary::Dictionary* m_dic;
+ NdbConnection* m_tx;
+ NdbOperation* m_op;
+ NdbConnection* m_scantx;
+ NdbOperation* m_scanop;
+ enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive };
+ ScanMode m_scanmode;
+ enum ErrType { ErrNone = 0, ErrDeadlock, ErrOther };
+ ErrType m_errtype;
+ Con() :
+ m_ndb(0), m_dic(0), m_tx(0), m_op(0),
+ m_scantx(0), m_scanop(0), m_scanmode(ScanNo), m_errtype(ErrNone) {}
+ int connect();
+ void disconnect();
+ int startTransaction();
+ int startBuddyTransaction(const Con& con);
+ int getNdbOperation(const Tab& tab);
+ int getNdbOperation(const ITab& itab, const Tab& tab);
+ int equal(int num, const char* addr);
+ int getValue(int num, NdbRecAttr*& rec);
+ int setValue(int num, const char* addr);
+ int setBound(int num, int type, const void* value);
+ int execute(ExecType t);
+ int openScanRead(unsigned parallelism);
+ int openScanExclusive(unsigned parallelism);
+ int executeScan();
+ int nextScanResult();
+ int takeOverForUpdate(Con& scan);
+ int takeOverForDelete(Con& scan);
+ void closeTransaction();
+ void printerror(NdbOut& out);
+ // flush dict cache
+ int bugger() {
+ //disconnect();
+ //CHK(connect() == 0);
+ return 0;
+ }
+};
+
+int
+Con::connect()
+{
+ assert(m_ndb == 0);
+ m_ndb = new Ndb("TEST_DB");
+ CHKCON(m_ndb->init() == 0, *this);
+ CHKCON(m_ndb->waitUntilReady(30) == 0, *this);
+ m_dic = m_ndb->getDictionary();
+ m_tx = 0, m_op = 0;
+ return 0;
+}
+
+void
+Con::disconnect()
+{
+ delete m_ndb;
+ m_ndb = 0, m_dic = 0, m_tx = 0, m_op = 0;
+}
+
+int
+Con::startTransaction()
+{
+ assert(m_ndb != 0 && m_tx == 0);
+ CHKCON((m_tx = m_ndb->startTransaction()) != 0, *this);
+ return 0;
+}
+
+int
+Con::startBuddyTransaction(const Con& con)
+{
+ assert(m_ndb != 0 && m_tx == 0 && con.m_ndb == m_ndb && con.m_tx != 0);
+ CHKCON((m_tx = m_ndb->hupp(con.m_tx)) != 0, *this);
+ return 0;
+}
+
+int
+Con::getNdbOperation(const Tab& tab)
+{
+ assert(m_tx != 0);
+ CHKCON((m_op = m_tx->getNdbOperation(tab.m_name)) != 0, *this);
+ return 0;
+}
+
+int
+Con::getNdbOperation(const ITab& itab, const Tab& tab)
+{
+ CHKCON((m_op = m_tx->getNdbOperation(itab.m_name, tab.m_name)) != 0, *this);
+ return 0;
+}
+
+int
+Con::equal(int num, const char* addr)
+{
+ assert(m_tx != 0 && m_op != 0);
+ CHKCON(m_op->equal(num, addr) == 0, *this);
+ return 0;
+}
+
+int
+Con::getValue(int num, NdbRecAttr*& rec)
+{
+ assert(m_tx != 0 && m_op != 0);
+ CHKCON((rec = m_op->getValue(num, 0)) != 0, *this);
+ return 0;
+}
+
+int
+Con::setValue(int num, const char* addr)
+{
+ assert(m_tx != 0 && m_op != 0);
+ CHKCON(m_op->setValue(num, addr) == 0, *this);
+ return 0;
+}
+
+int
+Con::setBound(int num, int type, const void* value)
+{
+ assert(m_tx != 0 && m_op != 0);
+ CHKCON(m_op->setBound(num, type, value) == 0, *this);
+ return 0;
+}
+
+int
+Con::execute(ExecType t)
+{
+ assert(m_tx != 0);
+ CHKCON(m_tx->execute(t) == 0, *this);
+ return 0;
+}
+
+int
+Con::openScanRead(unsigned parallelism)
+{
+ assert(m_tx != 0 && m_op != 0);
+ CHKCON(m_op->openScanRead(parallelism) == 0, *this);
+ return 0;
+}
+
+int
+Con::openScanExclusive(unsigned parallelism)
+{
+ assert(m_tx != 0 && m_op != 0);
+ CHKCON(m_op->openScanExclusive(parallelism) == 0, *this);
+ return 0;
+}
+
+int
+Con::executeScan()
+{
+ CHKCON(m_tx->executeScan() == 0, *this);
+ return 0;
+}
+
+int
+Con::nextScanResult()
+{
+ int ret;
+ CHKCON((ret = m_tx->nextScanResult()) != -1, *this);
+ assert(ret == 0 || ret == 1);
+ return ret;
+}
+
+int
+Con::takeOverForUpdate(Con& scan)
+{
+ assert(m_tx != 0 && scan.m_op != 0);
+ CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan);
+ return 0;
+}
+
+int
+Con::takeOverForDelete(Con& scan)
+{
+ assert(m_tx != 0 && scan.m_op != 0);
+ CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan);
+ return 0;
+}
+
+void
+Con::closeTransaction()
+{
+ assert(m_ndb != 0 && m_tx != 0);
+ m_ndb->closeTransaction(m_tx);
+ m_tx = 0, m_op = 0;
+}
+
+void
+Con::printerror(NdbOut& out)
+{
+ m_errtype = ErrOther;
+ unsigned any = 0;
+ int code;
+ if (m_ndb) {
+ if ((code = m_ndb->getNdbError().code) != 0) {
+ LL0(++any << " ndb: error " << m_ndb->getNdbError());
+ }
+ if (m_dic && (code = m_dic->getNdbError().code) != 0) {
+ LL0(++any << " dic: error " << m_dic->getNdbError());
+ }
+ if (m_tx) {
+ if ((code = m_tx->getNdbError().code) != 0) {
+ LL0(++any << " con: error " << m_tx->getNdbError());
+ if (code == 266 || code == 274 || code == 296 || code == 297)
+ m_errtype = ErrDeadlock;
+ }
+ if (m_op && m_op->getNdbError().code != 0) {
+ LL0(++any << " op : error " << m_op->getNdbError());
+ }
+ }
+ }
+ if (! any) {
+ LL0("failed but no NDB error code");
+ }
+}
+
+// dictionary operations
+
+static int
+invalidateindex(Par par, const ITab& itab)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ con.m_dic->invalidateIndex(itab.m_name, tab.m_name);
+ return 0;
+}
+
+static int
+invalidateindex(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ for (unsigned i = 0; i < tab.m_itabs; i++) {
+ if (! useindex(i))
+ continue;
+ const ITab& itab = tab.m_itab[i];
+ invalidateindex(par, itab);
+ }
+ return 0;
+}
+
+static int
+invalidatetable(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ invalidateindex(par);
+ con.m_dic->invalidateTable(tab.m_name);
+ return 0;
+}
+
+static int
+droptable(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ if (con.m_dic->getTable(tab.m_name) == 0) {
+ // how to check for error
+ LL4("no table " << tab.m_name);
+ } else {
+ LL3("drop table " << tab.m_name);
+ CHKCON(con.m_dic->dropTable(tab.m_name) == 0, con);
+ }
+ return 0;
+}
+
+static int
+createtable(Par par)
+{
+ Con& con = par.con();
+ CHK(con.bugger() == 0);
+ const Tab& tab = par.tab();
+ LL3("create table " << tab.m_name);
+ LL4(tab);
+ NdbDictionary::Table t(tab.m_name);
+ if (par.m_fragtype != NdbDictionary::Object::FragUndefined) {
+ t.setFragmentType(par.m_fragtype);
+ }
+ if (par.m_nologging) {
+ t.setLogging(false);
+ }
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Col& col = tab.m_col[k];
+ NdbDictionary::Column c(col.m_name);
+ c.setPrimaryKey(col.m_pk);
+ c.setType(col.m_type);
+ c.setLength(col.m_length);
+ c.setNullable(col.m_nullable);
+ t.addColumn(c);
+ }
+ CHKCON(con.m_dic->createTable(t) == 0, con);
+ return 0;
+}
+
+static int
+dropindex(Par par, const ITab& itab)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ if (con.m_dic->getIndex(itab.m_name, tab.m_name) == 0) {
+ // how to check for error
+ LL4("no index " << itab.m_name);
+ } else {
+ LL3("drop index " << itab.m_name);
+ CHKCON(con.m_dic->dropIndex(itab.m_name, tab.m_name) == 0, con);
+ }
+ return 0;
+}
+
+static int
+dropindex(Par par)
+{
+ const Tab& tab = par.tab();
+ for (unsigned i = 0; i < tab.m_itabs; i++) {
+ if (! useindex(i))
+ continue;
+ const ITab& itab = tab.m_itab[i];
+ CHK(dropindex(par, itab) == 0);
+ }
+ return 0;
+}
+
+static int
+createindex(Par par, const ITab& itab)
+{
+ Con& con = par.con();
+ CHK(con.bugger() == 0);
+ const Tab& tab = par.tab();
+ LL3("create index " << itab.m_name);
+ LL4(itab);
+ NdbDictionary::Index x(itab.m_name);
+ x.setTable(tab.m_name);
+ x.setType(NdbDictionary::Index::OrderedIndex);
+ x.setLogging(false);
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ const Col& col = itab.m_icol[k].m_col;
+ x.addColumnName(col.m_name);
+ }
+ CHKCON(con.m_dic->createIndex(x) == 0, con);
+ return 0;
+}
+
+static int
+createindex(Par par)
+{
+ const Tab& tab = par.tab();
+ for (unsigned i = 0; i < tab.m_itabs; i++) {
+ if (! useindex(i))
+ continue;
+ const ITab& itab = tab.m_itab[i];
+ CHK(createindex(par, itab) == 0);
+ }
+ return 0;
+}
+
+// data sets
+
+static unsigned
+urandom(unsigned n)
+{
+ if (n == 0)
+ return 0;
+ unsigned i = random() % n;
+ return i;
+}
+
+static int
+irandom(unsigned n)
+{
+ if (n == 0)
+ return 0;
+ int i = random() % n;
+ if (random() & 0x1)
+ i = -i;
+ return i;
+}
+
+// Val - typed column value
+
+struct Val {
+ const Col& m_col;
+ union {
+ Uint32 m_uint32;
+ char* m_varchar;
+ };
+ Val(const Col& col);
+ ~Val();
+ void copy(const Val& val2);
+ void copy(const void* addr);
+ const void* dataaddr() const;
+ bool m_null;
+ int setval(Par par) const;
+ void calc(Par par, unsigned i);
+ int verify(const Val& val2) const;
+ int cmp(const Val& val2) const;
+private:
+ Val& operator=(const Val& val2);
+};
+
+static NdbOut&
+operator<<(NdbOut& out, const Val& val);
+
+Val::Val(const Col& col) :
+ m_col(col)
+{
+ switch (col.m_type) {
+ case NdbDictionary::Column::Unsigned:
+ break;
+ case NdbDictionary::Column::Varchar:
+ m_varchar = new char [2 + col.m_length];
+ break;
+ default:
+ assert(false);
+ break;
+ }
+}
+
+Val::~Val()
+{
+ const Col& col = m_col;
+ switch (col.m_type) {
+ case NdbDictionary::Column::Unsigned:
+ break;
+ case NdbDictionary::Column::Varchar:
+ delete [] m_varchar;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+}
+
+void
+Val::copy(const Val& val2)
+{
+ const Col& col = m_col;
+ const Col& col2 = val2.m_col;
+ assert(col.m_type == col2.m_type && col.m_length == col2.m_length);
+ if (val2.m_null) {
+ m_null = true;
+ return;
+ }
+ copy(val2.dataaddr());
+}
+
+void
+Val::copy(const void* addr)
+{
+ const Col& col = m_col;
+ switch (col.m_type) {
+ case NdbDictionary::Column::Unsigned:
+ m_uint32 = *(const Uint32*)addr;
+ break;
+ case NdbDictionary::Column::Varchar:
+ memcpy(m_varchar, addr, 2 + col.m_length);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ m_null = false;
+}
+
+const void*
+Val::dataaddr() const
+{
+ const Col& col = m_col;
+ switch (col.m_type) {
+ case NdbDictionary::Column::Unsigned:
+ return &m_uint32;
+ case NdbDictionary::Column::Varchar:
+ return m_varchar;
+ default:
+ break;
+ }
+ assert(false);
+ return 0;
+}
+
+int
+Val::setval(Par par) const
+{
+ Con& con = par.con();
+ const Col& col = m_col;
+ const char* addr = (const char*)dataaddr();
+ if (m_null)
+ addr = 0;
+ if (col.m_pk)
+ CHK(con.equal(col.m_num, addr) == 0);
+ else
+ CHK(con.setValue(col.m_num, addr) == 0);
+ LL5("setval [" << m_col << "] " << *this);
+ return 0;
+}
+
+void
+Val::calc(Par par, unsigned i)
+{
+ const Col& col = m_col;
+ m_null = false;
+ if (col.m_pk) {
+ m_uint32 = i;
+ return;
+ }
+ if (col.m_nullable && urandom(100) < par.m_pctnull) {
+ m_null = true;
+ return;
+ }
+ unsigned v = par.m_range + irandom((par.m_pctrange * par.m_range) / 100);
+ switch (col.m_type) {
+ case NdbDictionary::Column::Unsigned:
+ m_uint32 = v;
+ break;
+ case NdbDictionary::Column::Varchar:
+ {
+ unsigned n = 0;
+ while (n < col.m_length) {
+ if (urandom(1 + col.m_length) == 0) {
+ // nice distribution on lengths
+ break;
+ }
+ m_varchar[2 + n++] = 'a' + urandom((par.m_pctrange * 10) / 100);
+ }
+ m_varchar[0] = (n >> 8);
+ m_varchar[1] = (n & 0xff);
+ while (n < col.m_length) {
+ m_varchar[2 + n++] = 0;
+ }
+ }
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ // verify format
+ col.verify(dataaddr());
+}
+
+int
+Val::verify(const Val& val2) const
+{
+ CHK(cmp(val2) == 0);
+ return 0;
+}
+
+int
+Val::cmp(const Val& val2) const
+{
+ const Col& col = m_col;
+ const Col& col2 = val2.m_col;
+ assert(col.m_type == col2.m_type && col.m_length == col2.m_length);
+ if (m_null || val2.m_null) {
+ if (! m_null)
+ return -1;
+ if (! val2.m_null)
+ return +1;
+ return 0;
+ }
+ // verify data formats
+ col.verify(dataaddr());
+ col.verify(val2.dataaddr());
+ // compare
+ switch (col.m_type) {
+ case NdbDictionary::Column::Unsigned:
+ if (m_uint32 < val2.m_uint32)
+ return -1;
+ if (m_uint32 > val2.m_uint32)
+ return +1;
+ return 0;
+ case NdbDictionary::Column::Varchar:
+ return memcmp(&m_varchar[2], &val2.m_varchar[2], col.m_length);
+ default:
+ break;
+ }
+ assert(false);
+ return 0;
+}
+
+static NdbOut&
+operator<<(NdbOut& out, const Val& val)
+{
+ const Col& col = val.m_col;
+ if (val.m_null) {
+ out << "NULL";
+ return out;
+ }
+ switch (col.m_type) {
+ case NdbDictionary::Column::Unsigned:
+ out << val.m_uint32;
+ break;
+ case NdbDictionary::Column::Varchar:
+ {
+ char buf[8000];
+ unsigned n = (val.m_varchar[0] << 8) | val.m_varchar[1];
+ assert(n <= col.m_length);
+ sprintf(buf, "'%.*s'[%d]", n, &val.m_varchar[2], n);
+ out << buf;
+ }
+ break;
+ default:
+ out << "type" << col.m_type;
+ assert(false);
+ break;
+ }
+ return out;
+}
+
+// Row - table tuple
+
+struct Row {
+ const Tab& m_tab;
+ Val** m_val;
+ bool m_exist;
+ Row(const Tab& tab);
+ ~Row();
+ void copy(const Row& row2);
+ void calc(Par par, unsigned i);
+ int verify(const Row& row2) const;
+ int insrow(Par par);
+ int updrow(Par par);
+ int delrow(Par par);
+ int selrow(Par par);
+ int setrow(Par par);
+ int cmp(const Row& row2) const;
+private:
+ Row& operator=(const Row& row2);
+};
+
+Row::Row(const Tab& tab) :
+ m_tab(tab)
+{
+ m_val = new Val* [tab.m_cols];
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Col& col = tab.m_col[k];
+ m_val[k] = new Val(col);
+ }
+ m_exist = false;
+}
+
+Row::~Row()
+{
+ const Tab& tab = m_tab;
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ delete m_val[k];
+ }
+ delete [] m_val;
+}
+
+void
+Row::copy(const Row& row2)
+{
+ const Tab& tab = m_tab;
+ assert(&tab == &row2.m_tab);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ Val& val = *m_val[k];
+ const Val& val2 = *row2.m_val[k];
+ val.copy(val2);
+ }
+}
+
+void
+Row::calc(Par par, unsigned i)
+{
+ const Tab& tab = m_tab;
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ Val& val = *m_val[k];
+ val.calc(par, i);
+ }
+}
+
+int
+Row::verify(const Row& row2) const
+{
+ const Tab& tab = m_tab;
+ assert(&tab == &row2.m_tab);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Val& val = *m_val[k];
+ const Val& val2 = *row2.m_val[k];
+ CHK(val.verify(val2) == 0);
+ }
+ return 0;
+}
+
+int
+Row::insrow(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = m_tab;
+ assert(! m_exist);
+ CHK(con.getNdbOperation(tab) == 0);
+ CHKCON(con.m_op->insertTuple() == 0, con);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Val& val = *m_val[k];
+ CHK(val.setval(par) == 0);
+ }
+ m_exist = true;
+ return 0;
+}
+
+int
+Row::updrow(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = m_tab;
+ assert(m_exist);
+ CHK(con.getNdbOperation(tab) == 0);
+ CHKCON(con.m_op->updateTuple() == 0, con);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Val& val = *m_val[k];
+ CHK(val.setval(par) == 0);
+ }
+ return 0;
+}
+
+int
+Row::delrow(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = m_tab;
+ assert(m_exist);
+ CHK(con.getNdbOperation(m_tab) == 0);
+ CHKCON(con.m_op->deleteTuple() == 0, con);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Val& val = *m_val[k];
+ const Col& col = val.m_col;
+ if (col.m_pk)
+ CHK(val.setval(par) == 0);
+ }
+ m_exist = false;
+ return 0;
+}
+
+int
+Row::selrow(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = m_tab;
+ CHK(con.getNdbOperation(m_tab) == 0);
+ CHKCON(con.m_op->readTuple() == 0, con);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Val& val = *m_val[k];
+ const Col& col = val.m_col;
+ if (col.m_pk)
+ CHK(val.setval(par) == 0);
+ }
+ m_exist = false;
+ return 0;
+}
+
+int
+Row::setrow(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = m_tab;
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Val& val = *m_val[k];
+ const Col& col = val.m_col;
+ if (! col.m_pk)
+ CHK(val.setval(par) == 0);
+ }
+ return 0;
+}
+
+int
+Row::cmp(const Row& row2) const
+{
+ const Tab& tab = m_tab;
+ assert(&tab == &row2.m_tab);
+ int c = 0;
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Val& val = *m_val[k];
+ const Val& val2 = *row2.m_val[k];
+ if ((c = val.cmp(val2)) != 0)
+ break;
+ }
+ return c;
+}
+
+static NdbOut&
+operator<<(NdbOut& out, const Row& row)
+{
+ const Tab& tab = row.m_tab;
+ for (unsigned i = 0; i < tab.m_cols; i++) {
+ if (i > 0)
+ out << " ";
+ out << *row.m_val[i];
+ }
+ return out;
+}
+
+// Set - set of table tuples
+
+struct Set {
+ const Tab& m_tab;
+ unsigned m_rows;
+ unsigned m_count;
+ Row** m_row;
+ Row** m_saverow;
+ Row* m_keyrow;
+ NdbRecAttr** m_rec;
+ Set(const Tab& tab, unsigned rows);
+ ~Set();
+ // row methods
+ bool exist(unsigned i) const;
+ void calc(Par par, unsigned i);
+ int insrow(Par par, unsigned i);
+ int updrow(Par par, unsigned i);
+ int delrow(Par par, unsigned i);
+ int selrow(Par par, unsigned i);
+ int setrow(Par par, unsigned i);
+ int getval(Par par);
+ int getkey(Par par, unsigned* i);
+ int putval(unsigned i, bool force);
+ // set methods
+ int verify(const Set& set2) const;
+ void savepoint();
+ void commit();
+ void rollback();
+ // locking (not perfect since ops may complete in different order)
+ NdbMutex* m_mutex;
+ void lock() {
+ NdbMutex_Lock(m_mutex);
+ }
+ void unlock() {
+ NdbMutex_Unlock(m_mutex);
+ }
+private:
+ Set& operator=(const Set& set2);
+};
+
+Set::Set(const Tab& tab, unsigned rows) :
+ m_tab(tab)
+{
+ m_rows = rows;
+ m_count = 0;
+ m_row = new Row* [m_rows];
+ for (unsigned i = 0; i < m_rows; i++) {
+ m_row[i] = 0;
+ }
+ m_saverow = 0;
+ m_keyrow = new Row(tab);
+ m_rec = new NdbRecAttr* [tab.m_cols];
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ m_rec[k] = 0;
+ }
+ m_mutex = NdbMutex_Create();
+ assert(m_mutex != 0);
+}
+
+Set::~Set()
+{
+ for (unsigned i = 0; i < m_rows; i++) {
+ delete m_row[i];
+ if (m_saverow != 0)
+ delete m_saverow[i];
+ }
+ delete [] m_row;
+ delete [] m_saverow;
+ delete m_keyrow;
+ delete [] m_rec;
+ NdbMutex_Destroy(m_mutex);
+}
+
+bool
+Set::exist(unsigned i) const
+{
+ assert(i < m_rows);
+ return m_row[i] != 0 && m_row[i]->m_exist;
+}
+
+void
+Set::calc(Par par, unsigned i)
+{
+ const Tab& tab = m_tab;
+ if (m_row[i] == 0)
+ m_row[i] = new Row(tab);
+ Row& row = *m_row[i];
+ // value generation parameters
+ par.m_pctnull = 10;
+ par.m_pctrange = 40;
+ row.calc(par, i);
+}
+
+int
+Set::insrow(Par par, unsigned i)
+{
+ assert(m_row[i] != 0 && m_count < m_rows);
+ CHK(m_row[i]->insrow(par) == 0);
+ m_count++;
+ return 0;
+}
+
+int
+Set::updrow(Par par, unsigned i)
+{
+ assert(m_row[i] != 0);
+ CHK(m_row[i]->updrow(par) == 0);
+ return 0;
+}
+
+int
+Set::delrow(Par par, unsigned i)
+{
+ assert(m_row[i] != 0 && m_count != 0);
+ CHK(m_row[i]->delrow(par) == 0);
+ m_count--;
+ return 0;
+}
+
+int
+Set::selrow(Par par, unsigned i)
+{
+ Con& con = par.con();
+ m_keyrow->calc(par, i);
+ CHK(m_keyrow->selrow(par) == 0);
+ CHK(getval(par) == 0);
+ return 0;
+}
+
+int
+Set::setrow(Par par, unsigned i)
+{
+ Con& con = par.con();
+ assert(m_row[i] != 0);
+ CHK(m_row[i]->setrow(par) == 0);
+ return 0;
+}
+
+int
+Set::getval(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = m_tab;
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ CHK(con.getValue(k, m_rec[k]) == 0);
+ }
+ return 0;
+}
+
+int
+Set::getkey(Par par, unsigned* i)
+{
+ assert(m_rec[0] != 0);
+ const char* aRef0 = m_rec[0]->aRef();
+ Uint32 key = *(const Uint32*)aRef0;
+ CHKMSG(key < m_rows, "key=" << key << " rows=" << m_rows);
+ *i = key;
+ return 0;
+}
+
+int
+Set::putval(unsigned i, bool force)
+{
+ const Tab& tab = m_tab;
+ if (m_row[i] == 0)
+ m_row[i] = new Row(tab);
+ Row& row = *m_row[i];
+ CHK(! row.m_exist || force);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ Val& val = *row.m_val[k];
+ NdbRecAttr* rec = m_rec[k];
+ assert(rec != 0);
+ if (rec->isNULL()) {
+ val.m_null = true;
+ continue;
+ }
+ const char* aRef = m_rec[k]->aRef();
+ val.copy(aRef);
+ val.m_null = false;
+ }
+ if (! row.m_exist) {
+ row.m_exist = true;
+ m_count++;
+ }
+ return 0;
+}
+
+int
+Set::verify(const Set& set2) const
+{
+ const Tab& tab = m_tab;
+ assert(&tab == &set2.m_tab && m_rows == set2.m_rows);
+ CHKMSG(m_count == set2.m_count, "set=" << m_count << " set2=" << set2.m_count);
+ for (unsigned i = 0; i < m_rows; i++) {
+ CHK(exist(i) == set2.exist(i));
+ if (! exist(i))
+ continue;
+ Row& row = *m_row[i];
+ Row& row2 = *set2.m_row[i];
+ CHK(row.verify(row2) == 0);
+ }
+ return 0;
+}
+
+void
+Set::savepoint()
+{
+ const Tab& tab = m_tab;
+ assert(m_saverow == 0);
+ m_saverow = new Row* [m_rows];
+ for (unsigned i = 0; i < m_rows; i++) {
+ if (m_row[i] == 0)
+ m_saverow[i] = 0;
+ else {
+ m_saverow[i] = new Row(tab);
+ m_saverow[i]->copy(*m_row[i]);
+ }
+ }
+}
+
+void
+Set::commit()
+{
+ delete [] m_saverow;
+ m_saverow = 0;
+}
+
+void
+Set::rollback()
+{
+ assert(m_saverow != 0);
+ m_row = m_saverow;
+ m_saverow = 0;
+}
+
+static NdbOut&
+operator<<(NdbOut& out, const Set& set)
+{
+ for (unsigned i = 0; i < set.m_rows; i++) {
+ const Row& row = *set.m_row[i];
+ if (i > 0)
+ out << endl;
+ out << row;
+ }
+ return out;
+}
+
+// BVal - range scan bound
+
+struct BVal : public Val {
+ const ICol& m_icol;
+ int m_type;
+ BVal(const ICol& icol);
+ int setbnd(Par par) const;
+};
+
+BVal::BVal(const ICol& icol) :
+ Val(icol.m_col),
+ m_icol(icol)
+{
+}
+
+int
+BVal::setbnd(Par par) const
+{
+ Con& con = par.con();
+ const char* addr = (const char*)dataaddr();
+ assert(! m_null);
+ const ICol& icol = m_icol;
+ CHK(con.setBound(icol.m_num, m_type, addr) == 0);
+ return 0;
+}
+
+static NdbOut&
+operator<<(NdbOut& out, const BVal& bval)
+{
+ const ICol& icol = bval.m_icol;
+ const Col& col = icol.m_col;
+ const Val& val = bval;
+ out << "type " << bval.m_type;
+ out << " icol " << icol.m_num;
+ out << " col " << col.m_name << "(" << col.m_num << ")";
+ out << " value " << val;
+ return out;
+}
+
+// BSet - set of bounds
+
+struct BSet {
+ const Tab& m_tab;
+ const ITab& m_itab;
+ unsigned m_alloc;
+ unsigned m_bvals;
+ BVal** m_bval;
+ BSet(const Tab& tab, const ITab& itab, unsigned rows);
+ void calc(Par par);
+ int setbnd(Par par) const;
+ void filter(const Set& set, Set& set2) const;
+};
+
+BSet::BSet(const Tab& tab, const ITab& itab, unsigned rows) :
+ m_tab(tab),
+ m_itab(itab),
+ m_alloc(2 * itab.m_icols),
+ m_bvals(0)
+{
+ m_bval = new BVal* [m_alloc];
+}
+
+void
+BSet::calc(Par par)
+{
+ const ITab& itab = m_itab;
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ const ICol& icol = itab.m_icol[k];
+ const Col& col = icol.m_col;
+ for (unsigned i = 0; i <= 1; i++) {
+ if (urandom(10) == 0)
+ return;
+ assert(m_bvals < m_alloc);
+ BVal& bval = *new BVal(icol);
+ m_bval[m_bvals++] = &bval;
+ bval.m_null = false;
+ // equality bound only on i==0
+ unsigned sel = urandom(5 - i);
+ if (sel < 2)
+ bval.m_type = 0 | (1 << i);
+ else if (sel < 4)
+ bval.m_type = 1 | (1 << i);
+ else
+ bval.m_type = 4;
+ if (k + 1 < itab.m_icols)
+ bval.m_type = 4;
+ // value generation parammeters
+ par.m_pctnull = 0;
+ par.m_pctrange = 50; // bit higher
+ do {
+ bval.calc(par, 0);
+ if (i == 1) {
+ assert(m_bvals >= 2);
+ const BVal& bv1 = *m_bval[m_bvals - 2];
+ const BVal& bv2 = *m_bval[m_bvals - 1];
+ if (bv1.cmp(bv2) > 0 && urandom(100) != 0)
+ continue;
+ }
+ } while (0);
+ // equality bound only once
+ if (bval.m_type == 4)
+ break;
+ }
+ }
+}
+
+int
+BSet::setbnd(Par par) const
+{
+ for (unsigned j = 0; j < m_bvals; j++) {
+ const BVal& bval = *m_bval[j];
+ CHK(bval.setbnd(par) == 0);
+ }
+ return 0;
+}
+
+void
+BSet::filter(const Set& set, Set& set2) const
+{
+ const Tab& tab = m_tab;
+ const ITab& itab = m_itab;
+ assert(&tab == &set2.m_tab && set.m_rows == set2.m_rows);
+ assert(set2.m_count == 0);
+ for (unsigned i = 0; i < set.m_rows; i++) {
+ if (! set.exist(i))
+ continue;
+ const Row& row = *set.m_row[i];
+ bool ok1 = false;
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ const ICol& icol = itab.m_icol[k];
+ const Col& col = icol.m_col;
+ const Val& val = *row.m_val[col.m_num];
+ if (! val.m_null) {
+ ok1 = true;
+ break;
+ }
+ }
+ if (! ok1)
+ continue;
+ bool ok2 = true;
+ for (unsigned j = 0; j < m_bvals; j++) {
+ const BVal& bval = *m_bval[j];
+ const ICol& icol = bval.m_icol;
+ const Col& col = icol.m_col;
+ const Val& val = *row.m_val[col.m_num];
+ int ret = bval.cmp(val);
+ if (bval.m_type == 0)
+ ok2 = (ret <= 0);
+ else if (bval.m_type == 1)
+ ok2 = (ret < 0);
+ else if (bval.m_type == 2)
+ ok2 = (ret >= 0);
+ else if (bval.m_type == 3)
+ ok2 = (ret > 0);
+ else if (bval.m_type == 4)
+ ok2 = (ret == 0);
+ else {
+ assert(false);
+ }
+ if (! ok2)
+ break;
+ }
+ if (! ok2)
+ continue;
+ if (set2.m_row[i] == 0)
+ set2.m_row[i] = new Row(tab);
+ Row& row2 = *set2.m_row[i];
+ assert(! row2.m_exist);
+ row2.copy(row);
+ row2.m_exist = true;
+ set2.m_count++;
+ }
+}
+
+static NdbOut&
+operator<<(NdbOut& out, const BSet& bset)
+{
+ out << "bounds=" << bset.m_bvals;
+ for (unsigned j = 0; j < bset.m_bvals; j++) {
+ out << endl;
+ const BVal& bval = *bset.m_bval[j];
+ out << "bound " << j << ": " << bval;
+ }
+ return out;
+}
+
+// pk operations
+
+static int
+pkinsert(Par par)
+{
+ Con& con = par.con();
+ Set& set = par.set();
+ LL3("pkinsert");
+ CHK(con.startTransaction() == 0);
+ unsigned n = 0;
+ for (unsigned j = 0; j < par.m_rows; j++) {
+ unsigned i = thrrow(par, j);
+ set.lock();
+ if (set.exist(i)) {
+ set.unlock();
+ continue;
+ }
+ set.calc(par, i);
+ LL4("pkinsert " << i << ": " << *set.m_row[i]);
+ CHKTRY(set.insrow(par, i) == 0, set.unlock());
+ set.unlock();
+ if (++n == par.m_batch) {
+ CHK(con.execute(Commit) == 0);
+ con.closeTransaction();
+ CHK(con.startTransaction() == 0);
+ n = 0;
+ }
+ }
+ if (n != 0) {
+ CHK(con.execute(Commit) == 0);
+ n = 0;
+ }
+ con.closeTransaction();
+ return 0;
+};
+
+static int
+pkupdate(Par par)
+{
+ Con& con = par.con();
+ Set& set = par.set();
+ LL3("pkupdate");
+ CHK(con.startTransaction() == 0);
+ unsigned n = 0;
+ for (unsigned j = 0; j < par.m_rows; j++) {
+ unsigned i = thrrow(par, j);
+ set.lock();
+ if (! set.exist(i)) {
+ set.unlock();
+ continue;
+ }
+ set.calc(par, i);
+ LL4("pkupdate " << i << ": " << *set.m_row[i]);
+ CHKTRY(set.updrow(par, i) == 0, set.unlock());
+ set.unlock();
+ if (++n == par.m_batch) {
+ CHK(con.execute(Commit) == 0);
+ con.closeTransaction();
+ CHK(con.startTransaction() == 0);
+ n = 0;
+ }
+ }
+ if (n != 0) {
+ CHK(con.execute(Commit) == 0);
+ n = 0;
+ }
+ con.closeTransaction();
+ return 0;
+};
+
+static int
+pkdelete(Par par)
+{
+ Con& con = par.con();
+ Set& set = par.set();
+ LL3("pkdelete");
+ CHK(con.startTransaction() == 0);
+ unsigned n = 0;
+ for (unsigned j = 0; j < par.m_rows; j++) {
+ unsigned i = thrrow(par, j);
+ set.lock();
+ if (! set.exist(i)) {
+ set.unlock();
+ continue;
+ }
+ LL4("pkdelete " << i << ": " << *set.m_row[i]);
+ CHKTRY(set.delrow(par, i) == 0, set.unlock());
+ set.unlock();
+ if (++n == par.m_batch) {
+ CHK(con.execute(Commit) == 0);
+ con.closeTransaction();
+ CHK(con.startTransaction() == 0);
+ n = 0;
+ }
+ }
+ if (n != 0) {
+ CHK(con.execute(Commit) == 0);
+ n = 0;
+ }
+ con.closeTransaction();
+ return 0;
+};
+
+static int
+pkread(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ const Set& set = par.set();
+ LL3((par.m_verify ? "pkverify " : "pkread ") << tab.m_name);
+ // expected
+ const Set& set1 = set;
+ Set set2(tab, set.m_rows);
+ for (unsigned i = 0; i < set.m_rows; i++) {
+ if (! set.exist(i))
+ continue;
+ CHK(con.startTransaction() == 0);
+ CHK(set2.selrow(par, i) == 0);
+ CHK(con.execute(Commit) == 0);
+ unsigned i2 = (unsigned)-1;
+ CHK(set2.getkey(par, &i2) == 0 && i == i2);
+ CHK(set2.putval(i, false) == 0);
+ LL4("row " << set2.m_count << ": " << *set2.m_row[i]);
+ con.closeTransaction();
+ }
+ if (par.m_verify)
+ CHK(set1.verify(set2) == 0);
+ return 0;
+}
+
+// scan read
+
+static int
+scanreadtable(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ const Set& set = par.set();
+ // expected
+ const Set& set1 = set;
+ LL3((par.m_verify ? "scanverify " : "scanread ") << tab.m_name);
+ Set set2(tab, set.m_rows);
+ CHK(con.startTransaction() == 0);
+ CHK(con.getNdbOperation(tab) == 0);
+ CHK(con.openScanRead(par.m_scanrd) == 0);
+ set2.getval(par);
+ CHK(con.executeScan() == 0);
+ while (1) {
+ int ret;
+ CHK((ret = con.nextScanResult()) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ unsigned i = (unsigned)-1;
+ CHK(set2.getkey(par, &i) == 0);
+ CHK(set2.putval(i, false) == 0);
+ LL4("row " << set2.m_count << ": " << *set2.m_row[i]);
+ }
+ con.closeTransaction();
+ if (par.m_verify)
+ CHK(set1.verify(set2) == 0);
+ return 0;
+}
+
+static int
+scanreadindex(Par par, const ITab& itab, const BSet& bset)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ const Set& set = par.set();
+ // expected
+ Set set1(tab, set.m_rows);
+ bset.filter(set, set1);
+ LL3((par.m_verify ? "scanverify " : "scanread ") << itab.m_name << " bounds=" << bset.m_bvals);
+ LL4(bset);
+ Set set2(tab, set.m_rows);
+ CHK(con.startTransaction() == 0);
+ CHK(con.getNdbOperation(itab, tab) == 0);
+ CHK(con.openScanRead(par.m_scanrd) == 0);
+ CHK(bset.setbnd(par) == 0);
+ set2.getval(par);
+ CHK(con.executeScan() == 0);
+ while (1) {
+ int ret;
+ CHK((ret = con.nextScanResult()) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ unsigned i = (unsigned)-1;
+ CHK(set2.getkey(par, &i) == 0);
+ LL4("key " << i);
+ CHK(set2.putval(i, par.m_dups) == 0);
+ LL4("row " << set2.m_count << ": " << *set2.m_row[i]);
+ }
+ con.closeTransaction();
+ if (par.m_verify)
+ CHK(set1.verify(set2) == 0);
+ return 0;
+}
+
+static int
+scanreadindex(Par par, const ITab& itab)
+{
+ const Tab& tab = par.tab();
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ BSet bset(tab, itab, par.m_rows);
+ bset.calc(par);
+ CHK(scanreadindex(par, itab, bset) == 0);
+ }
+ return 0;
+}
+
+static int
+scanreadindex(Par par)
+{
+ const Tab& tab = par.tab();
+ for (unsigned i = 0; i < tab.m_itabs; i++) {
+ if (! useindex(i))
+ continue;
+ const ITab& itab = tab.m_itab[i];
+ CHK(scanreadindex(par, itab) == 0);
+ }
+ return 0;
+}
+
+static int
+scanreadall(Par par)
+{
+ if (par.m_no < 11)
+ CHK(scanreadtable(par) == 0);
+ CHK(scanreadindex(par) == 0);
+ return 0;
+}
+
+// scan update
+
+static int
+scanupdatetable(Par par)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ Set& set = par.set();
+ LL3("scan update " << tab.m_name);
+ Set set2(tab, set.m_rows);
+ CHK(con.startTransaction() == 0);
+ CHK(con.getNdbOperation(tab) == 0);
+ CHK(con.openScanExclusive(par.m_scanex) == 0);
+ set2.getval(par);
+ CHK(con.executeScan() == 0);
+ unsigned count = 0;
+ // updating trans
+ Con con2;
+ con2.m_ndb = con.m_ndb;
+ CHK(con2.startBuddyTransaction(con) == 0);
+ while (1) {
+ int ret;
+ CHK((ret = con.nextScanResult()) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ unsigned i = (unsigned)-1;
+ CHK(set2.getkey(par, &i) == 0);
+ LL4("key " << i);
+ CHK(set2.putval(i, false) == 0);
+ CHK(con2.takeOverForUpdate(con) == 0);
+ Par par2 = par;
+ par2.m_con = &con2;
+ set.lock();
+ set.calc(par, i);
+ LL4("scan update " << tab.m_name << ": " << *set.m_row[i]);
+ CHKTRY(set.setrow(par2, i) == 0, set.unlock());
+ set.unlock();
+ CHK(con2.execute(NoCommit) == 0);
+ count++;
+ }
+ CHK(con2.execute(Commit) == 0);
+ con2.closeTransaction();
+ LL3("scan update " << tab.m_name << " rows updated=" << count);
+ con.closeTransaction();
+ return 0;
+}
+
+static int
+scanupdateindex(Par par, const ITab& itab, const BSet& bset)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ Set& set = par.set();
+ LL3("scan update " << itab.m_name);
+ Set set2(tab, set.m_rows);
+ CHK(con.startTransaction() == 0);
+ CHK(con.getNdbOperation(itab, tab) == 0);
+ CHK(con.openScanExclusive(par.m_scanex) == 0);
+ CHK(bset.setbnd(par) == 0);
+ set2.getval(par);
+ CHK(con.executeScan() == 0);
+ unsigned count = 0;
+ // updating trans
+ Con con2;
+ con2.m_ndb = con.m_ndb;
+ CHK(con2.startBuddyTransaction(con) == 0);
+ while (1) {
+ int ret;
+ CHK((ret = con.nextScanResult()) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ unsigned i = (unsigned)-1;
+ CHK(set2.getkey(par, &i) == 0);
+ LL4("key " << i);
+ CHK(set2.putval(i, par.m_dups) == 0);
+ // avoid deadlock for now
+ //if (! isthrrow(par, i))
+ //continue;
+ CHK(con2.takeOverForUpdate(con) == 0);
+ Par par2 = par;
+ par2.m_con = &con2;
+ set.lock();
+ set.calc(par, i);
+ LL4("scan update " << itab.m_name << ": " << *set.m_row[i]);
+ CHKTRY(set.setrow(par2, i) == 0, set.unlock());
+ set.unlock();
+ CHK(con2.execute(NoCommit) == 0);
+ count++;
+ }
+ CHK(con2.execute(Commit) == 0);
+ con2.closeTransaction();
+ LL3("scan update " << itab.m_name << " rows updated=" << count);
+ con.closeTransaction();
+ return 0;
+}
+
+static int
+scanupdateindex(Par par, const ITab& itab)
+{
+ const Tab& tab = par.tab();
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ BSet bset(tab, itab, par.m_rows);
+ bset.calc(par);
+ CHK(scanupdateindex(par, itab, bset) == 0);
+ }
+ return 0;
+}
+
+static int
+scanupdateindex(Par par)
+{
+ const Tab& tab = par.tab();
+ for (unsigned i = 0; i < tab.m_itabs; i++) {
+ if (! useindex(i))
+ continue;
+ const ITab& itab = tab.m_itab[i];
+ CHK(scanupdateindex(par, itab) == 0);
+ }
+ return 0;
+}
+
+static int
+scanupdateall(Par par)
+{
+ CHK(scanupdatetable(par) == 0);
+ CHK(scanupdateindex(par) == 0);
+ return 0;
+}
+
+// medium level routines
+
+static bool
+ignoreverifyerror(Par par)
+{
+ Con& con = par.con();
+ bool b = par.m_threads > 1;
+ if (b) {
+ LL1("ignore verify error");
+ if (con.m_tx != 0)
+ con.closeTransaction();
+ return true;
+ }
+ return b;
+}
+
+static int
+readverify(Par par)
+{
+ par.m_verify = true;
+ CHK(pkread(par) == 0 || ignoreverifyerror(par));
+ CHK(scanreadall(par) == 0 || ignoreverifyerror(par));
+ return 0;
+}
+
+static bool
+ignoredeadlock(Par par)
+{
+ Con& con = par.con();
+ if (con.m_errtype == Con::ErrDeadlock) {
+ LL1("ignore deadlock");
+ con.closeTransaction();
+ return true;
+ }
+ return false;
+}
+
+static int
+pkupdatescanread(Par par)
+{
+ par.m_dups = true;
+ unsigned sel = urandom(10);
+ if (sel < 5) {
+ CHK(pkupdate(par) == 0);
+ } else if (sel < 6) {
+ par.m_verify = false;
+ CHK(scanreadtable(par) == 0);
+ } else {
+ par.m_verify = false;
+ CHK(scanreadindex(par) == 0);
+ }
+ return 0;
+}
+
+static int
+mixedoperations(Par par)
+{
+ par.m_dups = true;
+ unsigned sel = urandom(10);
+ if (sel < 2) {
+ CHK(pkdelete(par) == 0 || ignoredeadlock(par));
+ } else if (sel < 4) {
+ CHK(pkupdate(par) == 0 || ignoredeadlock(par));
+ } else if (sel < 6) {
+ CHK(scanupdatetable(par) == 0 || ignoredeadlock(par));
+ } else {
+ CHK(scanupdateindex(par) == 0 || ignoredeadlock(par));
+ }
+ return 0;
+}
+
+static int
+pkupdateindexbuild(Par par)
+{
+ if (par.m_no == 0) {
+ CHK(createindex(par) == 0);
+ } else {
+ CHK(pkupdate(par) == 0);
+ }
+ return 0;
+}
+
+// threads
+
+typedef int (*TFunc)(Par par);
+enum TMode { ST = 1, MT = 2 };
+
+extern "C" { static void* runthread(void* arg); }
+
+struct Thr {
+ enum State { Wait, Start, Stop, Stopped, Exit };
+ State m_state;
+ Par m_par;
+ Uint64 m_id;
+ NdbThread* m_thread;
+ NdbMutex* m_mutex;
+ NdbCondition* m_cond;
+ TFunc m_func;
+ int m_ret;
+ void* m_status;
+ Thr(Par par, unsigned n);
+ ~Thr();
+ int run();
+ void start();
+ void stop();
+ void stopped();
+ void exit();
+ //
+ void lock() {
+ NdbMutex_Lock(m_mutex);
+ }
+ void unlock() {
+ NdbMutex_Unlock(m_mutex);
+ }
+ void wait() {
+ NdbCondition_Wait(m_cond, m_mutex);
+ }
+ void signal() {
+ NdbCondition_Signal(m_cond);
+ }
+ void join() {
+ NdbThread_WaitFor(m_thread, &m_status);
+ m_thread = 0;
+ }
+};
+
+Thr::Thr(Par par, unsigned n) :
+ m_state(Wait),
+ m_par(par),
+ m_id(0),
+ m_thread(0),
+ m_mutex(0),
+ m_cond(0),
+ m_func(0),
+ m_ret(0),
+ m_status(0)
+{
+ m_par.m_no = n;
+ char buf[10];
+ sprintf(buf, "thr%03u", par.m_no);
+ const char* name = strcpy(new char[10], buf);
+ // mutex
+ m_mutex = NdbMutex_Create();
+ m_cond = NdbCondition_Create();
+ assert(m_mutex != 0 && m_cond != 0);
+ // run
+ const unsigned stacksize = 256 * 1024;
+ const NDB_THREAD_PRIO prio = NDB_THREAD_PRIO_LOW;
+ m_thread = NdbThread_Create(runthread, (void**)this, stacksize, name, prio);
+}
+
+Thr::~Thr()
+{
+ if (m_thread != 0) {
+ NdbThread_Destroy(&m_thread);
+ m_thread = 0;
+ }
+ if (m_cond != 0) {
+ NdbCondition_Destroy(m_cond);
+ m_cond = 0;
+ }
+ if (m_mutex != 0) {
+ NdbMutex_Destroy(m_mutex);
+ m_mutex = 0;
+ }
+}
+
+static void*
+runthread(void* arg)
+{
+ Thr& thr = *(Thr*)arg;
+ thr.m_id = (Uint64)pthread_self();
+ if (thr.run() < 0) {
+ LL1("exit on error");
+ } else {
+ LL4("exit ok");
+ }
+ return 0;
+}
+
+int
+Thr::run()
+{
+ LL4("run");
+ Con con;
+ CHK(con.connect() == 0);
+ m_par.m_con = &con;
+ LL4("connected");
+ while (1) {
+ lock();
+ while (m_state != Start && m_state != Exit) {
+ LL4("wait");
+ wait();
+ }
+ if (m_state == Exit) {
+ LL4("exit");
+ unlock();
+ break;
+ }
+ LL4("start");
+ CHK(con.bugger() == 0);
+ assert(m_state == Start);
+ m_ret = (*m_func)(m_par);
+ m_state = Stopped;
+ LL4("stop");
+ signal();
+ unlock();
+ CHK(m_ret == 0);
+ }
+ con.disconnect();
+ return 0;
+}
+
+void
+Thr::start()
+{
+ lock();
+ m_state = Start;
+ signal();
+ unlock();
+}
+
+void
+Thr::stop()
+{
+ lock();
+ m_state = Stop;
+ signal();
+ unlock();
+}
+
+void
+Thr::stopped()
+{
+ lock();
+ while (m_state != Stopped)
+ wait();
+ m_state = Wait;
+ unlock();
+}
+
+void
+Thr::exit()
+{
+ lock();
+ m_state = Exit;
+ signal();
+ unlock();
+}
+
+// test run
+
+static Thr** g_thrlist = 0;
+
+static unsigned
+getthrno()
+{
+ if (g_thrlist != 0) {
+ Uint64 id = (Uint64)pthread_self();
+ for (unsigned n = 0; n < g_opt.m_threads; n++) {
+ if (g_thrlist[n] != 0) {
+ const Thr& thr = *g_thrlist[n];
+ if (thr.m_id == id)
+ return thr.m_par.m_no;
+ }
+ }
+ }
+ return (unsigned)-1;
+}
+
+static int
+runstep(Par par, const char* fname, TFunc func, unsigned mode)
+{
+ LL2(fname);
+ const int threads = (mode & ST ? 1 : par.m_threads);
+ for (int n = 0; n < threads; n++) {
+ LL4("start " << n);
+ Thr& thr = *g_thrlist[n];
+ thr.m_par.m_tab = par.m_tab;
+ thr.m_par.m_set = par.m_set;
+ thr.m_func = func;
+ thr.start();
+ }
+ unsigned errs = 0;
+ for (int n = threads - 1; n >= 0; n--) {
+ LL4("stop " << n);
+ Thr& thr = *g_thrlist[n];
+ thr.stopped();
+ if (thr.m_ret != 0)
+ errs++;
+ }
+ CHK(errs == 0);
+ return 0;
+}
+
+#define RUNSTEP(par, func, mode) CHK(runstep(par, #func, func, mode) == 0)
+
+static int
+tbuild(Par par)
+{
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ if (i % 2 == 0) {
+ RUNSTEP(par, createindex, ST);
+ RUNSTEP(par, invalidateindex, MT);
+ RUNSTEP(par, pkinsert, MT);
+ } else {
+ RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, createindex, ST);
+ RUNSTEP(par, invalidateindex, MT);
+ }
+ RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, pkdelete, MT);
+ RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, dropindex, ST);
+ }
+ return 0;
+}
+
+static int
+tpkops(Par par)
+{
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, createindex, ST);
+ RUNSTEP(par, invalidateindex, MT);
+ RUNSTEP(par, readverify, MT);
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ RUNSTEP(par, pkupdatescanread, MT);
+ RUNSTEP(par, readverify, MT);
+ }
+ RUNSTEP(par, pkdelete, MT);
+ RUNSTEP(par, readverify, MT);
+ return 0;
+}
+
+static int
+tmixedops(Par par)
+{
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, createindex, ST);
+ RUNSTEP(par, invalidateindex, MT);
+ RUNSTEP(par, readverify, MT);
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ RUNSTEP(par, mixedoperations, MT);
+ RUNSTEP(par, readverify, MT);
+ }
+ return 0;
+}
+
+static int
+tbusybuild(Par par)
+{
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ RUNSTEP(par, pkinsert, MT);
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ RUNSTEP(par, pkupdateindexbuild, MT);
+ RUNSTEP(par, invalidateindex, MT);
+ RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, dropindex, ST);
+ }
+ return 0;
+}
+
+static int
+ttimebuild(Par par)
+{
+ Tmr t1;
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ RUNSTEP(par, pkinsert, MT);
+ t1.on();
+ RUNSTEP(par, createindex, ST);
+ t1.off(par.m_totrows);
+ RUNSTEP(par, invalidateindex, MT);
+ RUNSTEP(par, dropindex, ST);
+ }
+ LL1("build index - " << t1.time());
+ return 0;
+}
+
+static int
+ttimemaint(Par par)
+{
+ Tmr t1, t2;
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ RUNSTEP(par, pkinsert, MT);
+ t1.on();
+ RUNSTEP(par, pkupdate, MT);
+ t1.off(par.m_totrows);
+ RUNSTEP(par, createindex, ST);
+ RUNSTEP(par, invalidateindex, MT);
+ t2.on();
+ RUNSTEP(par, pkupdate, MT);
+ t2.off(par.m_totrows);
+ RUNSTEP(par, dropindex, ST);
+ }
+ LL1("update - " << t1.time());
+ LL1("update indexed - " << t2.time());
+ LL1("overhead - " << t2.over(t1));
+ return 0;
+}
+
+static int
+tdrop(Par par)
+{
+ RUNSTEP(par, droptable, ST);
+ return 0;
+}
+
+struct TCase {
+ const char* m_name;
+ TFunc m_func;
+ const char* m_desc;
+ TCase(const char* name, TFunc func, const char* desc) :
+ m_name(name),
+ m_func(func),
+ m_desc(desc) {
+ }
+};
+
+static const TCase
+tcaselist[] = {
+ TCase("a", tbuild, "index build"),
+ TCase("b", tpkops, "pk operations and scan reads"),
+ TCase("c", tmixedops, "pk operations and scan operations"),
+ TCase("d", tbusybuild, "pk operations and index build"),
+ TCase("t", ttimebuild, "time index build"),
+ TCase("u", ttimemaint, "time index maintenance"),
+ TCase("z", tdrop, "drop test tables")
+};
+
+static const unsigned
+tcasecount = sizeof(tcaselist) / sizeof(tcaselist[0]);
+
+static void
+printcases()
+{
+ ndbout << "test cases:" << endl;
+ for (unsigned i = 0; i < tcasecount; i++) {
+ const TCase& tcase = tcaselist[i];
+ ndbout << " " << tcase.m_name << " - " << tcase.m_desc << endl;
+ }
+}
+
+static void
+printtables()
+{
+ ndbout << "tables and indexes:" << endl;
+ for (unsigned j = 0; j < tabcount; j++) {
+ const Tab& tab = tablist[j];
+ ndbout << " " << tab.m_name;
+ for (unsigned i = 0; i < tab.m_itabs; i++) {
+ const ITab& itab = tab.m_itab[i];
+ ndbout << " " << itab.m_name;
+ }
+ ndbout << endl;
+ }
+}
+
+static int
+runtest(Par par)
+{
+ LL1("start");
+ srandom(par.m_seed);
+ Con con;
+ CHK(con.connect() == 0);
+ par.m_con = &con;
+ g_thrlist = new Thr* [par.m_threads];
+ for (unsigned n = 0; n < par.m_threads; n++) {
+ g_thrlist[n] = 0;
+ }
+ for (unsigned n = 0; n < par.m_threads; n++) {
+ g_thrlist[n] = new Thr(par, n);
+ Thr& thr = *g_thrlist[n];
+ assert(thr.m_thread != 0);
+ }
+ for (unsigned l = 0; par.m_loop == 0 || l < par.m_loop; l++) {
+ LL1("loop " << l);
+ for (unsigned i = 0; i < tcasecount; i++) {
+ const TCase& tcase = tcaselist[i];
+ if (par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0)
+ continue;
+ LL1("case " << tcase.m_name << " - " << tcase.m_desc);
+ for (unsigned j = 0; j < tabcount; j++) {
+ if (! usetable(j))
+ continue;
+ const Tab& tab = tablist[j];
+ par.m_tab = &tab;
+ Set set(tab, par.m_totrows);
+ par.m_set = &set;
+ LL1("table " << tab.m_name);
+ CHK(tcase.m_func(par) == 0);
+ }
+ }
+ }
+ for (unsigned n = 0; n < par.m_threads; n++) {
+ Thr& thr = *g_thrlist[n];
+ thr.exit();
+ }
+ for (unsigned n = 0; n < par.m_threads; n++) {
+ Thr& thr = *g_thrlist[n];
+ thr.join();
+ delete &thr;
+ }
+ delete [] g_thrlist;
+ g_thrlist = 0;
+ con.disconnect();
+ LL1("done");
+ return 0;
+}
+
+NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
+{
+ while (++argv, --argc > 0) {
+ const char* arg = argv[0];
+ if (*arg != '-') {
+ ndbout << "testOIBasic: unknown argument " << arg;
+ goto usage;
+ }
+ if (strcmp(arg, "-case") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_case = strdup(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-core") == 0) {
+ g_opt.m_core = true;
+ continue;
+ }
+ if (strcmp(arg, "-dups") == 0) {
+ g_opt.m_dups = true;
+ continue;
+ }
+ if (strcmp(arg, "-fragtype") == 0) {
+ if (++argv, --argc > 0) {
+ if (strcmp(argv[0], "single") == 0) {
+ g_opt.m_fragtype = NdbDictionary::Object::FragSingle;
+ continue;
+ }
+ if (strcmp(argv[0], "small") == 0) {
+ g_opt.m_fragtype = NdbDictionary::Object::FragAllSmall;
+ continue;
+ }
+ if (strcmp(argv[0], "medium") == 0) {
+ g_opt.m_fragtype = NdbDictionary::Object::FragAllMedium;
+ continue;
+ }
+ if (strcmp(argv[0], "large") == 0) {
+ g_opt.m_fragtype = NdbDictionary::Object::FragAllLarge;
+ continue;
+ }
+ }
+ }
+ if (strcmp(arg, "-index") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_index = strdup(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-loop") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_loop = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-nologging") == 0) {
+ g_opt.m_nologging = true;
+ continue;
+ }
+ if (strcmp(arg, "-rows") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_rows = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-scanrd") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_scanrd = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-scanex") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_scanex = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-seed") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_seed = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-subloop") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_subloop = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-table") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_table = strdup(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-threads") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_threads = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-v") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_v = atoi(argv[0]);
+ continue;
+ }
+ }
+ if (strncmp(arg, "-v", 2) == 0 && isdigit(arg[2])) {
+ g_opt.m_v = atoi(&arg[2]);
+ continue;
+ }
+ if (strcmp(arg, "-h") == 0 || strcmp(arg, "-help") == 0) {
+ printhelp();
+ goto wrongargs;
+ }
+ ndbout << "testOIBasic: unknown option " << arg;
+ goto usage;
+ }
+ {
+ Par par(g_opt);
+ if (runtest(par) < 0)
+ goto failed;
+ }
+ // always exit with NDBT code
+ok:
+ return NDBT_ProgramExit(NDBT_OK);
+failed:
+ return NDBT_ProgramExit(NDBT_FAILED);
+usage:
+ ndbout << " (use -h for help)" << endl;
+wrongargs:
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+}
+
+// vim: set sw=2 et:
diff --git a/ndb/test/ndbapi/testOIBasic/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic/testOIBasic.cpp
deleted file mode 100644
index a47d9d2099e..00000000000
--- a/ndb/test/ndbapi/testOIBasic/testOIBasic.cpp
+++ /dev/null
@@ -1,2767 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- * testOIBasic - ordered index test
- */
-
-#include <ndb_global.h>
-
-#include <NdbMain.h>
-#include <NdbOut.hpp>
-#include <NdbApi.hpp>
-#include <NdbTest.hpp>
-#include <NdbMutex.h>
-#include <NdbCondition.h>
-#include <NdbThread.h>
-#include <NdbTick.h>
-
-// options
-
-struct Opt {
- // common options
- const char* m_case;
- bool m_core;
- bool m_dups;
- NdbDictionary::Object::FragmentType m_fragtype;
- const char* m_index;
- unsigned m_loop;
- unsigned m_rows;
- unsigned m_scanrd;
- unsigned m_scanex;
- unsigned m_seed;
- unsigned m_subloop;
- const char* m_table;
- unsigned m_threads;
- unsigned m_v;
- Opt() :
- m_case(0),
- m_core(false),
- m_dups(false),
- m_fragtype(NdbDictionary::Object::FragUndefined),
- m_index(0),
- m_loop(1),
- m_rows(1000),
- m_scanrd(240),
- m_scanex(240),
- m_seed(1),
- m_subloop(4),
- m_table(0),
- m_threads(4),
- m_v(1) {
- }
-};
-
-static Opt g_opt;
-
-static void printcases();
-static void printtables();
-
-static void
-printhelp()
-{
- Opt d;
- ndbout
- << "usage: testOIbasic [options]" << endl
- << " -case abc only given test cases (letters a-z)" << endl
- << " -core core dump on error [" << d.m_core << "]" << endl
- << " -dups allow duplicate tuples from index scan [" << d.m_dups << "]" << endl
- << " -fragtype T fragment type single/small/medium/large" << endl
- << " -index xyz only given index numbers (digits 1-9)" << endl
- << " -loop N loop count full suite forever=0 [" << d.m_loop << "]" << endl
- << " -rows N rows per thread [" << d.m_rows << "]" << endl
- << " -scanrd N scan read parallelism [" << d.m_scanrd << "]" << endl
- << " -scanex N scan exclusive parallelism [" << d.m_scanex << "]" << endl
- << " -seed N srandom seed [" << d.m_seed << "]" << endl
- << " -subloop N subtest loop count [" << d.m_subloop << "]" << endl
- << " -table xyz only given table numbers (digits 1-9)" << endl
- << " -threads N number of threads [" << d.m_threads << "]" << endl
- << " -vN verbosity [" << d.m_v << "]" << endl
- << " -h or -help print this help text" << endl
- ;
- printcases();
- printtables();
-}
-
-// log and error macros
-
-static NdbMutex ndbout_mutex = NDB_MUTEX_INITIALIZER;
-
-static unsigned getthrno();
-
-static const char*
-getthrstr()
-{
- static char buf[20];
- unsigned n = getthrno();
- if (n == (unsigned)-1)
- strcpy(buf, "");
- else {
- unsigned m =
- g_opt.m_threads < 10 ? 1 :
- g_opt.m_threads < 100 ? 2 : 3;
- sprintf(buf, "[%0*u] ", m, n);
- }
- return buf;
-}
-
-#define LLN(n, s) \
- do { \
- if ((n) > g_opt.m_v) break; \
- NdbMutex_Lock(&ndbout_mutex); \
- ndbout << getthrstr() << s << endl; \
- NdbMutex_Unlock(&ndbout_mutex); \
- } while(0)
-
-#define LL0(s) LLN(0, s)
-#define LL1(s) LLN(1, s)
-#define LL2(s) LLN(2, s)
-#define LL3(s) LLN(3, s)
-#define LL4(s) LLN(4, s)
-#define LL5(s) LLN(5, s)
-
-// following check a condition and return -1 on failure
-
-#undef CHK // simple check
-#undef CHKTRY // execute action (try-catch) on failure
-#undef CHKMSG // print extra message on failure
-#undef CHKCON // print NDB API errors on failure
-
-#define CHK(x) CHKTRY(x, ;)
-
-#define CHKTRY(x, act) \
- do { \
- if (x) break; \
- LL0("line " << __LINE__ << ": " << #x << " failed"); \
- if (g_opt.m_core) abort(); \
- act; \
- return -1; \
- } while (0)
-
-#define CHKMSG(x, msg) \
- do { \
- if (x) break; \
- LL0("line " << __LINE__ << ": " << #x << " failed: " << msg); \
- if (g_opt.m_core) abort(); \
- return -1; \
- } while (0)
-
-#define CHKCON(x, con) \
- do { \
- if (x) break; \
- LL0("line " << __LINE__ << ": " << #x << " failed"); \
- (con).printerror(ndbout); \
- if (g_opt.m_core) abort(); \
- return -1; \
- } while (0)
-
-// method parameters base class
-
-class Thr;
-class Con;
-class Tab;
-class Set;
-
-struct Par : public Opt {
- unsigned m_no;
- Con* m_con;
- Con& con() const { assert(m_con != 0); return *m_con; }
- const Tab* m_tab;
- const Tab& tab() const { assert(m_tab != 0); return *m_tab; }
- Set* m_set;
- Set& set() const { assert(m_set != 0); return *m_set; }
- unsigned m_totrows;
- unsigned m_batch;
- // value calculation
- unsigned m_pctnull;
- unsigned m_range;
- unsigned m_pctrange;
- // do verify after read
- bool m_verify;
- // timer location
- Par(const Opt& opt) :
- Opt(opt),
- m_no(0),
- m_con(0),
- m_tab(0),
- m_set(0),
- m_totrows(m_threads * m_rows),
- m_batch(32),
- m_pctnull(10),
- m_range(m_rows),
- m_pctrange(0),
- m_verify(false) {
- }
-};
-
-static bool
-usetable(unsigned i)
-{
- return g_opt.m_table == 0 || strchr(g_opt.m_table, '1' + i) != 0;
-}
-
-static bool
-useindex(unsigned i)
-{
- return g_opt.m_index == 0 || strchr(g_opt.m_index, '1' + i) != 0;
-}
-
-static unsigned
-thrrow(Par par, unsigned j)
-{
- return par.m_threads * j + par.m_no;
-}
-
-static bool
-isthrrow(Par par, unsigned i)
-{
- return i % par.m_threads == par.m_no;
-}
-
-// timer
-
-struct Tmr {
- void clr();
- void on();
- void off(unsigned cnt = 0);
- const char* time();
- const char* over(const Tmr& t1);
- NDB_TICKS m_on;
- unsigned m_ms;
- unsigned m_cnt;
- char m_time[100];
- char m_over[100];
- Tmr() { clr(); }
-};
-
-void
-Tmr::clr()
-{
- m_on = m_ms = m_cnt = m_time[0] = m_over[0] = 0;
-}
-
-void
-Tmr::on()
-{
- assert(m_on == 0);
- m_on = NdbTick_CurrentMillisecond();
-}
-
-void
-Tmr::off(unsigned cnt)
-{
- NDB_TICKS off = NdbTick_CurrentMillisecond();
- assert(m_on != 0 && off >= m_on);
- m_ms += off - m_on;
- m_cnt += cnt;
- m_on = 0;
-}
-
-const char*
-Tmr::time()
-{
- if (m_cnt == 0) {
- sprintf(m_time, "%u ms", m_ms);
- } else {
- sprintf(m_time, "%u ms per %u ( %u ms per 1000 )", m_ms, m_cnt, (1000 * m_ms) / m_cnt);
- }
- return m_time;
-}
-
-const char*
-Tmr::over(const Tmr& t1)
-{
- if (0 < t1.m_ms && t1.m_ms < m_ms) {
- sprintf(m_over, "%u pct", (100 * (m_ms - t1.m_ms)) / t1.m_ms);
- } else {
- sprintf(m_over, "[cannot measure]");
- }
- return m_over;
-}
-
-// tables and indexes
-
-// Col - table column
-
-struct Col {
- unsigned m_num;
- const char* m_name;
- bool m_pk;
- NdbDictionary::Column::Type m_type;
- unsigned m_length;
- bool m_nullable;
- void verify(const void* addr) const;
-};
-
-void
-Col::verify(const void* addr) const
-{
- switch (m_type) {
- case NdbDictionary::Column::Unsigned:
- break;
- case NdbDictionary::Column::Varchar:
- {
- const unsigned char* p = (const unsigned char*)addr;
- unsigned n = (p[0] << 8) | p[1];
- assert(n <= m_length);
- for (unsigned i = 0; i < n; i++) {
- assert(p[2 + i] != 0);
- }
- for (unsigned i = n; i < m_length; i++) {
- assert(p[2 + i] == 0);
- }
- }
- break;
- default:
- assert(false);
- break;
- }
-}
-
-static NdbOut&
-operator<<(NdbOut& out, const Col& col)
-{
- out << "col " << col.m_num;
- out << " " << col.m_name;
- switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
- out << " unsigned";
- break;
- case NdbDictionary::Column::Varchar:
- out << " varchar(" << col.m_length << ")";
- break;
- default:
- out << "type" << (int)col.m_type;
- assert(false);
- break;
- }
- out << (col.m_pk ? " pk" : "");
- out << (col.m_nullable ? " nullable" : "");
- return out;
-}
-
-// ICol - index column
-
-struct ICol {
- unsigned m_num;
- struct Col m_col;
-};
-
-// ITab - index
-
-struct ITab {
- const char* m_name;
- unsigned m_icols;
- const ICol* m_icol;
-};
-
-static NdbOut&
-operator<<(NdbOut& out, const ITab& itab)
-{
- out << "itab " << itab.m_name << " " << itab.m_icols;
- for (unsigned k = 0; k < itab.m_icols; k++) {
- out << endl;
- out << "icol " << k << " " << itab.m_icol[k].m_col;
- }
- return out;
-}
-
-// Tab - table
-
-struct Tab {
- const char* m_name;
- unsigned m_cols;
- const Col* m_col;
- unsigned m_itabs;
- const ITab* m_itab;
-};
-
-static NdbOut&
-operator<<(NdbOut& out, const Tab& tab)
-{
- out << "tab " << tab.m_name << " " << tab.m_cols;
- for (unsigned k = 0; k < tab.m_cols; k++) {
- out << endl;
- out << tab.m_col[k];
- }
- for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
- continue;
- out << endl;
- out << tab.m_itab[i];
- }
- return out;
-}
-
-// tt1 + tt1x1 tt1x2 tt1x3 tt1x4
-
-static const Col
-tt1col[] = {
- { 0, "A", 1, NdbDictionary::Column::Unsigned, 1, 0 },
- { 1, "B", 0, NdbDictionary::Column::Unsigned, 1, 1 },
- { 2, "C", 0, NdbDictionary::Column::Unsigned, 1, 1 },
- { 3, "D", 0, NdbDictionary::Column::Unsigned, 1, 1 },
- { 4, "E", 0, NdbDictionary::Column::Unsigned, 1, 1 }
-};
-
-static const ICol
-tt1x1col[] = {
- { 0, tt1col[1] }
-};
-
-static const ICol
-tt1x2col[] = {
- { 0, tt1col[1] },
- { 1, tt1col[2] }
-};
-
-static const ICol
-tt1x3col[] = {
- { 0, tt1col[3] },
- { 1, tt1col[2] },
- { 2, tt1col[1] }
-};
-
-static const ICol
-tt1x4col[] = {
- { 0, tt1col[1] },
- { 1, tt1col[4] },
- { 2, tt1col[2] },
- { 3, tt1col[3] }
-};
-
-static const ITab
-tt1x1 = {
- "TT1X1", 1, tt1x1col
-};
-
-static const ITab
-tt1x2 = {
- "TT1X2", 2, tt1x2col
-};
-
-static const ITab
-tt1x3 = {
- "TT1X3", 3, tt1x3col
-};
-
-static const ITab
-tt1x4 = {
- "TT1X4", 4, tt1x4col
-};
-
-static const ITab
-tt1itab[] = {
- tt1x1,
- tt1x2,
- tt1x3,
- tt1x4
-};
-
-static const Tab
-tt1 = {
- "TT1", 5, tt1col, 4, tt1itab
-};
-
-// tt2 + tt2x1 tt2x2 tt2x3
-
-static const Col
-tt2col[] = {
- { 0, "A", 1, NdbDictionary::Column::Unsigned, 1, 0 },
- { 1, "B", 0, NdbDictionary::Column::Unsigned, 1, 1 },
- { 2, "C", 0, NdbDictionary::Column::Varchar, 20, 1 },
- { 3, "D", 0, NdbDictionary::Column::Varchar, 5, 1 },
- { 4, "E", 0, NdbDictionary::Column::Varchar, 5, 1 }
-};
-
-static const ICol
-tt2x1col[] = {
- { 0, tt2col[1] },
- { 1, tt2col[2] }
-};
-
-static const ICol
-tt2x2col[] = {
- { 0, tt2col[2] },
- { 1, tt2col[1] }
-};
-
-static const ICol
-tt2x3col[] = {
- { 0, tt2col[3] },
- { 1, tt2col[4] }
-};
-
-static const ITab
-tt2x1 = {
- "TT2X1", 2, tt2x1col
-};
-
-static const ITab
-tt2x2 = {
- "TT2X2", 2, tt2x2col
-};
-
-static const ITab
-tt2x3 = {
- "TT2X3", 2, tt2x3col
-};
-
-static const ITab
-tt2itab[] = {
- tt2x1,
- tt2x2,
- tt2x3
-};
-
-static const Tab
-tt2 = {
- "TT2", 5, tt2col, 3, tt2itab
-};
-
-// all tables
-
-static const Tab
-tablist[] = {
- tt1,
- tt2
-};
-
-static const unsigned
-tabcount = sizeof(tablist) / sizeof(tablist[0]);
-
-// connections
-
-struct Con {
- Ndb* m_ndb;
- NdbDictionary::Dictionary* m_dic;
- NdbConnection* m_tx;
- NdbOperation* m_op;
- NdbConnection* m_scantx;
- NdbOperation* m_scanop;
- enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive };
- ScanMode m_scanmode;
- enum ErrType { ErrNone = 0, ErrDeadlock, ErrOther };
- ErrType m_errtype;
- Con() :
- m_ndb(0), m_dic(0), m_tx(0), m_op(0),
- m_scantx(0), m_scanop(0), m_scanmode(ScanNo), m_errtype(ErrNone) {}
- int connect();
- void disconnect();
- int startTransaction();
- int startBuddyTransaction(const Con& con);
- int getNdbOperation(const Tab& tab);
- int getNdbOperation(const ITab& itab, const Tab& tab);
- int equal(int num, const char* addr);
- int getValue(int num, NdbRecAttr*& rec);
- int setValue(int num, const char* addr);
- int setBound(int num, int type, const void* value);
- int execute(ExecType t);
- int openScanRead(unsigned parallelism);
- int openScanExclusive(unsigned parallelism);
- int executeScan();
- int nextScanResult();
- int takeOverForUpdate(Con& scan);
- int takeOverForDelete(Con& scan);
- void closeTransaction();
- void printerror(NdbOut& out);
- // flush dict cache
- int bugger() {
- //disconnect();
- //CHK(connect() == 0);
- return 0;
- }
-};
-
-int
-Con::connect()
-{
- assert(m_ndb == 0);
- m_ndb = new Ndb("TEST_DB");
- CHKCON(m_ndb->init() == 0, *this);
- CHKCON(m_ndb->waitUntilReady(30) == 0, *this);
- m_dic = m_ndb->getDictionary();
- m_tx = 0, m_op = 0;
- return 0;
-}
-
-void
-Con::disconnect()
-{
- delete m_ndb;
- m_ndb = 0, m_dic = 0, m_tx = 0, m_op = 0;
-}
-
-int
-Con::startTransaction()
-{
- assert(m_ndb != 0 && m_tx == 0);
- CHKCON((m_tx = m_ndb->startTransaction()) != 0, *this);
- return 0;
-}
-
-int
-Con::startBuddyTransaction(const Con& con)
-{
- assert(m_ndb != 0 && m_tx == 0 && con.m_ndb == m_ndb && con.m_tx != 0);
- CHKCON((m_tx = m_ndb->hupp(con.m_tx)) != 0, *this);
- return 0;
-}
-
-int
-Con::getNdbOperation(const Tab& tab)
-{
- assert(m_tx != 0);
- CHKCON((m_op = m_tx->getNdbOperation(tab.m_name)) != 0, *this);
- return 0;
-}
-
-int
-Con::getNdbOperation(const ITab& itab, const Tab& tab)
-{
- CHKCON((m_op = m_tx->getNdbOperation(itab.m_name, tab.m_name)) != 0, *this);
- return 0;
-}
-
-int
-Con::equal(int num, const char* addr)
-{
- assert(m_tx != 0 && m_op != 0);
- CHKCON(m_op->equal(num, addr) == 0, *this);
- return 0;
-}
-
-int
-Con::getValue(int num, NdbRecAttr*& rec)
-{
- assert(m_tx != 0 && m_op != 0);
- CHKCON((rec = m_op->getValue(num, 0)) != 0, *this);
- return 0;
-}
-
-int
-Con::setValue(int num, const char* addr)
-{
- assert(m_tx != 0 && m_op != 0);
- CHKCON(m_op->setValue(num, addr) == 0, *this);
- return 0;
-}
-
-int
-Con::setBound(int num, int type, const void* value)
-{
- assert(m_tx != 0 && m_op != 0);
- CHKCON(m_op->setBound(num, type, value) == 0, *this);
- return 0;
-}
-
-int
-Con::execute(ExecType t)
-{
- assert(m_tx != 0);
- CHKCON(m_tx->execute(t) == 0, *this);
- return 0;
-}
-
-int
-Con::openScanRead(unsigned parallelism)
-{
- assert(m_tx != 0 && m_op != 0);
- CHKCON(m_op->openScanRead(parallelism) == 0, *this);
- return 0;
-}
-
-int
-Con::openScanExclusive(unsigned parallelism)
-{
- assert(m_tx != 0 && m_op != 0);
- CHKCON(m_op->openScanExclusive(parallelism) == 0, *this);
- return 0;
-}
-
-int
-Con::executeScan()
-{
- CHKCON(m_tx->executeScan() == 0, *this);
- return 0;
-}
-
-int
-Con::nextScanResult()
-{
- int ret;
- CHKCON((ret = m_tx->nextScanResult()) != -1, *this);
- assert(ret == 0 || ret == 1);
- return ret;
-}
-
-int
-Con::takeOverForUpdate(Con& scan)
-{
- assert(m_tx != 0 && scan.m_op != 0);
- CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan);
- return 0;
-}
-
-int
-Con::takeOverForDelete(Con& scan)
-{
- assert(m_tx != 0 && scan.m_op != 0);
- CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan);
- return 0;
-}
-
-void
-Con::closeTransaction()
-{
- assert(m_ndb != 0 && m_tx != 0);
- m_ndb->closeTransaction(m_tx);
- m_tx = 0, m_op = 0;
-}
-
-void
-Con::printerror(NdbOut& out)
-{
- m_errtype = ErrOther;
- unsigned any = 0;
- int code;
- if (m_ndb) {
- if ((code = m_ndb->getNdbError().code) != 0) {
- LL0(++any << " ndb: error " << m_ndb->getNdbError());
- }
- if (m_dic && (code = m_dic->getNdbError().code) != 0) {
- LL0(++any << " dic: error " << m_dic->getNdbError());
- }
- if (m_tx) {
- if ((code = m_tx->getNdbError().code) != 0) {
- LL0(++any << " con: error " << m_tx->getNdbError());
- if (code == 266 || code == 274 || code == 296 || code == 297)
- m_errtype = ErrDeadlock;
- }
- if (m_op && m_op->getNdbError().code != 0) {
- LL0(++any << " op : error " << m_op->getNdbError());
- }
- }
- }
- if (! any) {
- LL0("failed but no NDB error code");
- }
-}
-
-// dictionary operations
-
-static int
-invalidateindex(Par par, const ITab& itab)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- con.m_dic->invalidateIndex(itab.m_name, tab.m_name);
- return 0;
-}
-
-static int
-invalidateindex(Par par)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
- continue;
- const ITab& itab = tab.m_itab[i];
- invalidateindex(par, itab);
- }
- return 0;
-}
-
-static int
-invalidatetable(Par par)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- invalidateindex(par);
- con.m_dic->invalidateTable(tab.m_name);
- return 0;
-}
-
-static int
-droptable(Par par)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- if (con.m_dic->getTable(tab.m_name) == 0) {
- // how to check for error
- LL4("no table " << tab.m_name);
- } else {
- LL3("drop table " << tab.m_name);
- CHKCON(con.m_dic->dropTable(tab.m_name) == 0, con);
- }
- return 0;
-}
-
-static int
-createtable(Par par)
-{
- Con& con = par.con();
- CHK(con.bugger() == 0);
- const Tab& tab = par.tab();
- LL3("create table " << tab.m_name);
- LL4(tab);
- NdbDictionary::Table t(tab.m_name);
- if (par.m_fragtype != NdbDictionary::Object::FragUndefined) {
- t.setFragmentType(par.m_fragtype);
- }
- for (unsigned k = 0; k < tab.m_cols; k++) {
- const Col& col = tab.m_col[k];
- NdbDictionary::Column c(col.m_name);
- c.setPrimaryKey(col.m_pk);
- c.setType(col.m_type);
- c.setLength(col.m_length);
- c.setNullable(col.m_nullable);
- t.addColumn(c);
- }
- CHKCON(con.m_dic->createTable(t) == 0, con);
- return 0;
-}
-
-static int
-dropindex(Par par, const ITab& itab)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- if (con.m_dic->getIndex(itab.m_name, tab.m_name) == 0) {
- // how to check for error
- LL4("no index " << itab.m_name);
- } else {
- LL3("drop index " << itab.m_name);
- CHKCON(con.m_dic->dropIndex(itab.m_name, tab.m_name) == 0, con);
- }
- return 0;
-}
-
-static int
-dropindex(Par par)
-{
- const Tab& tab = par.tab();
- for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
- continue;
- const ITab& itab = tab.m_itab[i];
- CHK(dropindex(par, itab) == 0);
- }
- return 0;
-}
-
-static int
-createindex(Par par, const ITab& itab)
-{
- Con& con = par.con();
- CHK(con.bugger() == 0);
- const Tab& tab = par.tab();
- LL3("create index " << itab.m_name);
- LL4(itab);
- NdbDictionary::Index x(itab.m_name);
- x.setTable(tab.m_name);
- x.setType(NdbDictionary::Index::OrderedIndex);
- x.setLogging(false);
- for (unsigned k = 0; k < itab.m_icols; k++) {
- const Col& col = itab.m_icol[k].m_col;
- x.addColumnName(col.m_name);
- }
- CHKCON(con.m_dic->createIndex(x) == 0, con);
- return 0;
-}
-
-static int
-createindex(Par par)
-{
- const Tab& tab = par.tab();
- for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
- continue;
- const ITab& itab = tab.m_itab[i];
- CHK(createindex(par, itab) == 0);
- }
- return 0;
-}
-
-// data sets
-
-static unsigned
-urandom(unsigned n)
-{
- if (n == 0)
- return 0;
- unsigned i = random() % n;
- return i;
-}
-
-static int
-irandom(unsigned n)
-{
- if (n == 0)
- return 0;
- int i = random() % n;
- if (random() & 0x1)
- i = -i;
- return i;
-}
-
-// Val - typed column value
-
-struct Val {
- const Col& m_col;
- union {
- Uint32 m_uint32;
- char* m_varchar;
- };
- Val(const Col& col);
- ~Val();
- void copy(const Val& val2);
- void copy(const void* addr);
- const void* dataaddr() const;
- bool m_null;
- int setval(Par par) const;
- void calc(Par par, unsigned i);
- int verify(const Val& val2) const;
- int cmp(const Val& val2) const;
-private:
- Val& operator=(const Val& val2);
-};
-
-static NdbOut&
-operator<<(NdbOut& out, const Val& val);
-
-Val::Val(const Col& col) :
- m_col(col)
-{
- switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
- break;
- case NdbDictionary::Column::Varchar:
- m_varchar = new char [2 + col.m_length];
- break;
- default:
- assert(false);
- break;
- }
-}
-
-Val::~Val()
-{
- const Col& col = m_col;
- switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
- break;
- case NdbDictionary::Column::Varchar:
- delete [] m_varchar;
- break;
- default:
- assert(false);
- break;
- }
-}
-
-void
-Val::copy(const Val& val2)
-{
- const Col& col = m_col;
- const Col& col2 = val2.m_col;
- assert(col.m_type == col2.m_type && col.m_length == col2.m_length);
- if (val2.m_null) {
- m_null = true;
- return;
- }
- copy(val2.dataaddr());
-}
-
-void
-Val::copy(const void* addr)
-{
- const Col& col = m_col;
- switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
- m_uint32 = *(const Uint32*)addr;
- break;
- case NdbDictionary::Column::Varchar:
- memcpy(m_varchar, addr, 2 + col.m_length);
- break;
- default:
- assert(false);
- break;
- }
- m_null = false;
-}
-
-const void*
-Val::dataaddr() const
-{
- const Col& col = m_col;
- switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
- return &m_uint32;
- case NdbDictionary::Column::Varchar:
- return m_varchar;
- default:
- break;
- }
- assert(false);
- return 0;
-}
-
-int
-Val::setval(Par par) const
-{
- Con& con = par.con();
- const Col& col = m_col;
- const char* addr = (const char*)dataaddr();
- if (m_null)
- addr = 0;
- if (col.m_pk)
- CHK(con.equal(col.m_num, addr) == 0);
- else
- CHK(con.setValue(col.m_num, addr) == 0);
- LL5("setval [" << m_col << "] " << *this);
- return 0;
-}
-
-void
-Val::calc(Par par, unsigned i)
-{
- const Col& col = m_col;
- m_null = false;
- if (col.m_pk) {
- m_uint32 = i;
- return;
- }
- if (col.m_nullable && urandom(100) < par.m_pctnull) {
- m_null = true;
- return;
- }
- unsigned v = par.m_range + irandom((par.m_pctrange * par.m_range) / 100);
- switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
- m_uint32 = v;
- break;
- case NdbDictionary::Column::Varchar:
- {
- unsigned n = 0;
- while (n < col.m_length) {
- if (urandom(1 + col.m_length) == 0) {
- // nice distribution on lengths
- break;
- }
- m_varchar[2 + n++] = 'a' + urandom((par.m_pctrange * 10) / 100);
- }
- m_varchar[0] = (n >> 8);
- m_varchar[1] = (n & 0xff);
- while (n < col.m_length) {
- m_varchar[2 + n++] = 0;
- }
- }
- break;
- default:
- assert(false);
- break;
- }
- // verify format
- col.verify(dataaddr());
-}
-
-int
-Val::verify(const Val& val2) const
-{
- CHK(cmp(val2) == 0);
- return 0;
-}
-
-int
-Val::cmp(const Val& val2) const
-{
- const Col& col = m_col;
- const Col& col2 = val2.m_col;
- assert(col.m_type == col2.m_type && col.m_length == col2.m_length);
- if (m_null || val2.m_null) {
- if (! m_null)
- return -1;
- if (! val2.m_null)
- return +1;
- return 0;
- }
- // verify data formats
- col.verify(dataaddr());
- col.verify(val2.dataaddr());
- // compare
- switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
- if (m_uint32 < val2.m_uint32)
- return -1;
- if (m_uint32 > val2.m_uint32)
- return +1;
- return 0;
- case NdbDictionary::Column::Varchar:
- return memcmp(&m_varchar[2], &val2.m_varchar[2], col.m_length);
- default:
- break;
- }
- assert(false);
- return 0;
-}
-
-static NdbOut&
-operator<<(NdbOut& out, const Val& val)
-{
- const Col& col = val.m_col;
- if (val.m_null) {
- out << "NULL";
- return out;
- }
- switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
- out << val.m_uint32;
- break;
- case NdbDictionary::Column::Varchar:
- {
- char buf[8000];
- unsigned n = (val.m_varchar[0] << 8) | val.m_varchar[1];
- assert(n <= col.m_length);
- sprintf(buf, "'%.*s'[%d]", n, &val.m_varchar[2], n);
- out << buf;
- }
- break;
- default:
- out << "type" << col.m_type;
- assert(false);
- break;
- }
- return out;
-}
-
-// Row - table tuple
-
-struct Row {
- const Tab& m_tab;
- Val** m_val;
- bool m_exist;
- Row(const Tab& tab);
- ~Row();
- void copy(const Row& row2);
- void calc(Par par, unsigned i);
- int verify(const Row& row2) const;
- int insrow(Par par);
- int updrow(Par par);
- int delrow(Par par);
- int selrow(Par par);
- int setrow(Par par);
- int cmp(const Row& row2) const;
-private:
- Row& operator=(const Row& row2);
-};
-
-Row::Row(const Tab& tab) :
- m_tab(tab)
-{
- m_val = new Val* [tab.m_cols];
- for (unsigned k = 0; k < tab.m_cols; k++) {
- const Col& col = tab.m_col[k];
- m_val[k] = new Val(col);
- }
- m_exist = false;
-}
-
-Row::~Row()
-{
- const Tab& tab = m_tab;
- for (unsigned k = 0; k < tab.m_cols; k++) {
- delete m_val[k];
- }
- delete [] m_val;
-}
-
-void
-Row::copy(const Row& row2)
-{
- const Tab& tab = m_tab;
- assert(&tab == &row2.m_tab);
- for (unsigned k = 0; k < tab.m_cols; k++) {
- Val& val = *m_val[k];
- const Val& val2 = *row2.m_val[k];
- val.copy(val2);
- }
-}
-
-void
-Row::calc(Par par, unsigned i)
-{
- const Tab& tab = m_tab;
- for (unsigned k = 0; k < tab.m_cols; k++) {
- Val& val = *m_val[k];
- val.calc(par, i);
- }
-}
-
-int
-Row::verify(const Row& row2) const
-{
- const Tab& tab = m_tab;
- assert(&tab == &row2.m_tab);
- for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
- const Val& val2 = *row2.m_val[k];
- CHK(val.verify(val2) == 0);
- }
- return 0;
-}
-
-int
-Row::insrow(Par par)
-{
- Con& con = par.con();
- const Tab& tab = m_tab;
- assert(! m_exist);
- CHK(con.getNdbOperation(tab) == 0);
- CHKCON(con.m_op->insertTuple() == 0, con);
- for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
- CHK(val.setval(par) == 0);
- }
- m_exist = true;
- return 0;
-}
-
-int
-Row::updrow(Par par)
-{
- Con& con = par.con();
- const Tab& tab = m_tab;
- assert(m_exist);
- CHK(con.getNdbOperation(tab) == 0);
- CHKCON(con.m_op->updateTuple() == 0, con);
- for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
- CHK(val.setval(par) == 0);
- }
- return 0;
-}
-
-int
-Row::delrow(Par par)
-{
- Con& con = par.con();
- const Tab& tab = m_tab;
- assert(m_exist);
- CHK(con.getNdbOperation(m_tab) == 0);
- CHKCON(con.m_op->deleteTuple() == 0, con);
- for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
- const Col& col = val.m_col;
- if (col.m_pk)
- CHK(val.setval(par) == 0);
- }
- m_exist = false;
- return 0;
-}
-
-int
-Row::selrow(Par par)
-{
- Con& con = par.con();
- const Tab& tab = m_tab;
- CHK(con.getNdbOperation(m_tab) == 0);
- CHKCON(con.m_op->readTuple() == 0, con);
- for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
- const Col& col = val.m_col;
- if (col.m_pk)
- CHK(val.setval(par) == 0);
- }
- m_exist = false;
- return 0;
-}
-
-int
-Row::setrow(Par par)
-{
- Con& con = par.con();
- const Tab& tab = m_tab;
- for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
- const Col& col = val.m_col;
- if (! col.m_pk)
- CHK(val.setval(par) == 0);
- }
- return 0;
-}
-
-int
-Row::cmp(const Row& row2) const
-{
- const Tab& tab = m_tab;
- assert(&tab == &row2.m_tab);
- int c = 0;
- for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
- const Val& val2 = *row2.m_val[k];
- if ((c = val.cmp(val2)) != 0)
- break;
- }
- return c;
-}
-
-static NdbOut&
-operator<<(NdbOut& out, const Row& row)
-{
- const Tab& tab = row.m_tab;
- for (unsigned i = 0; i < tab.m_cols; i++) {
- if (i > 0)
- out << " ";
- out << *row.m_val[i];
- }
- return out;
-}
-
-// Set - set of table tuples
-
-struct Set {
- const Tab& m_tab;
- unsigned m_rows;
- unsigned m_count;
- Row** m_row;
- Row** m_saverow;
- Row* m_keyrow;
- NdbRecAttr** m_rec;
- Set(const Tab& tab, unsigned rows);
- ~Set();
- // row methods
- bool exist(unsigned i) const;
- void calc(Par par, unsigned i);
- int insrow(Par par, unsigned i);
- int updrow(Par par, unsigned i);
- int delrow(Par par, unsigned i);
- int selrow(Par par, unsigned i);
- int setrow(Par par, unsigned i);
- int getval(Par par);
- int getkey(Par par, unsigned* i);
- int putval(unsigned i, bool force);
- // set methods
- int verify(const Set& set2) const;
- void savepoint();
- void commit();
- void rollback();
- // locking (not perfect since ops may complete in different order)
- NdbMutex* m_mutex;
- void lock() {
- NdbMutex_Lock(m_mutex);
- }
- void unlock() {
- NdbMutex_Unlock(m_mutex);
- }
-private:
- Set& operator=(const Set& set2);
-};
-
-Set::Set(const Tab& tab, unsigned rows) :
- m_tab(tab)
-{
- m_rows = rows;
- m_count = 0;
- m_row = new Row* [m_rows];
- for (unsigned i = 0; i < m_rows; i++) {
- m_row[i] = 0;
- }
- m_saverow = 0;
- m_keyrow = new Row(tab);
- m_rec = new NdbRecAttr* [tab.m_cols];
- for (unsigned k = 0; k < tab.m_cols; k++) {
- m_rec[k] = 0;
- }
- m_mutex = NdbMutex_Create();
- assert(m_mutex != 0);
-}
-
-Set::~Set()
-{
- for (unsigned i = 0; i < m_rows; i++) {
- delete m_row[i];
- if (m_saverow != 0)
- delete m_saverow[i];
- }
- delete [] m_row;
- delete [] m_saverow;
- delete m_keyrow;
- delete [] m_rec;
- NdbMutex_Destroy(m_mutex);
-}
-
-bool
-Set::exist(unsigned i) const
-{
- assert(i < m_rows);
- return m_row[i] != 0 && m_row[i]->m_exist;
-}
-
-void
-Set::calc(Par par, unsigned i)
-{
- const Tab& tab = m_tab;
- if (m_row[i] == 0)
- m_row[i] = new Row(tab);
- Row& row = *m_row[i];
- // value generation parameters
- par.m_pctnull = 10;
- par.m_pctrange = 40;
- row.calc(par, i);
-}
-
-int
-Set::insrow(Par par, unsigned i)
-{
- assert(m_row[i] != 0 && m_count < m_rows);
- CHK(m_row[i]->insrow(par) == 0);
- m_count++;
- return 0;
-}
-
-int
-Set::updrow(Par par, unsigned i)
-{
- assert(m_row[i] != 0);
- CHK(m_row[i]->updrow(par) == 0);
- return 0;
-}
-
-int
-Set::delrow(Par par, unsigned i)
-{
- assert(m_row[i] != 0 && m_count != 0);
- CHK(m_row[i]->delrow(par) == 0);
- m_count--;
- return 0;
-}
-
-int
-Set::selrow(Par par, unsigned i)
-{
- Con& con = par.con();
- m_keyrow->calc(par, i);
- CHK(m_keyrow->selrow(par) == 0);
- CHK(getval(par) == 0);
- return 0;
-}
-
-int
-Set::setrow(Par par, unsigned i)
-{
- Con& con = par.con();
- assert(m_row[i] != 0);
- CHK(m_row[i]->setrow(par) == 0);
- return 0;
-}
-
-int
-Set::getval(Par par)
-{
- Con& con = par.con();
- const Tab& tab = m_tab;
- for (unsigned k = 0; k < tab.m_cols; k++) {
- CHK(con.getValue(k, m_rec[k]) == 0);
- }
- return 0;
-}
-
-int
-Set::getkey(Par par, unsigned* i)
-{
- assert(m_rec[0] != 0);
- const char* aRef0 = m_rec[0]->aRef();
- Uint32 key = *(const Uint32*)aRef0;
- CHKMSG(key < m_rows, "key=" << key << " rows=" << m_rows);
- *i = key;
- return 0;
-}
-
-int
-Set::putval(unsigned i, bool force)
-{
- const Tab& tab = m_tab;
- if (m_row[i] == 0)
- m_row[i] = new Row(tab);
- Row& row = *m_row[i];
- CHK(! row.m_exist || force);
- for (unsigned k = 0; k < tab.m_cols; k++) {
- Val& val = *row.m_val[k];
- NdbRecAttr* rec = m_rec[k];
- assert(rec != 0);
- if (rec->isNULL()) {
- val.m_null = true;
- continue;
- }
- const char* aRef = m_rec[k]->aRef();
- val.copy(aRef);
- val.m_null = false;
- }
- if (! row.m_exist) {
- row.m_exist = true;
- m_count++;
- }
- return 0;
-}
-
-int
-Set::verify(const Set& set2) const
-{
- const Tab& tab = m_tab;
- assert(&tab == &set2.m_tab && m_rows == set2.m_rows);
- CHKMSG(m_count == set2.m_count, "set=" << m_count << " set2=" << set2.m_count);
- for (unsigned i = 0; i < m_rows; i++) {
- CHK(exist(i) == set2.exist(i));
- if (! exist(i))
- continue;
- Row& row = *m_row[i];
- Row& row2 = *set2.m_row[i];
- CHK(row.verify(row2) == 0);
- }
- return 0;
-}
-
-void
-Set::savepoint()
-{
- const Tab& tab = m_tab;
- assert(m_saverow == 0);
- m_saverow = new Row* [m_rows];
- for (unsigned i = 0; i < m_rows; i++) {
- if (m_row[i] == 0)
- m_saverow[i] = 0;
- else {
- m_saverow[i] = new Row(tab);
- m_saverow[i]->copy(*m_row[i]);
- }
- }
-}
-
-void
-Set::commit()
-{
- delete [] m_saverow;
- m_saverow = 0;
-}
-
-void
-Set::rollback()
-{
- assert(m_saverow != 0);
- m_row = m_saverow;
- m_saverow = 0;
-}
-
-static NdbOut&
-operator<<(NdbOut& out, const Set& set)
-{
- for (unsigned i = 0; i < set.m_rows; i++) {
- const Row& row = *set.m_row[i];
- if (i > 0)
- out << endl;
- out << row;
- }
- return out;
-}
-
-// BVal - range scan bound
-
-struct BVal : public Val {
- const ICol& m_icol;
- int m_type;
- BVal(const ICol& icol);
- int setbnd(Par par) const;
-};
-
-BVal::BVal(const ICol& icol) :
- Val(icol.m_col),
- m_icol(icol)
-{
-}
-
-int
-BVal::setbnd(Par par) const
-{
- Con& con = par.con();
- const char* addr = (const char*)dataaddr();
- assert(! m_null);
- const ICol& icol = m_icol;
- CHK(con.setBound(icol.m_num, m_type, addr) == 0);
- return 0;
-}
-
-static NdbOut&
-operator<<(NdbOut& out, const BVal& bval)
-{
- const ICol& icol = bval.m_icol;
- const Col& col = icol.m_col;
- const Val& val = bval;
- out << "type " << bval.m_type;
- out << " icol " << icol.m_num;
- out << " col " << col.m_name << "(" << col.m_num << ")";
- out << " value " << val;
- return out;
-}
-
-// BSet - set of bounds
-
-struct BSet {
- const Tab& m_tab;
- const ITab& m_itab;
- unsigned m_alloc;
- unsigned m_bvals;
- BVal** m_bval;
- BSet(const Tab& tab, const ITab& itab, unsigned rows);
- void calc(Par par);
- int setbnd(Par par) const;
- void filter(const Set& set, Set& set2) const;
-};
-
-BSet::BSet(const Tab& tab, const ITab& itab, unsigned rows) :
- m_tab(tab),
- m_itab(itab),
- m_alloc(2 * itab.m_icols),
- m_bvals(0)
-{
- m_bval = new BVal* [m_alloc];
-}
-
-void
-BSet::calc(Par par)
-{
- const ITab& itab = m_itab;
- for (unsigned k = 0; k < itab.m_icols; k++) {
- const ICol& icol = itab.m_icol[k];
- const Col& col = icol.m_col;
- for (unsigned i = 0; i <= 1; i++) {
- if (urandom(10) == 0)
- return;
- assert(m_bvals < m_alloc);
- BVal& bval = *new BVal(icol);
- m_bval[m_bvals++] = &bval;
- bval.m_null = false;
- // equality bound only on i==0
- unsigned sel = urandom(5 - i);
- if (sel < 2)
- bval.m_type = 0 | (1 << i);
- else if (sel < 4)
- bval.m_type = 1 | (1 << i);
- else
- bval.m_type = 4;
- if (k + 1 < itab.m_icols)
- bval.m_type = 4;
- // value generation parammeters
- par.m_pctnull = 0;
- par.m_pctrange = 50; // bit higher
- do {
- bval.calc(par, 0);
- if (i == 1) {
- assert(m_bvals >= 2);
- const BVal& bv1 = *m_bval[m_bvals - 2];
- const BVal& bv2 = *m_bval[m_bvals - 1];
- if (bv1.cmp(bv2) > 0 && urandom(100) != 0)
- continue;
- }
- } while (0);
- // equality bound only once
- if (bval.m_type == 4)
- break;
- }
- }
-}
-
-int
-BSet::setbnd(Par par) const
-{
- for (unsigned j = 0; j < m_bvals; j++) {
- const BVal& bval = *m_bval[j];
- CHK(bval.setbnd(par) == 0);
- }
- return 0;
-}
-
-void
-BSet::filter(const Set& set, Set& set2) const
-{
- const Tab& tab = m_tab;
- const ITab& itab = m_itab;
- assert(&tab == &set2.m_tab && set.m_rows == set2.m_rows);
- assert(set2.m_count == 0);
- for (unsigned i = 0; i < set.m_rows; i++) {
- if (! set.exist(i))
- continue;
- const Row& row = *set.m_row[i];
- bool ok1 = false;
- for (unsigned k = 0; k < itab.m_icols; k++) {
- const ICol& icol = itab.m_icol[k];
- const Col& col = icol.m_col;
- const Val& val = *row.m_val[col.m_num];
- if (! val.m_null) {
- ok1 = true;
- break;
- }
- }
- if (! ok1)
- continue;
- bool ok2 = true;
- for (unsigned j = 0; j < m_bvals; j++) {
- const BVal& bval = *m_bval[j];
- const ICol& icol = bval.m_icol;
- const Col& col = icol.m_col;
- const Val& val = *row.m_val[col.m_num];
- int ret = bval.cmp(val);
- if (bval.m_type == 0)
- ok2 = (ret <= 0);
- else if (bval.m_type == 1)
- ok2 = (ret < 0);
- else if (bval.m_type == 2)
- ok2 = (ret >= 0);
- else if (bval.m_type == 3)
- ok2 = (ret > 0);
- else if (bval.m_type == 4)
- ok2 = (ret == 0);
- else {
- assert(false);
- }
- if (! ok2)
- break;
- }
- if (! ok2)
- continue;
- if (set2.m_row[i] == 0)
- set2.m_row[i] = new Row(tab);
- Row& row2 = *set2.m_row[i];
- assert(! row2.m_exist);
- row2.copy(row);
- row2.m_exist = true;
- set2.m_count++;
- }
-}
-
-static NdbOut&
-operator<<(NdbOut& out, const BSet& bset)
-{
- out << "bounds=" << bset.m_bvals;
- for (unsigned j = 0; j < bset.m_bvals; j++) {
- out << endl;
- const BVal& bval = *bset.m_bval[j];
- out << "bound " << j << ": " << bval;
- }
- return out;
-}
-
-// pk operations
-
-static int
-pkinsert(Par par)
-{
- Con& con = par.con();
- Set& set = par.set();
- LL3("pkinsert");
- CHK(con.startTransaction() == 0);
- unsigned n = 0;
- for (unsigned j = 0; j < par.m_rows; j++) {
- unsigned i = thrrow(par, j);
- set.lock();
- if (set.exist(i)) {
- set.unlock();
- continue;
- }
- set.calc(par, i);
- LL4("pkinsert " << i << ": " << *set.m_row[i]);
- CHKTRY(set.insrow(par, i) == 0, set.unlock());
- set.unlock();
- if (++n == par.m_batch) {
- CHK(con.execute(Commit) == 0);
- con.closeTransaction();
- CHK(con.startTransaction() == 0);
- n = 0;
- }
- }
- if (n != 0) {
- CHK(con.execute(Commit) == 0);
- n = 0;
- }
- con.closeTransaction();
- return 0;
-};
-
-static int
-pkupdate(Par par)
-{
- Con& con = par.con();
- Set& set = par.set();
- LL3("pkupdate");
- CHK(con.startTransaction() == 0);
- unsigned n = 0;
- for (unsigned j = 0; j < par.m_rows; j++) {
- unsigned i = thrrow(par, j);
- set.lock();
- if (! set.exist(i)) {
- set.unlock();
- continue;
- }
- set.calc(par, i);
- LL4("pkupdate " << i << ": " << *set.m_row[i]);
- CHKTRY(set.updrow(par, i) == 0, set.unlock());
- set.unlock();
- if (++n == par.m_batch) {
- CHK(con.execute(Commit) == 0);
- con.closeTransaction();
- CHK(con.startTransaction() == 0);
- n = 0;
- }
- }
- if (n != 0) {
- CHK(con.execute(Commit) == 0);
- n = 0;
- }
- con.closeTransaction();
- return 0;
-};
-
-static int
-pkdelete(Par par)
-{
- Con& con = par.con();
- Set& set = par.set();
- LL3("pkdelete");
- CHK(con.startTransaction() == 0);
- unsigned n = 0;
- for (unsigned j = 0; j < par.m_rows; j++) {
- unsigned i = thrrow(par, j);
- set.lock();
- if (! set.exist(i)) {
- set.unlock();
- continue;
- }
- LL4("pkdelete " << i << ": " << *set.m_row[i]);
- CHKTRY(set.delrow(par, i) == 0, set.unlock());
- set.unlock();
- if (++n == par.m_batch) {
- CHK(con.execute(Commit) == 0);
- con.closeTransaction();
- CHK(con.startTransaction() == 0);
- n = 0;
- }
- }
- if (n != 0) {
- CHK(con.execute(Commit) == 0);
- n = 0;
- }
- con.closeTransaction();
- return 0;
-};
-
-static int
-pkread(Par par)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- const Set& set = par.set();
- LL3((par.m_verify ? "pkverify " : "pkread ") << tab.m_name);
- // expected
- const Set& set1 = set;
- Set set2(tab, set.m_rows);
- for (unsigned i = 0; i < set.m_rows; i++) {
- if (! set.exist(i))
- continue;
- CHK(con.startTransaction() == 0);
- CHK(set2.selrow(par, i) == 0);
- CHK(con.execute(Commit) == 0);
- unsigned i2 = (unsigned)-1;
- CHK(set2.getkey(par, &i2) == 0 && i == i2);
- CHK(set2.putval(i, false) == 0);
- LL4("row " << set2.m_count << ": " << *set2.m_row[i]);
- con.closeTransaction();
- }
- if (par.m_verify)
- CHK(set1.verify(set2) == 0);
- return 0;
-}
-
-// scan read
-
-static int
-scanreadtable(Par par)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- const Set& set = par.set();
- // expected
- const Set& set1 = set;
- LL3((par.m_verify ? "scanverify " : "scanread ") << tab.m_name);
- Set set2(tab, set.m_rows);
- CHK(con.startTransaction() == 0);
- CHK(con.getNdbOperation(tab) == 0);
- CHK(con.openScanRead(par.m_scanrd) == 0);
- set2.getval(par);
- CHK(con.executeScan() == 0);
- while (1) {
- int ret;
- CHK((ret = con.nextScanResult()) == 0 || ret == 1);
- if (ret == 1)
- break;
- unsigned i = (unsigned)-1;
- CHK(set2.getkey(par, &i) == 0);
- CHK(set2.putval(i, false) == 0);
- LL4("row " << set2.m_count << ": " << *set2.m_row[i]);
- }
- con.closeTransaction();
- if (par.m_verify)
- CHK(set1.verify(set2) == 0);
- return 0;
-}
-
-static int
-scanreadindex(Par par, const ITab& itab, const BSet& bset)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- const Set& set = par.set();
- // expected
- Set set1(tab, set.m_rows);
- bset.filter(set, set1);
- LL3((par.m_verify ? "scanverify " : "scanread ") << itab.m_name << " bounds=" << bset.m_bvals);
- LL4(bset);
- Set set2(tab, set.m_rows);
- CHK(con.startTransaction() == 0);
- CHK(con.getNdbOperation(itab, tab) == 0);
- CHK(con.openScanRead(par.m_scanrd) == 0);
- CHK(bset.setbnd(par) == 0);
- set2.getval(par);
- CHK(con.executeScan() == 0);
- while (1) {
- int ret;
- CHK((ret = con.nextScanResult()) == 0 || ret == 1);
- if (ret == 1)
- break;
- unsigned i = (unsigned)-1;
- CHK(set2.getkey(par, &i) == 0);
- LL4("key " << i);
- CHK(set2.putval(i, par.m_dups) == 0);
- LL4("row " << set2.m_count << ": " << *set2.m_row[i]);
- }
- con.closeTransaction();
- if (par.m_verify)
- CHK(set1.verify(set2) == 0);
- return 0;
-}
-
-static int
-scanreadindex(Par par, const ITab& itab)
-{
- const Tab& tab = par.tab();
- for (unsigned i = 0; i < par.m_subloop; i++) {
- BSet bset(tab, itab, par.m_rows);
- bset.calc(par);
- CHK(scanreadindex(par, itab, bset) == 0);
- }
- return 0;
-}
-
-static int
-scanreadindex(Par par)
-{
- const Tab& tab = par.tab();
- for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
- continue;
- const ITab& itab = tab.m_itab[i];
- CHK(scanreadindex(par, itab) == 0);
- }
- return 0;
-}
-
-static int
-scanreadall(Par par)
-{
- if (par.m_no < 11)
- CHK(scanreadtable(par) == 0);
- CHK(scanreadindex(par) == 0);
- return 0;
-}
-
-// scan update
-
-static int
-scanupdatetable(Par par)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- Set& set = par.set();
- LL3("scan update " << tab.m_name);
- Set set2(tab, set.m_rows);
- CHK(con.startTransaction() == 0);
- CHK(con.getNdbOperation(tab) == 0);
- CHK(con.openScanExclusive(par.m_scanex) == 0);
- set2.getval(par);
- CHK(con.executeScan() == 0);
- unsigned count = 0;
- // updating trans
- Con con2;
- con2.m_ndb = con.m_ndb;
- CHK(con2.startBuddyTransaction(con) == 0);
- while (1) {
- int ret;
- CHK((ret = con.nextScanResult()) == 0 || ret == 1);
- if (ret == 1)
- break;
- unsigned i = (unsigned)-1;
- CHK(set2.getkey(par, &i) == 0);
- LL4("key " << i);
- CHK(set2.putval(i, false) == 0);
- CHK(con2.takeOverForUpdate(con) == 0);
- Par par2 = par;
- par2.m_con = &con2;
- set.lock();
- set.calc(par, i);
- LL4("scan update " << tab.m_name << ": " << *set.m_row[i]);
- CHKTRY(set.setrow(par2, i) == 0, set.unlock());
- set.unlock();
- CHK(con2.execute(NoCommit) == 0);
- count++;
- }
- CHK(con2.execute(Commit) == 0);
- con2.closeTransaction();
- LL3("scan update " << tab.m_name << " rows updated=" << count);
- con.closeTransaction();
- return 0;
-}
-
-static int
-scanupdateindex(Par par, const ITab& itab, const BSet& bset)
-{
- Con& con = par.con();
- const Tab& tab = par.tab();
- Set& set = par.set();
- LL3("scan update " << itab.m_name);
- Set set2(tab, set.m_rows);
- CHK(con.startTransaction() == 0);
- CHK(con.getNdbOperation(itab, tab) == 0);
- CHK(con.openScanExclusive(par.m_scanex) == 0);
- CHK(bset.setbnd(par) == 0);
- set2.getval(par);
- CHK(con.executeScan() == 0);
- unsigned count = 0;
- // updating trans
- Con con2;
- con2.m_ndb = con.m_ndb;
- CHK(con2.startBuddyTransaction(con) == 0);
- while (1) {
- int ret;
- CHK((ret = con.nextScanResult()) == 0 || ret == 1);
- if (ret == 1)
- break;
- unsigned i = (unsigned)-1;
- CHK(set2.getkey(par, &i) == 0);
- LL4("key " << i);
- CHK(set2.putval(i, par.m_dups) == 0);
- // avoid deadlock for now
- //if (! isthrrow(par, i))
- //continue;
- CHK(con2.takeOverForUpdate(con) == 0);
- Par par2 = par;
- par2.m_con = &con2;
- set.lock();
- set.calc(par, i);
- LL4("scan update " << itab.m_name << ": " << *set.m_row[i]);
- CHKTRY(set.setrow(par2, i) == 0, set.unlock());
- set.unlock();
- CHK(con2.execute(NoCommit) == 0);
- count++;
- }
- CHK(con2.execute(Commit) == 0);
- con2.closeTransaction();
- LL3("scan update " << itab.m_name << " rows updated=" << count);
- con.closeTransaction();
- return 0;
-}
-
-static int
-scanupdateindex(Par par, const ITab& itab)
-{
- const Tab& tab = par.tab();
- for (unsigned i = 0; i < par.m_subloop; i++) {
- BSet bset(tab, itab, par.m_rows);
- bset.calc(par);
- CHK(scanupdateindex(par, itab, bset) == 0);
- }
- return 0;
-}
-
-static int
-scanupdateindex(Par par)
-{
- const Tab& tab = par.tab();
- for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
- continue;
- const ITab& itab = tab.m_itab[i];
- CHK(scanupdateindex(par, itab) == 0);
- }
- return 0;
-}
-
-static int
-scanupdateall(Par par)
-{
- CHK(scanupdatetable(par) == 0);
- CHK(scanupdateindex(par) == 0);
- return 0;
-}
-
-// medium level routines
-
-static bool
-ignoreverifyerror(Par par)
-{
- Con& con = par.con();
- bool b = par.m_threads > 1;
- if (b) {
- LL1("ignore verify error");
- if (con.m_tx != 0)
- con.closeTransaction();
- return true;
- }
- return b;
-}
-
-static int
-readverify(Par par)
-{
- par.m_verify = true;
- CHK(pkread(par) == 0 || ignoreverifyerror(par));
- CHK(scanreadall(par) == 0 || ignoreverifyerror(par));
- return 0;
-}
-
-static bool
-ignoredeadlock(Par par)
-{
- Con& con = par.con();
- if (con.m_errtype == Con::ErrDeadlock) {
- LL1("ignore deadlock");
- con.closeTransaction();
- return true;
- }
- return false;
-}
-
-static int
-pkupdatescanread(Par par)
-{
- par.m_dups = true;
- unsigned sel = urandom(10);
- if (sel < 5) {
- CHK(pkupdate(par) == 0);
- } else if (sel < 6) {
- par.m_verify = false;
- CHK(scanreadtable(par) == 0);
- } else {
- par.m_verify = false;
- CHK(scanreadindex(par) == 0);
- }
- return 0;
-}
-
-static int
-mixedoperations(Par par)
-{
- par.m_dups = true;
- unsigned sel = urandom(10);
- if (sel < 2) {
- CHK(pkdelete(par) == 0 || ignoredeadlock(par));
- } else if (sel < 4) {
- CHK(pkupdate(par) == 0 || ignoredeadlock(par));
- } else if (sel < 6) {
- CHK(scanupdatetable(par) == 0 || ignoredeadlock(par));
- } else {
- CHK(scanupdateindex(par) == 0 || ignoredeadlock(par));
- }
- return 0;
-}
-
-static int
-pkupdateindexbuild(Par par)
-{
- if (par.m_no == 0) {
- CHK(createindex(par) == 0);
- CHK(invalidateindex(par) == 0);
- } else {
- CHK(pkupdate(par) == 0);
- }
- return 0;
-}
-
-// threads
-
-typedef int (*TFunc)(Par par);
-enum TMode { ST = 1, MT = 2 };
-
-extern "C" { static void* runthread(void* arg); }
-
-struct Thr {
- enum State { Wait, Start, Stop, Stopped, Exit };
- State m_state;
- Par m_par;
- Uint64 m_id;
- NdbThread* m_thread;
- NdbMutex* m_mutex;
- NdbCondition* m_cond;
- TFunc m_func;
- int m_ret;
- void* m_status;
- Thr(Par par, unsigned n);
- ~Thr();
- int run();
- void start();
- void stop();
- void stopped();
- void exit();
- //
- void lock() {
- NdbMutex_Lock(m_mutex);
- }
- void unlock() {
- NdbMutex_Unlock(m_mutex);
- }
- void wait() {
- NdbCondition_Wait(m_cond, m_mutex);
- }
- void signal() {
- NdbCondition_Signal(m_cond);
- }
- void join() {
- NdbThread_WaitFor(m_thread, &m_status);
- m_thread = 0;
- }
-};
-
-Thr::Thr(Par par, unsigned n) :
- m_state(Wait),
- m_par(par),
- m_id(0),
- m_thread(0),
- m_mutex(0),
- m_cond(0),
- m_func(0),
- m_ret(0),
- m_status(0)
-{
- m_par.m_no = n;
- char buf[10];
- sprintf(buf, "thr%03u", par.m_no);
- const char* name = strcpy(new char[10], buf);
- // mutex
- m_mutex = NdbMutex_Create();
- m_cond = NdbCondition_Create();
- assert(m_mutex != 0 && m_cond != 0);
- // run
- const unsigned stacksize = 256 * 1024;
- const NDB_THREAD_PRIO prio = NDB_THREAD_PRIO_LOW;
- m_thread = NdbThread_Create(runthread, (void**)this, stacksize, name, prio);
-}
-
-Thr::~Thr()
-{
- if (m_thread != 0) {
- NdbThread_Destroy(&m_thread);
- m_thread = 0;
- }
- if (m_cond != 0) {
- NdbCondition_Destroy(m_cond);
- m_cond = 0;
- }
- if (m_mutex != 0) {
- NdbMutex_Destroy(m_mutex);
- m_mutex = 0;
- }
-}
-
-static void*
-runthread(void* arg)
-{
- Thr& thr = *(Thr*)arg;
- thr.m_id = (Uint64)pthread_self();
- if (thr.run() < 0) {
- LL1("exit on error");
- } else {
- LL4("exit ok");
- }
- return 0;
-}
-
-int
-Thr::run()
-{
- LL4("run");
- Con con;
- CHK(con.connect() == 0);
- m_par.m_con = &con;
- LL4("connected");
- while (1) {
- lock();
- while (m_state != Start && m_state != Exit) {
- LL4("wait");
- wait();
- }
- if (m_state == Exit) {
- LL4("exit");
- unlock();
- break;
- }
- LL4("start");
- CHK(con.bugger() == 0);
- assert(m_state == Start);
- m_ret = (*m_func)(m_par);
- m_state = Stopped;
- LL4("stop");
- signal();
- unlock();
- CHK(m_ret == 0);
- }
- con.disconnect();
- return 0;
-}
-
-void
-Thr::start()
-{
- lock();
- m_state = Start;
- signal();
- unlock();
-}
-
-void
-Thr::stop()
-{
- lock();
- m_state = Stop;
- signal();
- unlock();
-}
-
-void
-Thr::stopped()
-{
- lock();
- while (m_state != Stopped)
- wait();
- m_state = Wait;
- unlock();
-}
-
-void
-Thr::exit()
-{
- lock();
- m_state = Exit;
- signal();
- unlock();
-}
-
-// test run
-
-static Thr** g_thrlist = 0;
-
-static unsigned
-getthrno()
-{
- if (g_thrlist != 0) {
- Uint64 id = (Uint64)pthread_self();
- for (unsigned n = 0; n < g_opt.m_threads; n++) {
- if (g_thrlist[n] != 0) {
- const Thr& thr = *g_thrlist[n];
- if (thr.m_id == id)
- return thr.m_par.m_no;
- }
- }
- }
- return (unsigned)-1;
-}
-
-static int
-runstep(Par par, const char* fname, TFunc func, unsigned mode)
-{
- LL2(fname);
- const int threads = (mode & ST ? 1 : par.m_threads);
- for (int n = 0; n < threads; n++) {
- LL4("start " << n);
- Thr& thr = *g_thrlist[n];
- thr.m_par.m_tab = par.m_tab;
- thr.m_par.m_set = par.m_set;
- thr.m_func = func;
- thr.start();
- }
- unsigned errs = 0;
- for (int n = threads - 1; n >= 0; n--) {
- LL4("stop " << n);
- Thr& thr = *g_thrlist[n];
- thr.stopped();
- if (thr.m_ret != 0)
- errs++;
- }
- CHK(errs == 0);
- return 0;
-}
-
-#define RUNSTEP(par, func, mode) CHK(runstep(par, #func, func, mode) == 0)
-
-static int
-tbuild(Par par)
-{
- RUNSTEP(par, droptable, ST);
- RUNSTEP(par, createtable, ST);
- RUNSTEP(par, invalidatetable, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
- if (i % 2 == 0) {
- RUNSTEP(par, createindex, ST);
- RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, pkinsert, MT);
- } else {
- RUNSTEP(par, pkinsert, MT);
- RUNSTEP(par, createindex, ST);
- RUNSTEP(par, invalidateindex, MT);
- }
- RUNSTEP(par, readverify, MT);
- RUNSTEP(par, pkdelete, MT);
- RUNSTEP(par, readverify, MT);
- RUNSTEP(par, dropindex, ST);
- }
- return 0;
-}
-
-static int
-tpkops(Par par)
-{
- RUNSTEP(par, droptable, ST);
- RUNSTEP(par, createtable, ST);
- RUNSTEP(par, invalidatetable, MT);
- RUNSTEP(par, pkinsert, MT);
- RUNSTEP(par, createindex, ST);
- RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, readverify, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
- RUNSTEP(par, pkupdatescanread, MT);
- RUNSTEP(par, readverify, MT);
- }
- RUNSTEP(par, pkdelete, MT);
- RUNSTEP(par, readverify, MT);
- return 0;
-}
-
-static int
-tmixedops(Par par)
-{
- RUNSTEP(par, droptable, ST);
- RUNSTEP(par, createtable, ST);
- RUNSTEP(par, invalidatetable, MT);
- RUNSTEP(par, pkinsert, MT);
- RUNSTEP(par, createindex, ST);
- RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, readverify, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
- RUNSTEP(par, mixedoperations, MT);
- RUNSTEP(par, readverify, MT);
- }
- return 0;
-}
-
-static int
-tbusybuild(Par par)
-{
- RUNSTEP(par, droptable, ST);
- RUNSTEP(par, createtable, ST);
- RUNSTEP(par, invalidatetable, MT);
- RUNSTEP(par, pkinsert, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
- RUNSTEP(par, pkupdateindexbuild, MT);
- RUNSTEP(par, readverify, MT);
- RUNSTEP(par, dropindex, ST);
- }
- return 0;
-}
-
-static int
-ttiming(Par par)
-{
- Tmr t0, t1, t2;
- RUNSTEP(par, droptable, ST);
- RUNSTEP(par, createtable, ST);
- RUNSTEP(par, invalidatetable, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
- RUNSTEP(par, pkinsert, MT);
- t1.on();
- RUNSTEP(par, pkupdate, MT);
- t1.off(par.m_totrows);
- t0.on();
- RUNSTEP(par, createindex, ST);
- RUNSTEP(par, invalidateindex, MT);
- t0.off(par.m_totrows);
- t2.on();
- RUNSTEP(par, pkupdate, MT);
- t2.off(par.m_totrows);
- RUNSTEP(par, dropindex, ST);
- }
- LL1("build index - " << t0.time());
- LL1("update - " << t1.time());
- LL1("update indexed - " << t2.time());
- LL1("overhead - " << t2.over(t1));
- return 0;
-}
-
-static int
-tdrop(Par par)
-{
- RUNSTEP(par, droptable, ST);
- return 0;
-}
-
-struct TCase {
- const char* m_name;
- TFunc m_func;
- const char* m_desc;
- TCase(const char* name, TFunc func, const char* desc) :
- m_name(name),
- m_func(func),
- m_desc(desc) {
- }
-};
-
-static const TCase
-tcaselist[] = {
- TCase("a", tbuild, "index build"),
- TCase("b", tpkops, "pk operations and scan reads"),
- TCase("c", tmixedops, "pk operations and scan operations"),
- TCase("d", tbusybuild, "pk operations and index build"),
- TCase("t", ttiming, "time index build and maintenance"),
- TCase("z", tdrop, "drop test tables")
-};
-
-static const unsigned
-tcasecount = sizeof(tcaselist) / sizeof(tcaselist[0]);
-
-static void
-printcases()
-{
- ndbout << "test cases:" << endl;
- for (unsigned i = 0; i < tcasecount; i++) {
- const TCase& tcase = tcaselist[i];
- ndbout << " " << tcase.m_name << " - " << tcase.m_desc << endl;
- }
-}
-
-static void
-printtables()
-{
- ndbout << "tables and indexes:" << endl;
- for (unsigned j = 0; j < tabcount; j++) {
- const Tab& tab = tablist[j];
- ndbout << " " << tab.m_name;
- for (unsigned i = 0; i < tab.m_itabs; i++) {
- const ITab& itab = tab.m_itab[i];
- ndbout << " " << itab.m_name;
- }
- ndbout << endl;
- }
-}
-
-static int
-runtest(Par par)
-{
- LL1("start");
- srandom(par.m_seed);
- Con con;
- CHK(con.connect() == 0);
- par.m_con = &con;
- g_thrlist = new Thr* [par.m_threads];
- for (unsigned n = 0; n < par.m_threads; n++) {
- g_thrlist[n] = 0;
- }
- for (unsigned n = 0; n < par.m_threads; n++) {
- g_thrlist[n] = new Thr(par, n);
- Thr& thr = *g_thrlist[n];
- assert(thr.m_thread != 0);
- }
- for (unsigned l = 0; par.m_loop == 0 || l < par.m_loop; l++) {
- LL1("loop " << l);
- for (unsigned i = 0; i < tcasecount; i++) {
- const TCase& tcase = tcaselist[i];
- if (par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0)
- continue;
- LL1("case " << tcase.m_name << " - " << tcase.m_desc);
- for (unsigned j = 0; j < tabcount; j++) {
- if (! usetable(j))
- continue;
- const Tab& tab = tablist[j];
- par.m_tab = &tab;
- Set set(tab, par.m_totrows);
- par.m_set = &set;
- LL1("table " << tab.m_name);
- CHK(tcase.m_func(par) == 0);
- }
- }
- }
- for (unsigned n = 0; n < par.m_threads; n++) {
- Thr& thr = *g_thrlist[n];
- thr.exit();
- }
- for (unsigned n = 0; n < par.m_threads; n++) {
- Thr& thr = *g_thrlist[n];
- thr.join();
- delete &thr;
- }
- delete [] g_thrlist;
- g_thrlist = 0;
- con.disconnect();
- LL1("done");
- return 0;
-}
-
-NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
-{
- while (++argv, --argc > 0) {
- const char* arg = argv[0];
- if (*arg != '-') {
- ndbout << "testOIBasic: unknown argument " << arg;
- goto usage;
- }
- if (strcmp(arg, "-case") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_case = strdup(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-core") == 0) {
- g_opt.m_core = true;
- continue;
- }
- if (strcmp(arg, "-dups") == 0) {
- g_opt.m_dups = true;
- continue;
- }
- if (strcmp(arg, "-fragtype") == 0) {
- if (++argv, --argc > 0) {
- if (strcmp(argv[0], "single") == 0) {
- g_opt.m_fragtype = NdbDictionary::Object::FragSingle;
- continue;
- }
- if (strcmp(argv[0], "small") == 0) {
- g_opt.m_fragtype = NdbDictionary::Object::FragAllSmall;
- continue;
- }
- if (strcmp(argv[0], "medium") == 0) {
- g_opt.m_fragtype = NdbDictionary::Object::FragAllMedium;
- continue;
- }
- if (strcmp(argv[0], "large") == 0) {
- g_opt.m_fragtype = NdbDictionary::Object::FragAllLarge;
- continue;
- }
- }
- }
- if (strcmp(arg, "-index") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_index = strdup(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-loop") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_loop = atoi(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-rows") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_rows = atoi(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-scanrd") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_scanrd = atoi(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-scanex") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_scanex = atoi(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-seed") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_seed = atoi(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-subloop") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_subloop = atoi(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-table") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_table = strdup(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-threads") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_threads = atoi(argv[0]);
- continue;
- }
- }
- if (strcmp(arg, "-v") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_v = atoi(argv[0]);
- continue;
- }
- }
- if (strncmp(arg, "-v", 2) == 0 && isdigit(arg[2])) {
- g_opt.m_v = atoi(&arg[2]);
- continue;
- }
- if (strcmp(arg, "-h") == 0 || strcmp(arg, "-help") == 0) {
- printhelp();
- goto wrongargs;
- }
- ndbout << "testOIBasic: unknown option " << arg;
- goto usage;
- }
- {
- Par par(g_opt);
- if (runtest(par) < 0)
- goto failed;
- }
- // always exit with NDBT code
-ok:
- return NDBT_ProgramExit(NDBT_OK);
-failed:
- return NDBT_ProgramExit(NDBT_FAILED);
-usage:
- ndbout << " (use -h for help)" << endl;
-wrongargs:
- return NDBT_ProgramExit(NDBT_WRONGARGS);
-}
-
-// vim: set sw=2 et:
diff --git a/ndb/test/ndbapi/testOperations/testOperations.cpp b/ndb/test/ndbapi/testOperations.cpp
index bb58e69e898..bb58e69e898 100644
--- a/ndb/test/ndbapi/testOperations/testOperations.cpp
+++ b/ndb/test/ndbapi/testOperations.cpp
diff --git a/ndb/test/ndbapi/testOrderedIndex/testOrderedIndex.cpp b/ndb/test/ndbapi/testOrderedIndex.cpp
index 51cc53c9975..51cc53c9975 100644
--- a/ndb/test/ndbapi/testOrderedIndex/testOrderedIndex.cpp
+++ b/ndb/test/ndbapi/testOrderedIndex.cpp
diff --git a/ndb/test/ndbapi/testRestartGci.cpp b/ndb/test/ndbapi/testRestartGci.cpp
new file mode 100644
index 00000000000..e3dd1f8e2ce
--- /dev/null
+++ b/ndb/test/ndbapi/testRestartGci.cpp
@@ -0,0 +1,218 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "NDBT_Test.hpp"
+#include "NDBT_ReturnCodes.h"
+#include "HugoTransactions.hpp"
+#include "UtilTransactions.hpp"
+#include "NdbRestarter.hpp"
+
+
+/**
+ * Global vector to keep track of
+ * records stored in db
+ */
+
+struct SavedRecord {
+ int m_gci;
+ BaseString m_str;
+ SavedRecord(int _gci, BaseString _str){
+ m_gci = _gci;
+ m_str.assign(_str);
+ }
+ SavedRecord(){
+ m_gci = 0;
+ m_str = "";
+ };
+};
+Vector<SavedRecord> savedRecords;
+
+
+#define CHECK(b) if (!(b)) { \
+ ndbout << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ break; }
+
+int runInsertRememberGci(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int records = ctx->getNumRecords();
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+ int i = 0;
+
+ while(ctx->isTestStopped() == false && i < records){
+ // Insert record and read it in same transaction
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ CHECK(hugoOps.pkInsertRecord(pNdb, i) == 0);
+ if (hugoOps.execute_NoCommit(pNdb) != 0){
+ ndbout << "Could not insert record " << i << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ CHECK(hugoOps.pkReadRecord(pNdb, i, false) == 0);
+ if (hugoOps.execute_Commit(pNdb) != 0){
+ ndbout << "Did not find record in DB " << i << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ savedRecords.push_back(SavedRecord(hugoOps.getRecordGci(0),
+ hugoOps.getRecordStr(0)));
+
+ CHECK(hugoOps.closeTransaction(pNdb) == 0);
+ i++;
+ };
+
+ return result;
+}
+
+int runRestartGciControl(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ Ndb* pNdb = GETNDB(step);
+ UtilTransactions utilTrans(*ctx->getTab());
+ NdbRestarter restarter;
+
+ // Wait until we have enough records in db
+ int count = 0;
+ while (count < records){
+ if (utilTrans.selectCount(pNdb, 64, &count) != 0){
+ ctx->stopTest();
+ return NDBT_FAILED;
+ }
+ }
+
+ // Restart cluster with abort
+ if (restarter.restartAll(false, false, true) != 0){
+ ctx->stopTest();
+ return NDBT_FAILED;
+ }
+
+ // Stop the other thread
+ ctx->stopTest();
+
+ if (restarter.waitClusterStarted(300) != 0){
+ return NDBT_FAILED;
+ }
+
+ if (pNdb->waitUntilReady() != 0){
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+int runVerifyInserts(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ Ndb* pNdb = GETNDB(step);
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoOperations hugoOps(*ctx->getTab());
+ NdbRestarter restarter;
+
+ int restartGCI = pNdb->NdbTamper(Ndb::ReadRestartGCI, 0);
+
+ ndbout << "restartGCI = " << restartGCI << endl;
+ int count = 0;
+ if (utilTrans.selectCount(pNdb, 64, &count) != 0){
+ return NDBT_FAILED;
+ }
+
+ // RULE1: The vector with saved records should have exactly as many
+ // records with lower or same gci as there are in DB
+ int recordsWithLowerOrSameGci = 0;
+ for (unsigned i = 0; i < savedRecords.size(); i++){
+ if (savedRecords[i].m_gci <= restartGCI)
+ recordsWithLowerOrSameGci++;
+ }
+ if (recordsWithLowerOrSameGci != count){
+ ndbout << "ERR: Wrong number of expected records" << endl;
+ result = NDBT_FAILED;
+ }
+
+
+ // RULE2: The records found in db should have same or lower
+ // gci as in the vector
+ for (unsigned i = 0; i < savedRecords.size(); i++){
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, i, false) == 0);
+ if (hugoOps.execute_Commit(pNdb) != 0){
+ // Record was not found in db'
+
+ // Check record gci
+ if (savedRecords[i].m_gci <= restartGCI){
+ ndbout << "ERR: Record "<<i<<" should have existed" << endl;
+ result = NDBT_FAILED;
+ }
+ } else {
+ // Record was found in db
+ BaseString str = hugoOps.getRecordStr(0);
+ // Check record string
+ if (!(savedRecords[i].m_str == str)){
+ ndbout << "ERR: Record "<<i<<" str did not match "<< endl;
+ result = NDBT_FAILED;
+ }
+ // Check record gci
+ if (savedRecords[i].m_gci > restartGCI){
+ ndbout << "ERR: Record "<<i<<" should not have existed" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+
+ CHECK(hugoOps.closeTransaction(pNdb) == 0);
+ }
+
+
+ ndbout << "There are " << count << " records in db" << endl;
+ ndbout << "There are " << savedRecords.size()
+ << " records in vector" << endl;
+
+ ndbout << "There are " << recordsWithLowerOrSameGci
+ << " records with lower or same gci than " << restartGCI << endl;
+
+ return result;
+}
+
+int runClearGlobals(NDBT_Context* ctx, NDBT_Step* step){
+ savedRecords.clear();
+ return NDBT_OK;
+}
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable2(GETNDB(step), records, 240) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+
+NDBT_TESTSUITE(testRestartGci);
+TESTCASE("InsertRestartGci",
+ "Verify that only expected records are still in NDB\n"
+ "after a restart" ){
+ INITIALIZER(runClearTable);
+ INITIALIZER(runClearGlobals);
+ STEP(runInsertRememberGci);
+ STEP(runRestartGciControl);
+ VERIFIER(runVerifyInserts);
+ FINALIZER(runClearTable);
+}
+NDBT_TESTSUITE_END(testRestartGci);
+
+int main(int argc, const char** argv){
+ return testRestartGci.execute(argc, argv);
+}
diff --git a/ndb/test/ndbapi/testRestartGci/testRestartGci.cpp b/ndb/test/ndbapi/testRestartGci/testRestartGci.cpp
deleted file mode 100644
index 1e36368ba62..00000000000
--- a/ndb/test/ndbapi/testRestartGci/testRestartGci.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "NDBT_Test.hpp"
-#include "NDBT_ReturnCodes.h"
-#include "HugoTransactions.hpp"
-#include "UtilTransactions.hpp"
-#include "NdbRestarter.hpp"
-
-
-/**
- * Global vector to keep track of
- * records stored in db
- */
-
-struct SavedRecord {
- int m_gci;
- BaseString m_str;
- SavedRecord(int _gci, BaseString _str){
- m_gci = _gci;
- m_str.assign(_str);
- }
- SavedRecord(){
- m_gci = 0;
- m_str = "";
- };
-};
-Vector<SavedRecord> savedRecords;
-
-
-#define CHECK(b) if (!(b)) { \
- ndbout << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- break; }
-
-int runInsertRememberGci(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int records = ctx->getNumRecords();
- HugoOperations hugoOps(*ctx->getTab());
- Ndb* pNdb = GETNDB(step);
- int i = 0;
-
- while(ctx->isTestStopped() == false && i < records){
- // Insert record and read it in same transaction
- CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkInsertRecord(pNdb, i) == 0);
- if (hugoOps.execute_NoCommit(pNdb) != 0){
- ndbout << "Could not insert record " << i << endl;
- result = NDBT_FAILED;
- break;
- }
- CHECK(hugoOps.pkReadRecord(pNdb, i, false) == 0);
- if (hugoOps.execute_Commit(pNdb) != 0){
- ndbout << "Did not find record in DB " << i << endl;
- result = NDBT_FAILED;
- break;
- }
- savedRecords.push_back(SavedRecord(hugoOps.getRecordGci(0),
- hugoOps.getRecordStr(0)));
-
- CHECK(hugoOps.closeTransaction(pNdb) == 0);
- i++;
- };
-
- return result;
-}
-
-int runRestartGciControl(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- Ndb* pNdb = GETNDB(step);
- UtilTransactions utilTrans(*ctx->getTab());
- NdbRestarter restarter;
-
- // Wait until we have enough records in db
- int count = 0;
- while (count < records){
- if (utilTrans.selectCount(pNdb, 64, &count) != 0){
- ctx->stopTest();
- return NDBT_FAILED;
- }
- }
-
- // Restart cluster with abort
- if (restarter.restartAll(false, false, true) != 0){
- ctx->stopTest();
- return NDBT_FAILED;
- }
-
- // Stop the other thread
- ctx->stopTest();
-
- if (restarter.waitClusterStarted(300) != 0){
- return NDBT_FAILED;
- }
-
- if (pNdb->waitUntilReady() != 0){
- return NDBT_FAILED;
- }
-
- return NDBT_OK;
-}
-
-int runVerifyInserts(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- Ndb* pNdb = GETNDB(step);
- UtilTransactions utilTrans(*ctx->getTab());
- HugoOperations hugoOps(*ctx->getTab());
- NdbRestarter restarter;
-
- int restartGCI = pNdb->NdbTamper(ReadRestartGCI, 0);
-
- ndbout << "restartGCI = " << restartGCI << endl;
- int count = 0;
- if (utilTrans.selectCount(pNdb, 64, &count) != 0){
- return NDBT_FAILED;
- }
-
- // RULE1: The vector with saved records should have exactly as many
- // records with lower or same gci as there are in DB
- int recordsWithLowerOrSameGci = 0;
- for (unsigned i = 0; i < savedRecords.size(); i++){
- if (savedRecords[i].m_gci <= restartGCI)
- recordsWithLowerOrSameGci++;
- }
- if (recordsWithLowerOrSameGci != count){
- ndbout << "ERR: Wrong number of expected records" << endl;
- result = NDBT_FAILED;
- }
-
-
- // RULE2: The records found in db should have same or lower
- // gci as in the vector
- for (unsigned i = 0; i < savedRecords.size(); i++){
- CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, i, false) == 0);
- if (hugoOps.execute_Commit(pNdb) != 0){
- // Record was not found in db'
-
- // Check record gci
- if (savedRecords[i].m_gci <= restartGCI){
- ndbout << "ERR: Record "<<i<<" should have existed" << endl;
- result = NDBT_FAILED;
- }
- } else {
- // Record was found in db
- BaseString str = hugoOps.getRecordStr(0);
- // Check record string
- if (!(savedRecords[i].m_str == str)){
- ndbout << "ERR: Record "<<i<<" str did not match "<< endl;
- result = NDBT_FAILED;
- }
- // Check record gci
- if (savedRecords[i].m_gci > restartGCI){
- ndbout << "ERR: Record "<<i<<" should not have existed" << endl;
- result = NDBT_FAILED;
- }
- }
-
- CHECK(hugoOps.closeTransaction(pNdb) == 0);
- }
-
-
- ndbout << "There are " << count << " records in db" << endl;
- ndbout << "There are " << savedRecords.size()
- << " records in vector" << endl;
-
- ndbout << "There are " << recordsWithLowerOrSameGci
- << " records with lower or same gci than " << restartGCI << endl;
-
- return result;
-}
-
-int runClearGlobals(NDBT_Context* ctx, NDBT_Step* step){
- savedRecords.clear();
- return NDBT_OK;
-}
-
-int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
-
- UtilTransactions utilTrans(*ctx->getTab());
- if (utilTrans.clearTable2(GETNDB(step), records, 240) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-
-NDBT_TESTSUITE(testRestartGci);
-TESTCASE("InsertRestartGci",
- "Verify that only expected records are still in NDB\n"
- "after a restart" ){
- INITIALIZER(runClearTable);
- INITIALIZER(runClearGlobals);
- STEP(runInsertRememberGci);
- STEP(runRestartGciControl);
- VERIFIER(runVerifyInserts);
- FINALIZER(runClearTable);
-}
-NDBT_TESTSUITE_END(testRestartGci);
-
-int main(int argc, const char** argv){
- return testRestartGci.execute(argc, argv);
-}
diff --git a/ndb/test/ndbapi/testScan.cpp b/ndb/test/ndbapi/testScan.cpp
new file mode 100644
index 00000000000..bc3be0b7dc9
--- /dev/null
+++ b/ndb/test/ndbapi/testScan.cpp
@@ -0,0 +1,1402 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbRestarter.hpp>
+#include <Vector.hpp>
+#include "ScanFunctions.hpp"
+#include <random.h>
+
+const NdbDictionary::Table *
+getTable(Ndb* pNdb, int i){
+ const NdbDictionary::Table* t = NDBT_Tables::getTable(i);
+ if (t == NULL){
+ return 0;
+ }
+ return pNdb->getDictionary()->getTable(t->getName());
+}
+
+
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+
+int runCreateAllTables(NDBT_Context* ctx, NDBT_Step* step){
+
+ int a = NDBT_Tables::createAllTables(GETNDB(step), false, true);
+ return a;
+}
+
+int runDropAllTablesExceptTestTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ for (int i=0; i < NDBT_Tables::getNumTables(); i++){
+
+ const NdbDictionary::Table* tab = NDBT_Tables::getTable(i);
+ if (tab == NULL){
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ // Don't drop test table
+ if (strcmp(tab->getName(), ctx->getTab()->getName()) == 0){
+ continue;
+ }
+
+ int res = GETNDB(step)->getDictionary()->dropTable(tab->getName());
+ if(res != -1){
+ return NDBT_FAILED;
+ }
+ }
+ return NDBT_OK;
+}
+
+
+int runLoadAllTables(NDBT_Context* ctx, NDBT_Step* step){
+
+ int records = ctx->getNumRecords();
+ for (int i=0; i < NDBT_Tables::getNumTables(); i++){
+
+ const NdbDictionary::Table* tab = getTable(GETNDB(step), i);
+ if (tab == NULL){
+ return NDBT_FAILED;
+ }
+ HugoTransactions hugoTrans(*tab);
+ if (hugoTrans.loadTable(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ }
+ return NDBT_OK;
+}
+
+int runScanReadRandomTable(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = ctx->getProperty("Parallelism", 240);
+ int abort = ctx->getProperty("AbortProb");
+
+ int i = 0;
+ while (i<loops) {
+
+ int tabNum = myRandom48(NDBT_Tables::getNumTables());
+ const NdbDictionary::Table* tab = getTable(GETNDB(step), tabNum);
+ if (tab == NULL){
+ g_info << "tab == NULL" << endl;
+ return NDBT_FAILED;
+ }
+
+ g_info << "Scan reading from table " << tab->getName() << endl;
+ HugoTransactions hugoTrans(*tab);
+
+ g_info << i << ": ";
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runInsertUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (ctx->isTestStopped() == false) {
+ g_info << i << ": ";
+ if (hugoTrans.loadTable(GETNDB(step), records, 1) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runInsertDelete(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int records = ctx->getNumRecords();
+ int loops = ctx->getNumLoops();
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ UtilTransactions utilTrans(*ctx->getTab());
+ while (i<loops) {
+ g_info << i << ": ";
+ if (hugoTrans.loadTable(GETNDB(step), records, 1) != 0){
+ result = NDBT_FAILED;
+ break;
+ }
+ if (utilTrans.clearTable(GETNDB(step), records) != 0){
+ result = NDBT_FAILED;
+ break;
+ }
+ i++;
+ }
+
+ ctx->stopTest();
+
+ return result;
+}
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable2(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runScanDelete(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+
+ int i = 0;
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops) {
+ g_info << i << ": ";
+ if (utilTrans.clearTable(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ // Load table, don't allow any primary key violations
+ if (hugoTrans.loadTable(GETNDB(step), records, 512, false) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runScanDelete2(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+
+ int i = 0;
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ while (i<loops) {
+ g_info << i << ": ";
+ if (utilTrans.clearTable2(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ // Load table, don't allow any primary key violations
+ if (hugoTrans.loadTable(GETNDB(step), records, 512, false) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runVerifyTable(NDBT_Context* ctx, NDBT_Step* step){
+ return NDBT_OK;
+}
+
+int runScanRead(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = ctx->getProperty("Parallelism", 240);
+ int abort = ctx->getProperty("AbortProb");
+
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops && !ctx->isTestStopped()) {
+ g_info << i << ": ";
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runScanReadCommitted(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = ctx->getProperty("Parallelism", 240);
+ int abort = ctx->getProperty("AbortProb");
+
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops && !ctx->isTestStopped()) {
+ g_info << i << ": ";
+ if (hugoTrans.scanReadCommittedRecords(GETNDB(step), records,
+ abort, parallelism) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runScanReadError(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = 240; // Max parallelism
+ int error = ctx->getProperty("ErrorCode");
+ NdbRestarter restarter;
+
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops && !ctx->isTestStopped()) {
+ g_info << i << ": ";
+
+ ndbout << "insertErrorInAllNodes("<<error<<")"<<endl;
+ if (restarter.insertErrorInAllNodes(error) != 0){
+ ndbout << "Could not insert error in all nodes "<<endl;
+ return NDBT_FAILED;
+ }
+
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, parallelism) != 0){
+ result = NDBT_FAILED;
+ }
+ i++;
+ }
+
+ restarter.insertErrorInAllNodes(0);
+ return result;
+}
+
+int runScanReadErrorOneNode(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = 240; // Max parallelism
+ int error = ctx->getProperty("ErrorCode");
+ NdbRestarter restarter;
+ int lastId = 0;
+
+ if (restarter.getNumDbNodes() < 2){
+ ctx->stopTest();
+ return NDBT_OK;
+ }
+
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops && result == NDBT_OK) {
+ g_info << i << ": ";
+
+ int nodeId = restarter.getDbNodeId(lastId);
+ lastId = (lastId + 1) % restarter.getNumDbNodes();
+ ndbout << "insertErrorInNode("<<nodeId<<", "<<error<<")"<<endl;
+ if (restarter.insertErrorInNode(nodeId, error) != 0){
+ ndbout << "Could not insert error in node="<<nodeId<<endl;
+ return NDBT_FAILED;
+ }
+
+ for (int j=0; j<10; j++){
+ if (hugoTrans.scanReadRecords(GETNDB(step),
+ records, 0, parallelism) != 0)
+ result = NDBT_FAILED;
+ }
+
+
+ if(restarter.waitClusterStarted(120) != 0){
+ g_err << "Cluster failed to restart" << endl;
+ result = NDBT_FAILED;
+ }
+ restarter.insertErrorInAllNodes(0);
+
+ i++;
+ }
+ restarter.insertErrorInAllNodes(0);
+ return result;
+}
+
+int runRestartAll(NDBT_Context* ctx, NDBT_Step* step){
+
+ NdbRestarter restarter;
+
+ if (restarter.restartAll() != 0){
+ ndbout << "Could not restart all nodes"<<endl;
+ return NDBT_FAILED;
+ }
+
+ if (restarter.waitClusterStarted(120) != 0){
+ ndbout << "Could not restarted" << endl;
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+static int RANDOM_PARALLELISM = 9999;
+
+int runScanReadUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ int i = 0;
+
+ int parallelism = ctx->getProperty("Parallelism", 240);
+ int para = parallelism;
+
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (ctx->isTestStopped() == false) {
+ if (parallelism == RANDOM_PARALLELISM)
+ para = myRandom48(239)+1;
+
+ g_info << i << ": ";
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, para) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runScanReadUntilStoppedNoCount(NDBT_Context* ctx, NDBT_Step* step){
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (ctx->isTestStopped() == false) {
+ g_info << i << ": ";
+ if (hugoTrans.scanReadRecords(GETNDB(step), 0) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runScanReadUntilStoppedPrintTime(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ int i = 0;
+ int parallelism = ctx->getProperty("Parallelism", 240);
+ NdbTimer timer;
+ Ndb* ndb = GETNDB(step);
+
+
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (ctx->isTestStopped() == false) {
+ timer.doReset();
+ timer.doStart();
+ g_info << i << ": ";
+ if (ndb->waitUntilReady() != 0)
+ return NDBT_FAILED;
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, parallelism) != 0)
+ return NDBT_FAILED;
+ timer.doStop();
+ if ((timer.elapsedTime()/1000) > 1)
+ timer.printTotalTime();
+ i++;
+ }
+ return NDBT_OK;
+}
+
+
+int runPkRead(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops) {
+ g_info << i << ": ";
+ if (hugoTrans.pkReadRecords(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runScanUpdate(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = ctx->getProperty("Parallelism", 1);
+ int abort = ctx->getProperty("AbortProb");
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops) {
+ g_info << i << ": ";
+
+ if (hugoTrans.scanUpdateRecords(GETNDB(step), records, abort, parallelism) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runScanUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ int i = 0;
+
+ int parallelism = ctx->getProperty("Parallelism", 240);
+ int para = parallelism;
+
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (ctx->isTestStopped() == false) {
+ if (parallelism == RANDOM_PARALLELISM)
+ para = myRandom48(239)+1;
+
+ g_info << i << ": ";
+ if (hugoTrans.scanUpdateRecords(GETNDB(step), records, 0, para) == NDBT_FAILED){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+
+int runScanUpdate2(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = ctx->getProperty("Parallelism", 240);
+ int abort = ctx->getProperty("AbortProb");
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops) {
+ g_info << i << ": ";
+ if (hugoTrans.scanUpdateRecords2(GETNDB(step), records, abort, parallelism) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runLocker(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ if (hugoTrans.lockRecords(GETNDB(step), records, 5, 500) != 0){
+ result = NDBT_FAILED;
+ }
+ ctx->stopTest();
+
+ return result;
+}
+
+int runRestarter(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ NdbRestarter restarter;
+ int i = 0;
+ int lastId = 0;
+ int timeout = 240;
+
+ if (restarter.getNumDbNodes() < 2){
+ ctx->stopTest();
+ return NDBT_OK;
+ }
+ while(i<loops && result != NDBT_FAILED){
+ if(restarter.waitClusterStarted(timeout) != 0){
+ g_err << "Cluster failed to start 1" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ NdbSleep_SecSleep(10);
+
+ int nodeId = restarter.getDbNodeId(lastId);
+ lastId = (lastId + 1) % restarter.getNumDbNodes();
+ if(restarter.restartOneDbNode(nodeId) != 0){
+ g_err << "Failed to restartNextDbNode" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ i++;
+ }
+ if(restarter.waitClusterStarted(timeout) != 0){
+ g_err << "Cluster failed to start 2" << endl;
+ result = NDBT_FAILED;
+ }
+
+ ctx->stopTest();
+
+ return result;
+}
+
+
+int runStopAndStartNode(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ NdbRestarter restarter;
+ int i = 0;
+ int lastId = 0;
+ int timeout = 240;
+
+ if (restarter.getNumDbNodes() < 2){
+ ctx->stopTest();
+ return NDBT_OK;
+ }
+ while(i<loops && result != NDBT_FAILED){
+ if(restarter.waitClusterStarted(timeout) != 0){
+ g_err << "Cluster failed to start 1" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ NdbSleep_SecSleep(1);
+ int nodeId = restarter.getDbNodeId(lastId);
+ lastId = (lastId + 1) % restarter.getNumDbNodes();
+ g_err << "Stopping node " << nodeId << endl;
+
+ if(restarter.restartOneDbNode(nodeId, false, true) != 0){
+ g_err << "Failed to restartOneDbNode" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+
+ if(restarter.waitNodesNoStart(&nodeId, 1, timeout) != 0){
+ g_err << "Node failed to reach NoStart" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+
+ g_info << "Sleeping for 10 secs" << endl;
+ NdbSleep_SecSleep(10);
+
+ g_err << "Starting node " << nodeId << endl;
+ if(restarter.startNodes(&nodeId, 1) != 0){
+ g_err << "Failed to start the node" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+
+ i++;
+ }
+ if(restarter.waitClusterStarted(timeout) != 0){
+ g_err << "Cluster failed to start 2" << endl;
+ result = NDBT_FAILED;
+ }
+
+ ctx->stopTest();
+
+ return result;
+}
+
+int runRestarter9999(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ NdbRestarter restarter;
+ int i = 0;
+ int lastId = 0;
+
+ if (restarter.getNumDbNodes() < 2){
+ ctx->stopTest();
+ return NDBT_OK;
+ }
+ while(i<loops && result != NDBT_FAILED){
+ if(restarter.waitClusterStarted(120) != 0){
+ g_err << "Cluster failed to start" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ NdbSleep_SecSleep(10);
+
+ int nodeId = restarter.getDbNodeId(lastId);
+ lastId = (lastId + 1) % restarter.getNumDbNodes();
+ if(restarter.insertErrorInNode(nodeId, 9999) != 0){
+ g_err << "Failed to insertErrorInNode="<<nodeId << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ NdbSleep_SecSleep(10);
+ i++;
+ }
+ if(restarter.waitClusterStarted(120) != 0){
+ g_err << "Cluster failed to start" << endl;
+ result = NDBT_FAILED;
+ }
+
+ ctx->stopTest();
+
+ return result;
+}
+
+
+int runCheckGetValue(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int parallelism = ctx->getProperty("Parallelism", 1);
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+ AttribList alist;
+ alist.buildAttribList(pTab);
+ UtilTransactions utilTrans(*pTab);
+ for(size_t i = 0; i < alist.attriblist.size(); i++){
+ g_info << (unsigned)i << endl;
+ if(utilTrans.scanReadRecords(GETNDB(step),
+ parallelism,
+ false,
+ records,
+ alist.attriblist[i]->numAttribs,
+ alist.attriblist[i]->attribs) != 0){
+ numFailed++;
+ }
+ if(utilTrans.scanReadRecords(GETNDB(step),
+ parallelism,
+ true,
+ records,
+ alist.attriblist[i]->numAttribs,
+ alist.attriblist[i]->attribs) != 0){
+ numFailed++;
+ }
+ }
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+}
+
+int runCloseWithoutStop(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+ ScanFunctions scanF(*pTab);
+ // Iterate over all possible parallelism valuse
+ for (int p = 1; p<240; p++){
+ g_info << p << " CloseWithoutStop openScan" << endl;
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ p,
+ ScanFunctions::CloseWithoutStop,
+ false) != 0){
+ numFailed++;
+ }
+ g_info << p << " CloseWithoutStop openScanExclusive" << endl;
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ p,
+ ScanFunctions::CloseWithoutStop,
+ true) != 0){
+ numFailed++;
+ }
+ }
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+}
+
+int runNextScanWhenNoMore(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+ ScanFunctions scanF(*pTab);
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::NextScanWhenNoMore,
+ false) != 0){
+ numFailed++;
+ }
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::NextScanWhenNoMore,
+ true) != 0){
+ numFailed++;
+ }
+
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+}
+
+int runEqualAfterOpenScan(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+ ScanFunctions scanF(*pTab);
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::EqualAfterOpenScan,
+ false) == NDBT_OK){
+ numFailed++;
+ }
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::EqualAfterOpenScan,
+ true) == NDBT_OK){
+ numFailed++;
+ }
+
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+}
+
+int runOnlyOpenScanOnce(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+ ScanFunctions scanF(*pTab);
+ g_info << "OnlyOpenScanOnce openScanRead" << endl;
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::OnlyOpenScanOnce,
+ false) == 0){
+ numFailed++;
+ }
+ g_info << "OnlyOpenScanOnce openScanExclusive" << endl;
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::OnlyOpenScanOnce,
+ true) == 0){
+ numFailed++;
+ }
+
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+}
+
+int runOnlyOneOpInScanTrans(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+
+ ScanFunctions scanF(*pTab);
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::OnlyOneOpInScanTrans,
+ false) == 0){
+ numFailed++;
+ }
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::OnlyOneOpInScanTrans,
+ true) == 0){
+ numFailed++;
+ }
+
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+
+}
+
+int runExecuteScanWithoutOpenScan(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+ ScanFunctions scanF(*pTab);
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 1,
+ ScanFunctions::ExecuteScanWithOutOpenScan,
+ false) == 0){
+ numFailed++;
+ }
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+}
+
+
+
+int runOnlyOneOpBeforeOpenScan(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+
+ ScanFunctions scanF(*pTab);
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::OnlyOneOpBeforeOpenScan,
+ false) == 0){
+ numFailed++;
+ }
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::OnlyOneOpBeforeOpenScan,
+ true) == 0){
+ numFailed++;
+ }
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+
+}
+int runOnlyOneScanPerTrans(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+
+ ScanFunctions scanF(*pTab);
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::OnlyOneScanPerTrans,
+ false) == 0){
+ numFailed++;
+ }
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::OnlyOneScanPerTrans,
+ true) == 0){
+ numFailed++;
+ }
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+
+}
+
+int runNoCloseTransaction(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+
+ ScanFunctions scanF(*pTab);
+ int l = 0;
+ while(l < loops){
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::NoCloseTransaction,
+ false) != 0){
+ numFailed++;
+ }
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 6,
+ ScanFunctions::NoCloseTransaction,
+ true) != 0){
+ numFailed++;
+ }
+ l++;
+ }
+
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+
+}
+
+int runCheckInactivityTimeOut(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+
+ ScanFunctions scanF(*pTab);
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 1,
+ ScanFunctions::CheckInactivityTimeOut,
+ false) != NDBT_OK){
+ numFailed++;
+ }
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 240,
+ ScanFunctions::CheckInactivityTimeOut,
+ true) != NDBT_OK){
+ numFailed++;
+ }
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+
+}
+
+int runCheckInactivityBeforeClose(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int records = ctx->getNumRecords();
+ int numFailed = 0;
+
+ ScanFunctions scanF(*pTab);
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 16,
+ ScanFunctions::CheckInactivityBeforeClose,
+ false) != 0){
+ numFailed++;
+ }
+ if (scanF.scanReadFunctions(GETNDB(step),
+ records,
+ 240,
+ ScanFunctions::CheckInactivityBeforeClose,
+ true) != 0){
+ numFailed++;
+ }
+
+ if(numFailed > 0)
+ return NDBT_FAILED;
+ else
+ return NDBT_OK;
+
+}
+
+
+
+NDBT_TESTSUITE(testScan);
+TESTCASE("ScanRead",
+ "Verify scan requirement: It should be possible "\
+ "to read all records in a table without knowing their "\
+ "primary key."){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 1);
+ STEP(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead16",
+ "Verify scan requirement: It should be possible to scan read "\
+ "with parallelism, test with parallelism 16"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 16);
+ STEP(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead240",
+ "Verify scan requirement: It should be possible to scan read with "\
+ "parallelism, test with parallelism 240(240 would automatically be "\
+ "downgraded to the maximum parallelism value for the current config)"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 240);
+ STEP(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadCommitted240",
+ "Verify scan requirement: It should be possible to scan read committed with "\
+ "parallelism, test with parallelism 240(240 would automatically be "\
+ "downgraded to the maximum parallelism value for the current config)"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 240);
+ STEP(runScanReadCommitted);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanUpdate",
+ "Verify scan requirement: It should be possible "\
+ "to update all records in a table without knowing their"\
+ " primary key."){
+ INITIALIZER(runLoadTable);
+ STEP(runScanUpdate);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanUpdate2",
+ "Verify scan requirement: It should be possible "\
+ "to update all records in a table without knowing their"\
+ " primary key. Do this efficently by calling nextScanResult(false) "\
+ "in order to update the records already fetched to the api in one batch."){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 240);
+ STEP(runScanUpdate2);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanDelete",
+ "Verify scan requirement: It should be possible "\
+ "to delete all records in a table without knowing their"\
+ " primary key."){
+ INITIALIZER(runLoadTable);
+ STEP(runScanDelete);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanDelete2",
+ "Verify scan requirement: It should be possible "\
+ "to delete all records in a table without knowing their"\
+ " primary key. Do this efficently by calling nextScanResult(false) "\
+ "in order to delete the records already fetched to the api in one batch."){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 240);
+ STEP(runScanDelete2);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanUpdateAndScanRead",
+ "Verify scan requirement: It should be possible to run "\
+ "scan read and scan update at the same time"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 16);
+ STEP(runScanRead);
+ STEP(runScanUpdate);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadAndLocker",
+ "Verify scan requirement: The locks are not kept throughout "\
+ "the entire scan operation. This means that a scan does not "\
+ "lock the entire table, only the records it's currently "\
+ "operating on. This will test how scan performs when there are "\
+ " a number of 1 second locks in the table"){
+ INITIALIZER(runLoadTable);
+ STEP(runScanReadUntilStopped);
+ STEP(runLocker);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadAndPkRead",
+ "Verify scan requirement: The locks are not kept throughout "\
+ "the entire scan operation. This means that a scan does not "\
+ "lock the entire table, only the records it's currently "\
+ "operating on. This will test how scan performs when there are "\
+ " a pk reads "){
+ INITIALIZER(runLoadTable);
+ STEPS(runScanRead, 2);
+ STEPS(runPkRead, 2);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead488",
+ "Verify scan requirement: It's only possible to have 11 concurrent "\
+ "scans per fragment running in Ndb kernel at the same time. "\
+ "When this limit is exceeded the scan will be aborted with errorcode "\
+ "488."){
+ INITIALIZER(runLoadTable);
+ STEPS(runScanRead, 70);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead488Timeout",
+ ""){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("ErrorCode", 5034);
+ STEPS(runScanRead, 30);
+ STEP(runScanReadError);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead40",
+ "Verify scan requirement: Scan with 40 simultaneous threads"){
+ INITIALIZER(runLoadTable);
+ STEPS(runScanRead, 40);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead100",
+ "Verify scan requirement: Scan with 100 simultaneous threads"){
+ INITIALIZER(runLoadTable);
+ STEPS(runScanRead, 100);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead40RandomTable",
+ "Verify scan requirement: Scan with 40 simultaneous threads. "\
+ "Use random table for the scan"){
+ INITIALIZER(runCreateAllTables);
+ INITIALIZER(runLoadAllTables);
+ STEPS(runScanReadRandomTable, 40);
+ FINALIZER(runDropAllTablesExceptTestTable);
+}
+TESTCASE("ScanRead100RandomTable",
+ "Verify scan requirement: Scan with 100 simultaneous threads. "\
+ "Use random table for the scan"){
+ INITIALIZER(runCreateAllTables);
+ INITIALIZER(runLoadAllTables);
+ STEPS(runScanReadRandomTable, 100);
+ FINALIZER(runDropAllTablesExceptTestTable);
+}
+TESTCASE("ScanReadRandomPrepare",
+ "Create and load tables for ScanRead40RandomNoTableCreate."){
+ INITIALIZER(runCreateAllTables);
+ INITIALIZER(runLoadAllTables);
+}
+TESTCASE("ScanRead40RandomNoTableCreate",
+ "Verify scan requirement: Scan with 40 simultaneous threads. "\
+ "Use random table for the scan. Dont create or load the tables."){
+ STEPS(runScanReadRandomTable, 40);
+}
+TESTCASE("ScanRead100RandomNoTableCreate",
+ "Verify scan requirement: Scan with 100 simultaneous threads. "\
+ "Use random table for the scan. Dont create or load the tables."){
+ STEPS(runScanReadRandomTable, 100);
+}
+TESTCASE("ScanWithLocksAndInserts",
+ "TR457: This test is added to verify that an insert of a records "\
+ "that is already in the database does not delete the record"){
+ INITIALIZER(runLoadTable);
+ STEPS(runScanReadUntilStopped, 2);
+ STEP(runLocker);
+ STEP(runInsertUntilStopped);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadAbort",
+ "Scan requirement: A scan may be aborted by the application "\
+ "at any time. This can be performed even if there are more "\
+ "tuples to scan."){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("AbortProb", 90);
+ STEPS(runScanRead, 3);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadAbort15",
+ "Scan requirement: A scan may be aborted by the application "\
+ "at any time. This can be performed even if there are more "\
+ "tuples to scan. Use parallelism 15"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 15);
+ TC_PROPERTY("AbortProb", 90);
+ STEPS(runScanRead, 3);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadAbort240",
+ "Scan requirement: A scan may be aborted by the application "\
+ "at any time. This can be performed even if there are more "\
+ "tuples to scan. Use parallelism 240(it will be downgraded to max para for this config)"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 240);
+ TC_PROPERTY("AbortProb", 90);
+ STEPS(runScanRead, 3);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanUpdateAbort16",
+ "Scan requirement: A scan may be aborted by the application "\
+ "at any time. This can be performed even if there are more "\
+ "tuples to scan. Use parallelism 16"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 16);
+ TC_PROPERTY("AbortProb", 90);
+ STEPS(runScanUpdate, 3);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanUpdateAbort240",
+ "Scan requirement: A scan may be aborted by the application "\
+ "at any time. This can be performed even if there are more "\
+ "tuples to scan. Use parallelism 240(it will be downgraded to max para for this config)"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 240);
+ TC_PROPERTY("AbortProb", 90);
+ STEPS(runScanUpdate, 3);
+ FINALIZER(runClearTable);
+}
+TESTCASE("CheckGetValue",
+ "Check that we can call getValue to read attributes"\
+ "Especially interesting to see if we can read only the"\
+ " first, last or any two attributes from the table"){
+ INITIALIZER(runLoadTable);
+ STEP(runCheckGetValue);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("CloseWithoutStop",
+ "Check that we can close the scanning transaction without calling "\
+ "stopScan"){
+ INITIALIZER(runLoadTable);
+ STEP(runCloseWithoutStop);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("NextScanWhenNoMore",
+ "Check that we can call nextScanResult when there are no more "\
+ "records, and that it returns a valid value"){
+ INITIALIZER(runLoadTable);
+ STEP(runNextScanWhenNoMore);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("EqualAfterOpenScan",
+ "Check that we can't call equal after openScan"){
+ STEP(runEqualAfterOpenScan);
+}
+TESTCASE("ExecuteScanWithoutOpenScan",
+ "Check that we can't call executeScan without defining a scan "\
+ "with openScan"){
+ INITIALIZER(runLoadTable);
+ STEP(runExecuteScanWithoutOpenScan);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("OnlyOpenScanOnce",
+ "Check that we may only call openScan once in the same trans"){
+ INITIALIZER(runLoadTable);
+ STEP(runOnlyOpenScanOnce);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("OnlyOneOpInScanTrans",
+ "Check that we can have only one operation in a scan trans"){
+ INITIALIZER(runLoadTable);
+ STEP(runOnlyOneOpInScanTrans);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("OnlyOneOpBeforeOpenScan",
+ "Check that we can have only one operation in a trans defined "\
+ "when calling openScan "){
+ INITIALIZER(runLoadTable);
+ STEP(runOnlyOneOpBeforeOpenScan);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("OnlyOneScanPerTrans",
+ "Check that we can have only one scan operation in a trans"){
+ INITIALIZER(runLoadTable);
+ STEP(runOnlyOneScanPerTrans);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("NoCloseTransaction",
+ "Check behaviour when close transaction is not called "){
+ INITIALIZER(runLoadTable);
+ STEP(runNoCloseTransaction);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("CheckInactivityTimeOut",
+ "Check behaviour when the api sleeps for a long time before continuing scan "){
+ INITIALIZER(runLoadTable);
+ STEP(runCheckInactivityTimeOut);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("CheckInactivityBeforeClose",
+ "Check behaviour when the api sleeps for a long time before calling close scan "){
+ INITIALIZER(runLoadTable);
+ STEP(runCheckInactivityBeforeClose);
+ VERIFIER(runScanRead);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadError5021",
+ "Scan and insert error 5021, one node is expected to crash"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("ErrorCode", 5021);
+ STEP(runScanReadErrorOneNode);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadError5022",
+ "Scan and insert error 5022, one node is expected to crash"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("ErrorCode", 5022);
+ TC_PROPERTY("NodeNumber", 2);
+ STEP(runScanReadErrorOneNode);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadError5023",
+ "Scan and insert error 5023"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("ErrorCode", 5023);
+ STEP(runScanReadError);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadError5024",
+ "Scan and insert error 5024"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("ErrorCode", 5024);
+ STEP(runScanReadError);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadError5025",
+ "Scan and insert error 5025"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("ErrorCode", 5025);
+ STEP(runScanReadError);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadError5030",
+ "Scan and insert error 5030."\
+ "Drop all SCAN_NEXTREQ signals in LQH until the node is "\
+ "shutdown with SYSTEM_ERROR because of scan fragment timeout"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("ErrorCode", 5030);
+ STEP(runScanReadErrorOneNode);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadRestart",
+ "Scan requirement:A scan should be able to start and "\
+ "complete during node recovery and when one or more nodes "\
+ "in the cluster is down.Use random parallelism "){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", RANDOM_PARALLELISM); // Random
+ STEP(runScanReadUntilStopped);
+ STEP(runRestarter);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanUpdateRestart",
+ "Scan requirement:A scan should be able to start and "\
+ "complete during node recovery and when one or more nodes "\
+ "in the cluster is down. Use random parallelism"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", RANDOM_PARALLELISM); // Random
+ STEP(runScanUpdateUntilStopped);
+ STEP(runRestarter);
+ FINALIZER(runClearTable);
+}
+#if 0
+TESTCASE("ScanReadRestart9999",
+ "Scan requirement:A scan should be able to start and "\
+ "complete during node recovery and when one or more nodes "\
+ "in the cluster is down. Use parallelism 240."\
+ "Restart using error insert 9999"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 240);
+ STEP(runScanReadUntilStopped);
+ STEP(runRestarter9999);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanUpdateRestart9999",
+ "Scan requirement:A scan should be able to start and "\
+ "complete during node recovery and when one or more nodes "\
+ "in the cluster is down. Use parallelism 240."\
+ "Restart using error insert 9999"){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 240);
+ STEP(runScanReadUntilStopped);
+ STEP(runScanUpdateUntilStopped);
+ STEP(runRestarter9999);
+ FINALIZER(runClearTable);
+}
+#endif
+TESTCASE("InsertDelete",
+ "Load and delete all while scan updating and scan reading\n"\
+ "Alexander Lukas special"){
+ INITIALIZER(runClearTable);
+ STEP(runScanReadUntilStoppedNoCount);
+ STEP(runScanUpdateUntilStopped);
+ STEP(runInsertDelete);
+ FINALIZER(runClearTable);
+}
+TESTCASE("CheckAfterTerror",
+ "Check that we can still scan read after this terror of NdbApi"){
+ INITIALIZER(runLoadTable);
+ STEPS(runScanRead, 5);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanReadWhileNodeIsDown",
+ "Scan requirement:A scan should be able to run as fast when "\
+ "one or more nodes in the cluster is down."){
+ INITIALIZER(runLoadTable);
+ STEP(runScanReadUntilStoppedPrintTime);
+ STEP(runStopAndStartNode);
+ FINALIZER(runClearTable);
+}
+NDBT_TESTSUITE_END(testScan);
+
+int main(int argc, const char** argv){
+ myRandom48Init(NdbTick_CurrentMillisecond());
+ return testScan.execute(argc, argv);
+}
+
diff --git a/ndb/test/ndbapi/testScan/testScan.cpp b/ndb/test/ndbapi/testScan/testScan.cpp
deleted file mode 100644
index dbf91f016d8..00000000000
--- a/ndb/test/ndbapi/testScan/testScan.cpp
+++ /dev/null
@@ -1,1311 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NDBT.hpp>
-#include <NDBT_Test.hpp>
-#include <HugoTransactions.hpp>
-#include <UtilTransactions.hpp>
-#include <NdbRestarter.hpp>
-#include <Vector.hpp>
-#include "ScanFunctions.hpp"
-#include <random.h>
-
-const NdbDictionary::Table *
-getTable(Ndb* pNdb, int i){
- const NdbDictionary::Table* t = NDBT_Tables::getTable(i);
- if (t == NULL){
- return 0;
- }
- return pNdb->getDictionary()->getTable(t->getName());
-}
-
-
-int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
-
- int records = ctx->getNumRecords();
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-
-int runCreateAllTables(NDBT_Context* ctx, NDBT_Step* step){
-
- int a = NDBT_Tables::createAllTables(GETNDB(step), false, true);
- return a;
-}
-
-int runDropAllTablesExceptTestTable(NDBT_Context* ctx, NDBT_Step* step){
-
- for (int i=0; i < NDBT_Tables::getNumTables(); i++){
-
- const NdbDictionary::Table* tab = NDBT_Tables::getTable(i);
- if (tab == NULL){
- return NDBT_ProgramExit(NDBT_FAILED);
- }
-
- // Don't drop test table
- if (strcmp(tab->getName(), ctx->getTab()->getName()) == 0){
- continue;
- }
-
- int res = GETNDB(step)->getDictionary()->dropTable(tab->getName());
- if(res != -1){
- return NDBT_FAILED;
- }
- }
- return NDBT_OK;
-}
-
-
-int runLoadAllTables(NDBT_Context* ctx, NDBT_Step* step){
-
- int records = ctx->getNumRecords();
- for (int i=0; i < NDBT_Tables::getNumTables(); i++){
-
- const NdbDictionary::Table* tab = getTable(GETNDB(step), i);
- if (tab == NULL){
- return NDBT_FAILED;
- }
- HugoTransactions hugoTrans(*tab);
- if (hugoTrans.loadTable(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- }
- return NDBT_OK;
-}
-
-int runScanReadRandomTable(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int parallelism = ctx->getProperty("Parallelism", 240);
- int abort = ctx->getProperty("AbortProb");
-
- int i = 0;
- while (i<loops) {
-
- int tabNum = myRandom48(NDBT_Tables::getNumTables());
- const NdbDictionary::Table* tab = getTable(GETNDB(step), tabNum);
- if (tab == NULL){
- g_info << "tab == NULL" << endl;
- return NDBT_FAILED;
- }
-
- g_info << "Scan reading from table " << tab->getName() << endl;
- HugoTransactions hugoTrans(*tab);
-
- g_info << i << ": ";
- if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runInsertUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (ctx->isTestStopped() == false) {
- g_info << i << ": ";
- if (hugoTrans.loadTable(GETNDB(step), records, 1) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runInsertDelete(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int records = ctx->getNumRecords();
- int loops = ctx->getNumLoops();
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- UtilTransactions utilTrans(*ctx->getTab());
- while (i<loops) {
- g_info << i << ": ";
- if (hugoTrans.loadTable(GETNDB(step), records, 1) != 0){
- result = NDBT_FAILED;
- break;
- }
- if (utilTrans.clearTable(GETNDB(step), records) != 0){
- result = NDBT_FAILED;
- break;
- }
- i++;
- }
-
- ctx->stopTest();
-
- return result;
-}
-
-int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
-
- UtilTransactions utilTrans(*ctx->getTab());
- if (utilTrans.clearTable2(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runScanDelete(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
-
- int i = 0;
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
- while (i<loops) {
- g_info << i << ": ";
- if (utilTrans.clearTable(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- // Load table, don't allow any primary key violations
- if (hugoTrans.loadTable(GETNDB(step), records, 512, false) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runScanDelete2(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
-
- int i = 0;
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
-
- while (i<loops) {
- g_info << i << ": ";
- if (utilTrans.clearTable2(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- // Load table, don't allow any primary key violations
- if (hugoTrans.loadTable(GETNDB(step), records, 512, false) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runVerifyTable(NDBT_Context* ctx, NDBT_Step* step){
- return NDBT_OK;
-}
-
-int runScanRead(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int parallelism = ctx->getProperty("Parallelism", 240);
- int abort = ctx->getProperty("AbortProb");
-
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (i<loops && !ctx->isTestStopped()) {
- g_info << i << ": ";
- if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runScanReadCommitted(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int parallelism = ctx->getProperty("Parallelism", 240);
- int abort = ctx->getProperty("AbortProb");
-
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (i<loops && !ctx->isTestStopped()) {
- g_info << i << ": ";
- if (hugoTrans.scanReadCommittedRecords(GETNDB(step), records,
- abort, parallelism) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runScanReadError(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int parallelism = 240; // Max parallelism
- int error = ctx->getProperty("ErrorCode");
- NdbRestarter restarter;
-
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (i<loops && !ctx->isTestStopped()) {
- g_info << i << ": ";
-
- ndbout << "insertErrorInAllNodes("<<error<<")"<<endl;
- if (restarter.insertErrorInAllNodes(error) != 0){
- ndbout << "Could not insert error in all nodes "<<endl;
- return NDBT_FAILED;
- }
-
- if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, parallelism) != 0){
- result = NDBT_FAILED;
- }
- i++;
- }
-
- restarter.insertErrorInAllNodes(0);
- return result;
-}
-
-int runScanReadErrorOneNode(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int parallelism = 240; // Max parallelism
- int error = ctx->getProperty("ErrorCode");
- NdbRestarter restarter;
- int lastId = 0;
-
- if (restarter.getNumDbNodes() < 2){
- ctx->stopTest();
- return NDBT_OK;
- }
-
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (i<loops && result == NDBT_OK) {
- g_info << i << ": ";
-
- int nodeId = restarter.getDbNodeId(lastId);
- lastId = (lastId + 1) % restarter.getNumDbNodes();
- ndbout << "insertErrorInNode("<<nodeId<<", "<<error<<")"<<endl;
- if (restarter.insertErrorInNode(nodeId, error) != 0){
- ndbout << "Could not insert error in node="<<nodeId<<endl;
- return NDBT_FAILED;
- }
-
- for (int j=0; j<10; j++){
- if (hugoTrans.scanReadRecords(GETNDB(step),
- records, 0, parallelism) != 0)
- result = NDBT_FAILED;
- }
-
-
- if(restarter.waitClusterStarted(120) != 0){
- g_err << "Cluster failed to restart" << endl;
- result = NDBT_FAILED;
- }
- restarter.insertErrorInAllNodes(0);
-
- i++;
- }
- restarter.insertErrorInAllNodes(0);
- return result;
-}
-
-int runRestartAll(NDBT_Context* ctx, NDBT_Step* step){
-
- NdbRestarter restarter;
-
- if (restarter.restartAll() != 0){
- ndbout << "Could not restart all nodes"<<endl;
- return NDBT_FAILED;
- }
-
- if (restarter.waitClusterStarted(120) != 0){
- ndbout << "Could not restarted" << endl;
- return NDBT_FAILED;
- }
-
- return NDBT_OK;
-}
-
-static int RANDOM_PARALLELISM = 9999;
-
-int runScanReadUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- int i = 0;
-
- int parallelism = ctx->getProperty("Parallelism", 240);
- int para = parallelism;
-
- HugoTransactions hugoTrans(*ctx->getTab());
- while (ctx->isTestStopped() == false) {
- if (parallelism == RANDOM_PARALLELISM)
- para = myRandom48(239)+1;
-
- g_info << i << ": ";
- if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, para) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runScanReadUntilStoppedNoCount(NDBT_Context* ctx, NDBT_Step* step){
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (ctx->isTestStopped() == false) {
- g_info << i << ": ";
- if (hugoTrans.scanReadRecords(GETNDB(step), 0) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-
-int runPkRead(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (i<loops) {
- g_info << i << ": ";
- if (hugoTrans.pkReadRecords(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runScanUpdate(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int parallelism = ctx->getProperty("Parallelism", 1);
- int abort = ctx->getProperty("AbortProb");
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (i<loops) {
- g_info << i << ": ";
-
- if (hugoTrans.scanUpdateRecords(GETNDB(step), records, abort, parallelism) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runScanUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- int i = 0;
-
- int parallelism = ctx->getProperty("Parallelism", 240);
- int para = parallelism;
-
- HugoTransactions hugoTrans(*ctx->getTab());
- while (ctx->isTestStopped() == false) {
- if (parallelism == RANDOM_PARALLELISM)
- para = myRandom48(239)+1;
-
- g_info << i << ": ";
- if (hugoTrans.scanUpdateRecords(GETNDB(step), records, 0, para) == NDBT_FAILED){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-
-int runScanUpdate2(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int parallelism = ctx->getProperty("Parallelism", 240);
- int abort = ctx->getProperty("AbortProb");
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (i<loops) {
- g_info << i << ": ";
- if (hugoTrans.scanUpdateRecords2(GETNDB(step), records, abort, parallelism) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runLocker(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int records = ctx->getNumRecords();
- HugoTransactions hugoTrans(*ctx->getTab());
-
- if (hugoTrans.lockRecords(GETNDB(step), records, 5, 500) != 0){
- result = NDBT_FAILED;
- }
- ctx->stopTest();
-
- return result;
-}
-
-int runRestarter(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
- NdbRestarter restarter;
- int i = 0;
- int lastId = 0;
- int timeout = 240;
-
- if (restarter.getNumDbNodes() < 2){
- ctx->stopTest();
- return NDBT_OK;
- }
- while(i<loops && result != NDBT_FAILED){
- if(restarter.waitClusterStarted(timeout) != 0){
- g_err << "Cluster failed to start 1" << endl;
- result = NDBT_FAILED;
- break;
- }
- NdbSleep_SecSleep(10);
-
- int nodeId = restarter.getDbNodeId(lastId);
- lastId = (lastId + 1) % restarter.getNumDbNodes();
- if(restarter.restartOneDbNode(nodeId) != 0){
- g_err << "Failed to restartNextDbNode" << endl;
- result = NDBT_FAILED;
- break;
- }
- i++;
- }
- if(restarter.waitClusterStarted(timeout) != 0){
- g_err << "Cluster failed to start 2" << endl;
- result = NDBT_FAILED;
- }
-
- ctx->stopTest();
-
- return result;
-}
-
-int runRestarter9999(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
- NdbRestarter restarter;
- int i = 0;
- int lastId = 0;
-
- if (restarter.getNumDbNodes() < 2){
- ctx->stopTest();
- return NDBT_OK;
- }
- while(i<loops && result != NDBT_FAILED){
- if(restarter.waitClusterStarted(120) != 0){
- g_err << "Cluster failed to start" << endl;
- result = NDBT_FAILED;
- break;
- }
- NdbSleep_SecSleep(10);
-
- int nodeId = restarter.getDbNodeId(lastId);
- lastId = (lastId + 1) % restarter.getNumDbNodes();
- if(restarter.insertErrorInNode(nodeId, 9999) != 0){
- g_err << "Failed to insertErrorInNode="<<nodeId << endl;
- result = NDBT_FAILED;
- break;
- }
- NdbSleep_SecSleep(10);
- i++;
- }
- if(restarter.waitClusterStarted(120) != 0){
- g_err << "Cluster failed to start" << endl;
- result = NDBT_FAILED;
- }
-
- ctx->stopTest();
-
- return result;
-}
-
-
-int runCheckGetValue(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int parallelism = ctx->getProperty("Parallelism", 1);
- int records = ctx->getNumRecords();
- int numFailed = 0;
- AttribList alist;
- alist.buildAttribList(pTab);
- UtilTransactions utilTrans(*pTab);
- for(size_t i = 0; i < alist.attriblist.size(); i++){
- g_info << (unsigned)i << endl;
- if(utilTrans.scanReadRecords(GETNDB(step),
- parallelism,
- false,
- records,
- alist.attriblist[i]->numAttribs,
- alist.attriblist[i]->attribs) != 0){
- numFailed++;
- }
- if(utilTrans.scanReadRecords(GETNDB(step),
- parallelism,
- true,
- records,
- alist.attriblist[i]->numAttribs,
- alist.attriblist[i]->attribs) != 0){
- numFailed++;
- }
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-}
-
-int runCloseWithoutStop(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
- ScanFunctions scanF(*pTab);
- // Iterate over all possible parallelism valuse
- for (int p = 1; p<240; p++){
- g_info << p << " CloseWithoutStop openScan" << endl;
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- p,
- ScanFunctions::CloseWithoutStop,
- false) != 0){
- numFailed++;
- }
- g_info << p << " CloseWithoutStop openScanExclusive" << endl;
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- p,
- ScanFunctions::CloseWithoutStop,
- true) != 0){
- numFailed++;
- }
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-}
-
-int runNextScanWhenNoMore(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::NextScanWhenNoMore,
- false) != 0){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::NextScanWhenNoMore,
- true) != 0){
- numFailed++;
- }
-
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-}
-
-int runEqualAfterOpenScan(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::EqualAfterOpenScan,
- false) == NDBT_OK){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::EqualAfterOpenScan,
- true) == NDBT_OK){
- numFailed++;
- }
-
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-}
-
-int runOnlyOpenScanOnce(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
- ScanFunctions scanF(*pTab);
- g_info << "OnlyOpenScanOnce openScanRead" << endl;
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOpenScanOnce,
- false) == 0){
- numFailed++;
- }
- g_info << "OnlyOpenScanOnce openScanExclusive" << endl;
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOpenScanOnce,
- true) == 0){
- numFailed++;
- }
-
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-}
-
-int runOnlyOneOpInScanTrans(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
-
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneOpInScanTrans,
- false) == 0){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneOpInScanTrans,
- true) == 0){
- numFailed++;
- }
-
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-
-}
-
-int runExecuteScanWithoutOpenScan(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 1,
- ScanFunctions::ExecuteScanWithOutOpenScan,
- false) == 0){
- numFailed++;
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-}
-
-
-
-int runOnlyOneOpBeforeOpenScan(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
-
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneOpBeforeOpenScan,
- false) == 0){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneOpBeforeOpenScan,
- true) == 0){
- numFailed++;
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-
-}
-int runOnlyOneScanPerTrans(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
-
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneScanPerTrans,
- false) == 0){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneScanPerTrans,
- true) == 0){
- numFailed++;
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-
-}
-
-int runNoCloseTransaction(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int numFailed = 0;
-
- ScanFunctions scanF(*pTab);
- int l = 0;
- while(l < loops){
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::NoCloseTransaction,
- false) != 0){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::NoCloseTransaction,
- true) != 0){
- numFailed++;
- }
- l++;
- }
-
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-
-}
-
-int runCheckInactivityTimeOut(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
-
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 1,
- ScanFunctions::CheckInactivityTimeOut,
- false) != NDBT_OK){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 240,
- ScanFunctions::CheckInactivityTimeOut,
- true) != NDBT_OK){
- numFailed++;
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-
-}
-
-int runCheckInactivityBeforeClose(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
-
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 16,
- ScanFunctions::CheckInactivityBeforeClose,
- false) != 0){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 240,
- ScanFunctions::CheckInactivityBeforeClose,
- true) != 0){
- numFailed++;
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-
-}
-
-
-
-NDBT_TESTSUITE(testScan);
-TESTCASE("ScanRead",
- "Verify scan requirement: It should be possible "\
- "to read all records in a table without knowing their "\
- "primary key."){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 1);
- STEP(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanRead16",
- "Verify scan requirement: It should be possible to scan read "\
- "with parallelism, test with parallelism 16"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 16);
- STEP(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanRead240",
- "Verify scan requirement: It should be possible to scan read with "\
- "parallelism, test with parallelism 240(240 would automatically be "\
- "downgraded to the maximum parallelism value for the current config)"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 240);
- STEP(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadCommitted240",
- "Verify scan requirement: It should be possible to scan read committed with "\
- "parallelism, test with parallelism 240(240 would automatically be "\
- "downgraded to the maximum parallelism value for the current config)"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 240);
- STEP(runScanReadCommitted);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanUpdate",
- "Verify scan requirement: It should be possible "\
- "to update all records in a table without knowing their"\
- " primary key."){
- INITIALIZER(runLoadTable);
- STEP(runScanUpdate);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanUpdate2",
- "Verify scan requirement: It should be possible "\
- "to update all records in a table without knowing their"\
- " primary key. Do this efficently by calling nextScanResult(false) "\
- "in order to update the records already fetched to the api in one batch."){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 240);
- STEP(runScanUpdate2);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanDelete",
- "Verify scan requirement: It should be possible "\
- "to delete all records in a table without knowing their"\
- " primary key."){
- INITIALIZER(runLoadTable);
- STEP(runScanDelete);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanDelete2",
- "Verify scan requirement: It should be possible "\
- "to delete all records in a table without knowing their"\
- " primary key. Do this efficently by calling nextScanResult(false) "\
- "in order to delete the records already fetched to the api in one batch."){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 240);
- STEP(runScanDelete2);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanUpdateAndScanRead",
- "Verify scan requirement: It should be possible to run "\
- "scan read and scan update at the same time"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 16);
- STEP(runScanRead);
- STEP(runScanUpdate);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadAndLocker",
- "Verify scan requirement: The locks are not kept throughout "\
- "the entire scan operation. This means that a scan does not "\
- "lock the entire table, only the records it's currently "\
- "operating on. This will test how scan performs when there are "\
- " a number of 1 second locks in the table"){
- INITIALIZER(runLoadTable);
- STEP(runScanReadUntilStopped);
- STEP(runLocker);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadAndPkRead",
- "Verify scan requirement: The locks are not kept throughout "\
- "the entire scan operation. This means that a scan does not "\
- "lock the entire table, only the records it's currently "\
- "operating on. This will test how scan performs when there are "\
- " a pk reads "){
- INITIALIZER(runLoadTable);
- STEPS(runScanRead, 2);
- STEPS(runPkRead, 2);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanRead488",
- "Verify scan requirement: It's only possible to have 11 concurrent "\
- "scans per fragment running in Ndb kernel at the same time. "\
- "When this limit is exceeded the scan will be aborted with errorcode "\
- "488."){
- INITIALIZER(runLoadTable);
- STEPS(runScanRead, 70);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanRead488Timeout",
- ""){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("ErrorCode", 5034);
- STEPS(runScanRead, 30);
- STEP(runScanReadError);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanRead40",
- "Verify scan requirement: Scan with 40 simultaneous threads"){
- INITIALIZER(runLoadTable);
- STEPS(runScanRead, 40);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanRead100",
- "Verify scan requirement: Scan with 100 simultaneous threads"){
- INITIALIZER(runLoadTable);
- STEPS(runScanRead, 100);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanRead40RandomTable",
- "Verify scan requirement: Scan with 40 simultaneous threads. "\
- "Use random table for the scan"){
- INITIALIZER(runCreateAllTables);
- INITIALIZER(runLoadAllTables);
- STEPS(runScanReadRandomTable, 40);
- FINALIZER(runDropAllTablesExceptTestTable);
-}
-TESTCASE("ScanRead100RandomTable",
- "Verify scan requirement: Scan with 100 simultaneous threads. "\
- "Use random table for the scan"){
- INITIALIZER(runCreateAllTables);
- INITIALIZER(runLoadAllTables);
- STEPS(runScanReadRandomTable, 100);
- FINALIZER(runDropAllTablesExceptTestTable);
-}
-TESTCASE("ScanReadRandomPrepare",
- "Create and load tables for ScanRead40RandomNoTableCreate."){
- INITIALIZER(runCreateAllTables);
- INITIALIZER(runLoadAllTables);
-}
-TESTCASE("ScanRead40RandomNoTableCreate",
- "Verify scan requirement: Scan with 40 simultaneous threads. "\
- "Use random table for the scan. Dont create or load the tables."){
- STEPS(runScanReadRandomTable, 40);
-}
-TESTCASE("ScanRead100RandomNoTableCreate",
- "Verify scan requirement: Scan with 100 simultaneous threads. "\
- "Use random table for the scan. Dont create or load the tables."){
- STEPS(runScanReadRandomTable, 100);
-}
-TESTCASE("ScanWithLocksAndInserts",
- "TR457: This test is added to verify that an insert of a records "\
- "that is already in the database does not delete the record"){
- INITIALIZER(runLoadTable);
- STEPS(runScanReadUntilStopped, 2);
- STEP(runLocker);
- STEP(runInsertUntilStopped);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadAbort",
- "Scan requirement: A scan may be aborted by the application "\
- "at any time. This can be performed even if there are more "\
- "tuples to scan."){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("AbortProb", 90);
- STEPS(runScanRead, 3);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadAbort15",
- "Scan requirement: A scan may be aborted by the application "\
- "at any time. This can be performed even if there are more "\
- "tuples to scan. Use parallelism 15"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 15);
- TC_PROPERTY("AbortProb", 90);
- STEPS(runScanRead, 3);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadAbort240",
- "Scan requirement: A scan may be aborted by the application "\
- "at any time. This can be performed even if there are more "\
- "tuples to scan. Use parallelism 240(it will be downgraded to max para for this config)"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 240);
- TC_PROPERTY("AbortProb", 90);
- STEPS(runScanRead, 3);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanUpdateAbort16",
- "Scan requirement: A scan may be aborted by the application "\
- "at any time. This can be performed even if there are more "\
- "tuples to scan. Use parallelism 16"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 16);
- TC_PROPERTY("AbortProb", 90);
- STEPS(runScanUpdate, 3);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanUpdateAbort240",
- "Scan requirement: A scan may be aborted by the application "\
- "at any time. This can be performed even if there are more "\
- "tuples to scan. Use parallelism 240(it will be downgraded to max para for this config)"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 240);
- TC_PROPERTY("AbortProb", 90);
- STEPS(runScanUpdate, 3);
- FINALIZER(runClearTable);
-}
-TESTCASE("CheckGetValue",
- "Check that we can call getValue to read attributes"\
- "Especially interesting to see if we can read only the"\
- " first, last or any two attributes from the table"){
- INITIALIZER(runLoadTable);
- STEP(runCheckGetValue);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("CloseWithoutStop",
- "Check that we can close the scanning transaction without calling "\
- "stopScan"){
- INITIALIZER(runLoadTable);
- STEP(runCloseWithoutStop);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("NextScanWhenNoMore",
- "Check that we can call nextScanResult when there are no more "\
- "records, and that it returns a valid value"){
- INITIALIZER(runLoadTable);
- STEP(runNextScanWhenNoMore);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("EqualAfterOpenScan",
- "Check that we can't call equal after openScan"){
- STEP(runEqualAfterOpenScan);
-}
-TESTCASE("ExecuteScanWithoutOpenScan",
- "Check that we can't call executeScan without defining a scan "\
- "with openScan"){
- INITIALIZER(runLoadTable);
- STEP(runExecuteScanWithoutOpenScan);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("OnlyOpenScanOnce",
- "Check that we may only call openScan once in the same trans"){
- INITIALIZER(runLoadTable);
- STEP(runOnlyOpenScanOnce);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("OnlyOneOpInScanTrans",
- "Check that we can have only one operation in a scan trans"){
- INITIALIZER(runLoadTable);
- STEP(runOnlyOneOpInScanTrans);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("OnlyOneOpBeforeOpenScan",
- "Check that we can have only one operation in a trans defined "\
- "when calling openScan "){
- INITIALIZER(runLoadTable);
- STEP(runOnlyOneOpBeforeOpenScan);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("OnlyOneScanPerTrans",
- "Check that we can have only one scan operation in a trans"){
- INITIALIZER(runLoadTable);
- STEP(runOnlyOneScanPerTrans);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("NoCloseTransaction",
- "Check behaviour when close transaction is not called "){
- INITIALIZER(runLoadTable);
- STEP(runNoCloseTransaction);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("CheckInactivityTimeOut",
- "Check behaviour when the api sleeps for a long time before continuing scan "){
- INITIALIZER(runLoadTable);
- STEP(runCheckInactivityTimeOut);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("CheckInactivityBeforeClose",
- "Check behaviour when the api sleeps for a long time before calling close scan "){
- INITIALIZER(runLoadTable);
- STEP(runCheckInactivityBeforeClose);
- VERIFIER(runScanRead);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadError5021",
- "Scan and insert error 5021, one node is expected to crash"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("ErrorCode", 5021);
- STEP(runScanReadErrorOneNode);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadError5022",
- "Scan and insert error 5022, one node is expected to crash"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("ErrorCode", 5022);
- TC_PROPERTY("NodeNumber", 2);
- STEP(runScanReadErrorOneNode);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadError5023",
- "Scan and insert error 5023"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("ErrorCode", 5023);
- STEP(runScanReadError);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadError5024",
- "Scan and insert error 5024"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("ErrorCode", 5024);
- STEP(runScanReadError);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadError5025",
- "Scan and insert error 5025"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("ErrorCode", 5025);
- STEP(runScanReadError);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadError5030",
- "Scan and insert error 5030."\
- "Drop all SCAN_NEXTREQ signals in LQH until the node is "\
- "shutdown with SYSTEM_ERROR because of scan fragment timeout"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("ErrorCode", 5030);
- STEP(runScanReadErrorOneNode);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanReadRestart",
- "Scan requirement:A scan should be able to start and "\
- "complete during node recovery and when one or more nodes "\
- "in the cluster is down.Use random parallelism "){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", RANDOM_PARALLELISM); // Random
- STEP(runScanReadUntilStopped);
- STEP(runRestarter);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanUpdateRestart",
- "Scan requirement:A scan should be able to start and "\
- "complete during node recovery and when one or more nodes "\
- "in the cluster is down. Use random parallelism"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", RANDOM_PARALLELISM); // Random
- STEP(runScanUpdateUntilStopped);
- STEP(runRestarter);
- FINALIZER(runClearTable);
-}
-#if 0
-TESTCASE("ScanReadRestart9999",
- "Scan requirement:A scan should be able to start and "\
- "complete during node recovery and when one or more nodes "\
- "in the cluster is down. Use parallelism 240."\
- "Restart using error insert 9999"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 240);
- STEP(runScanReadUntilStopped);
- STEP(runRestarter9999);
- FINALIZER(runClearTable);
-}
-TESTCASE("ScanUpdateRestart9999",
- "Scan requirement:A scan should be able to start and "\
- "complete during node recovery and when one or more nodes "\
- "in the cluster is down. Use parallelism 240."\
- "Restart using error insert 9999"){
- INITIALIZER(runLoadTable);
- TC_PROPERTY("Parallelism", 240);
- STEP(runScanReadUntilStopped);
- STEP(runScanUpdateUntilStopped);
- STEP(runRestarter9999);
- FINALIZER(runClearTable);
-}
-#endif
-TESTCASE("InsertDelete",
- "Load and delete all while scan updating and scan reading\n"\
- "Alexander Lukas special"){
- INITIALIZER(runClearTable);
- STEP(runScanReadUntilStoppedNoCount);
- STEP(runScanUpdateUntilStopped);
- STEP(runInsertDelete);
- FINALIZER(runClearTable);
-}
-TESTCASE("CheckAfterTerror",
- "Check that we can still scan read after this terror of NdbApi"){
- INITIALIZER(runLoadTable);
- STEPS(runScanRead, 5);
- FINALIZER(runClearTable);
-}
-NDBT_TESTSUITE_END(testScan);
-
-int main(int argc, const char** argv){
- myRandom48Init(NdbTick_CurrentMillisecond());
- return testScan.execute(argc, argv);
-}
-
diff --git a/ndb/test/ndbapi/testScanInterpreter.cpp b/ndb/test/ndbapi/testScanInterpreter.cpp
new file mode 100644
index 00000000000..3b5baf954e0
--- /dev/null
+++ b/ndb/test/ndbapi/testScanInterpreter.cpp
@@ -0,0 +1,280 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "NDBT_Test.hpp"
+#include "NDBT_ReturnCodes.h"
+#include "HugoTransactions.hpp"
+#include "UtilTransactions.hpp"
+#include "NdbRestarter.hpp"
+#include <Vector.hpp>
+#include "ScanFilter.hpp"
+#include "ScanInterpretTest.hpp"
+
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable2(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runClearResTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ const NdbDictionary::Table* pResTab =
+ GETNDB(step)->getDictionary()->getTable(ctx->getProperty("ResultTabName", "NULL"));
+
+ UtilTransactions utilTrans(*pResTab);
+ if (utilTrans.clearTable2(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runScanRead(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = ctx->getProperty("Parallelism", 1);
+
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops) {
+ g_info << i << ": ";
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, parallelism) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runScanReadResTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ int parallelism = ctx->getProperty("Parallelism", 1);
+ const NdbDictionary::Table* pResTab =
+ NDBT_Table::discoverTableFromDb(GETNDB(step),
+ ctx->getProperty("ResultTabName", "NULL"));
+
+ HugoTransactions hugoTrans(*pResTab);
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, parallelism) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runCreateResultTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ char newTabName[256];
+ snprintf(newTabName, 256, "%s_RES", pTab->getName());
+ ctx->setProperty("ResultTabName", newTabName);
+
+ NdbDictionary::Table resTab(* pTab);
+ resTab.setName(newTabName);
+
+ if (GETNDB(step)->getDictionary()->createTable(resTab) != 0){
+ g_err << newTabName << " creation failed!"<< endl;
+ return NDBT_FAILED;
+ }else{
+ g_info << newTabName << " created!"<< endl;
+ return NDBT_OK;
+ }
+}
+
+int scanWithFilter(NDBT_Context* ctx, NDBT_Step* step, ScanFilter& filt){
+ int records = ctx->getNumRecords();
+ const char* resTabName = ctx->getProperty("ResultTabName", "NULL");
+ if (strcmp(resTabName, "NULL") == 0)
+ return NDBT_FAILED;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ const NdbDictionary::Table* pResTab = NDBT_Table::discoverTableFromDb(GETNDB(step), resTabName);
+ if (pResTab == NULL)
+ return NDBT_FAILED;
+
+ ScanInterpretTest interpretTest(*pTab, *pResTab);
+ if (interpretTest.scanRead(GETNDB(step),
+ records,
+ 16,
+ filt) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+int runScanLessThan(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ LessThanFilter filt(records);
+ return scanWithFilter(ctx, step, filt);
+}
+int runScanEqual(NDBT_Context* ctx, NDBT_Step* step){
+ EqualFilter filt;
+ return scanWithFilter(ctx, step, filt);
+}
+
+int scanVerifyWithFilter(NDBT_Context* ctx, NDBT_Step* step, ScanFilter& filt){
+ int records = ctx->getNumRecords();
+ const char* resTabName = ctx->getProperty("ResultTabName", "NULL");
+ if (strcmp(resTabName, "NULL") == 0)
+ return NDBT_FAILED;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ const NdbDictionary::Table* pResTab = NDBT_Table::discoverTableFromDb(GETNDB(step), resTabName);
+ if (pResTab == NULL)
+ return NDBT_FAILED;
+
+ ScanInterpretTest interpretTest(*pTab, *pResTab);
+ if (interpretTest.scanReadVerify(GETNDB(step),
+ records,
+ 16,
+ filt) != NDBT_OK){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+int runScanLessThanVerify(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ LessThanFilter filt(records);
+ return scanVerifyWithFilter(ctx, step, filt);
+}
+int runScanEqualVerify(NDBT_Context* ctx, NDBT_Step* step){
+ EqualFilter filt;
+ return scanVerifyWithFilter(ctx, step, filt);
+}
+
+int runScanEqualLoop(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int l = 0;
+ EqualFilter filt;
+ while(l < loops){
+ if (scanWithFilter(ctx, step, filt) != NDBT_OK)
+ return NDBT_FAILED;
+ if (runClearResTable(ctx, step) != NDBT_OK)
+ return NDBT_FAILED;
+ l++;
+ }
+ return NDBT_OK;
+}
+
+
+int runScanEqualVerifyLoop(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int l = 0;
+ EqualFilter filt;
+ while(l < loops){
+ if (scanWithFilter(ctx, step, filt) != NDBT_OK)
+ return NDBT_FAILED;
+ if (scanVerifyWithFilter(ctx, step, filt) != NDBT_OK)
+ return NDBT_FAILED;
+ if (runClearResTable(ctx, step) != NDBT_OK)
+ return NDBT_FAILED;
+ l++;
+ }
+ return NDBT_OK;
+}
+
+int runScanLessThanLoop(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int l = 0;
+ LessThanFilter filt(records);
+ while(l < loops){
+ if (scanWithFilter(ctx, step, filt) != NDBT_OK)
+ return NDBT_FAILED;
+ if (runClearResTable(ctx, step) != NDBT_OK)
+ return NDBT_FAILED;
+ l++;
+ }
+ return NDBT_OK;
+}
+
+NDBT_TESTSUITE(testScanInterpreter);
+TESTCASE("ScanLessThan",
+ "Read all records in table TX with attrX less "\
+ "than a value and store the resultset in TX_RES."\
+ "Then compare records in TX_RES with records in TX."){
+ // TABLE("T1");
+ // TABLE("T2");
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runCreateResultTable);
+ STEP(runScanLessThan);
+ VERIFIER(runScanLessThanVerify);
+ FINALIZER(runClearTable);
+ FINALIZER(runClearResTable);
+}
+TESTCASE("ScanEqual",
+ "Read all records in table TX with attrX equal "\
+ "to a value and store the resultset in TX_RES."\
+ "Then compare records in TX_RES with records in TX."){
+ // TABLE("T1");
+ // TABLE("T2");
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runCreateResultTable);
+ STEP(runScanEqual);
+ VERIFIER(runScanEqualVerify);
+ FINALIZER(runClearTable);
+ FINALIZER(runClearResTable);
+}
+TESTCASE("ScanEqualLoop",
+ "Scan all records in TX equal to a value."\
+ "Do this loop number of times"){
+ // TABLE("T1");
+ // TABLE("T2");
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runCreateResultTable);
+ STEP(runScanEqualLoop);
+ FINALIZER(runClearTable);
+ FINALIZER(runClearResTable);
+}
+TESTCASE("ScanEqualVerifyLoop",
+ "Scan all records in TX equal to a value."\
+ "Verify record in TX_RES table"\
+ "Do this loop number of times"){
+ // TABLE("T1");
+ // TABLE("T2");
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runCreateResultTable);
+ STEP(runScanEqualVerifyLoop);
+ FINALIZER(runClearTable);
+ FINALIZER(runClearResTable);
+}
+TESTCASE("ScanLessThanLoop",
+ "Scan all records in TX less than a value."\
+ "Do this loop number of times"){
+ // TABLE("T1");
+ // TABLE("T2");
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runCreateResultTable);
+ STEP(runScanLessThanLoop);
+ FINALIZER(runClearTable);
+ FINALIZER(runClearResTable);
+}
+NDBT_TESTSUITE_END(testScanInterpreter);
+
+int main(int argc, const char** argv){
+ return testScanInterpreter.execute(argc, argv);
+}
+
+
+
diff --git a/ndb/test/ndbapi/testScanInterpreter/testScanInterpreter.cpp b/ndb/test/ndbapi/testScanInterpreter/testScanInterpreter.cpp
deleted file mode 100644
index 18fd98bdbb3..00000000000
--- a/ndb/test/ndbapi/testScanInterpreter/testScanInterpreter.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "NDBT_Test.hpp"
-#include "NDBT_ReturnCodes.h"
-#include "HugoTransactions.hpp"
-#include "UtilTransactions.hpp"
-#include "NdbRestarter.hpp"
-#include <Vector.hpp>
-#include "ScanFilter.hpp"
-#include "ScanInterpretTest.hpp"
-
-int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
-
- int records = ctx->getNumRecords();
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
-
- UtilTransactions utilTrans(*ctx->getTab());
- if (utilTrans.clearTable2(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runClearResTable(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- const NdbDictionary::Table* pResTab =
- GETNDB(step)->getDictionary()->getTable(ctx->getProperty("ResultTabName", "NULL"));
-
- UtilTransactions utilTrans(*pResTab);
- if (utilTrans.clearTable2(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runScanRead(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int parallelism = ctx->getProperty("Parallelism", 1);
-
- int i = 0;
- HugoTransactions hugoTrans(*ctx->getTab());
- while (i<loops) {
- g_info << i << ": ";
- if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, parallelism) != 0){
- return NDBT_FAILED;
- }
- i++;
- }
- return NDBT_OK;
-}
-
-int runScanReadResTable(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- int parallelism = ctx->getProperty("Parallelism", 1);
- const NdbDictionary::Table* pResTab =
- NDBT_Table::discoverTableFromDb(GETNDB(step),
- ctx->getProperty("ResultTabName", "NULL"));
-
- HugoTransactions hugoTrans(*pResTab);
- if (hugoTrans.scanReadRecords(GETNDB(step), records, 0, parallelism) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runCreateResultTable(NDBT_Context* ctx, NDBT_Step* step){
-
- const NdbDictionary::Table* pTab = ctx->getTab();
- char newTabName[256];
- snprintf(newTabName, 256, "%s_RES", pTab->getName());
- ctx->setProperty("ResultTabName", newTabName);
-
- NdbDictionary::Table resTab(* pTab);
- resTab.setName(newTabName);
-
- if (GETNDB(step)->getDictionary()->createTable(resTab) != 0){
- g_err << newTabName << " creation failed!"<< endl;
- return NDBT_FAILED;
- }else{
- g_info << newTabName << " created!"<< endl;
- return NDBT_OK;
- }
-}
-
-int scanWithFilter(NDBT_Context* ctx, NDBT_Step* step, ScanFilter& filt){
- int records = ctx->getNumRecords();
- const char* resTabName = ctx->getProperty("ResultTabName", "NULL");
- if (strcmp(resTabName, "NULL") == 0)
- return NDBT_FAILED;
- const NdbDictionary::Table* pTab = ctx->getTab();
- const NdbDictionary::Table* pResTab = NDBT_Table::discoverTableFromDb(GETNDB(step), resTabName);
- if (pResTab == NULL)
- return NDBT_FAILED;
-
- ScanInterpretTest interpretTest(*pTab, *pResTab);
- if (interpretTest.scanRead(GETNDB(step),
- records,
- 16,
- filt) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-int runScanLessThan(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- LessThanFilter filt(records);
- return scanWithFilter(ctx, step, filt);
-}
-int runScanEqual(NDBT_Context* ctx, NDBT_Step* step){
- EqualFilter filt;
- return scanWithFilter(ctx, step, filt);
-}
-
-int scanVerifyWithFilter(NDBT_Context* ctx, NDBT_Step* step, ScanFilter& filt){
- int records = ctx->getNumRecords();
- const char* resTabName = ctx->getProperty("ResultTabName", "NULL");
- if (strcmp(resTabName, "NULL") == 0)
- return NDBT_FAILED;
- const NdbDictionary::Table* pTab = ctx->getTab();
- const NdbDictionary::Table* pResTab = NDBT_Table::discoverTableFromDb(GETNDB(step), resTabName);
- if (pResTab == NULL)
- return NDBT_FAILED;
-
- ScanInterpretTest interpretTest(*pTab, *pResTab);
- if (interpretTest.scanReadVerify(GETNDB(step),
- records,
- 16,
- filt) != NDBT_OK){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-int runScanLessThanVerify(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
- LessThanFilter filt(records);
- return scanVerifyWithFilter(ctx, step, filt);
-}
-int runScanEqualVerify(NDBT_Context* ctx, NDBT_Step* step){
- EqualFilter filt;
- return scanVerifyWithFilter(ctx, step, filt);
-}
-
-int runScanEqualLoop(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int l = 0;
- EqualFilter filt;
- while(l < loops){
- if (scanWithFilter(ctx, step, filt) != NDBT_OK)
- return NDBT_FAILED;
- if (runClearResTable(ctx, step) != NDBT_OK)
- return NDBT_FAILED;
- l++;
- }
- return NDBT_OK;
-}
-
-
-int runScanEqualVerifyLoop(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int l = 0;
- EqualFilter filt;
- while(l < loops){
- if (scanWithFilter(ctx, step, filt) != NDBT_OK)
- return NDBT_FAILED;
- if (scanVerifyWithFilter(ctx, step, filt) != NDBT_OK)
- return NDBT_FAILED;
- if (runClearResTable(ctx, step) != NDBT_OK)
- return NDBT_FAILED;
- l++;
- }
- return NDBT_OK;
-}
-
-int runScanLessThanLoop(NDBT_Context* ctx, NDBT_Step* step){
- int loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int l = 0;
- LessThanFilter filt(records);
- while(l < loops){
- if (scanWithFilter(ctx, step, filt) != NDBT_OK)
- return NDBT_FAILED;
- if (runClearResTable(ctx, step) != NDBT_OK)
- return NDBT_FAILED;
- l++;
- }
- return NDBT_OK;
-}
-
-NDBT_TESTSUITE(testScanInterpreter);
-TESTCASE("ScanLessThan",
- "Read all records in table TX with attrX less "\
- "than a value and store the resultset in TX_RES."\
- "Then compare records in TX_RES with records in TX."){
- TABLE("T1");
- TABLE("T2");
- INITIALIZER(runLoadTable);
- INITIALIZER(runCreateResultTable);
- STEP(runScanLessThan);
- VERIFIER(runScanLessThanVerify);
- FINALIZER(runClearTable);
- FINALIZER(runClearResTable);
-}
-TESTCASE("ScanEqual",
- "Read all records in table TX with attrX equal "\
- "to a value and store the resultset in TX_RES."\
- "Then compare records in TX_RES with records in TX."){
- TABLE("T1");
- TABLE("T2");
- INITIALIZER(runLoadTable);
- INITIALIZER(runCreateResultTable);
- STEP(runScanEqual);
- VERIFIER(runScanEqualVerify);
- FINALIZER(runClearTable);
- FINALIZER(runClearResTable);
-}
-TESTCASE("ScanEqualLoop",
- "Scan all records in TX equal to a value."\
- "Do this loop number of times"){
- TABLE("T1");
- TABLE("T2");
- INITIALIZER(runLoadTable);
- INITIALIZER(runCreateResultTable);
- STEP(runScanEqualLoop);
- FINALIZER(runClearTable);
- FINALIZER(runClearResTable);
-}
-TESTCASE("ScanEqualVerifyLoop",
- "Scan all records in TX equal to a value."\
- "Verify record in TX_RES table"\
- "Do this loop number of times"){
- TABLE("T1");
- TABLE("T2");
- INITIALIZER(runLoadTable);
- INITIALIZER(runCreateResultTable);
- STEP(runScanEqualVerifyLoop);
- FINALIZER(runClearTable);
- FINALIZER(runClearResTable);
-}
-TESTCASE("ScanLessThanLoop",
- "Scan all records in TX less than a value."\
- "Do this loop number of times"){
- TABLE("T1");
- TABLE("T2");
- INITIALIZER(runLoadTable);
- INITIALIZER(runCreateResultTable);
- STEP(runScanLessThanLoop);
- FINALIZER(runClearTable);
- FINALIZER(runClearResTable);
-}
-NDBT_TESTSUITE_END(testScanInterpreter);
-
-int main(int argc, const char** argv){
- return testScanInterpreter.execute(argc, argv);
-}
-
-
-
diff --git a/ndb/test/ndbapi/testScanPerf/Makefile b/ndb/test/ndbapi/testScanPerf/Makefile
new file mode 100644
index 00000000000..fdf5980b385
--- /dev/null
+++ b/ndb/test/ndbapi/testScanPerf/Makefile
@@ -0,0 +1,9 @@
+include .defs.mk
+
+TYPE = ndbapitest
+
+BIN_TARGET = testScanPerf
+
+SOURCES = testScanPerf.cpp
+
+include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/test/ndbapi/testScanPerf/testScanPerf.cpp b/ndb/test/ndbapi/testScanPerf/testScanPerf.cpp
new file mode 100644
index 00000000000..61af1ffb989
--- /dev/null
+++ b/ndb/test/ndbapi/testScanPerf/testScanPerf.cpp
@@ -0,0 +1,368 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <random.h>
+#include <getarg.h>
+
+struct Parameter {
+ char * name;
+ unsigned value;
+ unsigned min;
+ unsigned max;
+};
+
+#define P_BATCH 0
+#define P_PARRA 1
+#define P_LOCK 2
+#define P_FILT 3
+#define P_BOUND 4
+#define P_ACCESS 5
+#define P_FETCH 6
+#define P_ROWS 7
+#define P_LOOPS 8
+#define P_CREATE 9
+#define P_LOAD 10
+
+#define P_MAX 11
+
+static
+Parameter
+g_paramters[] = {
+ { "batch", 0, 0, 1 }, // 0, 15
+ { "parallelism", 0, 0, 1 }, // 0, 1
+ { "lock", 0, 0, 2 }, // read, exclusive, dirty
+ { "filter", 0, 0, 3 }, // all, none, 1, 100
+ { "range", 0, 0, 3 }, // all, none, 1, 100
+ { "access", 0, 0, 2 }, // scan, idx, idx sorted
+ { "fetch", 0, 0, 1 }, // No, yes
+ { "size", 1000000, 1, ~0 },
+ { "iterations", 3, 1, ~0 },
+ { "create_drop", 1, 0, 1 },
+ { "data", 1, 0, 1 }
+};
+
+static Ndb* g_ndb = 0;
+static const NdbDictionary::Table * g_table;
+static const NdbDictionary::Index * g_index;
+static char g_tablename[256];
+static char g_indexname[256];
+
+int create_table();
+int load_table();
+int run_scan();
+int clear_table();
+int drop_table();
+
+int
+main(int argc, const char** argv){
+ int verbose = 1;
+ int optind = 0;
+
+ struct getargs args[1+P_MAX] = {
+ { "verbose", 'v', arg_flag, &verbose, "Print verbose status", "verbose" }
+ };
+ const int num_args = 1 + P_MAX;
+ for(int i = 0; i<P_MAX; i++){
+ args[i+1].long_name = g_paramters[i].name;
+ args[i+1].short_name = * g_paramters[i].name;
+ args[i+1].type = arg_integer;
+ args[i+1].value = &g_paramters[i].value;
+ BaseString tmp;
+ tmp.assfmt("min: %d max: %d", g_paramters[i].min, g_paramters[i].max);
+ args[i+1].help = strdup(tmp.c_str());
+ args[i+1].arg_help = 0;
+ }
+
+ if(getarg(args, num_args, argc, argv, &optind)) {
+ arg_printusage(args, num_args, argv[0], "tabname1 tabname2 ...");
+ return NDBT_WRONGARGS;
+ }
+
+ myRandom48Init(NdbTick_CurrentMillisecond());
+
+ g_ndb = new Ndb("TEST_DB");
+ if(g_ndb->init() != 0){
+ g_err << "init() failed" << endl;
+ goto error;
+ }
+ if(g_ndb->waitUntilReady() != 0){
+ g_err << "Wait until ready failed" << endl;
+ goto error;
+ }
+ for(int i = optind; i<argc; i++){
+ const char * T = argv[i];
+ g_info << "Testing " << T << endl;
+ snprintf(g_tablename, sizeof(g_tablename), T);
+ snprintf(g_indexname, sizeof(g_indexname), "IDX_%s", T);
+ if(create_table())
+ goto error;
+ if(load_table())
+ goto error;
+ if(run_scan())
+ goto error;
+ if(clear_table())
+ goto error;
+ if(drop_table())
+ goto error;
+ }
+
+ if(g_ndb) delete g_ndb;
+ return NDBT_OK;
+ error:
+ if(g_ndb) delete g_ndb;
+ return NDBT_FAILED;
+}
+
+int
+create_table(){
+ NdbDictionary::Dictionary* dict = g_ndb->getDictionary();
+ assert(dict);
+ if(g_paramters[P_CREATE].value){
+ const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_tablename);
+ assert(pTab);
+ NdbDictionary::Table copy = * pTab;
+ copy.setLogging(false);
+ if(dict->createTable(copy) != 0){
+ g_err << "Failed to create table: " << g_tablename << endl;
+ return -1;
+ }
+
+ NdbDictionary::Index x(g_indexname);
+ x.setTable(g_tablename);
+ x.setType(NdbDictionary::Index::OrderedIndex);
+ x.setLogging(false);
+ for (unsigned k = 0; k < copy.getNoOfColumns(); k++){
+ if(copy.getColumn(k)->getPrimaryKey()){
+ x.addColumnName(copy.getColumn(k)->getName());
+ }
+ }
+
+ if(dict->createIndex(x) != 0){
+ g_err << "Failed to create index: " << endl;
+ return -1;
+ }
+ }
+ g_table = dict->getTable(g_tablename);
+ g_index = dict->getIndex(g_indexname, g_tablename);
+ assert(g_table);
+ assert(g_index);
+ return 0;
+}
+
+int
+drop_table(){
+ if(!g_paramters[P_CREATE].value)
+ return 0;
+ if(g_ndb->getDictionary()->dropTable(g_table->getName()) != 0){
+ g_err << "Failed to drop table: " << g_table->getName() << endl;
+ return -1;
+ }
+ g_table = 0;
+ return 0;
+}
+
+int
+load_table(){
+ if(!g_paramters[P_LOAD].value)
+ return 0;
+
+ int rows = g_paramters[P_ROWS].value;
+ HugoTransactions hugoTrans(* g_table);
+ if (hugoTrans.loadTable(g_ndb, rows)){
+ g_err.println("Failed to load %s with %d rows", g_table->getName(), rows);
+ return -1;
+ }
+ return 0;
+}
+
+int
+clear_table(){
+ if(!g_paramters[P_LOAD].value)
+ return 0;
+
+ int rows = g_paramters[P_ROWS].value;
+
+ UtilTransactions utilTrans(* g_table);
+ if (utilTrans.clearTable(g_ndb, rows) != 0){
+ g_err.println("Failed to clear table %s", g_table->getName());
+ return -1;
+ }
+ return 0;
+}
+
+inline
+void err(NdbError e){
+ ndbout << e << endl;
+}
+
+int
+run_scan(){
+ int iter = g_paramters[P_LOOPS].value;
+ Uint64 start1;
+ Uint64 sum1 = 0;
+
+ Uint32 tot = g_paramters[P_ROWS].value;
+
+ for(int i = 0; i<iter; i++){
+ start1 = NdbTick_CurrentMillisecond();
+ NdbConnection * pTrans = g_ndb->startTransaction();
+ if(!pTrans){
+ g_err << "Failed to start transaction" << endl;
+ err(g_ndb->getNdbError());
+ return -1;
+ }
+
+ NdbScanOperation * pOp;
+#ifdef NdbIndexScanOperation_H
+ NdbIndexScanOperation * pIOp;
+#else
+ NdbScanOperation * pIOp;
+#endif
+
+ NdbResultSet * rs;
+ int par = g_paramters[P_PARRA].value;
+ int bat = g_paramters[P_BATCH].value;
+ NdbScanOperation::LockMode lm;
+ switch(g_paramters[P_LOCK].value){
+ case 0:
+ lm = NdbScanOperation::LM_Read;
+ break;
+ case 1:
+ lm = NdbScanOperation::LM_Exclusive;
+ break;
+ case 2:
+ lm = NdbScanOperation::LM_CommittedRead;
+ break;
+ default:
+ abort();
+ }
+
+ if(g_paramters[P_ACCESS].value == 0){
+ pOp = pTrans->getNdbScanOperation(g_tablename);
+ assert(pOp);
+#ifdef NdbIndexScanOperation_H
+ rs = pOp->readTuples(lm, bat, par);
+#else
+ int oldp = (par == 0 ? 240 : par) * (bat == 0 ? 15 : bat);
+ rs = pOp->readTuples(oldp > 240 ? 240 : oldp, lm);
+#endif
+ } else {
+#ifdef NdbIndexScanOperation_H
+ pOp = pIOp = pTrans->getNdbIndexScanOperation(g_indexname, g_tablename);
+ bool ord = g_paramters[P_ACCESS].value == 2;
+ rs = pIOp->readTuples(lm, bat, par, ord);
+#else
+ pOp = pIOp = pTrans->getNdbScanOperation(g_indexname, g_tablename);
+ assert(pOp);
+ int oldp = (par == 0 ? 240 : par) * (bat == 0 ? 15 : bat);
+ rs = pIOp->readTuples(oldp > 240 ? 240 : oldp, lm);
+#endif
+ switch(g_paramters[P_BOUND].value){
+ case 0: // All
+ break;
+ case 1: // None
+#ifdef NdbIndexScanOperation_H
+ pIOp->setBound((Uint32)0, NdbIndexScanOperation::BoundEQ, 0);
+#else
+ pIOp->setBound((Uint32)0, NdbOperation::BoundEQ, 0);
+#endif
+ break;
+ case 2: { // 1 row
+ default:
+ assert(g_table->getNoOfPrimaryKeys() == 1); // only impl. so far
+ abort();
+#if 0
+ int tot = g_paramters[P_ROWS].value;
+ int row = rand() % tot;
+ fix_eq_bound(pIOp, row);
+#endif
+ break;
+ }
+ }
+ }
+ assert(pOp);
+ assert(rs);
+
+ int check = 0;
+ switch(g_paramters[P_FILT].value){
+ case 0: // All
+ check = pOp->interpret_exit_ok();
+ break;
+ case 1: // None
+ check = pOp->interpret_exit_nok();
+ break;
+ case 2: { // 1 row
+ default:
+ assert(g_table->getNoOfPrimaryKeys() == 1); // only impl. so far
+ abort();
+#if 0
+ int tot = g_paramters[P_ROWS].value;
+ int row = rand() % tot;
+ NdbScanFilter filter(pOp) ;
+ filter.begin(NdbScanFilter::AND);
+ fix_eq(filter, pOp, row);
+ filter.end();
+ break;
+#endif
+ }
+ }
+ if(check != 0){
+ err(pOp->getNdbError());
+ return -1;
+ }
+ assert(check == 0);
+
+ for(int i = 0; i<g_table->getNoOfColumns(); i++){
+ pOp->getValue(i);
+ }
+
+ int rows = 0;
+ check = pTrans->execute(NoCommit);
+ assert(check == 0);
+ int fetch = g_paramters[P_FETCH].value;
+ while((check = rs->nextResult(true)) == 0){
+ do {
+ rows++;
+ } while(!fetch && ((check = rs->nextResult(false)) == 0));
+ if(check == -1){
+ err(pTrans->getNdbError());
+ return -1;
+ }
+ assert(check == 2);
+ }
+
+ if(check == -1){
+ err(pTrans->getNdbError());
+ return -1;
+ }
+ assert(check == 1);
+ g_info << "Found " << rows << " rows" << endl;
+
+ pTrans->close();
+
+ Uint64 stop = NdbTick_CurrentMillisecond();
+ start1 = (stop - start1);
+ sum1 += start1;
+ }
+ sum1 /= iter;
+
+ g_err.println("Avg time: %Ldms = %d rows/sec", sum1, (1000*tot)/sum1);
+ return 0;
+}
diff --git a/ndb/test/ndbapi/testSystemRestart.cpp b/ndb/test/ndbapi/testSystemRestart.cpp
new file mode 100644
index 00000000000..61e086ff941
--- /dev/null
+++ b/ndb/test/ndbapi/testSystemRestart.cpp
@@ -0,0 +1,1185 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbRestarter.hpp>
+#include <Vector.hpp>
+#include <signaldata/DumpStateOrd.hpp>
+
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+#define CHECK(b) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ continue; }
+
+int runSystemRestart1(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ int timeout = 300;
+ Uint32 loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int count;
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while(i<=loops && result != NDBT_FAILED){
+
+ ndbout << "Loop " << i << "/"<< loops <<" started" << endl;
+ /*
+ 1. Load data
+ 2. Restart cluster and verify records
+ 3. Update records
+ 4. Restart cluster and verify records
+ 5. Delete half of the records
+ 6. Restart cluster and verify records
+ 7. Delete all records
+ 8. Restart cluster and verify records
+ 9. Insert, update, delete records
+ 10. Restart cluster and verify records
+ 11. Insert, update, delete records
+ 12. Restart cluster with error insert 5020 and verify records
+ */
+ ndbout << "Loading records..." << endl;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+
+ ndbout << "Restarting cluster" << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+
+ ndbout << "Updating records..." << endl;
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+
+ ndbout << "Deleting 50% of records..." << endl;
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+
+ ndbout << "Deleting all records..." << endl;
+ CHECK(utilTrans.clearTable(pNdb, records/2) == 0);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+
+ ndbout << "Doing it all..." << endl;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+ CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+
+ ndbout << "Doing it all..." << endl;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+ CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+
+ ndbout << "Restarting cluster with error insert 5020..." << endl;
+ CHECK(restarter.restartAll(false, true) == 0);
+ CHECK(restarter.waitClusterNoStart(timeout) == 0);
+ CHECK(restarter.insertErrorInAllNodes(5020) == 0);
+ CHECK(restarter.startAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ i++;
+ }
+
+ ndbout << "runSystemRestart1 finished" << endl;
+
+ return result;
+}
+
+int runSystemRestart2(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+/// int timeout = 300;
+ int timeout = 120;
+ Uint32 loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int count;
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while(i<=loops && result != NDBT_FAILED && !ctx->isTestStopped()){
+
+ ndbout << "Loop " << i << "/"<< loops <<" started" << endl;
+ /* Use error 7070 to set time between LCP to it's min value
+ 1. Load data
+ 2. Restart cluster and verify records
+ 3. Update records
+ 4. Restart cluster and verify records
+ 5. Delete half of the records
+ 6. Restart cluster and verify records
+ 7. Delete all records
+ 8. Restart cluster and verify records
+ 9. Insert, update, delete records
+ 10. Restart cluster and verify records
+ */
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+
+ ndbout << "Loading records..." << endl;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+
+ ndbout << "Restarting cluster" << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+
+ ndbout << "Updating records..." << endl;
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+
+ ndbout << "Deleting 50% of records..." << endl;
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+
+ ndbout << "Deleting all records..." << endl;
+ CHECK(utilTrans.clearTable(pNdb, records/2) == 0);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+
+ ndbout << "Doing it all..." << endl;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+ CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+
+ i++;
+ }
+
+ ndbout << "runSystemRestart2 finished" << endl;
+
+ return result;
+}
+
+int runSystemRestartTestUndoLog(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ int timeout = 300;
+ Uint32 loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int count;
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ int dump7080[2];
+ dump7080[0] = 7080;
+ dump7080[1] = ctx->getTab()->getTableId();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while(i<=loops && result != NDBT_FAILED){
+
+ ndbout << "Loop " << i << "/"<< loops <<" started" << endl;
+ /*
+ 1. Start LCP, turn on undologging but delay write of datapages.
+ 2. Insert, update, delete records
+ 3. Complete writing of data pages and finish LCP.
+ 4. Restart cluster and verify records
+ */
+ // Use dump state 7080 to delay writing of datapages
+ // for the current table
+ ndbout << "Dump state: "<<dump7080[0]<<", "<<dump7080[1]<<endl;
+ CHECK(restarter.dumpStateAllNodes(dump7080, 2) == 0);
+ NdbSleep_SecSleep(10);
+
+ ndbout << "Doing it all..." << endl;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+ CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+
+ // Reset error and let LCP continue
+ CHECK(restarter.insertErrorInAllNodes(0) == 0);
+ NdbSleep_SecSleep(60);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+
+ // Use dump state 7080 to delay writing of datapages
+ // for the current table
+ ndbout << "Dump state: "<<dump7080[0]<<", "<<dump7080[1]<<endl;
+ CHECK(restarter.dumpStateAllNodes(dump7080, 2) == 0);
+ NdbSleep_SecSleep(10);
+
+ ndbout << "Doing it all, delete 50%..." << endl;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+
+ // Reset error and let LCP continue
+ CHECK(restarter.insertErrorInAllNodes(0) == 0);
+ NdbSleep_SecSleep(20);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+
+ i++;
+ }
+
+ ndbout << "runSystemRestartTestUndoLog finished" << endl;
+
+ return result;
+}
+
+int runSystemRestartTestFullDb(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ int timeout = 300;
+ Uint32 loops = ctx->getNumLoops();
+ int count1, count2;
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while(i<=loops && result != NDBT_FAILED){
+
+ ndbout << "Loop " << i << "/"<< loops <<" started" << endl;
+ /*
+ 1. Load data until db reports it's full
+ 2. Restart cluster and verify records
+ */
+ ndbout << "Filling up table..." << endl;
+ CHECK(hugoTrans.fillTable(pNdb) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count1) == 0);
+ ndbout << "Db is full. Table has "<<count1 <<" records."<< endl;
+
+ ndbout << "Restarting cluster" << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(hugoTrans.scanReadRecords(pNdb, count1) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count2) == 0);
+ CHECK(count1 == count2);
+
+ ndbout << "Deleting all records..." << endl;
+ CHECK(utilTrans.clearTable2(pNdb, count1) == 0);
+
+ ndbout << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count1) == 0);
+ CHECK(count1 == 0);
+
+ i++;
+ }
+
+ ndbout << "runSystemRestartTestFullDb finished" << endl;
+
+ return result;
+}
+
+int runSystemRestart3(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ int timeout = 300;
+ Uint32 loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int count;
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ const Uint32 nodeCount = restarter.getNumDbNodes();
+ if(nodeCount < 2){
+ g_info << "SR3 - Needs atleast 2 nodes to test" << endl;
+ return NDBT_OK;
+ }
+
+ Vector<int> nodeIds;
+ for(Uint32 i = 0; i<nodeCount; i++)
+ nodeIds.push_back(restarter.getDbNodeId(i));
+
+ Uint32 currentRestartNodeIndex = 0;
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ while(i<=loops && result != NDBT_FAILED){
+
+ g_info << "Loop " << i << "/"<< loops <<" started" << endl;
+ /**
+ * 1. Load data
+ * 2. Restart 1 node -nostart
+ * 3. Update records
+ * 4. Restart cluster and verify records
+ * 5. Restart 1 node -nostart
+ * 6. Delete half of the records
+ * 7. Restart cluster and verify records
+ * 8. Restart 1 node -nostart
+ * 9. Delete all records
+ * 10. Restart cluster and verify records
+ */
+ g_info << "Loading records..." << endl;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+
+ /*** 1 ***/
+ g_info << "1 - Stopping one node" << endl;
+ CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
+ false,
+ true,
+ false) == 0);
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+
+ g_info << "Updating records..." << endl;
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+
+ g_info << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ g_info << "Verifying records..." << endl;
+ CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+
+ g_info << "2 - Stopping one node" << endl;
+ CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
+ false,
+ true,
+ false) == 0);
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+
+ g_info << "Deleting 50% of records..." << endl;
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+
+ g_info << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ g_info << "Verifying records..." << endl;
+ CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+
+ g_info << "3 - Stopping one node" << endl;
+ CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
+ false,
+ true,
+ false) == 0);
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+ g_info << "Deleting all records..." << endl;
+ CHECK(utilTrans.clearTable(pNdb, records/2) == 0);
+
+ g_info << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+
+ i++;
+ }
+
+ g_info << "runSystemRestart3 finished" << endl;
+
+ return result;
+}
+
+int runSystemRestart4(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ int timeout = 300;
+ Uint32 loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int count;
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ const Uint32 nodeCount = restarter.getNumDbNodes();
+ if(nodeCount < 2){
+ g_info << "SR4 - Needs atleast 2 nodes to test" << endl;
+ return NDBT_OK;
+ }
+
+ Vector<int> nodeIds;
+ for(Uint32 i = 0; i<nodeCount; i++)
+ nodeIds.push_back(restarter.getDbNodeId(i));
+
+ Uint32 currentRestartNodeIndex = 0;
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ g_err << "ERR: "<< step->getName()
+ << " failed on line " << __LINE__ << endl;
+ return NDBT_FAILED;
+ }
+ }
+
+ while(i<=loops && result != NDBT_FAILED){
+
+ g_info << "Loop " << i << "/"<< loops <<" started" << endl;
+ /**
+ * 1. Load data
+ * 2. Restart 1 node -nostart
+ * 3. Update records
+ * 4. Restart cluster and verify records
+ * 5. Restart 1 node -nostart
+ * 6. Delete half of the records
+ * 7. Restart cluster and verify records
+ * 8. Restart 1 node -nostart
+ * 9. Delete all records
+ * 10. Restart cluster and verify records
+ */
+ g_info << "Loading records..." << endl;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+
+ /*** 1 ***/
+ g_info << "1 - Stopping one node" << endl;
+ CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
+ false,
+ true,
+ false) == 0);
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+
+ g_info << "Updating records..." << endl;
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+
+ g_info << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ g_info << "Verifying records..." << endl;
+ CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+
+ g_info << "2 - Stopping one node" << endl;
+ CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
+ false,
+ true,
+ false) == 0);
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+
+ g_info << "Deleting 50% of records..." << endl;
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+
+ g_info << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ g_info << "Verifying records..." << endl;
+ CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+
+ g_info << "3 - Stopping one node" << endl;
+ CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
+ false,
+ true,
+ false) == 0);
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+ g_info << "Deleting all records..." << endl;
+ CHECK(utilTrans.clearTable(pNdb, records/2) == 0);
+
+ g_info << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+
+ i++;
+ }
+
+ g_info << "runSystemRestart4 finished" << endl;
+
+ return result;
+}
+
+int runSystemRestart5(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ int timeout = 300;
+ Uint32 loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int count;
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ const Uint32 nodeCount = restarter.getNumDbNodes();
+ if(nodeCount < 2){
+ g_info << "SR5 - Needs atleast 2 nodes to test" << endl;
+ return NDBT_OK;
+ }
+
+ Vector<int> nodeIds;
+ for(Uint32 i = 0; i<nodeCount; i++)
+ nodeIds.push_back(restarter.getDbNodeId(i));
+
+ Uint32 currentRestartNodeIndex = 0;
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ g_err << "ERR: "<< step->getName()
+ << " failed on line " << __LINE__ << endl;
+ return NDBT_FAILED;
+ }
+ }
+
+ while(i<=loops && result != NDBT_FAILED){
+
+ g_info << "Loop " << i << "/"<< loops <<" started" << endl;
+ /**
+ * 1. Load data
+ * 2. Restart 1 node -nostart
+ * 3. Update records
+ * 4. Restart cluster and verify records
+ * 5. Restart 1 node -nostart
+ * 6. Delete half of the records
+ * 7. Restart cluster and verify records
+ * 8. Restart 1 node -nostart
+ * 9. Delete all records
+ * 10. Restart cluster and verify records
+ */
+ g_info << "Loading records..." << endl;
+ hugoTrans.loadTable(pNdb, records);
+
+ /*** 1 ***/
+ g_info << "1 - Stopping one node" << endl;
+ CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
+ false,
+ true,
+ false) == 0);
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+
+ g_info << "Updating records..." << endl;
+ hugoTrans.pkUpdateRecords(pNdb, records);
+
+ g_info << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll(false, false, true) == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ g_info << "Verifying records..." << endl;
+ hugoTrans.pkReadRecords(pNdb, records);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ //CHECK(count == records);
+
+ g_info << "2 - Stopping one node" << endl;
+ CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
+ false,
+ true,
+ false) == 0);
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+
+ g_info << "Deleting 50% of records..." << endl;
+ hugoTrans.pkDelRecords(pNdb, records/2);
+
+ g_info << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll(false, false, true) == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ g_info << "Verifying records..." << endl;
+ hugoTrans.scanReadRecords(pNdb, records/2, 0, 64);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ //CHECK(count == (records/2));
+
+ g_info << "3 - Stopping one node" << endl;
+ CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
+ false,
+ true,
+ false) == 0);
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+ g_info << "Deleting all records..." << endl;
+ utilTrans.clearTable(pNdb, records/2);
+
+ g_info << "Restarting cluster..." << endl;
+ CHECK(restarter.restartAll(false, false, true) == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ {
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
+ }
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ //CHECK(count == 0);
+
+ CHECK(utilTrans.clearTable(pNdb) == 0);
+ i++;
+ }
+
+ g_info << "runSystemRestart5 finished" << endl;
+
+ return result;
+}
+
+int runSystemRestart6(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ int timeout = 300;
+ Uint32 loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ const Uint32 nodeCount = restarter.getNumDbNodes();
+ if(nodeCount < 2){
+ g_info << "SR6 - Needs atleast 2 nodes to test" << endl;
+ return NDBT_OK;
+ }
+
+ Vector<int> nodeIds;
+ for(Uint32 i = 0; i<nodeCount; i++)
+ nodeIds.push_back(restarter.getDbNodeId(i));
+
+ Uint32 currentRestartNodeIndex = 0;
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ while(i<=loops && result != NDBT_FAILED){
+
+ g_info << "Loop " << i << "/"<< loops <<" started" << endl;
+ /**
+ * 1. Load data
+ * 2. Restart all node -nostart
+ * 3. Restart some nodes -i -nostart
+ * 4. Start all nodes verify records
+ */
+ g_info << "Loading records..." << endl;
+ hugoTrans.loadTable(pNdb, records);
+
+ CHECK(restarter.restartAll(false, true, false) == 0);
+
+ Uint32 nodeId = nodeIds[currentRestartNodeIndex];
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+
+ CHECK(restarter.restartOneDbNode(nodeId, true, true,false) == 0);
+ CHECK(restarter.waitClusterNoStart(timeout) == 0);
+ CHECK(restarter.startAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+ int count = records - 1;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+ CHECK(utilTrans.clearTable(pNdb) == 0);
+ i++;
+ }
+
+ g_info << "runSystemRestart6 finished" << endl;
+
+ return result;
+}
+
+int runSystemRestart7(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ Uint32 loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ const Uint32 nodeCount = restarter.getNumDbNodes();
+ if(nodeCount < 2){
+ g_info << "SR8 - Needs atleast 2 nodes to test" << endl;
+ return NDBT_OK;
+ }
+
+ Vector<int> nodeIds;
+ for(Uint32 i = 0; i<nodeCount; i++)
+ nodeIds.push_back(restarter.getDbNodeId(i));
+
+ int a_nodeIds[64];
+ if(nodeCount > 64)
+ abort();
+
+ Uint32 currentRestartNodeIndex = 1;
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ while(i<=loops && result != NDBT_FAILED){
+
+ g_info << "Loop " << i << "/"<< loops <<" started" << endl;
+ /**
+ * 1. Load data
+ * 2. Restart all node -nostart
+ * 3. Start all but one node
+ * 4. Wait for startphase >= 2
+ * 5. Start last node
+ * 6. Verify records
+ */
+ g_info << "Loading records..." << endl;
+ hugoTrans.loadTable(pNdb, records);
+
+ CHECK(restarter.restartAll(false, true, false) == 0);
+
+ int nodeId = nodeIds[currentRestartNodeIndex];
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+
+ Uint32 j = 0;
+ for(Uint32 k = 0; k<nodeCount; k++){
+ if(nodeIds[k] != nodeId){
+ a_nodeIds[j++] = nodeIds[k];
+ }
+ }
+
+ CHECK(restarter.startNodes(a_nodeIds, nodeCount - 1) == 0);
+ CHECK(restarter.waitNodesStarted(a_nodeIds, nodeCount - 1, 120) == 0);
+ CHECK(pNdb->waitUntilReady(5) == 0);
+ int count = records - 1;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+
+ CHECK(restarter.startNodes(&nodeId, 1) == 0);
+ CHECK(restarter.waitNodesStarted(&nodeId, 1, 120) == 0);
+
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+ CHECK(utilTrans.clearTable(pNdb) == 0);
+
+ i++;
+ }
+
+ g_info << "runSystemRestart7 finished" << endl;
+
+ return result;
+}
+
+int runSystemRestart8(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ int timeout = 300;
+ Uint32 loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ NdbRestarter restarter;
+ Uint32 i = 1;
+
+ const Uint32 nodeCount = restarter.getNumDbNodes();
+ if(nodeCount < 2){
+ g_info << "SR8 - Needs atleast 2 nodes to test" << endl;
+ return NDBT_OK;
+ }
+
+ Vector<int> nodeIds;
+ for(Uint32 i = 0; i<nodeCount; i++)
+ nodeIds.push_back(restarter.getDbNodeId(i));
+
+ int a_nodeIds[64];
+ if(nodeCount > 64)
+ abort();
+
+ Uint32 currentRestartNodeIndex = 1;
+ UtilTransactions utilTrans(*ctx->getTab());
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ while(i<=loops && result != NDBT_FAILED){
+
+ g_info << "Loop " << i << "/"<< loops <<" started" << endl;
+ /**
+ * 1. Load data
+ * 2. Restart all node -nostart
+ * 3. Start all but one node
+ * 4. Verify records
+ * 5. Start last node
+ * 6. Verify records
+ */
+ g_info << "Loading records..." << endl;
+ hugoTrans.loadTable(pNdb, records);
+
+ CHECK(restarter.restartAll(false, true, false) == 0);
+
+ int nodeId = nodeIds[currentRestartNodeIndex];
+ currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
+
+ Uint32 j = 0;
+ for(Uint32 k = 0; k<nodeCount; k++){
+ if(nodeIds[k] != nodeId){
+ a_nodeIds[j++] = nodeIds[k];
+ }
+ }
+
+ CHECK(restarter.startNodes(a_nodeIds, nodeCount-1) == 0);
+ CHECK(restarter.waitNodesStartPhase(a_nodeIds, nodeCount-1, 3, 120) == 0);
+ CHECK(restarter.startNodes(&nodeId, 1) == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+
+ int count = records - 1;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+ CHECK(utilTrans.clearTable(pNdb) == 0);
+ i++;
+ }
+
+ g_info << "runSystemRestart7 finished" << endl;
+
+ return result;
+}
+
+int runWaitStarted(NDBT_Context* ctx, NDBT_Step* step){
+
+ NdbRestarter restarter;
+ restarter.waitClusterStarted(300);
+
+ NdbSleep_SecSleep(3);
+ return NDBT_OK;
+}
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ Ndb* pNdb = GETNDB(step);
+ if(pNdb->waitUntilReady(5) != 0){
+ return NDBT_FAILED;
+ }
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable2(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+
+NDBT_TESTSUITE(testSystemRestart);
+TESTCASE("SR1",
+ "Basic system restart test. Focus on testing restart from REDO log.\n"
+ "NOTE! Time between lcp's and gcp's should be left at default, \n"
+ "so that Ndb uses the Redo log when restarting\n"
+ "1. Load records\n"
+ "2. Restart cluster and verify records \n"
+ "3. Update records\n"
+ "4. Restart cluster and verify records \n"
+ "5. Delete half of the records \n"
+ "6. Restart cluster and verify records \n"
+ "7. Delete all records \n"
+ "8. Restart cluster and verify records \n"
+ "9. Insert, update, delete records \n"
+ "10. Restart cluster and verify records\n"
+ "11. Insert, update, delete records \n"
+ "12. Restart cluster with error insert 5020 and verify records\n"){
+ INITIALIZER(runWaitStarted);
+ STEP(runSystemRestart1);
+ FINALIZER(runClearTable);
+}
+TESTCASE("SR2",
+ "Basic system restart test. Focus on testing restart from LCP\n"
+ "NOTE! Time between lcp's is automatically set to it's min value\n"
+ "so that Ndb uses LCP's when restarting.\n"
+ "1. Load records\n"
+ "2. Restart cluster and verify records \n"
+ "3. Update records\n"
+ "4. Restart cluster and verify records \n"
+ "5. Delete half of the records \n"
+ "6. Restart cluster and verify records \n"
+ "7. Delete all records \n"
+ "8. Restart cluster and verify records \n"
+ "9. Insert, update, delete records \n"
+ "10. Restart cluster and verify records\n"){
+ INITIALIZER(runWaitStarted);
+ STEP(runSystemRestart2);
+ FINALIZER(runClearTable);
+}
+TESTCASE("SR_UNDO",
+ "System restart test. Focus on testing of undologging\n"
+ "in DBACC and DBTUP.\n"
+ "This is done by starting a LCP, turn on undologging \n"
+ "but don't start writing the datapages. This will force all\n"
+ "operations to be written into the undolog.\n"
+ "Then write datapages and complete LCP.\n"
+ "Restart the system\n"){
+ INITIALIZER(runWaitStarted);
+ STEP(runSystemRestartTestUndoLog);
+ FINALIZER(runClearTable);
+}
+TESTCASE("SR_FULLDB",
+ "System restart test. Test to restart when DB is full.\n"){
+ INITIALIZER(runWaitStarted);
+ STEP(runSystemRestartTestFullDb);
+ FINALIZER(runClearTable);
+}
+TESTCASE("SR3",
+ "System restart test. Focus on testing restart from with\n"
+ "not all nodes alive when system went down\n"
+ "* 1. Load data\n"
+ "* 2. Restart 1 node -nostart\n"
+ "* 3. Update records\n"
+ "* 4. Restart cluster and verify records\n"
+ "* 5. Restart 1 node -nostart\n"
+ "* 6. Delete half of the records\n"
+ "* 7. Restart cluster and verify records\n"
+ "* 8. Restart 1 node -nostart\n"
+ "* 9. Delete all records\n"
+ "* 10. Restart cluster and verify records\n"){
+ INITIALIZER(runWaitStarted);
+ STEP(runSystemRestart3);
+ FINALIZER(runClearTable);
+}
+TESTCASE("SR4",
+ "System restart test. Focus on testing restart from with\n"
+ "not all nodes alive when system went down but running LCP at\n"
+ "high speed so that sometimes a TO is required to start cluster\n"
+ "* 1. Load data\n"
+ "* 2. Restart 1 node -nostart\n"
+ "* 3. Update records\n"
+ "* 4. Restart cluster and verify records\n"
+ "* 5. Restart 1 node -nostart\n"
+ "* 6. Delete half of the records\n"
+ "* 7. Restart cluster and verify records\n"
+ "* 8. Restart 1 node -nostart\n"
+ "* 9. Delete all records\n"
+ "* 10. Restart cluster and verify records\n"){
+ INITIALIZER(runWaitStarted);
+ STEP(runSystemRestart4);
+ FINALIZER(runClearTable);
+}
+TESTCASE("SR5",
+ "As SR4 but making restart aborts\n"
+ "* 1. Load data\n"
+ "* 2. Restart 1 node -nostart\n"
+ "* 3. Update records\n"
+ "* 4. Restart cluster and verify records\n"
+ "* 5. Restart 1 node -nostart\n"
+ "* 6. Delete half of the records\n"
+ "* 7. Restart cluster and verify records\n"
+ "* 8. Restart 1 node -nostart\n"
+ "* 9. Delete all records\n"
+ "* 10. Restart cluster and verify records\n"){
+ INITIALIZER(runWaitStarted);
+ STEP(runSystemRestart5);
+ FINALIZER(runClearTable);
+}
+TESTCASE("SR6",
+ "Perform system restart with some nodes having FS others wo/\n"
+ "* 1. Load data\n"
+ "* 2. Restart all node -nostart\n"
+ "* 3. Restart some nodes -i -nostart\n"
+ "* 4. Start all nodes verify records\n"){
+ INITIALIZER(runWaitStarted);
+ INITIALIZER(runClearTable);
+ STEP(runSystemRestart6);
+ FINALIZER(runClearTable);
+}
+TESTCASE("SR7",
+ "Perform partition win system restart\n"
+ "* 1. Load data\n"
+ "* 2. Restart all node -nostart\n"
+ "* 3. Start all but one node\n"
+ "* 4. Verify records\n"
+ "* 5. Start last node\n"
+ "* 6. Verify records\n"){
+ INITIALIZER(runWaitStarted);
+ INITIALIZER(runClearTable);
+ STEP(runSystemRestart7);
+ FINALIZER(runClearTable);
+}
+TESTCASE("SR8",
+ "Perform partition win system restart with other nodes delayed\n"
+ "* 1. Load data\n"
+ "* 2. Restart all node -nostart\n"
+ "* 3. Start all but one node\n"
+ "* 4. Wait for startphase >= 2\n"
+ "* 5. Start last node\n"
+ "* 6. Verify records\n"){
+ INITIALIZER(runWaitStarted);
+ INITIALIZER(runClearTable);
+ STEP(runSystemRestart8);
+ FINALIZER(runClearTable);
+}
+NDBT_TESTSUITE_END(testSystemRestart);
+
+int main(int argc, const char** argv){
+ return testSystemRestart.execute(argc, argv);
+}
+
+
diff --git a/ndb/test/ndbapi/testSystemRestart/testSystemRestart.cpp b/ndb/test/ndbapi/testSystemRestart/testSystemRestart.cpp
deleted file mode 100644
index 1b8a35487cb..00000000000
--- a/ndb/test/ndbapi/testSystemRestart/testSystemRestart.cpp
+++ /dev/null
@@ -1,942 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NDBT.hpp>
-#include <NDBT_Test.hpp>
-#include <HugoTransactions.hpp>
-#include <UtilTransactions.hpp>
-#include <NdbRestarter.hpp>
-#include <Vector.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-
-int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
-
- int records = ctx->getNumRecords();
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-#define CHECK(b) if (!(b)) { \
- g_err << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- continue; }
-
-int runSystemRestart1(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- int timeout = 300;
- Uint32 loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int count;
- NdbRestarter restarter;
- Uint32 i = 1;
-
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
- while(i<=loops && result != NDBT_FAILED){
-
- ndbout << "Loop " << i << "/"<< loops <<" started" << endl;
- /*
- 1. Load data
- 2. Restart cluster and verify records
- 3. Update records
- 4. Restart cluster and verify records
- 5. Delete half of the records
- 6. Restart cluster and verify records
- 7. Delete all records
- 8. Restart cluster and verify records
- 9. Insert, update, delete records
- 10. Restart cluster and verify records
- 11. Insert, update, delete records
- 12. Restart cluster with error insert 5020 and verify records
- */
- ndbout << "Loading records..." << endl;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
-
- ndbout << "Restarting cluster" << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == records);
-
- ndbout << "Updating records..." << endl;
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == records);
-
- ndbout << "Deleting 50% of records..." << endl;
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == (records/2));
-
- ndbout << "Deleting all records..." << endl;
- CHECK(utilTrans.clearTable(pNdb, records/2) == 0);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == 0);
-
- ndbout << "Doing it all..." << endl;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
- CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == 0);
-
- ndbout << "Doing it all..." << endl;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
- CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
-
- ndbout << "Restarting cluster with error insert 5020..." << endl;
- CHECK(restarter.restartAll(false, true) == 0);
- CHECK(restarter.waitClusterNoStart(timeout) == 0);
- CHECK(restarter.insertErrorInAllNodes(5020) == 0);
- CHECK(restarter.startAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- i++;
- }
-
- ndbout << "runSystemRestart1 finished" << endl;
-
- return result;
-}
-
-int runSystemRestart2(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
-/// int timeout = 300;
- int timeout = 120;
- Uint32 loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int count;
- NdbRestarter restarter;
- Uint32 i = 1;
-
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
- while(i<=loops && result != NDBT_FAILED && !ctx->isTestStopped()){
-
- ndbout << "Loop " << i << "/"<< loops <<" started" << endl;
- /* Use error 7070 to set time between LCP to it's min value
- 1. Load data
- 2. Restart cluster and verify records
- 3. Update records
- 4. Restart cluster and verify records
- 5. Delete half of the records
- 6. Restart cluster and verify records
- 7. Delete all records
- 8. Restart cluster and verify records
- 9. Insert, update, delete records
- 10. Restart cluster and verify records
- */
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
-
- ndbout << "Loading records..." << endl;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
-
- ndbout << "Restarting cluster" << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == records);
-
- ndbout << "Updating records..." << endl;
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == records);
-
- ndbout << "Deleting 50% of records..." << endl;
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == (records/2));
-
- ndbout << "Deleting all records..." << endl;
- CHECK(utilTrans.clearTable(pNdb, records/2) == 0);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == 0);
-
- ndbout << "Doing it all..." << endl;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
- CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == 0);
-
- i++;
- }
-
- ndbout << "runSystemRestart2 finished" << endl;
-
- return result;
-}
-
-int runSystemRestartTestUndoLog(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- int timeout = 300;
- Uint32 loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int count;
- NdbRestarter restarter;
- Uint32 i = 1;
-
- int dump7080[2];
- dump7080[0] = 7080;
- dump7080[1] = ctx->getTab()->getTableId();
-
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
- while(i<=loops && result != NDBT_FAILED){
-
- ndbout << "Loop " << i << "/"<< loops <<" started" << endl;
- /*
- 1. Start LCP, turn on undologging but delay write of datapages.
- 2. Insert, update, delete records
- 3. Complete writing of data pages and finish LCP.
- 4. Restart cluster and verify records
- */
- // Use dump state 7080 to delay writing of datapages
- // for the current table
- ndbout << "Dump state: "<<dump7080[0]<<", "<<dump7080[1]<<endl;
- CHECK(restarter.dumpStateAllNodes(dump7080, 2) == 0);
- NdbSleep_SecSleep(10);
-
- ndbout << "Doing it all..." << endl;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
- CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
-
- // Reset error and let LCP continue
- CHECK(restarter.insertErrorInAllNodes(0) == 0);
- NdbSleep_SecSleep(60);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == 0);
-
- // Use dump state 7080 to delay writing of datapages
- // for the current table
- ndbout << "Dump state: "<<dump7080[0]<<", "<<dump7080[1]<<endl;
- CHECK(restarter.dumpStateAllNodes(dump7080, 2) == 0);
- NdbSleep_SecSleep(10);
-
- ndbout << "Doing it all, delete 50%..." << endl;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
-
- // Reset error and let LCP continue
- CHECK(restarter.insertErrorInAllNodes(0) == 0);
- NdbSleep_SecSleep(20);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == (records/2));
- CHECK(utilTrans.clearTable(pNdb, records) == 0);
-
- i++;
- }
-
- ndbout << "runSystemRestartTestUndoLog finished" << endl;
-
- return result;
-}
-
-int runSystemRestartTestFullDb(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- int timeout = 300;
- Uint32 loops = ctx->getNumLoops();
- int count1, count2;
- NdbRestarter restarter;
- Uint32 i = 1;
-
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
- while(i<=loops && result != NDBT_FAILED){
-
- ndbout << "Loop " << i << "/"<< loops <<" started" << endl;
- /*
- 1. Load data until db reports it's full
- 2. Restart cluster and verify records
- */
- ndbout << "Filling up table..." << endl;
- CHECK(hugoTrans.fillTable(pNdb) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count1) == 0);
- ndbout << "Db is full. Table has "<<count1 <<" records."<< endl;
-
- ndbout << "Restarting cluster" << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(hugoTrans.scanReadRecords(pNdb, count1) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count2) == 0);
- CHECK(count1 == count2);
-
- ndbout << "Deleting all records..." << endl;
- CHECK(utilTrans.clearTable2(pNdb, count1) == 0);
-
- ndbout << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count1) == 0);
- CHECK(count1 == 0);
-
- i++;
- }
-
- ndbout << "runSystemRestartTestFullDb finished" << endl;
-
- return result;
-}
-
-int runSystemRestart3(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- int timeout = 300;
- Uint32 loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int count;
- NdbRestarter restarter;
- Uint32 i = 1;
-
- const Uint32 nodeCount = restarter.getNumDbNodes();
- if(nodeCount < 2){
- g_info << "SR3 - Needs atleast 2 nodes to test" << endl;
- return NDBT_OK;
- }
-
- Vector<int> nodeIds;
- for(Uint32 i = 0; i<nodeCount; i++)
- nodeIds.push_back(restarter.getDbNodeId(i));
-
- Uint32 currentRestartNodeIndex = 0;
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
-
- while(i<=loops && result != NDBT_FAILED){
-
- g_info << "Loop " << i << "/"<< loops <<" started" << endl;
- /**
- * 1. Load data
- * 2. Restart 1 node -nostart
- * 3. Update records
- * 4. Restart cluster and verify records
- * 5. Restart 1 node -nostart
- * 6. Delete half of the records
- * 7. Restart cluster and verify records
- * 8. Restart 1 node -nostart
- * 9. Delete all records
- * 10. Restart cluster and verify records
- */
- g_info << "Loading records..." << endl;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
-
- /*** 1 ***/
- g_info << "1 - Stopping one node" << endl;
- CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
- false,
- true,
- false) == 0);
- currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
-
- g_info << "Updating records..." << endl;
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
-
- g_info << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- g_info << "Verifying records..." << endl;
- CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == records);
-
- g_info << "2 - Stopping one node" << endl;
- CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
- false,
- true,
- false) == 0);
- currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
-
- g_info << "Deleting 50% of records..." << endl;
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
-
- g_info << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- g_info << "Verifying records..." << endl;
- CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == (records/2));
-
- g_info << "3 - Stopping one node" << endl;
- CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
- false,
- true,
- false) == 0);
- currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
- g_info << "Deleting all records..." << endl;
- CHECK(utilTrans.clearTable(pNdb, records/2) == 0);
-
- g_info << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == 0);
-
- i++;
- }
-
- g_info << "runSystemRestart3 finished" << endl;
-
- return result;
-}
-
-int runSystemRestart4(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- int timeout = 300;
- Uint32 loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int count;
- NdbRestarter restarter;
- Uint32 i = 1;
-
- const Uint32 nodeCount = restarter.getNumDbNodes();
- if(nodeCount < 2){
- g_info << "SR4 - Needs atleast 2 nodes to test" << endl;
- return NDBT_OK;
- }
-
- Vector<int> nodeIds;
- for(Uint32 i = 0; i<nodeCount; i++)
- nodeIds.push_back(restarter.getDbNodeId(i));
-
- Uint32 currentRestartNodeIndex = 0;
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
-
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- if(restarter.dumpStateAllNodes(&val, 1) != 0){
- g_err << "ERR: "<< step->getName()
- << " failed on line " << __LINE__ << endl;
- return NDBT_FAILED;
- }
- }
-
- while(i<=loops && result != NDBT_FAILED){
-
- g_info << "Loop " << i << "/"<< loops <<" started" << endl;
- /**
- * 1. Load data
- * 2. Restart 1 node -nostart
- * 3. Update records
- * 4. Restart cluster and verify records
- * 5. Restart 1 node -nostart
- * 6. Delete half of the records
- * 7. Restart cluster and verify records
- * 8. Restart 1 node -nostart
- * 9. Delete all records
- * 10. Restart cluster and verify records
- */
- g_info << "Loading records..." << endl;
- CHECK(hugoTrans.loadTable(pNdb, records) == 0);
-
- /*** 1 ***/
- g_info << "1 - Stopping one node" << endl;
- CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
- false,
- true,
- false) == 0);
- currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
-
- g_info << "Updating records..." << endl;
- CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
-
- g_info << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- g_info << "Verifying records..." << endl;
- CHECK(hugoTrans.pkReadRecords(pNdb, records) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == records);
-
- g_info << "2 - Stopping one node" << endl;
- CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
- false,
- true,
- false) == 0);
- currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
-
- g_info << "Deleting 50% of records..." << endl;
- CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
-
- g_info << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- g_info << "Verifying records..." << endl;
- CHECK(hugoTrans.scanReadRecords(pNdb, records/2, 0, 64) == 0);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == (records/2));
-
- g_info << "3 - Stopping one node" << endl;
- CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
- false,
- true,
- false) == 0);
- currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
- g_info << "Deleting all records..." << endl;
- CHECK(utilTrans.clearTable(pNdb, records/2) == 0);
-
- g_info << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll() == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- CHECK(count == 0);
-
- i++;
- }
-
- g_info << "runSystemRestart4 finished" << endl;
-
- return result;
-}
-
-int runSystemRestart5(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = GETNDB(step);
- int result = NDBT_OK;
- int timeout = 300;
- Uint32 loops = ctx->getNumLoops();
- int records = ctx->getNumRecords();
- int count;
- NdbRestarter restarter;
- Uint32 i = 1;
-
- const Uint32 nodeCount = restarter.getNumDbNodes();
- if(nodeCount < 2){
- g_info << "SR5 - Needs atleast 2 nodes to test" << endl;
- return NDBT_OK;
- }
-
- Vector<int> nodeIds;
- for(Uint32 i = 0; i<nodeCount; i++)
- nodeIds.push_back(restarter.getDbNodeId(i));
-
- Uint32 currentRestartNodeIndex = 0;
- UtilTransactions utilTrans(*ctx->getTab());
- HugoTransactions hugoTrans(*ctx->getTab());
-
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- if(restarter.dumpStateAllNodes(&val, 1) != 0){
- g_err << "ERR: "<< step->getName()
- << " failed on line " << __LINE__ << endl;
- return NDBT_FAILED;
- }
- }
-
- while(i<=loops && result != NDBT_FAILED){
-
- g_info << "Loop " << i << "/"<< loops <<" started" << endl;
- /**
- * 1. Load data
- * 2. Restart 1 node -nostart
- * 3. Update records
- * 4. Restart cluster and verify records
- * 5. Restart 1 node -nostart
- * 6. Delete half of the records
- * 7. Restart cluster and verify records
- * 8. Restart 1 node -nostart
- * 9. Delete all records
- * 10. Restart cluster and verify records
- */
- g_info << "Loading records..." << endl;
- hugoTrans.loadTable(pNdb, records);
-
- /*** 1 ***/
- g_info << "1 - Stopping one node" << endl;
- CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
- false,
- true,
- false) == 0);
- currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
-
- g_info << "Updating records..." << endl;
- hugoTrans.pkUpdateRecords(pNdb, records);
-
- g_info << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll(false, false, true) == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- g_info << "Verifying records..." << endl;
- hugoTrans.pkReadRecords(pNdb, records);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- //CHECK(count == records);
-
- g_info << "2 - Stopping one node" << endl;
- CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
- false,
- true,
- false) == 0);
- currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
-
- g_info << "Deleting 50% of records..." << endl;
- hugoTrans.pkDelRecords(pNdb, records/2);
-
- g_info << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll(false, false, true) == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- g_info << "Verifying records..." << endl;
- hugoTrans.scanReadRecords(pNdb, records/2, 0, 64);
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- //CHECK(count == (records/2));
-
- g_info << "3 - Stopping one node" << endl;
- CHECK(restarter.restartOneDbNode(nodeIds[currentRestartNodeIndex],
- false,
- true,
- false) == 0);
- currentRestartNodeIndex = (currentRestartNodeIndex + 1 ) % nodeCount;
- g_info << "Deleting all records..." << endl;
- utilTrans.clearTable(pNdb, records/2);
-
- g_info << "Restarting cluster..." << endl;
- CHECK(restarter.restartAll(false, false, true) == 0);
- CHECK(restarter.waitClusterStarted(timeout) == 0);
- {
- int val = DumpStateOrd::DihMinTimeBetweenLCP;
- CHECK(restarter.dumpStateAllNodes(&val, 1) == 0);
- }
- CHECK(pNdb->waitUntilReady(timeout) == 0);
-
- ndbout << "Verifying records..." << endl;
- CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
- //CHECK(count == 0);
-
- CHECK(utilTrans.clearTable(pNdb) == 0);
- i++;
- }
-
- g_info << "runSystemRestart5 finished" << endl;
-
- return result;
-}
-
-int runWaitStarted(NDBT_Context* ctx, NDBT_Step* step){
-
- NdbRestarter restarter;
- restarter.waitClusterStarted(300);
-
- NdbSleep_SecSleep(3);
- return NDBT_OK;
-}
-
-int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
-
- UtilTransactions utilTrans(*ctx->getTab());
- if (utilTrans.clearTable2(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-
-NDBT_TESTSUITE(testSystemRestart);
-TESTCASE("SR1",
- "Basic system restart test. Focus on testing restart from REDO log.\n"
- "NOTE! Time between lcp's and gcp's should be left at default, \n"
- "so that Ndb uses the Redo log when restarting\n"
- "1. Load records\n"
- "2. Restart cluster and verify records \n"
- "3. Update records\n"
- "4. Restart cluster and verify records \n"
- "5. Delete half of the records \n"
- "6. Restart cluster and verify records \n"
- "7. Delete all records \n"
- "8. Restart cluster and verify records \n"
- "9. Insert, update, delete records \n"
- "10. Restart cluster and verify records\n"
- "11. Insert, update, delete records \n"
- "12. Restart cluster with error insert 5020 and verify records\n"){
- INITIALIZER(runWaitStarted);
- STEP(runSystemRestart1);
- FINALIZER(runClearTable);
-}
-TESTCASE("SR2",
- "Basic system restart test. Focus on testing restart from LCP\n"
- "NOTE! Time between lcp's is automatically set to it's min value\n"
- "so that Ndb uses LCP's when restarting.\n"
- "1. Load records\n"
- "2. Restart cluster and verify records \n"
- "3. Update records\n"
- "4. Restart cluster and verify records \n"
- "5. Delete half of the records \n"
- "6. Restart cluster and verify records \n"
- "7. Delete all records \n"
- "8. Restart cluster and verify records \n"
- "9. Insert, update, delete records \n"
- "10. Restart cluster and verify records\n"){
- INITIALIZER(runWaitStarted);
- STEP(runSystemRestart2);
- FINALIZER(runClearTable);
-}
-TESTCASE("SR_UNDO",
- "System restart test. Focus on testing of undologging\n"
- "in DBACC and DBTUP.\n"
- "This is done by starting a LCP, turn on undologging \n"
- "but don't start writing the datapages. This will force all\n"
- "operations to be written into the undolog.\n"
- "Then write datapages and complete LCP.\n"
- "Restart the system\n"){
- INITIALIZER(runWaitStarted);
- STEP(runSystemRestartTestUndoLog);
- FINALIZER(runClearTable);
-}
-TESTCASE("SR_FULLDB",
- "System restart test. Test to restart when DB is full.\n"){
- INITIALIZER(runWaitStarted);
- STEP(runSystemRestartTestFullDb);
- FINALIZER(runClearTable);
-}
-TESTCASE("SR3",
- "System restart test. Focus on testing restart from with\n"
- "not all nodes alive when system went down\n"
- "* 1. Load data\n"
- "* 2. Restart 1 node -nostart\n"
- "* 3. Update records\n"
- "* 4. Restart cluster and verify records\n"
- "* 5. Restart 1 node -nostart\n"
- "* 6. Delete half of the records\n"
- "* 7. Restart cluster and verify records\n"
- "* 8. Restart 1 node -nostart\n"
- "* 9. Delete all records\n"
- "* 10. Restart cluster and verify records\n"){
- INITIALIZER(runWaitStarted);
- STEP(runSystemRestart3);
- FINALIZER(runClearTable);
-}
-TESTCASE("SR4",
- "System restart test. Focus on testing restart from with\n"
- "not all nodes alive when system went down but running LCP at\n"
- "high speed so that sometimes a TO is required to start cluster\n"
- "* 1. Load data\n"
- "* 2. Restart 1 node -nostart\n"
- "* 3. Update records\n"
- "* 4. Restart cluster and verify records\n"
- "* 5. Restart 1 node -nostart\n"
- "* 6. Delete half of the records\n"
- "* 7. Restart cluster and verify records\n"
- "* 8. Restart 1 node -nostart\n"
- "* 9. Delete all records\n"
- "* 10. Restart cluster and verify records\n"){
- INITIALIZER(runWaitStarted);
- STEP(runSystemRestart4);
- FINALIZER(runClearTable);
-}
-TESTCASE("SR5",
- "As SR4 but making restart aborts\n"
- "* 1. Load data\n"
- "* 2. Restart 1 node -nostart\n"
- "* 3. Update records\n"
- "* 4. Restart cluster and verify records\n"
- "* 5. Restart 1 node -nostart\n"
- "* 6. Delete half of the records\n"
- "* 7. Restart cluster and verify records\n"
- "* 8. Restart 1 node -nostart\n"
- "* 9. Delete all records\n"
- "* 10. Restart cluster and verify records\n"){
- INITIALIZER(runWaitStarted);
- STEP(runSystemRestart5);
- FINALIZER(runClearTable);
-}
-NDBT_TESTSUITE_END(testSystemRestart);
-
-int main(int argc, const char** argv){
- return testSystemRestart.execute(argc, argv);
-}
-
-
diff --git a/ndb/test/ndbapi/testTimeout.cpp b/ndb/test/ndbapi/testTimeout.cpp
new file mode 100644
index 00000000000..8a7866880b3
--- /dev/null
+++ b/ndb/test/ndbapi/testTimeout.cpp
@@ -0,0 +1,261 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <random.h>
+#include <NdbConfig.hpp>
+
+
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable2(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+
+#define CHECK(b) if (!(b)) { \
+ ndbout << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ break; }
+
+int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ NdbConfig conf(GETNDB(step)->getNodeId()+1);
+ unsigned int nodeId = conf.getMasterNodeId();
+ int stepNo = step->getStepNo();
+ Uint32 timeoutVal;
+ if (!conf.getProperty(nodeId,
+ NODE_TYPE_DB,
+ CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
+ &timeoutVal)){
+ return NDBT_FAILED;
+ }
+ int minSleep = (int)(timeoutVal * 1.5);
+ int maxSleep = timeoutVal * 2;
+ ndbout << "TransactionInactiveTimeout="<<timeoutVal
+ << ", minSleep="<<minSleep
+ << ", maxSleep="<<maxSleep<<endl;
+
+ 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, true) == 0);
+ CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
+
+ int sleep = minSleep + myRandom48(maxSleep-minSleep);
+ ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
+ NdbSleep_MilliSleep(sleep);
+
+ // Expect that transaction has timed-out
+ CHECK(hugoOps.execute_Commit(pNdb) == 237);
+
+ } while(false);
+
+ hugoOps.closeTransaction(pNdb);
+
+ }
+
+ return result;
+}
+
+int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ NdbConfig conf(GETNDB(step)->getNodeId()+1);
+ unsigned int nodeId = conf.getMasterNodeId();
+ int stepNo = step->getStepNo();
+ Uint32 timeoutVal;
+ if (!conf.getProperty(nodeId,
+ NODE_TYPE_DB,
+ CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
+ &timeoutVal)){
+ return NDBT_FAILED;
+ }
+ int maxSleep = (int)(timeoutVal * 0.5);
+ ndbout << "TransactionInactiveTimeout="<<timeoutVal
+ << ", maxSleep="<<maxSleep<<endl;
+
+
+ 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, true) == 0);
+ CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
+
+ int sleep = myRandom48(maxSleep);
+ 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();
+ int records = ctx->getNumRecords();
+ NdbConfig conf(GETNDB(step)->getNodeId()+1);
+ unsigned int nodeId = conf.getMasterNodeId();
+ int stepNo = step->getStepNo();
+ Uint32 timeoutVal;
+ if (!conf.getProperty(nodeId,
+ NODE_TYPE_DB,
+ CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
+ &timeoutVal)){
+ return NDBT_FAILED;
+ }
+ int maxSleep = (int)(timeoutVal * 0.3);
+ ndbout << "TransactionInactiveTimeout="<<timeoutVal
+ << ", maxSleep="<<maxSleep<<endl;
+
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+
+ for (int l = 1; l < loops && result == NDBT_OK; l++){
+
+ do{
+ // Start an insert trans
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ int recordNo = records + (stepNo*loops) + l;
+ CHECK(hugoOps.pkInsertRecord(pNdb, recordNo, true) == 0);
+ CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
+
+ for (int i = 0; i < 10; i++){
+ // Perform buddy scan reads
+ CHECK(hugoOps.scanReadRecords(pNdb) == 0);
+ CHECK(hugoOps.executeScanRead(pNdb) == 0);
+
+ int sleep = myRandom48(maxSleep);
+ 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;
+}
+
+NDBT_TESTSUITE(testTimeout);
+TESTCASE("DontTimeoutTransaction",
+ "Test that the transaction does not timeout "\
+ "if we sleep during the transaction. Use a sleep "\
+ "value which is smaller than TransactionInactiveTimeout"){
+ INITIALIZER(runLoadTable);
+ STEPS(runDontTimeoutTrans, 1);
+ FINALIZER(runClearTable);
+}
+TESTCASE("DontTimeoutTransaction5",
+ "Test that the transaction does not timeout "\
+ "if we sleep during the transaction. Use a sleep "\
+ "value which is smaller than TransactionInactiveTimeout" \
+ "Five simultaneous threads"){
+ INITIALIZER(runLoadTable);
+ STEPS(runDontTimeoutTrans, 5);
+ FINALIZER(runClearTable);
+}
+TESTCASE("TimeoutTransaction",
+ "Test that the transaction does timeout "\
+ "if we sleep during the transaction. Use a sleep "\
+ "value which is larger than TransactionInactiveTimeout"){
+ INITIALIZER(runLoadTable);
+ STEPS(runTimeoutTrans, 1);
+ FINALIZER(runClearTable);
+}
+TESTCASE("TimeoutTransaction5",
+ "Test that the transaction does timeout " \
+ "if we sleep during the transaction. Use a sleep " \
+ "value which is larger than TransactionInactiveTimeout" \
+ "Five simultaneous threads"){
+ INITIALIZER(runLoadTable);
+ STEPS(runTimeoutTrans, 5);
+ FINALIZER(runClearTable);
+}
+TESTCASE("BuddyTransNoTimeout",
+ "Start a transaction and perform an insert with NoCommit. " \
+ "Start a buddy transaction wich performs long running scans " \
+ "and sleeps. " \
+ "The total sleep time is longer than TransactionInactiveTimeout" \
+ "Commit the first transaction, it should not have timed out."){
+ INITIALIZER(runLoadTable);
+ STEPS(runBuddyTransNoTimeout, 1);
+ FINALIZER(runClearTable);
+}
+TESTCASE("BuddyTransNoTimeout5",
+ "Start a transaction and perform an insert with NoCommit. " \
+ "Start a buddy transaction wich performs long running scans " \
+ "and sleeps. " \
+ "The total sleep time is longer than TransactionInactiveTimeout" \
+ "Commit the first transaction, it should not have timed out." \
+ "Five simultaneous threads"){
+ INITIALIZER(runLoadTable);
+ STEPS(runBuddyTransNoTimeout, 5);
+ FINALIZER(runClearTable);
+}
+NDBT_TESTSUITE_END(testTimeout);
+
+int main(int argc, const char** argv){
+ myRandom48Init(NdbTick_CurrentMillisecond());
+ return testTimeout.execute(argc, argv);
+}
+
diff --git a/ndb/test/ndbapi/testTimeout/testTimeout.cpp b/ndb/test/ndbapi/testTimeout/testTimeout.cpp
deleted file mode 100644
index de1d2cfc40b..00000000000
--- a/ndb/test/ndbapi/testTimeout/testTimeout.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <NDBT.hpp>
-#include <NDBT_Test.hpp>
-#include <HugoTransactions.hpp>
-#include <UtilTransactions.hpp>
-#include <random.h>
-#include <NdbConfig.hpp>
-
-
-int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
-
- int records = ctx->getNumRecords();
- HugoTransactions hugoTrans(*ctx->getTab());
- if (hugoTrans.loadTable(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
- int records = ctx->getNumRecords();
-
- UtilTransactions utilTrans(*ctx->getTab());
- if (utilTrans.clearTable2(GETNDB(step), records) != 0){
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-
-#define CHECK(b) if (!(b)) { \
- ndbout << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- break; }
-
-int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
- NdbConfig conf(GETNDB(step)->getNodeId()+1);
- unsigned int nodeId = conf.getMasterNodeId();
- int stepNo = step->getStepNo();
- Uint32 timeoutVal;
- if (!conf.getProperty(nodeId,
- "DB",
- "TransactionInactiveTimeout",
- &timeoutVal)){
- return NDBT_FAILED;
- }
- int minSleep = (int)(timeoutVal * 1.5);
- int maxSleep = timeoutVal * 2;
- ndbout << "TransactionInactiveTimeout="<<timeoutVal
- << ", minSleep="<<minSleep
- << ", maxSleep="<<maxSleep<<endl;
-
- 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, true) == 0);
- CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
-
- int sleep = minSleep + myRandom48(maxSleep-minSleep);
- ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
- NdbSleep_MilliSleep(sleep);
-
- // Expect that transaction has timed-out
- CHECK(hugoOps.execute_Commit(pNdb) == 237);
-
- } while(false);
-
- hugoOps.closeTransaction(pNdb);
-
- }
-
- return result;
-}
-
-int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
- int loops = ctx->getNumLoops();
- NdbConfig conf(GETNDB(step)->getNodeId()+1);
- unsigned int nodeId = conf.getMasterNodeId();
- int stepNo = step->getStepNo();
- Uint32 timeoutVal;
- if (!conf.getProperty(nodeId,
- "DB",
- "TransactionInactiveTimeout",
- &timeoutVal)){
- return NDBT_FAILED;
- }
- int maxSleep = (int)(timeoutVal * 0.5);
- ndbout << "TransactionInactiveTimeout="<<timeoutVal
- << ", maxSleep="<<maxSleep<<endl;
-
-
- 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, true) == 0);
- CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
-
- int sleep = myRandom48(maxSleep);
- 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();
- int records = ctx->getNumRecords();
- NdbConfig conf(GETNDB(step)->getNodeId()+1);
- unsigned int nodeId = conf.getMasterNodeId();
- int stepNo = step->getStepNo();
- Uint32 timeoutVal;
- if (!conf.getProperty(nodeId,
- "DB",
- "TransactionInactiveTimeout",
- &timeoutVal)){
- return NDBT_FAILED;
- }
- int maxSleep = (int)(timeoutVal * 0.3);
- ndbout << "TransactionInactiveTimeout="<<timeoutVal
- << ", maxSleep="<<maxSleep<<endl;
-
- HugoOperations hugoOps(*ctx->getTab());
- Ndb* pNdb = GETNDB(step);
-
- for (int l = 1; l < loops && result == NDBT_OK; l++){
-
- do{
- // Start an insert trans
- CHECK(hugoOps.startTransaction(pNdb) == 0);
- int recordNo = records + (stepNo*loops) + l;
- CHECK(hugoOps.pkInsertRecord(pNdb, recordNo, true) == 0);
- CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
-
- for (int i = 0; i < 10; i++){
- // Perform buddy scan reads
- CHECK(hugoOps.scanReadRecords(pNdb) == 0);
- CHECK(hugoOps.executeScanRead(pNdb) == 0);
-
- int sleep = myRandom48(maxSleep);
- 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;
-}
-
-NDBT_TESTSUITE(testTimeout);
-TESTCASE("DontTimeoutTransaction",
- "Test that the transaction does not timeout "\
- "if we sleep during the transaction. Use a sleep "\
- "value which is smaller than TransactionInactiveTimeout"){
- INITIALIZER(runLoadTable);
- STEPS(runDontTimeoutTrans, 1);
- FINALIZER(runClearTable);
-}
-TESTCASE("DontTimeoutTransaction5",
- "Test that the transaction does not timeout "\
- "if we sleep during the transaction. Use a sleep "\
- "value which is smaller than TransactionInactiveTimeout" \
- "Five simultaneous threads"){
- INITIALIZER(runLoadTable);
- STEPS(runDontTimeoutTrans, 5);
- FINALIZER(runClearTable);
-}
-TESTCASE("TimeoutTransaction",
- "Test that the transaction does timeout "\
- "if we sleep during the transaction. Use a sleep "\
- "value which is larger than TransactionInactiveTimeout"){
- INITIALIZER(runLoadTable);
- STEPS(runTimeoutTrans, 1);
- FINALIZER(runClearTable);
-}
-TESTCASE("TimeoutTransaction5",
- "Test that the transaction does timeout " \
- "if we sleep during the transaction. Use a sleep " \
- "value which is larger than TransactionInactiveTimeout" \
- "Five simultaneous threads"){
- INITIALIZER(runLoadTable);
- STEPS(runTimeoutTrans, 5);
- FINALIZER(runClearTable);
-}
-TESTCASE("BuddyTransNoTimeout",
- "Start a transaction and perform an insert with NoCommit. " \
- "Start a buddy transaction wich performs long running scans " \
- "and sleeps. " \
- "The total sleep time is longer than TransactionInactiveTimeout" \
- "Commit the first transaction, it should not have timed out."){
- INITIALIZER(runLoadTable);
- STEPS(runBuddyTransNoTimeout, 1);
- FINALIZER(runClearTable);
-}
-TESTCASE("BuddyTransNoTimeout5",
- "Start a transaction and perform an insert with NoCommit. " \
- "Start a buddy transaction wich performs long running scans " \
- "and sleeps. " \
- "The total sleep time is longer than TransactionInactiveTimeout" \
- "Commit the first transaction, it should not have timed out." \
- "Five simultaneous threads"){
- INITIALIZER(runLoadTable);
- STEPS(runBuddyTransNoTimeout, 5);
- FINALIZER(runClearTable);
-}
-NDBT_TESTSUITE_END(testTimeout);
-
-int main(int argc, const char** argv){
- myRandom48Init(NdbTick_CurrentMillisecond());
- return testTimeout.execute(argc, argv);
-}
-
diff --git a/ndb/test/ndbapi/testTransactions/testTransactions.cpp b/ndb/test/ndbapi/testTransactions.cpp
index 9ce928f8736..9ce928f8736 100644
--- a/ndb/test/ndbapi/testTransactions/testTransactions.cpp
+++ b/ndb/test/ndbapi/testTransactions.cpp
diff --git a/ndb/test/ndbapi/test_event/test_event.cpp b/ndb/test/ndbapi/test_event.cpp
index 40fc1c6defa..40fc1c6defa 100644
--- a/ndb/test/ndbapi/test_event/test_event.cpp
+++ b/ndb/test/ndbapi/test_event.cpp
diff --git a/ndb/test/ndbapi/lmc-bench/async-src/user/userInterface.cpp b/ndb/test/ndbapi/userInterface.cpp
index fdbc229cc98..fdbc229cc98 100644
--- a/ndb/test/ndbapi/lmc-bench/async-src/user/userInterface.cpp
+++ b/ndb/test/ndbapi/userInterface.cpp
diff --git a/ndb/test/newtonapi/Makefile b/ndb/test/newtonapi/Makefile
deleted file mode 100644
index e3eabd26c64..00000000000
--- a/ndb/test/newtonapi/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include .defs.mk
-
-DIRS := \
- basic_test \
- perf_test
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/test/odbc/Makefile b/ndb/test/odbc/Makefile
deleted file mode 100644
index eb9f2dc9e3e..00000000000
--- a/ndb/test/odbc/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-include .defs.mk
-
-DIRS += driver
-
-#ifneq ($(findstring odbc, $(wildcard /usr/lib/libodbc.so)),)
-#DIRS += dm-unixodbc
-#endif
-
-ifneq ($(findstring $(NDB_OS), SOLARIS),)
-DIRS += dm-iodbc
-endif
-
-include ${NDB_TOP}/Epilogue.mk
diff --git a/ndb/test/odbc/driver/testOdbcDriver.cpp b/ndb/test/odbc/driver/testOdbcDriver.cpp
index b856b6a21f2..d3b3802ebe1 100644
--- a/ndb/test/odbc/driver/testOdbcDriver.cpp
+++ b/ndb/test/odbc/driver/testOdbcDriver.cpp
@@ -37,6 +37,7 @@
*/
#include <ndb_global.h>
+#undef test
#include <ndb_version.h>
#include <kernel/ndb_limits.h>
#include <Bitmask.hpp>
@@ -1281,6 +1282,7 @@ struct Fld {
return test.verify(m_double, m_ind, fld.m_double, fld.m_ind);
}
assert(false);
+ return false;
}
// debug
void print() const {
diff --git a/ndb/test/run-test/Makefile.am b/ndb/test/run-test/Makefile.am
new file mode 100644
index 00000000000..3dd9632ce4b
--- /dev/null
+++ b/ndb/test/run-test/Makefile.am
@@ -0,0 +1,18 @@
+
+ndbtest_PROGRAMS = atrt
+
+atrt_SOURCES = main.cpp
+
+ndbtest_SCRIPTS = atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \
+ atrt-clear-result.sh make-config.sh make-index.sh make-html-reports.sh
+EXTRA_DIST = $(ndbtest_SCRIPTS)
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmclient
+LDADD_LOC = $(top_builddir)/ndb/src/mgmclient/CpcClient.o $(top_builddir)/ndb/src/libndbclient.la
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_util.mk.am
+include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/test/run-test/Makefile b/ndb/test/run-test/Makefile_old
index 6b4689b2dbb..6b4689b2dbb 100644
--- a/ndb/test/run-test/Makefile
+++ b/ndb/test/run-test/Makefile_old
diff --git a/ndb/test/run-test/README b/ndb/test/run-test/README
new file mode 100644
index 00000000000..d5da8f05c17
--- /dev/null
+++ b/ndb/test/run-test/README
@@ -0,0 +1,43 @@
+run-test/README
+
+This document describes how atrt works and how to use it.
+
+atrt is a test program driver.
+atrt supports fully distributed test and utilizes ndb_cpcd.
+
+=================================
+atrt has the following main loop:
+
+/**
+ * Psuedo code for atrt
+ */
+ read config file (default d.txt)
+ contact each ndb_cpcd
+ start each ndb_mgmd
+ connect to each ndb_mgmd
+ for each read(test case)
+ do
+ if previous test failed (or is first test)
+ stop each ndbd
+ start each ndbd
+ wait for ndbd to get started
+
+ start each mysqld
+
+ start each test prg
+
+ wait while all is running and max time not elapsed
+
+ stop each mysqld
+
+ stop each test prg
+
+ gather result
+
+ done
+/**
+ * End of psuedo code
+ */
+
+=================================
+
diff --git a/ndb/test/run-test/atrt-example.tgz b/ndb/test/run-test/atrt-example.tgz
new file mode 100644
index 00000000000..8455b2eb00d
--- /dev/null
+++ b/ndb/test/run-test/atrt-example.tgz
Binary files differ
diff --git a/ndb/test/run-test/basic.txt b/ndb/test/run-test/basic.txt
new file mode 100644
index 00000000000..a952320db08
--- /dev/null
+++ b/ndb/test/run-test/basic.txt
@@ -0,0 +1,763 @@
+# BASIC FUNCTIONALITY
+max-time: 500
+cmd: testBasic
+args: -n PkRead
+
+max-time: 500
+cmd: testBasic
+args: -n PkUpdate
+
+max-time: 500
+cmd: testBasic
+args: -n PkDelete
+
+max-time: 500
+cmd: testBasic
+args: -n PkInsert
+
+max-time: 600
+cmd: testBasic
+args: -n UpdateAndRead
+
+max-time: 500
+cmd: testBasic
+args: -n PkReadAndLocker T6
+
+max-time: 500
+cmd: testBasic
+args: -n PkReadAndLocker2 T6
+
+max-time: 500
+cmd: testBasic
+args: -n PkReadUpdateAndLocker T6
+
+max-time: 500
+cmd: testBasic
+args: -n ReadWithLocksAndInserts T6
+
+max-time: 500
+cmd: testBasic
+args: -n PkInsertTwice T1 T6 T10
+
+max-time: 1500
+cmd: testBasic
+args: -n Fill T1
+
+max-time: 1500
+cmd: testBasic
+args: -n Fill T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitSleep T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommit626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitAndClose T6
+
+max-time: 500
+cmd: testBasic
+args: -n Commit626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitTry626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitAsMuch626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommit626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitRollback626 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n Commit630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitTry630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitAsMuch630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommit630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitRollback630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitAndClose T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n RollbackUpdate T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n RollbackDeleteMultiple T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n ImplicitRollbackDelete T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitDelete T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n RollbackNothing T1 T6
+
+max-time: 500
+cmd: testBasicAsynch
+args: -n PkInsertAsynch
+
+max-time: 500
+cmd: testBasicAsynch
+args: -n PkReadAsynch
+
+max-time: 500
+cmd: testBasicAsynch
+args: -n PkUpdateAsynch
+
+max-time: 500
+cmd: testBasicAsynch
+args: -n PkDeleteAsynch
+
+max-time: 500
+cmd: testBasic
+args: -n MassiveRollback T1 T6 T13
+
+max-time: 500
+cmd: testBasic
+args: -n MassiveRollback2 T1 T6 T13
+
+#-m 500 1: testBasic -n ReadConsistency T6
+cmd: testTimeout
+args: -n DontTimeoutTransaction T1
+
+cmd: testTimeout
+args: -n DontTimeoutTransaction5 T1
+
+cmd: testTimeout
+args: -n TimeoutTransaction T1
+
+cmd: testTimeout
+args: -n TimeoutTransaction5 T1
+
+cmd: testTimeout
+args: -n BuddyTransNoTimeout T1
+
+cmd: testTimeout
+args: -n BuddyTransNoTimeout5 T1
+
+#
+# SCAN TESTS
+#
+max-time: 500
+cmd: testScan
+args: -n ScanRead16
+
+max-time: 500
+cmd: testScan
+args: -n ScanRead240
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadCommitted240
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdate
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdate2 T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanDelete
+
+max-time: 500
+cmd: testScan
+args: -n ScanDelete2 T10
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdateAndScanRead T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAndLocker T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAndPkRead T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanRead488 -l 10 T6
+
+max-time: 600
+cmd: testScan
+args: -n ScanRead40 -l 100 T2
+
+max-time: 1800
+cmd: testScan
+args: -n ScanRead100 -l 100 T1
+
+max-time: 600
+cmd: testScan
+args: -n ScanRead40 -l 100 T1
+
+max-time: 1800
+cmd: testScan
+args: -n ScanRead40RandomTable -l 100 T1
+
+max-time: 3600
+cmd: testScan
+args: -n ScanRead40RandomTable -l 1000 T2
+
+max-time: 500
+cmd: testScan
+args: -n ScanWithLocksAndInserts T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAbort T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAbort15 T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAbort240 T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdateAbort16 T6
+
+max-time: 3600
+cmd: testScan
+args: -n ScanReadRestart T1 T6 T13
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdateRestart T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckGetValue T6
+
+max-time: 500
+cmd: testScan
+args: -n CloseWithoutStop T6
+
+max-time: 500
+cmd: testScan
+args: -n NextScanWhenNoMore T6
+
+max-time: 500
+cmd: testScan
+args: -n ExecuteScanWithoutOpenScan T6
+
+max-time: 500
+cmd: testScan
+args: -n OnlyOpenScanOnce T6
+
+max-time: 500
+cmd: testScan
+args: -n OnlyOneOpInScanTrans T6
+
+max-time: 500
+cmd: testScan
+args: -n OnlyOneOpBeforeOpenScan T6
+
+max-time: 500
+cmd: testScan
+args: -n OnlyOneScanPerTrans T6
+
+max-time: 500
+cmd: testScan
+args: -n NoCloseTransaction T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckInactivityTimeOut T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckInactivityBeforeClose T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckAfterTerror T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5021 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReaderror5022 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5023 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5024 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5025 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5030 T1
+
+# OLD FLEX
+max-time: 500
+cmd: flexBench
+args: -c 25 -t 10
+
+max-time: 500
+cmd: flexHammer
+args: -r 5 -t 32
+
+#
+# DICT TESTS
+max-time: 1500
+cmd: testDict
+args: -n CreateAndDrop
+
+max-time: 1500
+cmd: testDict
+args: -n CreateAndDropWithData
+
+max-time: 1500
+cmd: testDict
+args: -n CreateAndDropDuring T6 T10
+
+max-time: 1500
+cmd: testDict
+args: -n CreateInvalidTables
+
+max-time: 1500
+cmd: testDict
+args: -n CreateTableWhenDbIsFull T6
+
+max-time: 1500
+cmd: testDict
+args: -n CreateMaxTables T6
+
+max-time: 500
+cmd: testDict
+args: -n FragmentTypeSingle T1
+
+max-time: 1500
+cmd: testDict
+args: -n FragmentTypeAll T1 T6 T7 T8
+
+max-time: 1500
+cmd: testDict
+args: -n FragmentTypeAllLarge T1 T6 T7 T8
+
+max-time: 1500
+cmd: testDict
+args: -n TemporaryTables T1 T6 T7 T8
+
+#
+# TEST NDBAPI
+#
+max-time: 500
+cmd: testDataBuffers
+args:
+
+# Testsuite: testNdbApi
+# Number of tests: 5
+max-time: 500
+cmd: testNdbApi
+args: -n MaxNdb T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n MaxTransactions T1 T6 T7 T8 T13
+
+max-time: 500
+cmd: testNdbApi
+args: -n MaxOperations T1 T6 T7 T8 T13
+
+max-time: 500
+cmd: testNdbApi
+args: -n MaxGetValue T1 T6 T7 T8 T13
+
+max-time: 500
+cmd: testNdbApi
+args: -n MaxEqual
+
+max-time: 500
+cmd: testNdbApi
+args: -n DeleteNdb T1 T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n WaitUntilReady T1 T6 T7 T8 T13
+
+max-time: 500
+cmd: testNdbApi
+args: -n GetOperationNoTab T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n NdbErrorOperation T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n MissingOperation T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n GetValueInUpdate T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n UpdateWithoutKeys T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n UpdateWithoutValues T6
+
+max-time: 500
+cmd: testInterpreter
+args: T1
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadRead
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertRead
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateRead
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteRead
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteDirtyRead
+
+max-time: 1500
+cmd: testRestartGci
+args: T6
+
diff --git a/ndb/test/run-test/main.cpp b/ndb/test/run-test/main.cpp
index eb8a626dc2b..9e318b0219e 100644
--- a/ndb/test/run-test/main.cpp
+++ b/ndb/test/run-test/main.cpp
@@ -30,35 +30,6 @@
#include <mgmapi.h>
#include "CpcClient.hpp"
-/**
- psuedo code for run-test.bin
-
- define autotest_wrapper process at each host
- start ndb-processes
-
- for each testcase
- do
- start mysqld processes
- start replication processes
- start test programs
-
- wait until test program finished or max time passed
-
- stop test program
- stop replication processes
- stop mysqld processes
-
- write report data-file
- if test failed and ! last test
- restart ndb processes
-
- drop all tables created by test
- done
-
- stop ndb processes
- undefined wrapper processes
-*/
-
/** Global variables */
static const char progname[] = "ndb_atrt";
static const char * g_gather_progname = "atrt-gather-result.sh";
@@ -75,6 +46,7 @@ static const char * g_report_filename = 0;
static const char * g_default_user = 0;
static const char * g_default_base_dir = 0;
static int g_default_base_port = 0;
+static int g_mysqld_use_base = 1;
static int g_report = 0;
static int g_verbosity = 0;
@@ -158,10 +130,17 @@ main(int argc, const char ** argv){
if(!start_processes(g_config, atrt_process::NDB_DB))
goto end;
-
- if(!wait_ndb(g_config, NDB_MGM_NODE_STATUS_STARTED))
- goto end;
-
+
+ if(!wait_ndb(g_config, NDB_MGM_NODE_STATUS_NOT_STARTED))
+ goto end;
+
+ for(Uint32 i = 0; i<3; i++)
+ if(wait_ndb(g_config, NDB_MGM_NODE_STATUS_STARTED))
+ goto started;
+
+ goto end;
+
+started:
g_logger.info("Ndb start completed");
}
@@ -347,7 +326,7 @@ parse_args(int argc, const char** argv){
return false;
}
- g_default_user = strdup(getenv("USER"));
+ g_default_user = strdup(getenv("LOGNAME"));
return true;
}
@@ -377,6 +356,8 @@ setup_config(atrt_config& config){
int lineno = 0;
char buf[2048];
+ BaseString connect_string;
+ int mysql_port_offset = 0;
while(fgets(buf, 2048, f)){
lineno++;
@@ -408,6 +389,11 @@ setup_config(atrt_config& config){
continue;
}
+ if(split1[0].trim() == "mysqld-use-base" && split1[1].trim() == "no"){
+ g_mysqld_use_base = 0;
+ continue;
+ }
+
Vector<BaseString> hosts;
if(split1[1].trim().split(hosts) <= 0){
g_logger.warning("Invalid line %d in %s - ignoring",
@@ -449,8 +435,10 @@ setup_config(atrt_config& config){
for(size_t i = 0; i<hosts.size(); i++){
BaseString & tmp = hosts[i];
atrt_host * host = find(tmp, config.m_hosts);
+ BaseString & dir = host->m_base_dir;
const int index = config.m_processes.size() + 1;
+
atrt_process proc;
proc.m_index = index;
proc.m_host = host;
@@ -458,8 +446,8 @@ setup_config(atrt_config& config){
proc.m_proc.m_type = "temporary";
proc.m_proc.m_owner = "atrt";
proc.m_proc.m_group = "group";
- proc.m_proc.m_cwd.assign(host->m_base_dir).append("/run/");
- proc.m_proc.m_env.assign("LD_LIBRARY_PATH=").append(host->m_base_dir).append("/lib");
+ proc.m_proc.m_cwd.assign(dir).append("/run/");
+ proc.m_proc.m_env.assfmt("LD_LIBRARY_PATH=%s/lib/mysql", dir.c_str());
proc.m_proc.m_stdout = "log.out";
proc.m_proc.m_stderr = "2>&1";
proc.m_proc.m_runas = proc.m_host->m_user;
@@ -468,16 +456,33 @@ setup_config(atrt_config& config){
proc.m_ndb_mgm_port = g_default_base_port;
if(split1[0] == "mgm"){
proc.m_type = atrt_process::NDB_MGM;
- proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_mgm");
- proc.m_proc.m_path.assign(host->m_base_dir).append("/bin/mgmtsrvr");
+ proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_mgmd");
+ proc.m_proc.m_path.assign(dir).append("/libexec/ndb_mgmd");
proc.m_proc.m_args = "-n -c initconfig.txt";
- proc.m_proc.m_cwd.appfmt("%d.ndb_mgm", index);
+ proc.m_proc.m_cwd.appfmt("%d.ndb_mgmd", index);
+ connect_string.appfmt(";host=%s:%d",
+ proc.m_hostname.c_str(), proc.m_ndb_mgm_port);
} else if(split1[0] == "ndb"){
proc.m_type = atrt_process::NDB_DB;
- proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_db");
- proc.m_proc.m_path.assign(host->m_base_dir).append("/bin/ndb");
+ proc.m_proc.m_name.assfmt("%d-%s", index, "ndbd");
+ proc.m_proc.m_path.assign(dir).append("/libexec/ndbd");
proc.m_proc.m_args = "-i -n";
- proc.m_proc.m_cwd.appfmt("%d.ndb_db", index);
+ proc.m_proc.m_cwd.appfmt("%d.ndbd", index);
+ } else if(split1[0] == "mysqld"){
+ proc.m_type = atrt_process::MYSQL_SERVER;
+ proc.m_proc.m_name.assfmt("%d-%s", index, "mysqld");
+ proc.m_proc.m_path.assign(dir).append("/libexec/mysqld");
+ proc.m_proc.m_args = "--core-file --ndbcluster";
+ proc.m_proc.m_cwd.appfmt("%d.mysqld", index);
+ if(mysql_port_offset > 0 || g_mysqld_use_base){
+ // setup mysql specific stuff
+ const char * basedir = proc.m_proc.m_cwd.c_str();
+ proc.m_proc.m_args.appfmt("--datadir=%s", basedir);
+ proc.m_proc.m_args.appfmt("--pid-file=%s/mysql.pid", basedir);
+ proc.m_proc.m_args.appfmt("--socket=%s/mysql.sock", basedir);
+ proc.m_proc.m_args.appfmt("--port=%d",
+ g_default_base_port-(++mysql_port_offset));
+ }
} else if(split1[0] == "api"){
proc.m_type = atrt_process::NDB_API;
proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_api");
@@ -494,7 +499,13 @@ setup_config(atrt_config& config){
config.m_processes.push_back(proc);
}
}
-
+
+ // Setup connect string
+ for(size_t i = 0; i<config.m_processes.size(); i++){
+ config.m_processes[i].m_proc.m_env.appfmt(" NDB_CONNECTSTRING=nodeid=%d%s",
+ i+1, connect_string.c_str());
+ }
+
end:
fclose(f);
return result;
@@ -622,6 +633,11 @@ wait_ndb(atrt_config& config, int goal){
g_logger.critical("Strange DB status during start: %d %d", i, min2);
return false;
}
+
+ if(min2 < min){
+ g_logger.critical("wait ndb failed node: %d %d %d %d",
+ state->node_states[i].node_id, min, min2, goal);
+ }
}
}
@@ -691,7 +707,7 @@ bool
start_processes(atrt_config& config, int types){
for(size_t i = 0; i<config.m_processes.size(); i++){
atrt_process & proc = config.m_processes[i];
- if((types & proc.m_type) != 0){
+ if((types & proc.m_type) != 0 && proc.m_proc.m_path != ""){
if(!start_process(proc)){
return false;
}
@@ -759,18 +775,24 @@ update_status(atrt_config& config, int){
for(size_t i = 0; i<config.m_processes.size(); i++){
atrt_process & proc = config.m_processes[i];
- Vector<SimpleCpcClient::Process> & h_procs = m_procs[proc.m_host->m_index];
- bool found = false;
- for(size_t j = 0; j<h_procs.size(); j++){
- if(proc.m_proc.m_id == h_procs[j].m_id){
- found = true;
- proc.m_proc.m_status = h_procs[j].m_status;
- break;
+ if(proc.m_proc.m_id != -1){
+ Vector<SimpleCpcClient::Process> &h_procs= m_procs[proc.m_host->m_index];
+ bool found = false;
+ for(size_t j = 0; j<h_procs.size(); j++){
+ if(proc.m_proc.m_id == h_procs[j].m_id){
+ found = true;
+ proc.m_proc.m_status = h_procs[j].m_status;
+ break;
+ }
+ }
+ if(!found){
+ g_logger.error("update_status: not found");
+ g_logger.error("id: %d host: %s cmd: %s",
+ proc.m_proc.m_id,
+ proc.m_hostname.c_str(),
+ proc.m_proc.m_path.c_str());
+ return false;
}
- }
- if(!found){
- g_logger.error("update_status: not found");
- return false;
}
}
return true;
@@ -877,16 +899,24 @@ setup_test_case(atrt_config& config, const atrt_testcase& tc){
return false;
}
- for(size_t i = 0; i<config.m_processes.size(); i++){
+ size_t i = 0;
+ for(; i<config.m_processes.size(); i++){
atrt_process & proc = config.m_processes[i];
if(proc.m_type == atrt_process::NDB_API){
- proc.m_proc.m_path.assign(proc.m_host->m_base_dir).append("/bin/").append(tc.m_command);
+ proc.m_proc.m_path.assfmt("%s/bin/%s", proc.m_host->m_base_dir.c_str(),
+ tc.m_command.c_str());
proc.m_proc.m_args.assign(tc.m_args);
- return true;
+ break;
}
}
-
- return false;
+ for(i++; i<config.m_processes.size(); i++){
+ atrt_process & proc = config.m_processes[i];
+ if(proc.m_type == atrt_process::NDB_API){
+ proc.m_proc.m_path.assign("");
+ proc.m_proc.m_args.assign("");
+ }
+ }
+ return true;
}
bool
diff --git a/ndb/test/run-test/make-html-reports.sh b/ndb/test/run-test/make-html-reports.sh
index 079650a729f..89f13a4b62a 100755
--- a/ndb/test/run-test/make-html-reports.sh
+++ b/ndb/test/run-test/make-html-reports.sh
@@ -1,106 +1,23 @@
#!/bin/sh
-# NAME
-# make-html-reports.sh
-#
-# SYNOPSIS
-# make-html-reports.sh [-q] [ -R <YYYY-MM-DD> ] [ -s <src dir> ] [ -d <dst dir> ] [ -c <conf dir> ]
-#
-# DESCRIPTION
-#
-# OPTIONS
-#
-# EXAMPLES
-#
-#
-# ENVIRONMENT
-# NDB_PROJ_HOME Home dir for ndb
-#
-# FILES
-# $NDB_PROJ_HOME/lib/funcs.sh general shell script functions
-#
-#
-# SEE ALSO
-#
-# DIAGNOSTICTS
-#
-# VERSION
-# 1.0
-#
-# AUTHOR
-# Jonas Oreland
-#
-
-progname=`basename $0`
-synopsis="make-html-reports.sh [ -R <YYYY-MM-DD> ] [ -s <src dir> ] [ -d <dst dir> ] [ -c <conf dir> ]"
-
-: ${NDB_PROJ_HOME:?} # If undefined, exit with error message
-
-: ${NDB_LOCAL_BUILD_OPTIONS:=--} # If undef, set to --. Keeps getopts happy.
- # You may have to experiment a bit
- # to get quoting right (if you need it).
-
-
-. $NDB_PROJ_HOME/lib/funcs.sh # Load some good stuff
-
-# defaults for options related variables
-#
-
-
-src_dir=`pwd`
-dst_dir=`pwd`
-conf_dir=`pwd`
-report_date=`date '+%Y-%m-%d'`
-uniq_id=$$.$$
-verbose=yes
-
-# used if error when parsing the options environment variable
-#
-env_opterr="options environment variable: <<$options>>"
-
-# Option parsing, for the options variable as well as the command line.
-#
-# We want to be able to set options in an environment variable,
-# as well as on the command line. In order not to have to repeat
-# the same getopts information twice, we loop two times over the
-# getopts while loop. The first time, we process options from
-# the options environment variable, the second time we process
-# options from the command line.
-#
-# The things to change are the actual options and what they do.
-#
-#
-
-for optstring in "$options" "" # 1. options variable 2. cmd line
-do
-
- while getopts q:s:R:d:c: i $optstring # optstring empty => no arg => cmd line
- do
- case $i in
-
- q) verbose="";; # echo important things
- d) dst_dir=$OPTARG;; # Destination directory
- s) src_dir=$OPTARG;; # Destination directory
- c) conf_dir=$OPTARG;; #
- R) report_date=$OPTARG;; #
- \?) syndie $env_opterr;; # print synopsis and exit
-
- esac
- done
-
- [ -n "$optstring" ] && OPTIND=1 # Reset for round 2, cmdline options
- env_opterr= # Round 2 should not use the value
+src_dir=$1
+run=$2
+date=$3
+src_file=$src_dir/report.txt
-done
-shift `expr $OPTIND - 1`
-
-src_dir=`abspath $src_dir`
-dst_dir=`abspath $dst_dir`
-conf_dir=`abspath $conf_dir`
+if [ ! -f $src_dir/report.txt ]
+then
+ echo "$src_dir/report.txt is missing"
+ exit 1
+fi
###
#
# General html functions
+trim(){
+ echo $*
+}
+
header(){
cat <<EOF
<html><head><title>$*</title></head>
@@ -166,64 +83,7 @@ hr(){
EOF
}
-# --- option parsing done ---
-
# -- Verify
-trace "Verifying arguments"
-summary_file=$src_dir/reports/summary.$report_date
-
-if [ ! -r $summary_file ]
-then
- syndie "Invalid src directory or report date: $summary_file not found"
-fi
-
-if [ ! -d $conf_dir/configurations ]
-then
- syndie "Invalid src directory: $conf_dir/configurations not found"
-fi
-
-if [ ! -d $conf_dir/testcases ]
-then
- syndie "Invalid src directory: $conf_dir/testcases not found"
-fi
-
-if [ ! -d $dst_dir ]
-then
- syndie "Invalid dst dir..."
-fi
-
-# --- option verifying done ---
-
-trace "src_dir: $src_dir"
-trace "dst_dir: $dst_dir"
-trace "conf_dir: $conf_dir"
-trace "report date: $report_date"
-
-###
-config_spec(){
- cat <<EOF
-<a href=#$1>$1</a>
-EOF
-}
-
-config_spec_include(){
- # Print the $1 file to the file we are generating
- cat <<EOF
-<a name=$1><pre>
-EOF
- if [ -r $conf_dir/configurations/$1 ]
- then
- cat -E $conf_dir/configurations/$1 | sed 's/\$/<BR>/g'
- else
- cat <<EOF
- Config spec $1 not found
-EOF
- fi
-cat <<EOF
-</pre></a>
-EOF
-}
-
time_spec(){
# $1 - secs
_ts_tmp=$1
@@ -232,8 +92,14 @@ time_spec(){
_ts_tmp=`expr $_ts_tmp / 60`
_ts_m=`expr $_ts_tmp % 60`
- _ts_tmp=`expr $_ts_tmp / 60`
+ if [ $_ts_tmp -ge 60 ]
+ then
+ _ts_tmp=`expr $_ts_tmp / 60`
+ else
+ _ts_tmp=0
+ fi
+ a=3
_ts_h=$_ts_tmp
if [ $_ts_h -gt 0 ]
@@ -247,191 +113,77 @@ time_spec(){
echo $ret
}
-log_spec(){
- _ff_=$src_dir/log/$report_date/$1.$2/test.$3.out
- if [ -r $_ff_ ] && [ -s $_ff_ ]
- then
- _f2_=$dst_dir/log.$report_date.$1.$2.$3.out.gz
- if [ -r $_f2_ ]
- then
- rm $_f2_
- fi
- cp $_ff_ $dst_dir/log.$report_date.$1.$2.$3.out
- gzip $dst_dir/log.$report_date.$1.$2.$3.out
- rm -f $dst_dir/log.$report_date.$1.$2.$3.out
- echo "<a href=log.$report_date.$1.$2.$3.out.gz>Log file</a>"
- else
- echo "-"
- fi
-}
+### Main
-err_spec(){
- _ff_=$src_dir/log/$report_date/$1.$2/test.$3.err.tar
- if [ -r $_ff_ ] && [ -s $_ff_ ]
- then
- cp $_ff_ $dst_dir/err.$report_date.$1.$2.$3.err.tar
- gzip $dst_dir/err.$report_date.$1.$2.$3.err.tar
- rm -f $dst_dir/err.$report_date.$1.$2.$3.err.tar
- echo "<a href=err.$report_date.$1.$2.$3.err.tar.gz>Error tarball</a>"
- else
- echo "-"
- fi
-}
+report_file=$src_dir/report.html
+summary_file=$src_dir/summary.html
-command_spec(){
- echo $* | sed 's/;/<BR>/g'
-}
+passed=0
+failed=0
+total=0
-### Main
+pass(){
+ passed=`expr $passed + 1`
+}
-html_summary_file=$dst_dir/summary.$report_date.html
+fail(){
+ failed=`expr $failed + 1`
+}
-trace "Creating summary"
(
- eval `grep "TOTAL" $summary_file | awk -F";" '{ printf("test_file=\"%s\"; elapsed=\"%s\"; started=\"%s\"; stopped=\"%s\"", $2, $3, $4, $5); }'`
-
- header "Autotest summary $report_date"
- heading 1 "Autotest summary $report_date"
- table
- row ; column `bold test file: `; column $test_file ; end_row
- row ; column `bold Started:` ; column "$started "; end_row
- row ; column `bold Stopped:` ; column "$stopped "; end_row
- row ; column `bold Elapsed:` ; column "`time_spec $elapsed secs`" ; end_row
- end_table
- hr
-
- table "border=1"
- row
- c_column `bold Report`
- c_column `bold Tag`
- c_column `bold Version`
- c_column `bold Distr-Config`
- c_column `bold Db-Config`
- c_column `bold Type`
- c_column `bold Test file`
- c_column `bold Make`
- c_column `bold Config`
- c_column `bold Test time`
- c_column `bold Passed`
- c_column `bold Failed`
- end_row
-
- grep -v "^#" $summary_file | grep -v TOTAL | sed 's/;/ /g' | \
- while read tag version config template type test_file make_res make_time conf_res conf_time test_time passed failed
- do
+ header Report $run $date
+ table "border=1"
row
- if [ -r $src_dir/reports/report.$tag.$version.$config.$template.$type.$test_file.$report_date ]
- then
- column "<a href=\"report.$tag.$version.$config.$template.$type.$test_file.$report_date.html\">report</a>"
- else
- column "-"
- fi
-
- column $tag
- column $version
- column $config
- column $template
- column $type
- column $test_file
- column "$make_res(`time_spec $make_time`)"
- column "$conf_res(`time_spec $conf_time`)"
- c_column "`time_spec $test_time`"
- c_column `bold $passed`
- c_column `bold $failed`
+ column `bold Test case`
+ column `bold Result`
+ column `bold Elapsed`
+ column `bold Log`
end_row
- done
- end_table
+) > $report_file
- footer
-) > $html_summary_file
-
-for i in $src_dir/reports/report.*.$report_date
+cat $src_file | while read line
do
- f=`basename $i`
- trace "Creating report: $f"
- eval `echo $f | awk -F"." '{printf("tag=%s;version=%s;config=%s;template=%s;type=%s;test_file=%s", $2, $3, $4, $5, $6, $7);}'`
-
- (
- header "Autotest report $report_date"
- heading 1 "Autotest report $report_date"
- table #"border=1"
- row ; column `bold Tag:`; column $tag ; end_row
- row ; column `bold Version:` ; column $version ; end_row
- row ; column `bold Configuration:` ; column `config_spec $config`; end_row
- row ; column `bold Template:` ; column `config_spec $template`; end_row
- row ; column `bold Type:` ; column $type ; end_row
- row ; column `bold Test file:` ; column $test_file; end_row
- end_table
- hr
-
- table "border=1"
- row
- c_column `bold Test case`
- c_column `bold Result`
- c_column `bold Test time`
- c_column `bold Logfile`
- c_column `bold Error tarfile`
- end_row
-
- grep -v "^#" $i | sed 's/;/ /g' | \
- while read test_no test_res test_time cmd
- do
- row
- column "`command_spec $cmd`"
- case "$test_res" in
- 0)
- column "PASSED";;
- 1001)
- column "API error";;
- 1002)
- column "Max time expired";;
- 1003)
- column "Mgm port busy";;
- *)
- column "Unknown: $test_res";;
- esac
-
- column "`time_spec $test_time`"
-
- column "`log_spec $tag $version $test_no`"
- column "`err_spec $tag $version $test_no`"
- end_row
- done
- end_table
-
- # Last on page we include spec
- # of used machines and template for config
- # for future reference
- hr
- table "border=1"
- row; column `bold Configuration:` $config; end_row
- row; column `config_spec_include $config`; end_row
- end_table
- hr
- table "border=1"
- row; column `bold Template:` $template; end_row
- row; column `config_spec_include $template`; end_row
- end_table
-
- footer
-
- ) > $dst_dir/$f.html
+ eval `echo $line | awk -F";" '{ printf("prg=\"%s\"; no=\"%s\"; res=\"%s\"; time=\"%s\"", $1, $2, $3, $4); }'`
+
+ prg=`trim $prg`
+ no=`trim $no`
+ res=`trim $res`
+ time=`trim $time`
+ res_dir="<a href=\"result.$no/\">log</a>"
+
+ ts=`time_spec $time`
+ res_txt=""
+ case $res in
+ 0) pass; res_txt="PASSED"; res_dir="&nbsp;";;
+ *) fail; res_txt="FAILED";;
+ esac
+ total=`expr $total + $time`
+
+ (
+ row
+ column $prg
+ column $res_txt
+ column $ts
+ column $res_dir
+ end_row
+ ) >> $report_file
+
+ (
+ row
+ column $run
+ column $date
+ column $passed
+ column $failed
+ column `time_spec $total`
+ column "<a href=\"result-$run/$date/report.html\">report</a>"
+ column "<a href=\"result-$run/$date/log.txt\">log.txt</a>"
+ end_row
+ ) > $summary_file
done
-# Re creating index
-trace "Recreating index"
(
- header "Autotest super-duper index"
- heading 1 "<center>Autotest super-duper index</center>"
- hr
- for i in `ls $dst_dir/summary.*.html | sort -r -n`
- do
- f=`basename $i`
- cat <<EOF
-<p><a href=$f>$f</a></p>
-EOF
- done
- footer
-) > $dst_dir/index.html
+ end_table
+ footer
+) >> $report_file
exit 0
diff --git a/ndb/test/src/Makefile b/ndb/test/src/Makefile
deleted file mode 100644
index 2b634bcd3cd..00000000000
--- a/ndb/test/src/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapitest
-
-ARCHIVE_TARGET := NDBT
-
-SOURCES = NDBT_ReturnCodes.cpp \
- NDBT_Error.cpp NDBT_Tables.cpp NDBT_ResultRow.cpp \
- NDBT_Test.cpp HugoCalculator.cpp \
- HugoOperations.cpp HugoTransactions.cpp \
- HugoAsynchTransactions.cpp UtilTransactions.cpp \
- NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \
- NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp
-
-SOURCES.c =
-
-CFLAGS_NdbRestarter.cpp := -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
-CFLAGS_NdbBackup.cpp := -I$(call fixpath,$(NDB_TOP)/include/mgmcommon)
-CFLAGS_NdbConfig.cpp := -I$(call fixpath,$(NDB_TOP)/include/mgmcommon)
-CFLAGS_NdbRestarts.cpp := -I$(call fixpath,$(NDB_TOP)/include/kernel)
-CFLAGS_NdbBackup.cpp += -I$(call fixpath,$(NDB_TOP)/include/kernel)
-CFLAGS_NdbGrep.cpp += -I$(call fixpath,$(NDB_TOP)/include/kernel) -I$(call fixpath,$(NDB_TOP)/include/mgmcommon)
-
-include $(NDB_TOP)/Epilogue.mk
-
-
-
-
-
-
-
diff --git a/ndb/test/src/Makefile.am b/ndb/test/src/Makefile.am
new file mode 100644
index 00000000000..a513086dc33
--- /dev/null
+++ b/ndb/test/src/Makefile.am
@@ -0,0 +1,20 @@
+
+noinst_LIBRARIES = libNDBT.a
+
+libNDBT_a_SOURCES = \
+ NDBT_ReturnCodes.cpp \
+ NDBT_Error.cpp NDBT_Tables.cpp NDBT_ResultRow.cpp \
+ NDBT_Test.cpp HugoCalculator.cpp \
+ HugoOperations.cpp HugoTransactions.cpp \
+ HugoAsynchTransactions.cpp UtilTransactions.cpp \
+ NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \
+ NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp \
+ NdbSchemaCon.cpp NdbSchemaOp.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/common/mgmcommon -I$(top_srcdir)/ndb/include/mgmcommon -I$(top_srcdir)/ndb/include/kernel -I$(top_srcdir)/ndb/src/mgmapi
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/test/src/Makefile_old b/ndb/test/src/Makefile_old
new file mode 100644
index 00000000000..2738ce1aba2
--- /dev/null
+++ b/ndb/test/src/Makefile_old
@@ -0,0 +1,33 @@
+include .defs.mk
+
+TYPE := ndbapitest
+
+ARCHIVE_TARGET := NDBT
+
+SOURCES = NDBT_ReturnCodes.cpp \
+ NDBT_Error.cpp NDBT_Tables.cpp NDBT_ResultRow.cpp \
+ NDBT_Test.cpp HugoCalculator.cpp \
+ HugoOperations.cpp HugoTransactions.cpp \
+ HugoAsynchTransactions.cpp UtilTransactions.cpp \
+ NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \
+ NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp
+
+SOURCES.c =
+
+CFLAGS_NdbRestarter.cpp := -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
+CFLAGS_NdbConfig.cpp := -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \
+ -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
+CFLAGS_NdbRestarts.cpp := -I$(call fixpath,$(NDB_TOP)/include/kernel)
+CFLAGS_NdbBackup.cpp := -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \
+ -I$(call fixpath,$(NDB_TOP)/src/mgmapi) \
+ -I$(call fixpath,$(NDB_TOP)/include/kernel)
+CFLAGS_NdbGrep.cpp += -I$(call fixpath,$(NDB_TOP)/include/kernel) -I$(call fixpath,$(NDB_TOP)/include/mgmcommon)
+
+include $(NDB_TOP)/Epilogue.mk
+
+
+
+
+
+
+
diff --git a/ndb/test/src/NDBT_ResultRow.cpp b/ndb/test/src/NDBT_ResultRow.cpp
index ba46be203e1..7c419444760 100644
--- a/ndb/test/src/NDBT_ResultRow.cpp
+++ b/ndb/test/src/NDBT_ResultRow.cpp
@@ -17,6 +17,7 @@
#include <ndb_global.h>
#include "NDBT_ResultRow.hpp"
#include <NdbOut.hpp>
+#include <NdbSchemaCon.hpp>
NDBT_ResultRow::NDBT_ResultRow(const NdbDictionary::Table& tab,
char attrib_delimiter)
@@ -111,77 +112,8 @@ BaseString NDBT_ResultRow::c_str() {
NdbOut &
operator << (NdbOut& ndbout, const NDBT_ResultRow & res) {
- for(int i = 0; i<res.cols; i++){
- if(res.data[i]->isNULL())
- ndbout << "NULL";
- else{
- const int size = res.data[i]->attrSize();
- const int aSize = res.data[i]->arraySize();
- switch(res.data[i]->attrType()){
- case UnSigned:
- switch(size){
- case 8:
- ndbout << res.data[i]->u_64_value();
- break;
- case 4:
- ndbout << res.data[i]->u_32_value();
- break;
- case 2:
- ndbout << res.data[i]->u_short_value();
- break;
- case 1:
- ndbout << (unsigned) res.data[i]->u_char_value();
- break;
- default:
- ndbout << "Unknown size";
- }
- break;
-
- case Signed:
- switch(size){
- case 8:
- ndbout << res.data[i]->int64_value();
- break;
- case 4:
- ndbout << res.data[i]->int32_value();
- break;
- case 2:
- ndbout << res.data[i]->short_value();
- break;
- case 1:
- ndbout << (int) res.data[i]->char_value();
- break;
- default:
- ndbout << "Unknown size";
- }
- break;
-
- case String:
- {
- char * buf = new char[aSize+1];
- memcpy(buf, res.data[i]->aRef(), aSize);
- buf[aSize] = 0;
- ndbout << buf;
- delete [] buf;
- // Null terminate string
- //res.data[i][res.sizes[i]] = 0;
- //ndbout << res.data[i];
- }
- break;
-
- case Float:
- ndbout_c("%f", res.data[i]->float_value());
- break;
-
- default:
- ndbout << "Unknown(" << res.data[i]->attrType() << ")";
- break;
- }
- }
- if (i < res.cols-1)
- ndbout << res.ad;
- }
-
+ for(int i = 0; i<res.cols; i++)
+ ndbout << *(res.data[i]) << "\t";
return ndbout;
}
diff --git a/ndb/test/src/NDBT_Table.cpp b/ndb/test/src/NDBT_Table.cpp
index c520b01c990..485377e690a 100644
--- a/ndb/test/src/NDBT_Table.cpp
+++ b/ndb/test/src/NDBT_Table.cpp
@@ -14,105 +14,35 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "NDBT_Table.hpp"
+#include <NDBT_Table.hpp>
#include <NdbTimer.hpp>
#include <NDBT.hpp>
-
class NdbOut&
operator <<(class NdbOut& ndbout, const NDBT_Attribute & attr){
NdbDictionary::Column::Type type = attr.getType();
- bool key = attr.getPrimaryKey();
- bool null = attr.getNullable();
- ndbout << attr.getName() << "\t";
- char tmp[100];
- if(attr.getLength() != 1)
- snprintf(tmp, 100," [%d]", attr.getLength());
- else
- tmp[0] = 0;
+ ndbout << attr.getName() << " " << type;
switch(type){
- case NdbDictionary::Column::Tinyint:
- ndbout << "Tinyint" << tmp;
- break;
- case NdbDictionary::Column::Tinyunsigned:
- ndbout << "Tinyunsigned" << tmp;
- break;
- case NdbDictionary::Column::Smallint:
- ndbout << "Smallint" << tmp;
- break;
- case NdbDictionary::Column::Smallunsigned:
- ndbout << "Smallunsigned" << tmp;
- break;
- case NdbDictionary::Column::Mediumint:
- ndbout << "Mediumint" << tmp;
- break;
- case NdbDictionary::Column::Mediumunsigned:
- ndbout << "Mediumunsigned" << tmp;
- break;
- case NdbDictionary::Column::Int:
- ndbout << "Int" << tmp;
- break;
- case NdbDictionary::Column::Unsigned:
- ndbout << "Unsigned" << tmp;
- break;
- case NdbDictionary::Column::Bigint:
- ndbout << "Bigint" << tmp;
- break;
- case NdbDictionary::Column::Bigunsigned:
- ndbout << "Bigunsigned" << tmp;
- break;
- case NdbDictionary::Column::Float:
- ndbout << "Float" << tmp;
- break;
- case NdbDictionary::Column::Double:
- ndbout << "Double" << tmp;
- break;
case NdbDictionary::Column::Decimal:
- ndbout << "Decimal("
- << attr.getScale() << ", " << attr.getPrecision() << ")"
- << tmp;
- break;
- case NdbDictionary::Column::Char:
- ndbout << "Char(" << attr.getLength() << ")";
- break;
- case NdbDictionary::Column::Varchar:
- ndbout << "Varchar(" << attr.getLength() << ")";
- break;
- case NdbDictionary::Column::Binary:
- ndbout << "Binary(" << attr.getLength() << ")";
- break;
- case NdbDictionary::Column::Varbinary:
- ndbout << "Varbinary(" << attr.getLength() << ")";
- break;
- case NdbDictionary::Column::Datetime:
- ndbout << "Datetime" << tmp;
- break;
- case NdbDictionary::Column::Timespec:
- ndbout << "Timespec" << tmp;
- break;
- case NdbDictionary::Column::Blob:
- ndbout << "Blob" << tmp;
- break;
- case NdbDictionary::Column::Undefined:
- ndbout << "Undefined" << tmp;
+ ndbout << "(" << attr.getScale() << ", " << attr.getPrecision() << ")";
break;
default:
- ndbout << "Unknown(" << type << ")";
+ break;
}
- ndbout << "\t";
- if(null){
- ndbout << "NULL";
- } else {
- ndbout << "NOT NULL";
- }
- ndbout << "\t";
+ if(attr.getLength() != 1)
+ ndbout << "[" << attr.getLength() << "]";
+
+ if(attr.getNullable())
+ ndbout << " NULL";
+ else
+ ndbout << " NOT NULL";
- if(key)
- ndbout << "\tprimary key";
+ if(attr.getPrimaryKey())
+ ndbout << " PRIMARY KEY";
return ndbout;
}
@@ -130,6 +60,9 @@ operator <<(class NdbOut& ndbout, const NDBT_Table & tab)
ndbout << "Temporary table: " << (tab.getStoredTable() ? "no" : "yes") << endl;
ndbout << "Number of attributes: " << tab.getNoOfColumns() << endl;
ndbout << "Number of primary keys: " << tab.getNoOfPrimaryKeys() << endl;
+ ndbout << "Length of frm data: " << tab.getFrmLength() << endl;
+
+
//<< ((tab.getTupleKey() == TupleId) ? " tupleid" : "") <<endl;
ndbout << "TableStatus: ";
switch(tab.getObjectStatus()){
@@ -154,3 +87,32 @@ operator <<(class NdbOut& ndbout, const NDBT_Table & tab)
return ndbout;
}
+
+class NdbOut& operator <<(class NdbOut&, const NdbDictionary::Index & idx)
+{
+ ndbout << idx.getName();
+ ndbout << "(";
+ for (unsigned i=0; i < idx.getNoOfColumns(); i++)
+ {
+ const NdbDictionary::Column *col = idx.getColumn(i);
+ ndbout << col->getName();
+ if (i < idx.getNoOfColumns()-1)
+ ndbout << ", ";
+ }
+ ndbout << ")";
+
+ ndbout << " - ";
+ switch (idx.getType()) {
+ case NdbDictionary::Object::UniqueHashIndex:
+ ndbout << "UniqueHashIndex";
+ break;
+ case NdbDictionary::Object::OrderedIndex:
+ ndbout << "OrderedIndex";
+ break;
+ default:
+ ndbout << "Type " << idx.getType();
+ break;
+ }
+ return ndbout;
+}
+
diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp
index 6cbb69508f5..169034e0c07 100644
--- a/ndb/test/src/NdbBackup.cpp
+++ b/ndb/test/src/NdbBackup.cpp
@@ -19,7 +19,6 @@
#include <NdbOut.hpp>
#include <NDBT_Output.hpp>
#include <NdbConfig.h>
-#include <ConfigRetriever.hpp>
#include <ndb_version.h>
#include <NDBT.hpp>
#include <NdbSleep.h>
@@ -32,6 +31,10 @@
<< " (Line: " << __LINE__ << ")" << "- " << _xx << endl; \
return NDBT_FAILED; } }
+#include <ConfigRetriever.hpp>
+#include <mgmapi.h>
+#include <mgmapi_config_parameters.h>
+#include <mgmapi_configuration.hpp>
int
NdbBackup::start(unsigned int & _backup_id){
@@ -68,16 +71,12 @@ NdbBackup::getFileSystemPathForNode(int _node_id){
*/
ConfigRetriever cr;
-
- Properties * p = cr.getConfig(host,
- port,
- _node_id,
- NDB_VERSION);
+ ndb_mgm_configuration * p = cr.getConfig(host, port, 0);
if(p == 0){
const char * s = cr.getErrorString();
if(s == 0)
s = "No error given!";
-
+
ndbout << "Could not fetch configuration" << endl;
ndbout << s << endl;
return NULL;
@@ -86,19 +85,20 @@ NdbBackup::getFileSystemPathForNode(int _node_id){
/**
* Setup cluster configuration data
*/
- const Properties * db = 0;
- if (!p->get("Node", _node_id, &db)) {
+ ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE);
+ if (iter.find(CFG_NODE_ID, _node_id)){
ndbout << "Invalid configuration fetched, DB missing" << endl;
return NULL;
}
- const char * type;
- if(!(db->get("Type", &type) && strcmp(type, "DB") == 0)){
+ unsigned int type = 123456;
+ if(iter.get(CFG_TYPE_OF_SECTION, &type) || type != NODE_TYPE_DB){
+ ndbout <<"type = " << type << endl;
ndbout <<"Invalid configuration fetched, I'm wrong type of node" << endl;
return NULL;
}
-
+
const char * path;
- if (!db->get("FileSystemPath", &path)){
+ if (iter.get(CFG_DB_FILESYSTEM_PATH, &path)){
ndbout << "FileSystemPath not found" << endl;
return NULL;
}
@@ -115,10 +115,13 @@ NdbBackup::execRestore(bool _restore_data,
const int buf_len = 1000;
char buf[buf_len];
+ ndbout << "getFileSystemPathForNode "<< _node_id <<endl;
+
const char* path = getFileSystemPathForNode(_node_id);
if (path == NULL)
return -1;
+ ndbout << "getHostName "<< _node_id <<endl;
const char *host;
if (!getHostName(_node_id, &host)){
return -1;
@@ -139,7 +142,7 @@ NdbBackup::execRestore(bool _restore_data,
ndbout << "res: " << res << endl;
#if 0
- snprintf(buf, 255, "restore -c \"nodeid=%d;host=%s\" -n %d -b %d %s %s %s/BACKUP/BACKUP-%d",
+ snprintf(buf, 255, "ndb_restore -c \"nodeid=%d;host=%s\" -n %d -b %d %s %s %s/BACKUP/BACKUP-%d",
ownNodeId,
addr,
_node_id,
@@ -151,7 +154,7 @@ NdbBackup::execRestore(bool _restore_data,
#endif
- snprintf(buf, 255, "restore -c \"nodeid=%d;host=%s\" -n %d -b %d %s %s .",
+ snprintf(buf, 255, "ndb_restore -c \"nodeid=%d;host=%s\" -n %d -b %d %s %s .",
ownNodeId,
addr,
_node_id,
diff --git a/ndb/test/src/NdbConfig.cpp b/ndb/test/src/NdbConfig.cpp
index 3a254bc1577..2fb466d1b8f 100644
--- a/ndb/test/src/NdbConfig.cpp
+++ b/ndb/test/src/NdbConfig.cpp
@@ -17,144 +17,67 @@
#include "NdbConfig.hpp"
#include <NdbOut.hpp>
#include <NDBT_Output.hpp>
+#include <assert.h>
#include <NdbConfig.h>
#include <ConfigRetriever.hpp>
#include <ndb_version.h>
-
-
+#include <mgmapi.h>
+#include <mgmapi_config_parameters.h>
+#include <mgmapi_configuration.hpp>
bool
-NdbConfig::getPropsForNode(unsigned int node_id,
- const char* type,
- const Properties ** props) const {
-
- /**
- * Fetch configuration from management server
- */
- ConfigRetriever cr;
-
-
- Properties * p = cr.getConfig(host,
- port,
- node_id,
- NDB_VERSION);
+NdbConfig::getHostName(unsigned int node_id, const char ** hostname) {
+
+ ndb_mgm_configuration * p = getConfig();
if(p == 0){
- const char * s = cr.getErrorString();
- if(s == 0)
- s = "No error given!";
-
- ndbout << "Could not fetch configuration" << endl;
- ndbout << s << endl;
return false;
- }
+ }
/**
* Setup cluster configuration data
*/
- if (!p->get("Node", node_id, props)) {
- ndbout << "Invalid configuration fetched no info for nodeId = "
- << node_id << endl;
+ ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE);
+ if (iter.find(CFG_NODE_ID, node_id)){
+ ndbout << "Invalid configuration fetched, DB missing" << endl;
return false;
}
- const char * str;
- if(!((*props)->get("Type", &str) && strcmp(str, type) == 0)){
- ndbout <<"Invalid configuration fetched, type != " << type << endl;
- return false;
- }
- return true;
-}
-
-bool
-NdbConfig::getProperty(unsigned int node_id,
- const char* type,
- const char* name,
- const char ** value) const {
- const Properties * db = 0;
-
- if(!getPropsForNode(node_id, type, &db)){
+ if (iter.get(CFG_NODE_HOST, hostname)){
+ ndbout << "Host not found" << endl;
return false;
}
- if (!db->get(name, value)){
- ndbout << name << " not found" << endl;
- return false;
- }
-
return true;
}
bool
-NdbConfig::getProperty(unsigned int node_id,
- const char* type,
- const char* name,
- Uint32 * value) const {
- const Properties * db = 0;
-
- if(!getPropsForNode(node_id, type, &db)){
- return false;
- }
-
- if (!db->get(name, value)){
- ndbout << name << " not found" << endl;
- return false;
- }
-
- return true;
-}
-
-
-bool
-NdbConfig::getHostName(unsigned int node_id,
- const char ** hostname) const {
- /**
- * Fetch configuration from management server
- */
- ConfigRetriever cr;
-
-
- Properties * p = cr.getConfig(host,
- port,
- node_id,
- NDB_VERSION);
+NdbConfig::getProperty(unsigned nodeid,
+ unsigned type, unsigned key, Uint32 * val){
+ ndb_mgm_configuration * p = getConfig();
if(p == 0){
- const char * s = cr.getErrorString();
- if(s == 0)
- s = "No error given!";
-
- ndbout << "Could not fetch configuration" << endl;
- ndbout << s << endl;
return false;
- }
+ }
/**
* Setup cluster configuration data
*/
- const Properties * node_props;
- if (!p->get("Node", node_id, &node_props)) {
- ndbout << "Invalid configuration fetched no info for node = "
- << node_id << endl;
- return false;
- }
- const char* computer_id_str;
- if (!node_props->get("ExecuteOnComputer", &computer_id_str)){
- ndbout << "ExecuteOnComputer not found" << endl;
+ ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE);
+ if (iter.find(CFG_NODE_ID, nodeid)){
+ ndbout << "Invalid configuration fetched, DB missing" << endl;
return false;
}
-
- const Properties * comp_props;
- if (!p->get("Computer", atoi(computer_id_str), &comp_props)) {
- ndbout << "Invalid configuration fetched no info for computer = "
- << node_id << endl;
+ unsigned _type;
+ if (iter.get(CFG_TYPE_OF_SECTION, &_type) || type != _type){
+ ndbout << "No such node in configuration" << endl;
return false;
}
- if (!comp_props->get("HostName", hostname)){
- ndbout << "HostName not found" << endl;
+
+ if (iter.get(key, val)){
+ ndbout << "No such key: " << key << " in configuration" << endl;
return false;
}
-
-
+
return true;
}
diff --git a/ndb/test/src/NdbRestarter.cpp b/ndb/test/src/NdbRestarter.cpp
index cc2fab46cc5..b731cccb259 100644
--- a/ndb/test/src/NdbRestarter.cpp
+++ b/ndb/test/src/NdbRestarter.cpp
@@ -36,7 +36,8 @@ NdbRestarter::NdbRestarter(const char* _addr):
addr(_addr),
host(NULL),
port(-1),
- handle(NULL)
+ handle(NULL),
+ m_config(0)
{
if (addr == NULL){
LocalConfig lcfg;
@@ -661,3 +662,13 @@ int NdbRestarter::exitSingleUserMode(){
}
return reply.return_code;
}
+
+ndb_mgm_configuration*
+NdbRestarter::getConfig(){
+ if(m_config) return m_config;
+
+ if (!isConnected())
+ return 0;
+ m_config = ndb_mgm_get_configuration(handle, 0);
+ return m_config;
+}
diff --git a/ndb/test/src/NdbSchemaCon.cpp b/ndb/test/src/NdbSchemaCon.cpp
new file mode 100644
index 00000000000..0de49ff983f
--- /dev/null
+++ b/ndb/test/src/NdbSchemaCon.cpp
@@ -0,0 +1,169 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+
+/*********************************************************************
+Name: NdbSchemaCon.cpp
+Include:
+Link:
+Author: UABMNST Mona Natterkvist UAB/B/SD
+ EMIKRON Mikael Ronstrom
+Date: 020826
+Version: 3.0
+Description: Old Interface between application and NDB
+Documentation:
+Adjust: 980126 UABMNST First version.
+ 020826 EMIKRON New version adapted to new DICT version
+ 040524 Magnus Svensson - Adapted to not be included in public NdbApi
+ unless the user wants to use it.
+
+ NOTE: This file is only used as a compatibility layer for old test programs,
+ New programs should use NdbDictionary.hpp
+*********************************************************************/
+
+#include <ndb_global.h>
+#include <NdbApi.hpp>
+#include <NdbSchemaCon.hpp>
+#include <NdbSchemaOp.hpp>
+
+
+/*********************************************************************
+NdbSchemaCon(Ndb* aNdb);
+
+Parameters: aNdb: Pointers to the Ndb object
+Remark: Creates a schemacon object.
+************************************************************************************************/
+NdbSchemaCon::NdbSchemaCon( Ndb* aNdb ) :
+ theNdb(aNdb),
+ theFirstSchemaOpInList(NULL),
+ theMagicNumber(0x75318642)
+{
+ theError.code = 0;
+}//NdbSchemaCon::NdbSchemaCon()
+
+/*********************************************************************
+~NdbSchemaCon();
+
+Remark: Deletes the connection object.
+************************************************************************************************/
+NdbSchemaCon::~NdbSchemaCon()
+{
+}//NdbSchemaCon::~NdbSchemaCon()
+
+/*********************************************************************
+NdbSchemaOp* getNdbSchemaOp();
+
+Return Value Return a pointer to a NdbSchemaOp object if getNdbSchemaOp was sussesful.
+ Return NULL: In all other case.
+Parameters: tableId : Id of the database table beeing deleted.
+************************************************************************************************/
+NdbSchemaOp*
+NdbSchemaCon::getNdbSchemaOp()
+{
+ NdbSchemaOp* tSchemaOp;
+ if (theFirstSchemaOpInList != NULL) {
+ theError.code = 4401; // Only support one add table per transaction
+ return NULL;
+ }//if
+ tSchemaOp = new NdbSchemaOp(theNdb);
+ if ( tSchemaOp == NULL ) {
+ theError.code = 4000; // Could not allocate schema operation
+ return NULL;
+ }//if
+ theFirstSchemaOpInList = tSchemaOp;
+ int retValue = tSchemaOp->init(this);
+ if (retValue == -1) {
+ release();
+ theError.code = 4000; // Could not allocate buffer in schema operation
+ return NULL;
+ }//if
+ return tSchemaOp;
+}//NdbSchemaCon::getNdbSchemaOp()
+
+/*********************************************************************
+int execute();
+
+Return Value: Return 0 : execute was successful.
+ Return -1: In all other case.
+Parameters : aTypeOfExec: Type of execute.
+Remark: Initialise connection object for new transaction.
+************************************************************************************************/
+int
+NdbSchemaCon::execute()
+{
+ if(theError.code != 0) {
+ return -1;
+ }//if
+
+ NdbSchemaOp* tSchemaOp;
+
+ tSchemaOp = theFirstSchemaOpInList;
+ if (tSchemaOp == NULL) {
+ theError.code = 4402;
+ return -1;
+ }//if
+
+ if ((tSchemaOp->sendRec() == -1) || (theError.code != 0)) {
+ // Error Code already set in other place
+ return -1;
+ }//if
+
+ return 0;
+}//NdbSchemaCon::execute()
+
+/*********************************************************************
+void release();
+
+Remark: Release all schemaop.
+************************************************************************************************/
+void
+NdbSchemaCon::release()
+{
+ NdbSchemaOp* tSchemaOp;
+ tSchemaOp = theFirstSchemaOpInList;
+ if (tSchemaOp != NULL) {
+ tSchemaOp->release();
+ delete tSchemaOp;
+ }//if
+ theFirstSchemaOpInList = NULL;
+ return;
+}//NdbSchemaCon::release()
+
+#include <NdbError.hpp>
+
+static void
+update(const NdbError & _err){
+ NdbError & error = (NdbError &) _err;
+ ndberror_struct ndberror = (ndberror_struct)error;
+ ndberror_update(&ndberror);
+ error = NdbError(ndberror);
+}
+
+const
+NdbError &
+NdbSchemaCon::getNdbError() const {
+ update(theError);
+ return theError;
+}
+
+
+
+
+
+
+
+
diff --git a/ndb/test/src/NdbSchemaOp.cpp b/ndb/test/src/NdbSchemaOp.cpp
new file mode 100644
index 00000000000..a296094ea9d
--- /dev/null
+++ b/ndb/test/src/NdbSchemaOp.cpp
@@ -0,0 +1,220 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/*****************************************************************************
+Name: NdbSchemaOp.cpp
+Include:
+Link:
+Author: UABMNST Mona Natterkvist UAB/B/SD
+ EMIKRON Mikael Ronstrom
+Date: 040524
+Version: 3.0
+Description: Interface between application and NDB
+Documentation: Handles createTable and createAttribute calls
+
+Adjust: 980125 UABMNST First version.
+ 020826 EMIKRON New version for new DICT
+ 040524 Magnus Svensson - Adapted to not be included in public NdbApi
+ unless the user wants to use it.
+
+ NOTE: This file is only used as a compatibility layer for old test programs,
+ New programs should use NdbDictionary.hpp
+*****************************************************************************/
+
+#include <ndb_global.h>
+#include <NdbApi.hpp>
+#include <NdbSchemaOp.hpp>
+#include <NdbSchemaCon.hpp>
+
+
+/*****************************************************************************
+NdbSchemaOp(Ndb* aNdb, Table* aTable);
+
+Return Value: None
+Parameters: aNdb: Pointers to the Ndb object.
+ aTable: Pointers to the Table object
+Remark: Creat an object of NdbSchemaOp.
+*****************************************************************************/
+NdbSchemaOp::NdbSchemaOp(Ndb* aNdb) :
+ theNdb(aNdb),
+ theSchemaCon(NULL),
+ m_currentTable(NULL)
+{
+}//NdbSchemaOp::NdbSchemaOp()
+
+/*****************************************************************************
+~NdbSchemaOp();
+
+Remark: Delete tables for connection pointers (id).
+*****************************************************************************/
+NdbSchemaOp::~NdbSchemaOp( )
+{
+}//~NdbSchemaOp::NdbSchemaOp()
+
+/*****************************************************************************
+int createTable( const char* tableName )
+*****************************************************************************/
+int
+NdbSchemaOp::createTable(const char* aTableName,
+ Uint32 aTableSize,
+ KeyType aTupleKey,
+ int aNrOfPages,
+ FragmentType aFragmentType,
+ int aKValue,
+ int aMinLoadFactor,
+ int aMaxLoadFactor,
+ int aMemoryType,
+ bool aStoredTable)
+{
+ if(m_currentTable != 0){
+ return -1;
+ }
+
+ m_currentTable = new NdbDictionary::Table(aTableName);
+ m_currentTable->setKValue(aKValue);
+ m_currentTable->setMinLoadFactor(aMinLoadFactor);
+ m_currentTable->setMaxLoadFactor(aMaxLoadFactor);
+ m_currentTable->setLogging(aStoredTable);
+ m_currentTable->setFragmentType(NdbDictionary::Object::FragAllMedium);
+ return 0;
+}//NdbSchemaOp::createTable()
+
+/******************************************************************************
+int createAttribute( const char* anAttrName,
+ KeyType aTupleyKey,
+ int anAttrSize,
+ int anArraySize,
+ AttrType anAttrType,
+ SafeType aSafeType,
+ StorageMode aStorageMode,
+ int aNullAttr,
+ int aStorageAttr );
+
+******************************************************************************/
+int
+NdbSchemaOp::createAttribute( const char* anAttrName,
+ KeyType aTupleKey,
+ int anAttrSize,
+ int anArraySize,
+ AttrType anAttrType,
+ StorageMode aStorageMode,
+ bool nullable,
+ StorageAttributeType aStorageAttr,
+ int aDistributionKeyFlag,
+ int aDistributionGroupFlag,
+ int aDistributionGroupNoOfBits,
+ bool aAutoIncrement,
+ const char* aDefaultValue)
+{
+ if (m_currentTable == 0){
+ return -1;
+ }//if
+
+ NdbDictionary::Column col(anAttrName);
+ switch(anAttrType){
+ case Signed:
+ if(anAttrSize == 64)
+ col.setType(NdbDictionary::Column::Bigint);
+ else
+ col.setType(NdbDictionary::Column::Int);
+ break;
+ case UnSigned:
+ if(anAttrSize == 64)
+ col.setType(NdbDictionary::Column::Bigunsigned);
+ else
+ col.setType(NdbDictionary::Column::Unsigned);
+ break;
+ case Float:
+ if(anAttrSize == 64)
+ col.setType(NdbDictionary::Column::Double);
+ else
+ col.setType(NdbDictionary::Column::Float);
+ break;
+ case String:
+ col.setType(NdbDictionary::Column::Char);
+ break;
+ case NoAttrTypeDef:
+ abort();
+ }
+ col.setLength(anArraySize);
+ col.setNullable(nullable);
+ if(aTupleKey != NoKey)
+ col.setPrimaryKey(true);
+ else
+ col.setPrimaryKey(false);
+
+ col.setDistributionKey(aDistributionKeyFlag);
+ col.setDistributionGroup(aDistributionGroupFlag,aDistributionGroupNoOfBits);
+ col.setAutoIncrement(aAutoIncrement);
+ col.setDefaultValue(aDefaultValue != 0 ? aDefaultValue : "");
+
+ m_currentTable->addColumn(col);
+ return 0;
+}
+
+/******************************************************************************
+void release();
+
+Remark: Release all objects connected to the schemaop object.
+******************************************************************************/
+void
+NdbSchemaOp::release(){
+}//NdbSchemaOp::release()
+
+/******************************************************************************
+int sendRec()
+
+Return Value: Return 0 : send was succesful.
+ Return -1: In all other case.
+Parameters:
+Remark: Send and receive signals for schema transaction based on state
+******************************************************************************/
+int
+NdbSchemaOp::sendRec(){
+ int retVal = 0;
+ if(m_currentTable == 0){
+ retVal = -1;
+ } else {
+ retVal = theNdb->getDictionary()->createTable(* m_currentTable);
+ delete m_currentTable;
+ theSchemaCon->theError.code = theNdb->getDictionary()->getNdbError().code;
+ }
+
+ return retVal;
+}//NdbSchemaOp::sendRec()
+
+/******************************************************************************
+int init();
+
+Return Value: Return 0 : init was successful.
+ Return -1: In all other case.
+Remark: Initiates SchemaOp record after allocation.
+******************************************************************************/
+int
+NdbSchemaOp::init(NdbSchemaCon* aSchemaCon)
+{
+ theSchemaCon = aSchemaCon;
+ return 0;
+}//NdbSchemaOp::init()
+
+
+const NdbError &
+NdbSchemaOp::getNdbError() const
+{
+ return theSchemaCon->getNdbError();
+}
+
diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp
index 2e6ff360123..3ef31a2f535 100644
--- a/ndb/test/src/UtilTransactions.cpp
+++ b/ndb/test/src/UtilTransactions.cpp
@@ -980,8 +980,8 @@ UtilTransactions::verifyIndex(Ndb* pNdb,
}
switch (pIndex->getType()){
- case UniqueHashIndex:
- case OrderedIndex:
+ case NdbDictionary::Index::UniqueHashIndex:
+ case NdbDictionary::Index::OrderedIndex:
return verifyUniqueIndex(pNdb, indexName, parallelism, transactional);
break;
default:
diff --git a/ndb/test/tools/Makefile.am b/ndb/test/tools/Makefile.am
new file mode 100644
index 00000000000..8d94c21b721
--- /dev/null
+++ b/ndb/test/tools/Makefile.am
@@ -0,0 +1,31 @@
+
+ndbtest_PROGRAMS = hugoCalculator hugoLoad hugoFill hugoLockRecords hugoPkDelete hugoPkRead hugoPkReadRecord hugoPkUpdate hugoScanRead hugoScanUpdate restart verify_index copy_tab create_index ndb_cpcc
+
+# transproxy
+
+hugoCalculator_SOURCES = hugoCalculator.cpp
+hugoFill_SOURCES = hugoFill.cpp
+hugoLoad_SOURCES = hugoLoad.cpp
+hugoLockRecords_SOURCES = hugoLockRecords.cpp
+hugoPkDelete_SOURCES = hugoPkDelete.cpp
+hugoPkRead_SOURCES = hugoPkRead.cpp
+hugoPkReadRecord_SOURCES = hugoPkReadRecord.cpp
+hugoPkUpdate_SOURCES = hugoPkUpdate.cpp
+hugoScanRead_SOURCES = hugoScanRead.cpp
+hugoScanUpdate_SOURCES = hugoScanUpdate.cpp
+restart_SOURCES = restart.cpp
+# transproxy_SOURCES = transproxy.cpp
+verify_index_SOURCES = verify_index.cpp
+copy_tab_SOURCES = copy_tab.cpp
+create_index_SOURCES = create_index.cpp
+ndb_cpcc_SOURCES = cpcc.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmclient
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am
+
+ndb_cpcc_LDADD = $(LDADD) $(top_builddir)/ndb/src/mgmclient/CpcClient.o
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/test/tools/Makefile b/ndb/test/tools/Makefile_old
index b8e90ae207f..b8e90ae207f 100644
--- a/ndb/test/tools/Makefile
+++ b/ndb/test/tools/Makefile_old
diff --git a/ndb/tools/copy_tab/copy_tab.cpp b/ndb/test/tools/copy_tab.cpp
index 33ce8e01d9a..33ce8e01d9a 100644
--- a/ndb/tools/copy_tab/copy_tab.cpp
+++ b/ndb/test/tools/copy_tab.cpp
diff --git a/ndb/tools/cpcc/cpcc.cpp b/ndb/test/tools/cpcc.cpp
index e768d707bbc..e768d707bbc 100644
--- a/ndb/tools/cpcc/cpcc.cpp
+++ b/ndb/test/tools/cpcc.cpp
diff --git a/ndb/tools/create_index/create_index.cpp b/ndb/test/tools/create_index.cpp
index dc9e6c606d6..dc9e6c606d6 100644
--- a/ndb/tools/create_index/create_index.cpp
+++ b/ndb/test/tools/create_index.cpp
diff --git a/ndb/test/tools/hugoCalculator/hugoCalculator.cpp b/ndb/test/tools/hugoCalculator.cpp
index 7f2751be2ba..7f2751be2ba 100644
--- a/ndb/test/tools/hugoCalculator/hugoCalculator.cpp
+++ b/ndb/test/tools/hugoCalculator.cpp
diff --git a/ndb/test/tools/hugoFill/hugoFill.cpp b/ndb/test/tools/hugoFill.cpp
index dee6ce2e6c8..dee6ce2e6c8 100644
--- a/ndb/test/tools/hugoFill/hugoFill.cpp
+++ b/ndb/test/tools/hugoFill.cpp
diff --git a/ndb/test/tools/hugoLoad/hugoLoad.cpp b/ndb/test/tools/hugoLoad.cpp
index be7f878d106..be7f878d106 100644
--- a/ndb/test/tools/hugoLoad/hugoLoad.cpp
+++ b/ndb/test/tools/hugoLoad.cpp
diff --git a/ndb/test/tools/hugoLockRecords/hugoLockRecords.cpp b/ndb/test/tools/hugoLockRecords.cpp
index e2c2cd13f00..e2c2cd13f00 100644
--- a/ndb/test/tools/hugoLockRecords/hugoLockRecords.cpp
+++ b/ndb/test/tools/hugoLockRecords.cpp
diff --git a/ndb/test/tools/hugoPkDelete/hugoPkDel.cpp b/ndb/test/tools/hugoPkDelete.cpp
index 1855f19796f..1855f19796f 100644
--- a/ndb/test/tools/hugoPkDelete/hugoPkDel.cpp
+++ b/ndb/test/tools/hugoPkDelete.cpp
diff --git a/ndb/test/tools/hugoPkRead/hugoPkRead.cpp b/ndb/test/tools/hugoPkRead.cpp
index 50351f08195..50351f08195 100644
--- a/ndb/test/tools/hugoPkRead/hugoPkRead.cpp
+++ b/ndb/test/tools/hugoPkRead.cpp
diff --git a/ndb/test/tools/hugoPkReadRecord/hugoPkReadRecord.cpp b/ndb/test/tools/hugoPkReadRecord.cpp
index ac17ffffee8..ac17ffffee8 100644
--- a/ndb/test/tools/hugoPkReadRecord/hugoPkReadRecord.cpp
+++ b/ndb/test/tools/hugoPkReadRecord.cpp
diff --git a/ndb/test/tools/hugoPkUpdate/hugoPkUpd.cpp b/ndb/test/tools/hugoPkUpdate.cpp
index e7edc3a991d..e7edc3a991d 100644
--- a/ndb/test/tools/hugoPkUpdate/hugoPkUpd.cpp
+++ b/ndb/test/tools/hugoPkUpdate.cpp
diff --git a/ndb/test/tools/hugoScanRead/hugoScanRead.cpp b/ndb/test/tools/hugoScanRead.cpp
index 47ea8f4a8a7..47ea8f4a8a7 100644
--- a/ndb/test/tools/hugoScanRead/hugoScanRead.cpp
+++ b/ndb/test/tools/hugoScanRead.cpp
diff --git a/ndb/test/tools/hugoScanUpdate/hugoScanUpd.cpp b/ndb/test/tools/hugoScanUpdate.cpp
index 3e2255ca0f3..3e2255ca0f3 100644
--- a/ndb/test/tools/hugoScanUpdate/hugoScanUpd.cpp
+++ b/ndb/test/tools/hugoScanUpdate.cpp
diff --git a/ndb/test/tools/hugoCalculator/Makefile b/ndb/test/tools/old_dirs/hugoCalculator/Makefile
index a29deeaacd3..a29deeaacd3 100644
--- a/ndb/test/tools/hugoCalculator/Makefile
+++ b/ndb/test/tools/old_dirs/hugoCalculator/Makefile
diff --git a/ndb/test/tools/hugoFill/Makefile b/ndb/test/tools/old_dirs/hugoFill/Makefile
index 3da745810b6..3da745810b6 100644
--- a/ndb/test/tools/hugoFill/Makefile
+++ b/ndb/test/tools/old_dirs/hugoFill/Makefile
diff --git a/ndb/test/tools/hugoLoad/Makefile b/ndb/test/tools/old_dirs/hugoLoad/Makefile
index 7c5756d0d41..7c5756d0d41 100644
--- a/ndb/test/tools/hugoLoad/Makefile
+++ b/ndb/test/tools/old_dirs/hugoLoad/Makefile
diff --git a/ndb/test/tools/hugoLockRecords/Makefile b/ndb/test/tools/old_dirs/hugoLockRecords/Makefile
index 3235750cbf8..3235750cbf8 100644
--- a/ndb/test/tools/hugoLockRecords/Makefile
+++ b/ndb/test/tools/old_dirs/hugoLockRecords/Makefile
diff --git a/ndb/test/tools/hugoPkDelete/Makefile b/ndb/test/tools/old_dirs/hugoPkDelete/Makefile
index e6d53611c54..e6d53611c54 100644
--- a/ndb/test/tools/hugoPkDelete/Makefile
+++ b/ndb/test/tools/old_dirs/hugoPkDelete/Makefile
diff --git a/ndb/test/tools/hugoPkRead/Makefile b/ndb/test/tools/old_dirs/hugoPkRead/Makefile
index 03580dc0d18..03580dc0d18 100644
--- a/ndb/test/tools/hugoPkRead/Makefile
+++ b/ndb/test/tools/old_dirs/hugoPkRead/Makefile
diff --git a/ndb/test/tools/hugoPkReadRecord/Makefile b/ndb/test/tools/old_dirs/hugoPkReadRecord/Makefile
index 158a79a5666..158a79a5666 100644
--- a/ndb/test/tools/hugoPkReadRecord/Makefile
+++ b/ndb/test/tools/old_dirs/hugoPkReadRecord/Makefile
diff --git a/ndb/test/tools/hugoPkUpdate/Makefile b/ndb/test/tools/old_dirs/hugoPkUpdate/Makefile
index 48795b62206..48795b62206 100644
--- a/ndb/test/tools/hugoPkUpdate/Makefile
+++ b/ndb/test/tools/old_dirs/hugoPkUpdate/Makefile
diff --git a/ndb/test/tools/hugoScanRead/Makefile b/ndb/test/tools/old_dirs/hugoScanRead/Makefile
index b88377c299e..b88377c299e 100644
--- a/ndb/test/tools/hugoScanRead/Makefile
+++ b/ndb/test/tools/old_dirs/hugoScanRead/Makefile
diff --git a/ndb/test/tools/hugoScanUpdate/Makefile b/ndb/test/tools/old_dirs/hugoScanUpdate/Makefile
index ec0e07bfd84..ec0e07bfd84 100644
--- a/ndb/test/tools/hugoScanUpdate/Makefile
+++ b/ndb/test/tools/old_dirs/hugoScanUpdate/Makefile
diff --git a/ndb/test/tools/restart/Makefile b/ndb/test/tools/old_dirs/restart/Makefile
index 05d9e98c5bc..05d9e98c5bc 100644
--- a/ndb/test/tools/restart/Makefile
+++ b/ndb/test/tools/old_dirs/restart/Makefile
diff --git a/ndb/tools/transproxy/Makefile b/ndb/test/tools/old_dirs/transproxy/Makefile
index d6a76ed2e3d..d6a76ed2e3d 100644
--- a/ndb/tools/transproxy/Makefile
+++ b/ndb/test/tools/old_dirs/transproxy/Makefile
diff --git a/ndb/tools/verify_index/Makefile b/ndb/test/tools/old_dirs/verify_index/Makefile
index f6b31e4dc8e..f6b31e4dc8e 100644
--- a/ndb/tools/verify_index/Makefile
+++ b/ndb/test/tools/old_dirs/verify_index/Makefile
diff --git a/ndb/test/tools/waiter/Makefile b/ndb/test/tools/old_dirs/waiter/Makefile_old
index da2c9daff00..da2c9daff00 100644
--- a/ndb/test/tools/waiter/Makefile
+++ b/ndb/test/tools/old_dirs/waiter/Makefile_old
diff --git a/ndb/test/tools/waiter/waiter.cpp b/ndb/test/tools/old_dirs/waiter/waiter.cpp
index d57daff3aea..d57daff3aea 100644
--- a/ndb/test/tools/waiter/waiter.cpp
+++ b/ndb/test/tools/old_dirs/waiter/waiter.cpp
diff --git a/ndb/test/tools/restart/restart.cpp b/ndb/test/tools/restart.cpp
index 88cfb231a72..88cfb231a72 100644
--- a/ndb/test/tools/restart/restart.cpp
+++ b/ndb/test/tools/restart.cpp
diff --git a/ndb/tools/transproxy/transproxy.cpp b/ndb/test/tools/transproxy.cpp
index 384a8a34f03..384a8a34f03 100644
--- a/ndb/tools/transproxy/transproxy.cpp
+++ b/ndb/test/tools/transproxy.cpp
diff --git a/ndb/tools/verify_index/verify_index.cpp b/ndb/test/tools/verify_index.cpp
index 1295b657e9b..1295b657e9b 100644
--- a/ndb/tools/verify_index/verify_index.cpp
+++ b/ndb/test/tools/verify_index.cpp
diff --git a/ndb/tools/Makefile.am b/ndb/tools/Makefile.am
new file mode 100644
index 00000000000..64625f69ea2
--- /dev/null
+++ b/ndb/tools/Makefile.am
@@ -0,0 +1,36 @@
+
+ndbtools_PROGRAMS = \
+ ndb_waiter \
+ ndb_drop_table \
+ ndb_delete_all \
+ ndb_desc \
+ ndb_drop_index \
+ ndb_show_tables \
+ ndb_select_all \
+ ndb_select_count
+
+tools_common_sources = ../test/src/NDBT_ReturnCodes.cpp ../test/src/NDBT_Table.cpp ../test/src/NDBT_Output.cpp
+
+ndb_waiter_SOURCES = waiter.cpp $(tools_common_sources)
+ndb_delete_all_SOURCES = delete_all.cpp $(tools_common_sources)
+ndb_desc_SOURCES = desc.cpp $(tools_common_sources)
+ndb_drop_index_SOURCES = drop_index.cpp $(tools_common_sources)
+ndb_drop_table_SOURCES = drop_tab.cpp $(tools_common_sources)
+ndb_show_tables_SOURCES = listTables.cpp $(tools_common_sources)
+ndb_select_all_SOURCES = select_all.cpp ../test/src/NDBT_ResultRow.cpp $(tools_common_sources)
+ndb_select_count_SOURCES = select_count.cpp $(tools_common_sources)
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapitools.mk.am
+
+ndb_waiter_LDFLAGS = @ndb_bin_am_ldflags@
+ndb_drop_table_LDFLAGS = @ndb_bin_am_ldflags@
+ndb_delete_all_LDFLAGS = @ndb_bin_am_ldflags@
+ndb_desc_LDFLAGS = @ndb_bin_am_ldflags@
+ndb_drop_index_LDFLAGS = @ndb_bin_am_ldflags@
+ndb_show_tables_LDFLAGS = @ndb_bin_am_ldflags@
+ndb_select_all_LDFLAGS = @ndb_bin_am_ldflags@
+ndb_select_count_LDFLAGS = @ndb_bin_am_ldflags@
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/tools/Makefile b/ndb/tools/Makefile_old
index b9dc6883e18..b9dc6883e18 100644
--- a/ndb/tools/Makefile
+++ b/ndb/tools/Makefile_old
diff --git a/ndb/tools/delete_all.cpp b/ndb/tools/delete_all.cpp
new file mode 100644
index 00000000000..dabd9a0e8fa
--- /dev/null
+++ b/ndb/tools/delete_all.cpp
@@ -0,0 +1,181 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+
+#include <NdbOut.hpp>
+#include <NdbApi.hpp>
+#include <NdbSleep.h>
+#include <NDBT.hpp>
+
+#include <getarg.h>
+
+static int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism=240);
+
+int main(int argc, const char** argv){
+
+ const char* _tabname = NULL;
+ const char* _dbname = "TEST_DB";
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "usage", '?', arg_flag, &_help, "Print help", "" },
+ { "database", 'd', arg_string, &_dbname, "dbname",
+ "Name of database table is in"}
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "tabname\n"\
+ "This program will delete all records in the specified table using scan delete.\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) ||
+ argv[optind] == NULL || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ _tabname = argv[optind];
+
+ // Connect to Ndb
+ Ndb MyNdb(_dbname);
+
+ if(MyNdb.init() != 0){
+ ERR(MyNdb.getNdbError());
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ // Connect to Ndb and wait for it to become ready
+ while(MyNdb.waitUntilReady() != 0)
+ ndbout << "Waiting for ndb to become ready..." << endl;
+
+ // Check if table exists in db
+ int res = NDBT_OK;
+ for(int i = optind; i<argc; i++){
+ const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]);
+ if(pTab == NULL){
+ ndbout << " Table " << _tabname << " does not exist!" << endl;
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ ndbout << "Deleting all from " << argv[i] << "...";
+ if(clear_table(&MyNdb, pTab) == NDBT_FAILED){
+ res = NDBT_FAILED;
+ ndbout << "FAILED" << endl;
+ }
+ }
+ return NDBT_ProgramExit(res);
+}
+
+
+int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism)
+{
+ // Scan all records exclusive and delete
+ // them one by one
+ int retryAttempt = 0;
+ const int retryMax = 10;
+ int deletedRows = 0;
+ int check;
+ NdbConnection *pTrans;
+ NdbScanOperation *pOp;
+ NdbError err;
+
+ int par = parallelism;
+ while (true){
+ restart:
+ if (retryAttempt++ >= retryMax){
+ g_info << "ERROR: has retried this operation " << retryAttempt
+ << " times, failing!" << endl;
+ return NDBT_FAILED;
+ }
+
+ pTrans = pNdb->startTransaction();
+ if (pTrans == NULL) {
+ err = pNdb->getNdbError();
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ NdbSleep_MilliSleep(50);
+ continue;
+ }
+ goto failed;
+ }
+
+ pOp = pTrans->getNdbScanOperation(pTab->getName());
+ if (pOp == NULL) {
+ goto failed;
+ }
+
+ NdbResultSet * rs = pOp->readTuplesExclusive(par);
+ if( rs == 0 ) {
+ goto failed;
+ }
+
+ if(pTrans->execute(NoCommit) != 0){
+ err = pTrans->getNdbError();
+ if(err.status == NdbError::TemporaryError){
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ NdbSleep_MilliSleep(50);
+ continue;
+ }
+ goto failed;
+ }
+
+ while((check = rs->nextResult(true)) == 0){
+ do {
+ if (rs->deleteTuple() != 0){
+ goto failed;
+ }
+ deletedRows++;
+ } while((check = rs->nextResult(false)) == 0);
+
+ if(check != -1){
+ check = pTrans->execute(Commit);
+ pTrans->releaseCompletedOperations();
+ }
+
+ err = pTrans->getNdbError();
+ if(check == -1){
+ if(err.status == NdbError::TemporaryError){
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ NdbSleep_MilliSleep(50);
+ par = 1;
+ goto restart;
+ }
+ goto failed;
+ }
+ }
+ if(check == -1){
+ err = pTrans->getNdbError();
+ if(err.status == NdbError::TemporaryError){
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ NdbSleep_MilliSleep(50);
+ par = 1;
+ goto restart;
+ }
+ goto failed;
+ }
+ pNdb->closeTransaction(pTrans);
+ return NDBT_OK;
+ }
+ return NDBT_FAILED;
+
+ failed:
+ if(pTrans != 0) pNdb->closeTransaction(pTrans);
+ ERR(err);
+ return (err.code != 0 ? err.code : NDBT_FAILED);
+}
diff --git a/ndb/tools/delete_all/delete_all.cpp b/ndb/tools/delete_all/delete_all.cpp
deleted file mode 100644
index 9cbba503e68..00000000000
--- a/ndb/tools/delete_all/delete_all.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <ndb_global.h>
-
-#include <NdbOut.hpp>
-#include <NdbApi.hpp>
-#include <NdbSleep.h>
-#include <NDBT.hpp>
-
-#include <getarg.h>
-
-#include <UtilTransactions.hpp>
-
-int main(int argc, const char** argv){
-
- const char* _tabname = NULL;
- const char* _dbname = "TEST_DB";
- int _help = 0;
- int _ver2 = 1;
-
- struct getargs args[] = {
- { "usage", '?', arg_flag, &_help, "Print help", "" },
- { "ver2", '2', arg_flag, &_ver2, "Use version 2 of clearTable (default)", "" },
- { "ver2", '1', arg_negative_flag, &_ver2, "Use version 1 of clearTable", "" },
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"}
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "tabname\n"\
- "This program will delete all records in the specified table using scan delete.\n";
-
- if(getarg(args, num_args, argc, argv, &optind) ||
- argv[optind] == NULL || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
- _tabname = argv[optind];
-
- // Connect to Ndb
- Ndb MyNdb(_dbname);
-
- if(MyNdb.init() != 0){
- ERR(MyNdb.getNdbError());
- return NDBT_ProgramExit(NDBT_FAILED);
- }
-
- // Connect to Ndb and wait for it to become ready
- while(MyNdb.waitUntilReady() != 0)
- ndbout << "Waiting for ndb to become ready..." << endl;
-
- // Check if table exists in db
- int res = NDBT_OK;
- for(int i = optind; i<argc; i++){
- const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]);
- if(pTab == NULL){
- ndbout << " Table " << _tabname << " does not exist!" << endl;
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- ndbout << "Deleting all from " << argv[i] << "...";
- UtilTransactions utilTrans(*pTab);
- int tmp = NDBT_OK;
- if (_ver2 == 0){
- if(utilTrans.clearTable(&MyNdb) == NDBT_FAILED)
- tmp = NDBT_FAILED;
- } else {
- if(utilTrans.clearTable3(&MyNdb) == NDBT_FAILED)
- tmp = NDBT_FAILED;
- }
- if(tmp == NDBT_FAILED){
- res = tmp;
- ndbout << "FAILED" << endl;
- }
- }
- return NDBT_ProgramExit(res);
-}
-
diff --git a/ndb/tools/desc.cpp b/ndb/tools/desc.cpp
new file mode 100644
index 00000000000..a5ff11edca9
--- /dev/null
+++ b/ndb/tools/desc.cpp
@@ -0,0 +1,103 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <getarg.h>
+#include <NDBT.hpp>
+#include <NdbApi.hpp>
+
+
+
+
+int main(int argc, const char** argv){
+ const char* _tabname = NULL;
+ const char* _dbname = "TEST_DB";
+ int _unqualified = 0;
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "unqualified", 'u', arg_flag, &_unqualified, "unqualified",
+ "Use unqualified table names"},
+ { "database", 'd', arg_string, &_dbname, "dbname",
+ "Name of database table is in"},
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "tabname\n"\
+ "This program list all properties of table(s) in NDB Cluster.\n"\
+ " ex: desc T1 T2 T4\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) ||
+ argv[optind] == NULL ||_help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ _tabname = argv[optind];
+
+ Ndb* pMyNdb;
+ pMyNdb = new Ndb(_dbname);
+ pMyNdb->useFullyQualifiedNames(!_unqualified);
+ pMyNdb->init();
+
+ ndbout << "Waiting...";
+ while (pMyNdb->waitUntilReady() != 0) {
+ ndbout << "...";
+ }
+ ndbout << endl;
+
+ NdbDictionary::Dictionary * dict = pMyNdb->getDictionary();
+ for (int i = optind; i < argc; i++) {
+ NDBT_Table* pTab = (NDBT_Table*)dict->getTable(argv[i]);
+ if (pTab != 0){
+ ndbout << (* pTab) << endl;
+
+ NdbDictionary::Dictionary::List list;
+ if (dict->listIndexes(list, argv[i]) != 0){
+ ndbout << argv[i] << ": " << dict->getNdbError() << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ ndbout << "-- Indexes -- " << endl;
+ ndbout << "PRIMARY KEY(";
+ for (unsigned j= 0; j < pTab->getNoOfPrimaryKeys(); j++)
+ {
+ const NdbDictionary::Column * col = pTab->getColumn(j);
+ ndbout << col->getName();
+ if (j < pTab->getNoOfPrimaryKeys()-1)
+ ndbout << ", ";
+ }
+ ndbout << ") - UniqueHashIndex" << endl;
+
+ for (unsigned j= 0; j < list.count; j++) {
+ NdbDictionary::Dictionary::List::Element& elt = list.elements[j];
+ const NdbDictionary::Index *pIdx = dict->getIndex(elt.name, argv[i]);
+ if (!pIdx){
+ ndbout << argv[i] << ": " << dict->getNdbError() << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ ndbout << (*pIdx) << endl;
+ }
+ ndbout << endl;
+ }
+ else
+ ndbout << argv[i] << ": " << dict->getNdbError() << endl;
+ }
+
+ delete pMyNdb;
+ return NDBT_ProgramExit(NDBT_OK);
+}
diff --git a/ndb/tools/desc/desc.cpp b/ndb/tools/desc/desc.cpp
deleted file mode 100644
index 7481190614c..00000000000
--- a/ndb/tools/desc/desc.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <getarg.h>
-#include <NDBT.hpp>
-#include <NdbApi.hpp>
-
-
-int main(int argc, const char** argv){
- const char* _tabname = NULL;
- const char* _dbname = "TEST_DB";
- int _frm = 0;
- int _unqualified = 0;
- int _help = 0;
-
- struct getargs args[] = {
- { "unqualified", 'u', arg_integer, &_unqualified, "unqualified",
- "Use unqualified table names"},
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"},
- { "frm-data", 'f', arg_flag, &_frm, "Show frm data for table", "" } ,
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "tabname\n"\
- "This program list all properties of table(s) in NDB Cluster.\n"\
- " ex: desc T1 T2 T4\n";
-
- if(getarg(args, num_args, argc, argv, &optind) ||
- argv[optind] == NULL ||_help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
- _tabname = argv[optind];
-
- Ndb* pMyNdb;
- pMyNdb = new Ndb(_dbname);
- pMyNdb->useFullyQualifiedNames(!_unqualified);
- pMyNdb->init();
-
- ndbout << "Waiting...";
- while (pMyNdb->waitUntilReady() != 0) {
- ndbout << "...";
- }
- ndbout << endl;
-
- NdbDictionary::Dictionary * dict = pMyNdb->getDictionary();
- for (int i = optind; i < argc; i++) {
- NDBT_Table* pTab = (NDBT_Table*)dict->getTable(argv[i]);
- if (pTab != 0) {
- ndbout << (* pTab) << endl;
- if (_frm){
- ndbout << "getFrmLength: "<< endl
- << pTab->getFrmLength() << endl;
- }
- } else {
- ndbout << argv[i] << ": " << dict->getNdbError() << endl;
- }
- }
-
- delete pMyNdb;
- return NDBT_ProgramExit(NDBT_OK);
-}
diff --git a/ndb/tools/drop_index/drop_index.cpp b/ndb/tools/drop_index.cpp
index 327f15741c9..327f15741c9 100644
--- a/ndb/tools/drop_index/drop_index.cpp
+++ b/ndb/tools/drop_index.cpp
diff --git a/ndb/tools/drop_tab/drop_tab.cpp b/ndb/tools/drop_tab.cpp
index 70e5d85aabe..70e5d85aabe 100644
--- a/ndb/tools/drop_tab/drop_tab.cpp
+++ b/ndb/tools/drop_tab.cpp
diff --git a/ndb/tools/listTables.cpp b/ndb/tools/listTables.cpp
new file mode 100644
index 00000000000..bddf61848e8
--- /dev/null
+++ b/ndb/tools/listTables.cpp
@@ -0,0 +1,195 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ * list_tables
+ *
+ * List objects(tables, triggers, etc.) in NDB Cluster
+ *
+ */
+
+#include <ndb_global.h>
+#include <getarg.h>
+
+#include <NdbApi.hpp>
+#include <NDBT.hpp>
+
+
+static Ndb* ndb = 0;
+static NdbDictionary::Dictionary* dic = 0;
+static int _unqualified = 0;
+
+static void
+fatal(char const* fmt, ...)
+{
+ va_list ap;
+ char buf[500];
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ ndbout << buf;
+ if (ndb)
+ ndbout << " - " << ndb->getNdbError();
+ ndbout << endl;
+ NDBT_ProgramExit(NDBT_FAILED);
+ exit(1);
+}
+
+static void
+list(const char * tabname,
+ NdbDictionary::Object::Type type)
+{
+ NdbDictionary::Dictionary::List list;
+ if (tabname == 0) {
+ if (dic->listObjects(list, type) == -1)
+ fatal("listObjects");
+ } else {
+ if (dic->listIndexes(list, tabname) == -1)
+ fatal("listIndexes");
+ }
+ if (ndb->usingFullyQualifiedNames())
+ ndbout_c("%-5s %-20s %-8s %-7s %-12s %-8s %s", "id", "type", "state", "logging", "database", "schema", "name");
+ else
+ ndbout_c("%-5s %-20s %-8s %-7s %s", "id", "type", "state", "logging", "name");
+ for (unsigned i = 0; i < list.count; i++) {
+ NdbDictionary::Dictionary::List::Element& elt = list.elements[i];
+ char type[100];
+ bool isTable = false;
+ switch (elt.type) {
+ case NdbDictionary::Object::SystemTable:
+ strcpy(type, "SystemTable");
+ isTable = true;
+ break;
+ case NdbDictionary::Object::UserTable:
+ strcpy(type, "UserTable");
+ isTable = true;
+ break;
+ case NdbDictionary::Object::UniqueHashIndex:
+ strcpy(type, "UniqueHashIndex");
+ isTable = true;
+ break;
+ case NdbDictionary::Object::OrderedIndex:
+ strcpy(type, "OrderedIndex");
+ isTable = true;
+ break;
+ case NdbDictionary::Object::HashIndexTrigger:
+ strcpy(type, "HashIndexTrigger");
+ break;
+ case NdbDictionary::Object::IndexTrigger:
+ strcpy(type, "IndexTrigger");
+ break;
+ case NdbDictionary::Object::SubscriptionTrigger:
+ strcpy(type, "SubscriptionTrigger");
+ break;
+ case NdbDictionary::Object::ReadOnlyConstraint:
+ strcpy(type, "ReadOnlyConstraint");
+ break;
+ default:
+ sprintf(type, "%d", (int)elt.type);
+ break;
+ }
+ char state[100];
+ switch (elt.state) {
+ case NdbDictionary::Object::StateOffline:
+ strcpy(state, "Offline");
+ break;
+ case NdbDictionary::Object::StateBuilding:
+ strcpy(state, "Building");
+ break;
+ case NdbDictionary::Object::StateDropping:
+ strcpy(state, "Dropping");
+ break;
+ case NdbDictionary::Object::StateOnline:
+ strcpy(state, "Online");
+ break;
+ case NdbDictionary::Object::StateBroken:
+ strcpy(state, "Broken");
+ break;
+ default:
+ sprintf(state, "%d", (int)elt.state);
+ break;
+ }
+ char store[100];
+ if (! isTable)
+ strcpy(store, "-");
+ else {
+ switch (elt.store) {
+ case NdbDictionary::Object::StoreTemporary:
+ strcpy(store, "No");
+ break;
+ case NdbDictionary::Object::StorePermanent:
+ strcpy(store, "Yes");
+ break;
+ default:
+ sprintf(state, "%d", (int)elt.store);
+ break;
+ }
+ }
+ if (ndb->usingFullyQualifiedNames())
+ ndbout_c("%-5d %-20s %-8s %-7s %-12s %-8s %s", elt.id, type, state, store, (elt.database)?elt.database:"", (elt.schema)?elt.schema:"", elt.name);
+ else
+ ndbout_c("%-5d %-20s %-8s %-7s %s", elt.id, type, state, store, elt.name);
+ }
+}
+
+int main(int argc, const char** argv){
+ int _loops = 1;
+ const char* _tabname = NULL;
+ const char* _dbname = "TEST_DB";
+ int _type = 0;
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "loops", 'l', arg_integer, &_loops, "loops",
+ "Number of times to run(default = 1)" },
+ { "unqualified", 'u', arg_flag, &_unqualified, "unqualified",
+ "Use unqualified table names"},
+ { "database", 'd', arg_string, &_dbname, "dbname",
+ "Name of database table is in"},
+ { "type", 't', arg_integer, &_type, "type",
+ "Type of objects to show, see NdbDictionary.hpp for numbers(default = 0)" },
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "tabname\n"\
+ "This program list all system objects in NDB Cluster.\n"\
+ "Type of objects to display can be limited with -t option\n"\
+ " ex: list_tables -t 2 would show all UserTables\n"\
+ "To show all indexes for a table write table name as final argument\n"\
+ " ex: list_tables T1\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ _tabname = argv[optind];
+
+ ndb = new Ndb(_dbname);
+ ndb->useFullyQualifiedNames(!_unqualified);
+ if (ndb->init() != 0)
+ fatal("init");
+ if (ndb->waitUntilReady(30) < 0)
+ fatal("waitUntilReady");
+ dic = ndb->getDictionary();
+ for (int i = 0; _loops == 0 || i < _loops; i++) {
+ list(_tabname, (NdbDictionary::Object::Type)_type);
+ }
+ return NDBT_ProgramExit(NDBT_OK);
+}
+
+// vim: set sw=4:
diff --git a/ndb/tools/list_tables/listTables.cpp b/ndb/tools/list_tables/listTables.cpp
deleted file mode 100644
index 41433862304..00000000000
--- a/ndb/tools/list_tables/listTables.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- * list_tables
- *
- * List objects(tables, triggers, etc.) in NDB Cluster
- *
- */
-
-#include <ndb_global.h>
-#include <getarg.h>
-
-#include <NdbApi.hpp>
-#include <NDBT.hpp>
-
-
-static Ndb* ndb = 0;
-static NdbDictionary::Dictionary* dic = 0;
-
-static void
-fatal(char const* fmt, ...)
-{
- va_list ap;
- char buf[500];
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
- ndbout << buf;
- if (ndb)
- ndbout << " - " << ndb->getNdbError();
- ndbout << endl;
- NDBT_ProgramExit(NDBT_FAILED);
- exit(1);
-}
-
-static void
-list(const char * tabname,
- NdbDictionary::Object::Type type)
-{
- NdbDictionary::Dictionary::List list;
- if (tabname == 0) {
- if (dic->listObjects(list, type) == -1)
- fatal("listObjects");
- } else {
- if (dic->listIndexes(list, tabname) == -1)
- fatal("listIndexes");
- }
- if (Ndb::usingFullyQualifiedNames())
- ndbout_c("%-5s %-20s %-8s %-7s %-12s %-8s %s", "id", "type", "state", "logging", "database", "schema", "name");
- else
- ndbout_c("%-5s %-20s %-8s %-7s %s", "id", "type", "state", "logging", "name");
- for (unsigned i = 0; i < list.count; i++) {
- NdbDictionary::Dictionary::List::Element& elt = list.elements[i];
- char type[100];
- bool isTable = false;
- switch (elt.type) {
- case NdbDictionary::Object::SystemTable:
- strcpy(type, "SystemTable");
- isTable = true;
- break;
- case NdbDictionary::Object::UserTable:
- strcpy(type, "UserTable");
- isTable = true;
- break;
- case NdbDictionary::Object::UniqueHashIndex:
- strcpy(type, "UniqueHashIndex");
- isTable = true;
- break;
- case NdbDictionary::Object::OrderedIndex:
- strcpy(type, "OrderedIndex");
- isTable = true;
- break;
- case NdbDictionary::Object::HashIndexTrigger:
- strcpy(type, "HashIndexTrigger");
- break;
- case NdbDictionary::Object::IndexTrigger:
- strcpy(type, "IndexTrigger");
- break;
- case NdbDictionary::Object::SubscriptionTrigger:
- strcpy(type, "SubscriptionTrigger");
- break;
- case NdbDictionary::Object::ReadOnlyConstraint:
- strcpy(type, "ReadOnlyConstraint");
- break;
- default:
- sprintf(type, "%d", (int)elt.type);
- break;
- }
- char state[100];
- switch (elt.state) {
- case NdbDictionary::Object::StateOffline:
- strcpy(state, "Offline");
- break;
- case NdbDictionary::Object::StateBuilding:
- strcpy(state, "Building");
- break;
- case NdbDictionary::Object::StateDropping:
- strcpy(state, "Dropping");
- break;
- case NdbDictionary::Object::StateOnline:
- strcpy(state, "Online");
- break;
- case NdbDictionary::Object::StateBroken:
- strcpy(state, "Broken");
- break;
- default:
- sprintf(state, "%d", (int)elt.state);
- break;
- }
- char store[100];
- if (! isTable)
- strcpy(store, "-");
- else {
- switch (elt.store) {
- case NdbDictionary::Object::StoreTemporary:
- strcpy(store, "No");
- break;
- case NdbDictionary::Object::StorePermanent:
- strcpy(store, "Yes");
- break;
- default:
- sprintf(state, "%d", (int)elt.store);
- break;
- }
- }
- if (Ndb::usingFullyQualifiedNames())
- ndbout_c("%-5d %-20s %-8s %-7s %-12s %-8s %s", elt.id, type, state, store, (elt.database)?elt.database:"", (elt.schema)?elt.schema:"", elt.name);
- else
- ndbout_c("%-5d %-20s %-8s %-7s %s", elt.id, type, state, store, elt.name);
- }
-}
-
-int main(int argc, const char** argv){
- int _loops = 1;
- const char* _tabname = NULL;
- const char* _dbname = "TEST_DB";
- int _unqualified = 0;
- int _type = 0;
- int _help = 0;
-
- struct getargs args[] = {
- { "loops", 'l', arg_integer, &_loops, "loops",
- "Number of times to run(default = 1)" },
- { "unqualified", 'u', arg_flag, &_unqualified, "unqualified",
- "Use unqualified table names"},
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"},
- { "type", 't', arg_integer, &_type, "type",
- "Type of objects to show, see NdbDictionary.hpp for numbers(default = 0)" },
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "tabname\n"\
- "This program list all system objects in NDB Cluster.\n"\
- "Type of objects to display can be limited with -t option\n"\
- " ex: list_tables -t 2 would show all UserTables\n"\
- "To show all indexes for a table write table name as final argument\n"\
- " ex: list_tables T1\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
- _tabname = argv[optind];
-
- ndb = new Ndb(_dbname);
- ndb->useFullyQualifiedNames(!_unqualified);
- if (ndb->init() != 0)
- fatal("init");
- if (ndb->waitUntilReady(30) < 0)
- fatal("waitUntilReady");
- dic = ndb->getDictionary();
- for (int i = 0; _loops == 0 || i < _loops; i++) {
- list(_tabname, (NdbDictionary::Object::Type)_type);
- }
- return NDBT_ProgramExit(NDBT_OK);
-}
-
-// vim: set sw=4:
diff --git a/ndb/tools/ndbsql.cpp b/ndb/tools/ndbsql.cpp
new file mode 100644
index 00000000000..6af5f47f6f4
--- /dev/null
+++ b/ndb/tools/ndbsql.cpp
@@ -0,0 +1,956 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*******************************************************************************
+ * NDB Cluster NDB SQL -- A simple SQL Command-line Interface
+ *
+ ******************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef NDB_MACOSX
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include <errno.h>
+#include <editline/editline.h>
+#include <NdbOut.hpp>
+#include <ctype.h>
+#include <wctype.h>
+
+#ifndef SQL_BLOB
+#define SQL_BLOB 30
+#endif
+#ifndef SQL_CLOB
+#define SQL_CLOB 40
+#endif
+
+/**************************************************************************
+ * ------------------------------------------------------------------------
+ * MODULE: Readline and string handling
+ * ------------------------------------------------------------------------
+ **************************************************************************/
+#define MAXBUF 2048
+static char* s_readBuf;
+static int s_bufSize = MAXBUF;
+
+static char*
+readSQL_File(FILE* inputFile)
+{
+ int c;
+ int i = 0;
+ if (feof(inputFile))
+ return 0;
+ while ((c = getc(inputFile)) != EOF) {
+ if (i == s_bufSize-1) {
+ s_bufSize *= 2;
+ s_readBuf = (char*)realloc(s_readBuf, s_bufSize);
+ }
+ s_readBuf[i] = c;
+ if (c == '\n')
+ break;
+ i++;
+ }
+ s_readBuf[i] = 0;
+ return s_readBuf;
+}
+
+static char*
+readline_gets(const char* prompt, bool batchMode, FILE* inputFile)
+{
+ static char *line_read = (char *)NULL;
+
+ // Disable the default file-name completion action of TAB
+ // rl_bind_key ('\t', rl_insert);
+
+ if (batchMode)
+ /* Read one line from a file. */
+ line_read = readSQL_File(inputFile);
+ else
+ /* Get a line from the user. */
+ line_read = readline(prompt);
+
+ /* If the line has any text in it, save it in the history. */
+ if (!batchMode)
+ if (line_read && *line_read) add_history(line_read);
+
+ return (line_read);
+}
+
+#ifdef NDB_WIN32
+extern "C"
+{
+ char* readline(const char* prompt)
+ {
+ fputs(prompt, stdout);
+ return fgets(s_readBuf, MAXBUF, stdin);
+ }
+ void add_history(char*)
+ {
+ }
+}
+#endif
+
+bool emptyString(const char* s) {
+ if (s == NULL) {
+ return true;
+ }
+
+ for (unsigned int i = 0; i < strlen(s); ++i) {
+ if (! isspace(s[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**************************************************************************
+ * ------------------------------------------------------------------------
+ * MODULE: ODBC Handling
+ * ------------------------------------------------------------------------
+ **************************************************************************/
+
+#include <sqlext.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef NDB_MACOSX
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+/**
+ * In the case where the user types a SELECT statement,
+ * the function fetches and displays all rows of the result set.
+ *
+ * This example illustrates the use of GetDiagField to identify the
+ * type of SQL statement executed and, for SQL statements where the
+ * row count is defined on all implementations, the use of GetDiagField
+ * to obtain the row count.
+ */
+#define MAXCOLS 100
+#undef max
+#define max(a,b) ((a)>(b)?(a):(b))
+
+#define MAX_MESSAGE 500
+
+void getDiag(SQLSMALLINT type, SQLHANDLE handle, unsigned k, unsigned count)
+{
+ char message[MAX_MESSAGE];
+ char state[6];
+ SQLINTEGER native;
+
+ SQLSMALLINT length = -1;
+ memset(message, 0, MAX_MESSAGE);
+ int ret = SQLGetDiagRec(type, handle, k, (SQLCHAR*)state,
+ &native, (SQLCHAR*)message, MAX_MESSAGE, &length);
+ if (ret == SQL_NO_DATA) {
+ ndbout << "No error diagnostics available" << endl;
+ return;
+ }
+ ndbout << message << endl;
+
+ if (k <= count && ret != SQL_SUCCESS)
+ ndbout_c("SQLGetDiagRec %d of %d: return %d != SQL_SUCCESS",
+ k, count, (int)ret);
+ if (k <= count && (SQLSMALLINT) strlen(message) != length)
+ ndbout_c("SQLGetDiagRec %d of %d: message length %d != %d",
+ k, count, strlen(message), length);
+ if (k > count && ret != SQL_NO_DATA)
+ ndbout_c("SQLGetDiagRec %d of %d: return %d != SQL_NO_DATA",
+ k, count, (int)ret);
+}
+
+int print_err(SQLSMALLINT handletype, SQLHDBC hdbc) {
+ getDiag(handletype, hdbc, 1, 1);
+
+ return -1;
+}
+
+
+/***************************************************************
+ * The following functions are given for completeness, but are
+ * not relevant for understanding the database processing
+ * nature of CLI
+ ***************************************************************/
+#define MAX_NUM_PRECISION 15
+/*#define max length of char string representation of no. as:
+= max(precision) + leading sign +E +expsign + max exp length
+= 15 +1 +1 +1 +2
+= 15 +5
+*/
+#define MAX_NUM_STRING_SIZE (MAX_NUM_PRECISION + 5)
+
+int build_indicator_message(SQLCHAR *errmsg, SQLPOINTER *data,
+ SQLINTEGER collen, SQLINTEGER *outlen,
+ SQLSMALLINT colnum) {
+ if (*outlen == SQL_NULL_DATA) {
+ (void)strcpy((char *)data, "NULL");
+ *outlen=4;
+ } else {
+ sprintf((char *)errmsg+strlen((char *)errmsg),
+ "%ld chars truncated, col %d\n", *outlen-collen+1,
+ colnum);
+ *outlen=255;
+ }
+ return 0;
+}
+
+
+SQLINTEGER display_length(SQLSMALLINT coltype, SQLINTEGER collen,
+ SQLCHAR *colname) {
+ switch (coltype) {
+ case SQL_VARCHAR:
+ case SQL_CHAR:
+ case SQL_VARBINARY:
+ case SQL_BINARY:
+ case SQL_BLOB:
+ case SQL_CLOB:
+ case SQL_BIT:
+ //case SQL_REF:
+ //case SQL_BIT_VARYING:
+ return(max(collen,(SQLINTEGER) strlen((char *)colname))+1);
+ case SQL_FLOAT:
+ case SQL_DOUBLE:
+ case SQL_NUMERIC:
+ case SQL_REAL:
+ case SQL_DECIMAL:
+ return(max(MAX_NUM_STRING_SIZE,strlen((char *)colname))+1);
+ case SQL_TYPE_DATE:
+ case SQL_TYPE_TIME:
+ //case SQL_TYPE_TIME_WITH_TIMEZONE:
+ case SQL_TYPE_TIMESTAMP:
+ //case SQL_TYPE_TIMESTAMP_WITH_TIMEZONE:
+ case SQL_INTERVAL_YEAR:
+ case SQL_INTERVAL_MONTH:
+ case SQL_INTERVAL_DAY:
+ case SQL_INTERVAL_HOUR:
+ case SQL_INTERVAL_MINUTE:
+ case SQL_INTERVAL_SECOND:
+ case SQL_INTERVAL_YEAR_TO_MONTH:
+ case SQL_INTERVAL_DAY_TO_HOUR:
+ case SQL_INTERVAL_DAY_TO_MINUTE:
+ case SQL_INTERVAL_DAY_TO_SECOND:
+ case SQL_INTERVAL_HOUR_TO_MINUTE:
+ case SQL_INTERVAL_HOUR_TO_SECOND:
+ case SQL_INTERVAL_MINUTE_TO_SECOND:
+ return(max(collen,(SQLINTEGER) strlen((char *)colname))+1);
+ case SQL_INTEGER:
+ //case SQL_BLOB_LOCATOR:
+ //case SQL_CLOB_LOCATOR:
+ //case SQL_UDT_LOCATOR:
+ //case SQL_ARRAY_LOCATOR:
+ return(max(11,strlen((char *)colname))+1);
+ case SQL_BIGINT:
+ return(max(21,strlen((char *)colname))+1);
+ case SQL_SMALLINT:
+ return(max(5,strlen((char *)colname))+1);
+ default:
+ (void)printf("Unknown datatype, %d\n", coltype);
+ return(0);
+ }
+}
+
+struct Con {
+ const char* dsn;
+ SQLHENV henv;
+ SQLHDBC hdbc;
+ Con(const char* _dsn) :
+ dsn(_dsn), henv(SQL_NULL_HANDLE), hdbc(SQL_NULL_HANDLE) {}
+};
+
+static int
+do_connect(Con& con)
+{
+ int ret;
+
+ // allocate an environment handle
+ ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &con.henv);
+ if (ret != SQL_SUCCESS)
+ return -1;
+
+ // set odbc version (required)
+ ret = SQLSetEnvAttr(con.henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
+ if (ret != SQL_SUCCESS)
+ return -1;
+
+ // allocate a connection handle
+ ret = SQLAllocHandle(SQL_HANDLE_DBC, con.henv, &con.hdbc);
+ if (ret != SQL_SUCCESS)
+ return -1;
+
+ // connect to database
+ SQLCHAR szConnStrOut[256];
+ SQLSMALLINT cbConnStrOut;
+ ret = SQLDriverConnect(con.hdbc, 0, (SQLCHAR*)con.dsn, SQL_NTS,
+ szConnStrOut, sizeof(szConnStrOut), &cbConnStrOut, SQL_DRIVER_COMPLETE);
+ if (ret != SQL_SUCCESS) {
+ ndbout << "Connection failure: Could not connect to database" << endl;
+ print_err(SQL_HANDLE_DBC, con.hdbc);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+do_disconnect(Con& con)
+{
+ // disconnect from database
+ SQLDisconnect(con.hdbc);
+
+ // free connection handle
+ SQLFreeHandle(SQL_HANDLE_DBC, con.hdbc);
+ con.hdbc = SQL_NULL_HANDLE;
+
+ // free environment handle
+ SQLFreeHandle(SQL_HANDLE_ENV, con.henv);
+ con.henv = SQL_NULL_HANDLE;
+
+ return 0;
+}
+
+static int
+get_autocommit(Con& con)
+{
+ int ret;
+ SQLUINTEGER v;
+ ret = SQLGetConnectAttr(con.hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)&v, SQL_IS_UINTEGER, 0);
+ if (ret != SQL_SUCCESS) {
+ ndbout << "Get autocommit failed" << endl;
+ print_err(SQL_HANDLE_DBC, con.hdbc);
+ return -1;
+ }
+ return v;
+}
+
+static int
+set_autocommit(Con& con, SQLUINTEGER v)
+{
+ int ret;
+ ret = SQLSetConnectAttr(con.hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)v, SQL_IS_UINTEGER);
+ if (ret != SQL_SUCCESS) {
+ ndbout << "Set autocommit failed" << endl;
+ print_err(SQL_HANDLE_DBC, con.hdbc);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+do_commit(Con& con)
+{
+ int ret = SQLEndTran(SQL_HANDLE_DBC, con.hdbc, SQL_COMMIT);
+ if (ret != SQL_SUCCESS) {
+ ndbout << "Commit failed" << endl;
+ print_err(SQL_HANDLE_DBC, con.hdbc);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+do_rollback(Con& con)
+{
+ int ret = SQLEndTran(SQL_HANDLE_DBC, con.hdbc, SQL_ROLLBACK);
+ if (ret != SQL_SUCCESS) {
+ ndbout << "Rollback failed" << endl;
+ print_err(SQL_HANDLE_DBC, con.hdbc);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+do_stmt(Con& con, const char *sqlstr)
+{
+ SQLHSTMT hstmt;
+ SQLCHAR errmsg[256];
+ SQLCHAR colname[32];
+ SQLSMALLINT coltype;
+ SQLSMALLINT colnamelen;
+ SQLSMALLINT nullable;
+ SQLUINTEGER collen[MAXCOLS];
+ SQLSMALLINT scale;
+ SQLINTEGER outlen[MAXCOLS];
+ SQLCHAR *data[MAXCOLS];
+ SQLSMALLINT nresultcols = 0;
+ SQLINTEGER rowcount;
+ SQLINTEGER stmttype;
+ SQLRETURN rc;
+
+ /* allocate a statement handle */
+ SQLAllocHandle(SQL_HANDLE_STMT, con.hdbc, &hstmt);
+
+ /* execute the SQL statement */
+ rc = SQLExecDirect(hstmt, (SQLCHAR*)sqlstr, SQL_NTS);
+ if (rc == SQL_ERROR) {
+ ndbout << "Operation failed" << endl;
+ print_err(SQL_HANDLE_STMT, hstmt);
+ return -1;
+ }
+ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA_FOUND) {
+ ndbout << "Operation returned unknown code " << rc << endl;
+ return -1;
+ }
+
+ /* see what kind of statement it was */
+ SQLGetDiagField(SQL_HANDLE_STMT, hstmt, 0,
+ SQL_DIAG_DYNAMIC_FUNCTION_CODE,
+ (SQLPOINTER)&stmttype, SQL_IS_INTEGER, (SQLSMALLINT *)NULL);
+
+ switch (stmttype) {
+ /* SELECT statement */
+ case SQL_DIAG_SELECT_CURSOR:
+ /* determine number of result columns */
+ SQLNumResultCols(hstmt, &nresultcols);
+
+ /***********************
+ * Display column names
+ ***********************/
+ /* Print vertical divider */
+ printf("|");
+ for (int i=0; i<nresultcols; i++) {
+ SQLDescribeCol(hstmt, i+1, colname, sizeof(colname),
+ &colnamelen, &coltype, &collen[i], &scale, &nullable);
+ collen[i] = display_length(coltype, collen[i], colname);
+ for (SQLUINTEGER j=0; j<collen[i]; j++) printf("-");
+ printf("--+");
+ }
+ printf("\n");
+
+ printf("|");
+ for (int i=0; i<nresultcols; i++) {
+ SQLDescribeCol(hstmt, i+1, colname, sizeof(colname),
+ &colnamelen, &coltype, &collen[i], &scale, &nullable);
+
+ /* assume there is a display_length function which
+ computes correct length given the data type */
+ collen[i] = display_length(coltype, collen[i], colname);
+ (void)printf(" %*.*s |", (int)collen[i], (int)collen[i], (char *)colname);
+
+ /* allocate memory to bind column */
+ data[i] = (SQLCHAR *) malloc(collen[i]);
+ if (data[i] == NULL) {
+ ndbout << "Failed to allocate malloc memory in NDB SQL program"
+ << endl;
+ exit(-1);
+ }
+
+ /* bind columns to program vars, converting all types to CHAR */
+ SQLBindCol(hstmt, i+1, SQL_C_CHAR, data[i], collen[i], &outlen[i]);
+ }
+ printf("\n");
+
+ /* Print vertical divider */
+ printf("|");
+ for (int i=0; i<nresultcols; i++) {
+ SQLDescribeCol(hstmt, i+1, colname, sizeof(colname),
+ &colnamelen, &coltype, &collen[i], &scale, &nullable);
+ collen[i] = display_length(coltype, collen[i], colname);
+ for (SQLUINTEGER j=0; j<collen[i]; j++) printf("-");
+ printf("--+");
+ }
+ printf("\n");
+
+ /**********************
+ * Display result rows
+ **********************/
+ {
+ int no_of_rows_fetched=0;
+ while (1) {
+ rc=SQLFetch(hstmt);
+ errmsg[0] = '\0';
+ if (rc == SQL_ERROR) {
+ print_err(SQL_HANDLE_STMT, hstmt);
+ break;
+ }
+ if (rc == SQL_NO_DATA) break;
+ if (rc == SQL_SUCCESS) {
+ printf("|");
+ for (int i=0; i<nresultcols; i++) {
+ if (outlen[i] == SQL_NULL_DATA
+ || outlen[i] >= (SQLINTEGER) collen[i])
+ build_indicator_message(errmsg,
+ (SQLPOINTER *)data[i], collen[i],
+ &outlen[i], i);
+ (void)printf(" %*.*s |", (int)collen[i], (int)collen[i],
+ (char *)data[i]);
+ }
+ /* print any truncation messages */
+ (void)printf("\n%s", (char *)errmsg);
+ } else if (rc == SQL_SUCCESS_WITH_INFO) {
+ printf("|");
+ for (int i=0; i<nresultcols; i++) {
+ if (outlen[i] == SQL_NULL_DATA
+ || outlen[i] >= (SQLINTEGER) collen[i])
+ build_indicator_message(errmsg,
+ (SQLPOINTER *)data[i], collen[i],
+ &outlen[i], i);
+ (void)printf(" %*.*s |", (int)collen[i], (int)collen[i],
+ (char *)data[i]);
+ } /* for all columns in this row */
+ /* print any truncation messages */
+ (void)printf("\n%s", (char *)errmsg);
+ }
+ no_of_rows_fetched++;
+ } /* while rows to fetch */
+ /* Print vertical divider */
+ printf("|");
+ for (int i=0; i<nresultcols; i++) {
+ SQLDescribeCol(hstmt, i+1, colname, sizeof(colname),
+ &colnamelen, &coltype, &collen[i], &scale, &nullable);
+ collen[i] = display_length(coltype, collen[i], colname);
+ for (SQLUINTEGER j=0; j<collen[i]; j++) printf("-");
+ printf("--+");
+ }
+ printf("\n");
+ ndbout << no_of_rows_fetched << " rows fetched" << endl;
+ }
+ SQLCloseCursor(hstmt);
+ break;
+ /* searched DELETE, INSERT or searched UPDATE statement */
+ case SQL_DIAG_DELETE_WHERE:
+ case SQL_DIAG_INSERT:
+ case SQL_DIAG_UPDATE_WHERE:
+ /* check rowcount */
+ SQLRowCount(hstmt, (SQLINTEGER*)&rowcount);
+ ndbout << (int)rowcount << " rows affected" << endl;
+ break;
+ /* other statements */
+ case SQL_DIAG_ALTER_TABLE:
+ case SQL_DIAG_CREATE_TABLE:
+ case SQL_DIAG_CREATE_VIEW:
+ case SQL_DIAG_DROP_TABLE:
+ case SQL_DIAG_DROP_VIEW:
+ case SQL_DIAG_CREATE_INDEX:
+ case SQL_DIAG_DROP_INDEX:
+ case SQL_DIAG_DYNAMIC_DELETE_CURSOR:
+ case SQL_DIAG_DYNAMIC_UPDATE_CURSOR:
+ case SQL_DIAG_GRANT:
+ case SQL_DIAG_REVOKE:
+ ndbout << "Operation successful" << endl;
+ break;
+ /* implementation-defined statement */
+ default:
+ (void)printf("Unknown Statement type=%ld\n", stmttype);
+ break;
+ }
+
+ /* free data buffers */
+ for (int i=0; i<nresultcols; i++) {
+ (void)free(data[i]);
+ }
+
+ SQLFreeHandle(SQL_HANDLE_STMT, hstmt); // free statement handle
+ return(0);
+}
+
+/**************************************************************************
+ * ------------------------------------------------------------------------
+ * MODULE: Help
+ * ------------------------------------------------------------------------
+ **************************************************************************/
+
+void print_help() {
+ ndbout << "Commands:" << endl
+ << "set Print currect settings" << endl
+ << "set trace N Set NDB ODBC trace level to N (0-5)" << endl
+ << "set autocommit on Commit each statement (default)" << endl
+ << "set autocommit off Use explicit commit/rollback - may time out!" << endl
+ << "commit Commit changes to database" << endl
+ << "rollback Rollback (undo) any changes" << endl
+ << "whenever sqlerror Define action: exit or continue (default)" << endl
+ << endl
+ << "help Print this help" << endl
+ << "help create Print create table examples" << endl
+ << "help insert Print insert examples" << endl
+ << "help select Print select examples" << endl
+ << "help delete Print delete examples" << endl
+ << "help update Print update examples" << endl
+ << "help virtual Print help on NDB ODBC virtual tables" << endl
+ << "list tables Lists all table names" << endl
+ << endl
+ << "All other commands are sent to the NDB ODBC SQL executor"
+ << endl << endl;
+}
+
+void print_help_create() {
+ ndbout << "Create Table Examples" << endl << endl
+ << "create table t ( a integer not null, b char(20) not null," << endl
+ << " c float, primary key(a, b) )" << endl
+ << "create table t ( ndb$tid bigint unsigned primary key," << endl
+ << " b char(20) not null, c float )" << endl
+ << "create table t ( a int auto_increment primary key," << endl
+ << " b char(20) not null, c float )" << endl
+ << "create table t ( a int primary key," << endl
+ << " b int default 100 )" << endl
+ << endl
+ << "For more information read NDB Cluster ODBC Manual."
+ << endl;
+}
+
+void print_help_insert() {
+ ndbout << "Insert Examples" << endl << endl
+ << "insert into t(a, c) values (123, 'abc')" << endl
+ << "insert into t1(a, c) select a + 10 * b, c from t2" << endl
+ << "insert into t values(null, 'abc', 1.23)" << endl
+ << "insert into t(b, c) values('abc', 1.23)" << endl
+ << endl
+ << "For more information read NDB Cluster ODBC Manual."
+ << endl;
+}
+
+void print_help_select() {
+ ndbout << "Select Examples" << endl << endl
+ << "select a + b * c from t where a <= b + c and (b > c or c > 10)"
+ << endl
+ << "select a.x, b.y, c.z from t1 a, t2 b, t2 c where a.x + b.y < c.z"
+ << endl
+ << "select * from t1, t2 where a1 > 5 order by b1 + b2, c1 desc"
+ << endl
+ << "select count(*), max(a), 1 + sum(b) + avg(c * d) from t" << endl
+ << "select * from t where a < 10 or b > 10" << endl
+ << "select * from t where pk = 5 and b > 10" << endl
+ << "select * from t1, t2, t3 where t1.pk = t2.x and t2.pk = t3.y"
+ << endl << endl
+ << "For more information read NDB Cluster ODBC Manual."
+ << endl;
+}
+
+void print_help_update() {
+ ndbout << "Update and Delete Examples" << endl << endl
+ << "update t set a = b + 5, c = d where c > 10" << endl
+ << "update t set a = b + 5, c = d where pk = 5 and c > 10" << endl
+ << "update t set a = 5, c = 7 where pk = 5" << endl
+ << "delete from t where c > 10" << endl
+ << "delete from t where pk = 5 and c > 10" << endl
+ << "delete from t where pk = 5" << endl
+ << endl
+ << "For more information read NDB Cluster ODBC Manual."
+ << endl;
+}
+
+void print_help_virtual() {
+ ndbout << "Virtual tables" << endl << endl
+ << "* DUAL"
+ << " a 1-row table - example: select SYSDATE from DUAL" << endl
+ << "* ODBC$TYPEINFO" << endl
+ << " corresponds to SQLGetTypeInfo" << endl
+ << "* ODBC$TABLES" << endl
+ << " corresponds to SQLTables (ordered by NDB table id)" << endl
+ << "* ODBC$COLUMNS" << endl
+ << " corresponds to SQLColumns (ordered by NDB table id)" << endl
+ << "* ODBC$PRIMARYKEYS" << endl
+ << " corresponds to SQLPrimaryKeys (ordered by NDB table id)" << endl
+ << endl
+ << "For more information read NDB Cluster ODBC Manual."
+ << endl;
+}
+
+/**************************************************************************
+ * ------------------------------------------------------------------------
+ * MODULE: Main
+ * ------------------------------------------------------------------------
+ **************************************************************************/
+
+int main(int argc, const char** argv)
+{
+ const char* usage = "Usage: ndbsql [-h] [-d dsn] [-f file] [stmt]\n-h help\n-d <database name or connect string>\n-f <file name> batch mode\nstmt single SQL statement\n";
+ const char* dsn = "TEST_DB";
+ bool helpFlg = false, batchMode = false;
+ const char* fileName = 0;
+ FILE* inputFile = stdin;
+ const char* singleStmt = 0;
+
+ s_readBuf = (char*)malloc(s_bufSize);
+ while (++argv, --argc > 0) {
+ const char* arg = argv[0];
+ if (arg[0] != '-')
+ break;
+ if (strcmp(arg, "-d") == 0) {
+ if (++argv, --argc > 0) {
+ dsn = argv[0];
+ continue;
+ }
+ }
+ if (strcmp(arg, "-h") == 0) {
+ helpFlg = true;
+ continue;
+ }
+ if (strcmp(arg, "-f") == 0) {
+ if (++argv, --argc > 0) {
+ fileName = argv[0];
+ continue;
+ }
+ }
+ ndbout << usage;
+ return 1;
+ }
+ if (helpFlg) {
+ ndbout << usage << "\n";
+ print_help();
+ return 0;
+ }
+ if (fileName != 0) {
+ if (argc > 0) {
+ ndbout << usage;
+ return 1;
+ }
+ if ((inputFile = fopen(fileName, "r")) == 0) {
+ ndbout << "Could not read file " << fileName << ": " << strerror(errno) << endl;
+ return 1;
+ }
+ batchMode = true;
+ }
+ if (argc > 0) {
+ singleStmt = argv[0];
+ batchMode = true;
+ }
+ if (! batchMode)
+ ndbout << "NDB Cluster NDB SQL -- A simple SQL Command-line Interface\n\n";
+
+ Con con(dsn);
+ if (do_connect(con) < 0)
+ return 1;
+ if (! batchMode)
+ ndbout << "Terminate SQL statements with a semi-colon ';'\n";
+
+ char* line = 0;
+ char* line2 = 0;
+ char* line3 = 0;
+ unsigned lineno = 0;
+ bool has_semi;
+ bool exit_on_error = false;
+ int exit_code = 0;
+ while (1) {
+ free(line);
+ line = 0;
+ lineno = 0;
+
+more_lines:
+ free(line2);
+ free(line3);
+ line2 = line3 = 0;
+ lineno++;
+ has_semi = false;
+ char prompt[20];
+ if (lineno == 1)
+ strcpy(prompt, "SQL> ");
+ else
+ sprintf(prompt, "%4d ", lineno);
+ if (singleStmt != 0) {
+ line = strdup(singleStmt);
+ int n = strlen(line);
+ while (n > 0 && isspace(line[n - 1])) {
+ line[--n] = 0;
+ }
+ if (n > 0 && line[n - 1] == ';')
+ line[n - 1] = 0;
+ has_semi = true; // regardless
+ } else {
+ const char *line1 = readline_gets(prompt, batchMode, inputFile);
+ if (line1 != 0) {
+ if (line == 0)
+ line = strdup(line1);
+ else {
+ line = (char*)realloc(line, strlen(line) + 1 + strlen(line1) + 1);
+ strcat(line, "\n");
+ strcat(line, line1);
+ }
+ if (batchMode)
+ ndbout << prompt << line1 << endl;
+ } else {
+ if (! batchMode)
+ ndbout << endl;
+ if (line != 0)
+ ndbout << "Ignored unterminated SQL statement" << endl;
+ break;
+ }
+ }
+
+ line2 = (char*)malloc(strlen(line) + 1);
+ {
+ char* p = line2;
+ char* q = line;
+ bool str = false;
+ while (*q != 0) {
+ if (*q == '\'') {
+ str = !str;
+ *p++ = *q++;
+ } else if (!str && *q == '-' && *(q + 1) == '-') {
+ while (*q != 0 && *q != '\n')
+ q++;
+ } else
+ *p++ = *q++;
+ }
+ *p = 0;
+ int n = strlen(line2);
+ while (n > 0 && isspace(line2[n - 1]))
+ line2[--n] = 0;
+ if (n > 0 && line2[n - 1] == ';') {
+ line2[--n] = 0;
+ has_semi = true;
+ }
+ }
+ line3 = strdup(line2);
+ char* tok[10];
+ int ntok = 0;
+ tok[ntok] = strtok(line3, " ");
+ while (tok[ntok] != 0) {
+ ntok++;
+ if (ntok == 10)
+ break;
+ tok[ntok] = strtok(0, " ");
+ }
+ if (ntok == 0)
+ continue;
+
+ if (!strcasecmp(tok[0], "help") || !strcmp(tok[0], "?")) {
+ if (ntok != 2)
+ print_help();
+ else if (!strcasecmp(tok[1], "create"))
+ print_help_create();
+ else if (!strcasecmp(tok[1], "insert"))
+ print_help_insert();
+ else if (strcasecmp(tok[1], "select"))
+ print_help_select();
+ else if (!strcasecmp(tok[1], "delete"))
+ print_help_update();
+ else if (!strcasecmp(tok[1], "update"))
+ print_help_update();
+ else if (!strcasecmp(tok[1], "virtual"))
+ print_help_virtual();
+ else
+ print_help();
+ continue;
+ }
+
+ if (!strcasecmp(tok[0], "list")) {
+ if (ntok == 2 && !strcasecmp(tok[1], "tables")) {
+ free(line2);
+ line2 = strdup("SELECT TABLE_NAME FROM ODBC$TABLES");
+ has_semi = true;
+ } else {
+ ndbout << "Invalid list option - try help" << endl;
+ continue;
+ }
+ }
+
+ if (ntok == 1 && !strcasecmp(tok[0], "quit"))
+ break;
+ if (ntok == 1 && !strcasecmp(tok[0], "exit"))
+ break;
+ if (ntok == 1 && !strcasecmp(tok[0], "bye"))
+ break;
+
+ if (!strcasecmp(tok[0], "set")) {
+ if (ntok == 1) {
+ char* p;
+ p = getenv("NDB_ODBC_TRACE");
+ ndbout << "Trace level is " << (p ? atoi(p) : 0) << endl;
+ int ret = get_autocommit(con);
+ if (ret != -1)
+ ndbout << "Autocommit is " << (ret == SQL_AUTOCOMMIT_ON ? "on" : "off") << endl;
+ } else if (ntok == 3 && !strcasecmp(tok[1], "trace")) {
+ static char env[40];
+ int n = tok[2] ? atoi(tok[2]) : 0;
+ sprintf(env, "NDB_ODBC_TRACE=%d", n);
+ putenv(env);
+ ndbout << "Trace level set to " << n << endl;
+ } else if (ntok == 3 && !strcasecmp(tok[1], "autocommit")) {
+ if (tok[2] && !strcasecmp(tok[2], "on")) {
+ int ret = set_autocommit(con, SQL_AUTOCOMMIT_ON);
+ if (ret != -1)
+ ndbout << "Autocommit set to ON" << endl;
+ } else if (tok[2] && !strcasecmp(tok[2], "off")) {
+ int ret = set_autocommit(con, SQL_AUTOCOMMIT_OFF);
+ if (ret != -1)
+ ndbout << "Autocommit set to OFF - transaction may time out" << endl;
+ } else {
+ ndbout << "Invalid autocommit option - try help" << endl;
+ }
+ } else {
+ ndbout << "Invalid set command - try help" << endl;
+ }
+ continue;
+ }
+
+ if (ntok >= 2 &&
+ !strcasecmp(tok[0], "whenever") && !strcasecmp(tok[1], "sqlerror")) {
+ if (ntok == 3 && !strcasecmp(tok[2], "exit"))
+ exit_on_error = true;
+ else if (ntok == 3 && !strcasecmp(tok[2], "continue"))
+ exit_on_error = false;
+ else {
+ ndbout << "Invalid whenever clause - try help" << endl;
+ }
+ continue;
+ }
+
+ if (!strcasecmp(tok[0], "commit")) {
+ if (ntok == 1) {
+ if (do_commit(con) != -1)
+ ndbout << "Commit done" << endl;
+ else {
+ exit_code = 1;
+ if (exit_on_error) {
+ ndbout << "Exit on error" << endl;
+ break;
+ }
+ }
+ } else {
+ ndbout << "Invalid commit command - try help" << endl;
+ }
+ continue;
+ }
+
+ if (!strcasecmp(tok[0], "rollback")) {
+ if (ntok == 1) {
+ if (do_rollback(con) != -1)
+ ndbout << "Rollback done" << endl;
+ else {
+ exit_code = 1;
+ if (exit_on_error) {
+ ndbout << "Exit on error" << endl;
+ break;
+ }
+ }
+ } else {
+ ndbout << "Invalid commit command - try help" << endl;
+ }
+ continue;
+ }
+
+ if (! has_semi)
+ goto more_lines;
+ if (do_stmt(con, line2) != 0) {
+ exit_code = 1;
+ if (exit_on_error) {
+ ndbout << "Exit on error" << endl;
+ break;
+ }
+ }
+ if (singleStmt)
+ break;
+ }
+ do_disconnect(con);
+ return exit_code;
+}
+
+// vim: set sw=2 et:
diff --git a/ndb/tools/ndbsql/ndbsql.cpp b/ndb/tools/ndbsql/ndbsql.cpp
deleted file mode 100644
index ce73a972f47..00000000000
--- a/ndb/tools/ndbsql/ndbsql.cpp
+++ /dev/null
@@ -1,947 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*******************************************************************************
- * NDB Cluster NDB SQL -- A simple SQL Command-line Interface
- *
- ******************************************************************************/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#ifdef NDB_MACOSX
-#include <stdlib.h>
-#else
-#include <malloc.h>
-#endif
-#include <errno.h>
-#include <editline/editline.h>
-#include <NdbOut.hpp>
-#include <ctype.h>
-#include <wctype.h>
-
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: Readline and string handling
- * ------------------------------------------------------------------------
- **************************************************************************/
-#define MAXBUF 2048
-static char* s_readBuf;
-static int s_bufSize = MAXBUF;
-
-static char*
-readSQL_File(FILE* inputFile)
-{
- int c;
- int i = 0;
- if (feof(inputFile))
- return 0;
- while ((c = getc(inputFile)) != EOF) {
- if (i == s_bufSize-1) {
- s_bufSize *= 2;
- s_readBuf = (char*)realloc(s_readBuf, s_bufSize);
- }
- s_readBuf[i] = c;
- if (c == '\n')
- break;
- i++;
- }
- s_readBuf[i] = 0;
- return s_readBuf;
-}
-
-static char*
-readline_gets(const char* prompt, bool batchMode, FILE* inputFile)
-{
- static char *line_read = (char *)NULL;
-
- // Disable the default file-name completion action of TAB
- // rl_bind_key ('\t', rl_insert);
-
- if (batchMode)
- /* Read one line from a file. */
- line_read = readSQL_File(inputFile);
- else
- /* Get a line from the user. */
- line_read = readline(prompt);
-
- /* If the line has any text in it, save it in the history. */
- if (!batchMode)
- if (line_read && *line_read) add_history(line_read);
-
- return (line_read);
-}
-
-#ifdef NDB_WIN32
-extern "C"
-{
- char* readline(const char* prompt)
- {
- fputs(prompt, stdout);
- return fgets(s_readBuf, MAXBUF, stdin);
- }
- void add_history(char*)
- {
- }
-}
-#endif
-
-bool emptyString(const char* s) {
- if (s == NULL) {
- return true;
- }
-
- for (unsigned int i = 0; i < strlen(s); ++i) {
- if (! isspace(s[i])) {
- return false;
- }
- }
-
- return true;
-}
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: ODBC Handling
- * ------------------------------------------------------------------------
- **************************************************************************/
-
-#include <sqlext.h>
-#include <stdio.h>
-#include <string.h>
-#ifdef NDB_MACOSX
-#include <stdlib.h>
-#else
-#include <malloc.h>
-#endif
-/**
- * In the case where the user types a SELECT statement,
- * the function fetches and displays all rows of the result set.
- *
- * This example illustrates the use of GetDiagField to identify the
- * type of SQL statement executed and, for SQL statements where the
- * row count is defined on all implementations, the use of GetDiagField
- * to obtain the row count.
- */
-#define MAXCOLS 100
-#define max(a,b) ((a)>(b)?(a):(b))
-
-#define MAX_MESSAGE 500
-
-void getDiag(SQLSMALLINT type, SQLHANDLE handle, unsigned k, unsigned count)
-{
- char message[MAX_MESSAGE];
- char state[6];
- SQLINTEGER native;
-
- SQLSMALLINT length = -1;
- memset(message, 0, MAX_MESSAGE);
- int ret = SQLGetDiagRec(type, handle, k, (SQLCHAR*)state,
- &native, (SQLCHAR*)message, MAX_MESSAGE, &length);
- if (ret == SQL_NO_DATA) {
- ndbout << "No error diagnostics available" << endl;
- return;
- }
- ndbout << message << endl;
-
- if (k <= count && ret != SQL_SUCCESS)
- ndbout_c("SQLGetDiagRec %d of %d: return %d != SQL_SUCCESS",
- k, count, (int)ret);
- if (k <= count && (SQLSMALLINT) strlen(message) != length)
- ndbout_c("SQLGetDiagRec %d of %d: message length %d != %d",
- k, count, strlen(message), length);
- if (k > count && ret != SQL_NO_DATA)
- ndbout_c("SQLGetDiagRec %d of %d: return %d != SQL_NO_DATA",
- k, count, (int)ret);
-}
-
-int print_err(SQLSMALLINT handletype, SQLHDBC hdbc) {
- getDiag(handletype, hdbc, 1, 1);
-
- return -1;
-}
-
-
-/***************************************************************
- * The following functions are given for completeness, but are
- * not relevant for understanding the database processing
- * nature of CLI
- ***************************************************************/
-#define MAX_NUM_PRECISION 15
-/*#define max length of char string representation of no. as:
-= max(precision) + leading sign +E +expsign + max exp length
-= 15 +1 +1 +1 +2
-= 15 +5
-*/
-#define MAX_NUM_STRING_SIZE (MAX_NUM_PRECISION + 5)
-
-int build_indicator_message(SQLCHAR *errmsg, SQLPOINTER *data,
- SQLINTEGER collen, SQLINTEGER *outlen,
- SQLSMALLINT colnum) {
- if (*outlen == SQL_NULL_DATA) {
- (void)strcpy((char *)data, "NULL");
- *outlen=4;
- } else {
- sprintf((char *)errmsg+strlen((char *)errmsg),
- "%ld chars truncated, col %d\n", *outlen-collen+1,
- colnum);
- *outlen=255;
- }
- return 0;
-}
-
-
-SQLINTEGER display_length(SQLSMALLINT coltype, SQLINTEGER collen,
- SQLCHAR *colname) {
- switch (coltype) {
- case SQL_VARCHAR:
- case SQL_CHAR:
- //case SQL_BLOB:
- //case SQL_CLOB:
- case SQL_BIT:
- //case SQL_REF:
- //case SQL_BIT_VARYING:
- return(max(collen,(SQLINTEGER) strlen((char *)colname))+1);
- case SQL_FLOAT:
- case SQL_DOUBLE:
- case SQL_NUMERIC:
- case SQL_REAL:
- case SQL_DECIMAL:
- return(max(MAX_NUM_STRING_SIZE,strlen((char *)colname))+1);
- case SQL_TYPE_DATE:
- case SQL_TYPE_TIME:
- //case SQL_TYPE_TIME_WITH_TIMEZONE:
- case SQL_TYPE_TIMESTAMP:
- //case SQL_TYPE_TIMESTAMP_WITH_TIMEZONE:
- case SQL_INTERVAL_YEAR:
- case SQL_INTERVAL_MONTH:
- case SQL_INTERVAL_DAY:
- case SQL_INTERVAL_HOUR:
- case SQL_INTERVAL_MINUTE:
- case SQL_INTERVAL_SECOND:
- case SQL_INTERVAL_YEAR_TO_MONTH:
- case SQL_INTERVAL_DAY_TO_HOUR:
- case SQL_INTERVAL_DAY_TO_MINUTE:
- case SQL_INTERVAL_DAY_TO_SECOND:
- case SQL_INTERVAL_HOUR_TO_MINUTE:
- case SQL_INTERVAL_HOUR_TO_SECOND:
- case SQL_INTERVAL_MINUTE_TO_SECOND:
- return(max(collen,(SQLINTEGER) strlen((char *)colname))+1);
- case SQL_INTEGER:
- //case SQL_BLOB_LOCATOR:
- //case SQL_CLOB_LOCATOR:
- //case SQL_UDT_LOCATOR:
- //case SQL_ARRAY_LOCATOR:
- return(max(11,strlen((char *)colname))+1);
- case SQL_BIGINT:
- return(max(21,strlen((char *)colname))+1);
- case SQL_SMALLINT:
- return(max(5,strlen((char *)colname))+1);
- default:
- (void)printf("Unknown datatype, %d\n", coltype);
- return(0);
- }
-}
-
-struct Con {
- const char* dsn;
- SQLHENV henv;
- SQLHDBC hdbc;
- Con(const char* _dsn) :
- dsn(_dsn), henv(SQL_NULL_HANDLE), hdbc(SQL_NULL_HANDLE) {}
-};
-
-static int
-do_connect(Con& con)
-{
- int ret;
-
- // allocate an environment handle
- ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &con.henv);
- if (ret != SQL_SUCCESS)
- return -1;
-
- // set odbc version (required)
- ret = SQLSetEnvAttr(con.henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
- if (ret != SQL_SUCCESS)
- return -1;
-
- // allocate a connection handle
- ret = SQLAllocHandle(SQL_HANDLE_DBC, con.henv, &con.hdbc);
- if (ret != SQL_SUCCESS)
- return -1;
-
- // connect to database
- SQLCHAR szConnStrOut[256];
- SQLSMALLINT cbConnStrOut;
- ret = SQLDriverConnect(con.hdbc, 0, (SQLCHAR*)con.dsn, SQL_NTS,
- szConnStrOut, sizeof(szConnStrOut), &cbConnStrOut, SQL_DRIVER_COMPLETE);
- if (ret != SQL_SUCCESS) {
- ndbout << "Connection failure: Could not connect to database" << endl;
- print_err(SQL_HANDLE_DBC, con.hdbc);
- return -1;
- }
-
- return 0;
-}
-
-static int
-do_disconnect(Con& con)
-{
- // disconnect from database
- SQLDisconnect(con.hdbc);
-
- // free connection handle
- SQLFreeHandle(SQL_HANDLE_DBC, con.hdbc);
- con.hdbc = SQL_NULL_HANDLE;
-
- // free environment handle
- SQLFreeHandle(SQL_HANDLE_ENV, con.henv);
- con.henv = SQL_NULL_HANDLE;
-
- return 0;
-}
-
-static int
-get_autocommit(Con& con)
-{
- int ret;
- SQLUINTEGER v;
- ret = SQLGetConnectAttr(con.hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)&v, SQL_IS_UINTEGER, 0);
- if (ret != SQL_SUCCESS) {
- ndbout << "Get autocommit failed" << endl;
- print_err(SQL_HANDLE_DBC, con.hdbc);
- return -1;
- }
- return v;
-}
-
-static int
-set_autocommit(Con& con, SQLUINTEGER v)
-{
- int ret;
- ret = SQLSetConnectAttr(con.hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)v, SQL_IS_UINTEGER);
- if (ret != SQL_SUCCESS) {
- ndbout << "Set autocommit failed" << endl;
- print_err(SQL_HANDLE_DBC, con.hdbc);
- return -1;
- }
- return 0;
-}
-
-static int
-do_commit(Con& con)
-{
- int ret = SQLEndTran(SQL_HANDLE_DBC, con.hdbc, SQL_COMMIT);
- if (ret != SQL_SUCCESS) {
- ndbout << "Commit failed" << endl;
- print_err(SQL_HANDLE_DBC, con.hdbc);
- return -1;
- }
- return 0;
-}
-
-static int
-do_rollback(Con& con)
-{
- int ret = SQLEndTran(SQL_HANDLE_DBC, con.hdbc, SQL_ROLLBACK);
- if (ret != SQL_SUCCESS) {
- ndbout << "Rollback failed" << endl;
- print_err(SQL_HANDLE_DBC, con.hdbc);
- return -1;
- }
- return 0;
-}
-
-static int
-do_stmt(Con& con, const char *sqlstr)
-{
- SQLHSTMT hstmt;
- SQLCHAR errmsg[256];
- SQLCHAR colname[32];
- SQLSMALLINT coltype;
- SQLSMALLINT colnamelen;
- SQLSMALLINT nullable;
- SQLUINTEGER collen[MAXCOLS];
- SQLSMALLINT scale;
- SQLINTEGER outlen[MAXCOLS];
- SQLCHAR *data[MAXCOLS];
- SQLSMALLINT nresultcols = 0;
- SQLINTEGER rowcount;
- SQLINTEGER stmttype;
- SQLRETURN rc;
-
- /* allocate a statement handle */
- SQLAllocHandle(SQL_HANDLE_STMT, con.hdbc, &hstmt);
-
- /* execute the SQL statement */
- rc = SQLExecDirect(hstmt, (SQLCHAR*)sqlstr, SQL_NTS);
- if (rc == SQL_ERROR) {
- ndbout << "Operation failed" << endl;
- print_err(SQL_HANDLE_STMT, hstmt);
- return -1;
- }
- if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA_FOUND) {
- ndbout << "Operation returned unknown code " << rc << endl;
- return -1;
- }
-
- /* see what kind of statement it was */
- SQLGetDiagField(SQL_HANDLE_STMT, hstmt, 0,
- SQL_DIAG_DYNAMIC_FUNCTION_CODE,
- (SQLPOINTER)&stmttype, SQL_IS_INTEGER, (SQLSMALLINT *)NULL);
-
- switch (stmttype) {
- /* SELECT statement */
- case SQL_DIAG_SELECT_CURSOR:
- /* determine number of result columns */
- SQLNumResultCols(hstmt, &nresultcols);
-
- /***********************
- * Display column names
- ***********************/
- /* Print vertical divider */
- printf("|");
- for (int i=0; i<nresultcols; i++) {
- SQLDescribeCol(hstmt, i+1, colname, sizeof(colname),
- &colnamelen, &coltype, &collen[i], &scale, &nullable);
- collen[i] = display_length(coltype, collen[i], colname);
- for (SQLUINTEGER j=0; j<collen[i]; j++) printf("-");
- printf("--+");
- }
- printf("\n");
-
- printf("|");
- for (int i=0; i<nresultcols; i++) {
- SQLDescribeCol(hstmt, i+1, colname, sizeof(colname),
- &colnamelen, &coltype, &collen[i], &scale, &nullable);
-
- /* assume there is a display_length function which
- computes correct length given the data type */
- collen[i] = display_length(coltype, collen[i], colname);
- (void)printf(" %*.*s |", (int)collen[i], (int)collen[i], (char *)colname);
-
- /* allocate memory to bind column */
- data[i] = (SQLCHAR *) malloc(collen[i]);
- if (data[i] == NULL) {
- ndbout << "Failed to allocate malloc memory in NDB SQL program"
- << endl;
- exit(-1);
- }
-
- /* bind columns to program vars, converting all types to CHAR */
- SQLBindCol(hstmt, i+1, SQL_C_CHAR, data[i], collen[i], &outlen[i]);
- }
- printf("\n");
-
- /* Print vertical divider */
- printf("|");
- for (int i=0; i<nresultcols; i++) {
- SQLDescribeCol(hstmt, i+1, colname, sizeof(colname),
- &colnamelen, &coltype, &collen[i], &scale, &nullable);
- collen[i] = display_length(coltype, collen[i], colname);
- for (SQLUINTEGER j=0; j<collen[i]; j++) printf("-");
- printf("--+");
- }
- printf("\n");
-
- /**********************
- * Display result rows
- **********************/
- {
- int no_of_rows_fetched=0;
- while (1) {
- rc=SQLFetch(hstmt);
- errmsg[0] = '\0';
- if (rc == SQL_ERROR) {
- print_err(SQL_HANDLE_STMT, hstmt);
- break;
- }
- if (rc == SQL_NO_DATA) break;
- if (rc == SQL_SUCCESS) {
- printf("|");
- for (int i=0; i<nresultcols; i++) {
- if (outlen[i] == SQL_NULL_DATA
- || outlen[i] >= (SQLINTEGER) collen[i])
- build_indicator_message(errmsg,
- (SQLPOINTER *)data[i], collen[i],
- &outlen[i], i);
- (void)printf(" %*.*s |", (int)collen[i], (int)collen[i],
- (char *)data[i]);
- }
- /* print any truncation messages */
- (void)printf("\n%s", (char *)errmsg);
- } else if (rc == SQL_SUCCESS_WITH_INFO) {
- printf("|");
- for (int i=0; i<nresultcols; i++) {
- if (outlen[i] == SQL_NULL_DATA
- || outlen[i] >= (SQLINTEGER) collen[i])
- build_indicator_message(errmsg,
- (SQLPOINTER *)data[i], collen[i],
- &outlen[i], i);
- (void)printf(" %*.*s |", (int)collen[i], (int)collen[i],
- (char *)data[i]);
- } /* for all columns in this row */
- /* print any truncation messages */
- (void)printf("\n%s", (char *)errmsg);
- }
- no_of_rows_fetched++;
- } /* while rows to fetch */
- /* Print vertical divider */
- printf("|");
- for (int i=0; i<nresultcols; i++) {
- SQLDescribeCol(hstmt, i+1, colname, sizeof(colname),
- &colnamelen, &coltype, &collen[i], &scale, &nullable);
- collen[i] = display_length(coltype, collen[i], colname);
- for (SQLUINTEGER j=0; j<collen[i]; j++) printf("-");
- printf("--+");
- }
- printf("\n");
- ndbout << no_of_rows_fetched << " rows fetched" << endl;
- }
- SQLCloseCursor(hstmt);
- break;
- /* searched DELETE, INSERT or searched UPDATE statement */
- case SQL_DIAG_DELETE_WHERE:
- case SQL_DIAG_INSERT:
- case SQL_DIAG_UPDATE_WHERE:
- /* check rowcount */
- SQLRowCount(hstmt, (SQLINTEGER*)&rowcount);
- ndbout << (int)rowcount << " rows affected" << endl;
- break;
- /* other statements */
- case SQL_DIAG_ALTER_TABLE:
- case SQL_DIAG_CREATE_TABLE:
- case SQL_DIAG_CREATE_VIEW:
- case SQL_DIAG_DROP_TABLE:
- case SQL_DIAG_DROP_VIEW:
- case SQL_DIAG_CREATE_INDEX:
- case SQL_DIAG_DROP_INDEX:
- case SQL_DIAG_DYNAMIC_DELETE_CURSOR:
- case SQL_DIAG_DYNAMIC_UPDATE_CURSOR:
- case SQL_DIAG_GRANT:
- case SQL_DIAG_REVOKE:
- ndbout << "Operation successful" << endl;
- break;
- /* implementation-defined statement */
- default:
- (void)printf("Unknown Statement type=%ld\n", stmttype);
- break;
- }
-
- /* free data buffers */
- for (int i=0; i<nresultcols; i++) {
- (void)free(data[i]);
- }
-
- SQLFreeHandle(SQL_HANDLE_STMT, hstmt); // free statement handle
- return(0);
-}
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: Help
- * ------------------------------------------------------------------------
- **************************************************************************/
-
-void print_help() {
- ndbout << "Commands:" << endl
- << "set Print currect settings" << endl
- << "set trace N Set NDB ODBC trace level to N (0-5)" << endl
- << "set autocommit on Commit each statement (default)" << endl
- << "set autocommit off Use explicit commit/rollback - may time out!" << endl
- << "commit Commit changes to database" << endl
- << "rollback Rollback (undo) any changes" << endl
- << "whenever sqlerror Define action: exit or continue (default)" << endl
- << endl
- << "help Print this help" << endl
- << "help create Print create table examples" << endl
- << "help insert Print insert examples" << endl
- << "help select Print select examples" << endl
- << "help delete Print delete examples" << endl
- << "help update Print update examples" << endl
- << "help virtual Print help on NDB ODBC virtual tables" << endl
- << "list tables Lists all table names" << endl
- << endl
- << "All other commands are sent to the NDB ODBC SQL executor"
- << endl << endl;
-}
-
-void print_help_create() {
- ndbout << "Create Table Examples" << endl << endl
- << "create table t ( a integer not null, b char(20) not null," << endl
- << " c float, primary key(a, b) )" << endl
- << "create table t ( ndb$tid bigint unsigned primary key," << endl
- << " b char(20) not null, c float )" << endl
- << "create table t ( a int auto_increment primary key," << endl
- << " b char(20) not null, c float )" << endl
- << "create table t ( a int primary key," << endl
- << " b int default 100 )" << endl
- << endl
- << "For more information read NDB Cluster ODBC Manual."
- << endl;
-}
-
-void print_help_insert() {
- ndbout << "Insert Examples" << endl << endl
- << "insert into t(a, c) values (123, 'abc')" << endl
- << "insert into t1(a, c) select a + 10 * b, c from t2" << endl
- << "insert into t values(null, 'abc', 1.23)" << endl
- << "insert into t(b, c) values('abc', 1.23)" << endl
- << endl
- << "For more information read NDB Cluster ODBC Manual."
- << endl;
-}
-
-void print_help_select() {
- ndbout << "Select Examples" << endl << endl
- << "select a + b * c from t where a <= b + c and (b > c or c > 10)"
- << endl
- << "select a.x, b.y, c.z from t1 a, t2 b, t2 c where a.x + b.y < c.z"
- << endl
- << "select * from t1, t2 where a1 > 5 order by b1 + b2, c1 desc"
- << endl
- << "select count(*), max(a), 1 + sum(b) + avg(c * d) from t" << endl
- << "select * from t where a < 10 or b > 10" << endl
- << "select * from t where pk = 5 and b > 10" << endl
- << "select * from t1, t2, t3 where t1.pk = t2.x and t2.pk = t3.y"
- << endl << endl
- << "For more information read NDB Cluster ODBC Manual."
- << endl;
-}
-
-void print_help_update() {
- ndbout << "Update and Delete Examples" << endl << endl
- << "update t set a = b + 5, c = d where c > 10" << endl
- << "update t set a = b + 5, c = d where pk = 5 and c > 10" << endl
- << "update t set a = 5, c = 7 where pk = 5" << endl
- << "delete from t where c > 10" << endl
- << "delete from t where pk = 5 and c > 10" << endl
- << "delete from t where pk = 5" << endl
- << endl
- << "For more information read NDB Cluster ODBC Manual."
- << endl;
-}
-
-void print_help_virtual() {
- ndbout << "Virtual tables" << endl << endl
- << "* DUAL"
- << " a 1-row table - example: select SYSDATE from DUAL" << endl
- << "* ODBC$TYPEINFO" << endl
- << " corresponds to SQLGetTypeInfo" << endl
- << "* ODBC$TABLES" << endl
- << " corresponds to SQLTables (ordered by NDB table id)" << endl
- << "* ODBC$COLUMNS" << endl
- << " corresponds to SQLColumns (ordered by NDB table id)" << endl
- << "* ODBC$PRIMARYKEYS" << endl
- << " corresponds to SQLPrimaryKeys (ordered by NDB table id)" << endl
- << endl
- << "For more information read NDB Cluster ODBC Manual."
- << endl;
-}
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: Main
- * ------------------------------------------------------------------------
- **************************************************************************/
-
-int main(int argc, const char** argv)
-{
- const char* usage = "Usage: ndbsql [-h] [-d dsn] [-f file] [stmt]\n-h help\n-d <database name or connect string>\n-f <file name> batch mode\nstmt single SQL statement\n";
- const char* dsn = "TEST_DB";
- bool helpFlg = false, batchMode = false;
- const char* fileName = 0;
- FILE* inputFile = stdin;
- const char* singleStmt = 0;
-
- s_readBuf = (char*)malloc(s_bufSize);
- while (++argv, --argc > 0) {
- const char* arg = argv[0];
- if (arg[0] != '-')
- break;
- if (strcmp(arg, "-d") == 0) {
- if (++argv, --argc > 0) {
- dsn = argv[0];
- continue;
- }
- }
- if (strcmp(arg, "-h") == 0) {
- helpFlg = true;
- continue;
- }
- if (strcmp(arg, "-f") == 0) {
- if (++argv, --argc > 0) {
- fileName = argv[0];
- continue;
- }
- }
- ndbout << usage;
- return 1;
- }
- if (helpFlg) {
- ndbout << usage << "\n";
- print_help();
- return 0;
- }
- if (fileName != 0) {
- if (argc > 0) {
- ndbout << usage;
- return 1;
- }
- if ((inputFile = fopen(fileName, "r")) == 0) {
- ndbout << "Could not read file " << fileName << ": " << strerror(errno) << endl;
- return 1;
- }
- batchMode = true;
- }
- if (argc > 0) {
- singleStmt = argv[0];
- batchMode = true;
- }
- if (! batchMode)
- ndbout << "NDB Cluster NDB SQL -- A simple SQL Command-line Interface\n\n";
-
- Con con(dsn);
- if (do_connect(con) < 0)
- return 1;
- if (! batchMode)
- ndbout << "Terminate SQL statements with a semi-colon ';'\n";
-
- char* line = 0;
- char* line2 = 0;
- char* line3 = 0;
- unsigned lineno = 0;
- bool has_semi;
- bool exit_on_error = false;
- int exit_code = 0;
- while (1) {
- free(line);
- line = 0;
- lineno = 0;
-
-more_lines:
- free(line2);
- free(line3);
- line2 = line3 = 0;
- lineno++;
- has_semi = false;
- char prompt[20];
- if (lineno == 1)
- strcpy(prompt, "SQL> ");
- else
- sprintf(prompt, "%4d ", lineno);
- if (singleStmt != 0) {
- line = strdup(singleStmt);
- int n = strlen(line);
- while (n > 0 && isspace(line[n - 1])) {
- line[--n] = 0;
- }
- if (n > 0 && line[n - 1] == ';')
- line[n - 1] = 0;
- has_semi = true; // regardless
- } else {
- const char *line1 = readline_gets(prompt, batchMode, inputFile);
- if (line1 != 0) {
- if (line == 0)
- line = strdup(line1);
- else {
- line = (char*)realloc(line, strlen(line) + 1 + strlen(line1) + 1);
- strcat(line, "\n");
- strcat(line, line1);
- }
- if (batchMode)
- ndbout << prompt << line1 << endl;
- } else {
- if (! batchMode)
- ndbout << endl;
- if (line != 0)
- ndbout << "Ignored unterminated SQL statement" << endl;
- break;
- }
- }
-
- line2 = (char*)malloc(strlen(line) + 1);
- {
- char* p = line2;
- char* q = line;
- bool str = false;
- while (*q != 0) {
- if (*q == '\'') {
- str = !str;
- *p++ = *q++;
- } else if (!str && *q == '-' && *(q + 1) == '-') {
- while (*q != 0 && *q != '\n')
- q++;
- } else
- *p++ = *q++;
- }
- *p = 0;
- int n = strlen(line2);
- while (n > 0 && isspace(line2[n - 1]))
- line2[--n] = 0;
- if (n > 0 && line2[n - 1] == ';') {
- line2[--n] = 0;
- has_semi = true;
- }
- }
- line3 = strdup(line2);
- char* tok[10];
- int ntok = 0;
- tok[ntok] = strtok(line3, " ");
- while (tok[ntok] != 0) {
- ntok++;
- if (ntok == 10)
- break;
- tok[ntok] = strtok(0, " ");
- }
- if (ntok == 0)
- continue;
-
- if (!strcasecmp(tok[0], "help") || !strcmp(tok[0], "?")) {
- if (ntok != 2)
- print_help();
- else if (!strcasecmp(tok[1], "create"))
- print_help_create();
- else if (!strcasecmp(tok[1], "insert"))
- print_help_insert();
- else if (strcasecmp(tok[1], "select"))
- print_help_select();
- else if (!strcasecmp(tok[1], "delete"))
- print_help_update();
- else if (!strcasecmp(tok[1], "update"))
- print_help_update();
- else if (!strcasecmp(tok[1], "virtual"))
- print_help_virtual();
- else
- print_help();
- continue;
- }
-
- if (!strcasecmp(tok[0], "list")) {
- if (ntok == 2 && !strcasecmp(tok[1], "tables")) {
- free(line2);
- line2 = strdup("SELECT TABLE_NAME FROM ODBC$TABLES");
- has_semi = true;
- } else {
- ndbout << "Invalid list option - try help" << endl;
- continue;
- }
- }
-
- if (ntok == 1 && !strcasecmp(tok[0], "quit"))
- break;
- if (ntok == 1 && !strcasecmp(tok[0], "exit"))
- break;
- if (ntok == 1 && !strcasecmp(tok[0], "bye"))
- break;
-
- if (!strcasecmp(tok[0], "set")) {
- if (ntok == 1) {
- char* p;
- p = getenv("NDB_ODBC_TRACE");
- ndbout << "Trace level is " << (p ? atoi(p) : 0) << endl;
- int ret = get_autocommit(con);
- if (ret != -1)
- ndbout << "Autocommit is " << (ret == SQL_AUTOCOMMIT_ON ? "on" : "off") << endl;
- } else if (ntok == 3 && !strcasecmp(tok[1], "trace")) {
- static char env[40];
- int n = tok[2] ? atoi(tok[2]) : 0;
- sprintf(env, "NDB_ODBC_TRACE=%d", n);
- putenv(env);
- ndbout << "Trace level set to " << n << endl;
- } else if (ntok == 3 && !strcasecmp(tok[1], "autocommit")) {
- if (tok[2] && !strcasecmp(tok[2], "on")) {
- int ret = set_autocommit(con, SQL_AUTOCOMMIT_ON);
- if (ret != -1)
- ndbout << "Autocommit set to ON" << endl;
- } else if (tok[2] && !strcasecmp(tok[2], "off")) {
- int ret = set_autocommit(con, SQL_AUTOCOMMIT_OFF);
- if (ret != -1)
- ndbout << "Autocommit set to OFF - transaction may time out" << endl;
- } else {
- ndbout << "Invalid autocommit option - try help" << endl;
- }
- } else {
- ndbout << "Invalid set command - try help" << endl;
- }
- continue;
- }
-
- if (ntok >= 2 &&
- !strcasecmp(tok[0], "whenever") && !strcasecmp(tok[1], "sqlerror")) {
- if (ntok == 3 && !strcasecmp(tok[2], "exit"))
- exit_on_error = true;
- else if (ntok == 3 && !strcasecmp(tok[2], "continue"))
- exit_on_error = false;
- else {
- ndbout << "Invalid whenever clause - try help" << endl;
- }
- continue;
- }
-
- if (!strcasecmp(tok[0], "commit")) {
- if (ntok == 1) {
- if (do_commit(con) != -1)
- ndbout << "Commit done" << endl;
- else {
- exit_code = 1;
- if (exit_on_error) {
- ndbout << "Exit on error" << endl;
- break;
- }
- }
- } else {
- ndbout << "Invalid commit command - try help" << endl;
- }
- continue;
- }
-
- if (!strcasecmp(tok[0], "rollback")) {
- if (ntok == 1) {
- if (do_rollback(con) != -1)
- ndbout << "Rollback done" << endl;
- else {
- exit_code = 1;
- if (exit_on_error) {
- ndbout << "Exit on error" << endl;
- break;
- }
- }
- } else {
- ndbout << "Invalid commit command - try help" << endl;
- }
- continue;
- }
-
- if (! has_semi)
- goto more_lines;
- if (do_stmt(con, line2) != 0) {
- exit_code = 1;
- if (exit_on_error) {
- ndbout << "Exit on error" << endl;
- break;
- }
- }
- if (singleStmt)
- break;
- }
- do_disconnect(con);
- return exit_code;
-}
-
-// vim: set sw=2 et:
diff --git a/ndb/tools/copy_tab/Makefile b/ndb/tools/old_dirs/copy_tab/Makefile
index 4ad33a26652..4ad33a26652 100644
--- a/ndb/tools/copy_tab/Makefile
+++ b/ndb/tools/old_dirs/copy_tab/Makefile
diff --git a/ndb/tools/cpcc/Makefile b/ndb/tools/old_dirs/cpcc/Makefile
index 78f8c61e464..78f8c61e464 100644
--- a/ndb/tools/cpcc/Makefile
+++ b/ndb/tools/old_dirs/cpcc/Makefile
diff --git a/ndb/tools/create_index/Makefile b/ndb/tools/old_dirs/create_index/Makefile
index 38f2df970c4..38f2df970c4 100644
--- a/ndb/tools/create_index/Makefile
+++ b/ndb/tools/old_dirs/create_index/Makefile
diff --git a/ndb/tools/delete_all/Makefile b/ndb/tools/old_dirs/delete_all/Makefile
index 1cae240eb8f..1cae240eb8f 100644
--- a/ndb/tools/delete_all/Makefile
+++ b/ndb/tools/old_dirs/delete_all/Makefile
diff --git a/ndb/tools/desc/Makefile b/ndb/tools/old_dirs/desc/Makefile
index 614984cfd35..614984cfd35 100644
--- a/ndb/tools/desc/Makefile
+++ b/ndb/tools/old_dirs/desc/Makefile
diff --git a/ndb/tools/drop_index/Makefile b/ndb/tools/old_dirs/drop_index/Makefile
index 969bee51064..969bee51064 100644
--- a/ndb/tools/drop_index/Makefile
+++ b/ndb/tools/old_dirs/drop_index/Makefile
diff --git a/ndb/tools/drop_tab/Makefile b/ndb/tools/old_dirs/drop_tab/Makefile
index d7b21fe982c..d7b21fe982c 100644
--- a/ndb/tools/drop_tab/Makefile
+++ b/ndb/tools/old_dirs/drop_tab/Makefile
diff --git a/ndb/tools/list_tables/Makefile b/ndb/tools/old_dirs/list_tables/Makefile
index b60f161ee68..b60f161ee68 100644
--- a/ndb/tools/list_tables/Makefile
+++ b/ndb/tools/old_dirs/list_tables/Makefile
diff --git a/ndb/tools/ndbnet/Makefile.PL b/ndb/tools/old_dirs/ndbnet/Makefile.PL
index 4b27a17de15..4b27a17de15 100644
--- a/ndb/tools/ndbnet/Makefile.PL
+++ b/ndb/tools/old_dirs/ndbnet/Makefile.PL
diff --git a/ndb/tools/ndbnet/lib/NDB/Net.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net.pm
index 3b7b16bb3cf..3b7b16bb3cf 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/Base.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Base.pm
index 900446138e8..900446138e8 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/Base.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Base.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/Client.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Client.pm
index d34a18d63af..d34a18d63af 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/Client.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Client.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/Command.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Command.pm
index 30145d09fa9..30145d09fa9 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/Command.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Command.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/Config.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Config.pm
index 4c5db3cd3f5..4c5db3cd3f5 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/Config.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Config.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/Database.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Database.pm
index 7ea15be0650..7ea15be0650 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/Database.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Database.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/Env.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Env.pm
index d79e72f2bb3..d79e72f2bb3 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/Env.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Env.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/Node.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Node.pm
index f41bf51168d..f41bf51168d 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/Node.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Node.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/NodeApi.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/NodeApi.pm
index 08f5f85577d..08f5f85577d 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/NodeApi.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/NodeApi.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/NodeDb.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/NodeDb.pm
index 88a35ba4f8d..88a35ba4f8d 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/NodeDb.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/NodeDb.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/NodeMgmt.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/NodeMgmt.pm
index 1056e3df623..1056e3df623 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/NodeMgmt.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/NodeMgmt.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/Server.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Server.pm
index 5d2118f0ffe..5d2118f0ffe 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/Server.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/Server.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/ServerINET.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/ServerINET.pm
index a065c186855..a065c186855 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/ServerINET.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/ServerINET.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Net/ServerUNIX.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/ServerUNIX.pm
index b3fa245d5ee..b3fa245d5ee 100644
--- a/ndb/tools/ndbnet/lib/NDB/Net/ServerUNIX.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Net/ServerUNIX.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Run.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run.pm
index a8cabde544c..a8cabde544c 100644
--- a/ndb/tools/ndbnet/lib/NDB/Run.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Run/Base.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Base.pm
index 4769f2c4441..4769f2c4441 100644
--- a/ndb/tools/ndbnet/lib/NDB/Run/Base.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Base.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Run/Database.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Database.pm
index 9a12ddb20b3..9a12ddb20b3 100644
--- a/ndb/tools/ndbnet/lib/NDB/Run/Database.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Database.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Run/Env.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Env.pm
index e851a82636b..e851a82636b 100644
--- a/ndb/tools/ndbnet/lib/NDB/Run/Env.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Env.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Run/Node.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Node.pm
index e657021b229..e657021b229 100644
--- a/ndb/tools/ndbnet/lib/NDB/Run/Node.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Run/Node.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util.pm
index d5db35cbf13..d5db35cbf13 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/Base.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Base.pm
index 20df78a3b9b..20df78a3b9b 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/Base.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Base.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/Dir.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Dir.pm
index 90609b971c7..90609b971c7 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/Dir.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Dir.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/Event.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Event.pm
index a3ad32cd7fb..a3ad32cd7fb 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/Event.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Event.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/File.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/File.pm
index 4b3cb38191c..4b3cb38191c 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/File.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/File.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/IO.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/IO.pm
index 34f4d0a150d..34f4d0a150d 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/IO.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/IO.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/Lock.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Lock.pm
index b515e633059..b515e633059 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/Lock.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Lock.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/Log.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Log.pm
index 44b39df84e6..44b39df84e6 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/Log.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Log.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/Socket.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Socket.pm
index 00e8b6eca51..00e8b6eca51 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/Socket.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/Socket.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/SocketINET.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/SocketINET.pm
index faaa568a08e..faaa568a08e 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/SocketINET.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/SocketINET.pm
diff --git a/ndb/tools/ndbnet/lib/NDB/Util/SocketUNIX.pm b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/SocketUNIX.pm
index 9c6b3115f6a..9c6b3115f6a 100644
--- a/ndb/tools/ndbnet/lib/NDB/Util/SocketUNIX.pm
+++ b/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/SocketUNIX.pm
diff --git a/ndb/tools/ndbnet/ndbnet.pl b/ndb/tools/old_dirs/ndbnet/ndbnet.pl
index 5f6648da46d..5f6648da46d 100644
--- a/ndb/tools/ndbnet/ndbnet.pl
+++ b/ndb/tools/old_dirs/ndbnet/ndbnet.pl
diff --git a/ndb/tools/ndbnet/ndbnetd.pl b/ndb/tools/old_dirs/ndbnet/ndbnetd.pl
index 95fa5322abc..95fa5322abc 100644
--- a/ndb/tools/ndbnet/ndbnetd.pl
+++ b/ndb/tools/old_dirs/ndbnet/ndbnetd.pl
diff --git a/ndb/tools/ndbnet/ndbrun b/ndb/tools/old_dirs/ndbnet/ndbrun
index 99121276d99..99121276d99 100644
--- a/ndb/tools/ndbnet/ndbrun
+++ b/ndb/tools/old_dirs/ndbnet/ndbrun
diff --git a/ndb/tools/ndbsql/Makefile b/ndb/tools/old_dirs/ndbsql/Makefile
index 81ca87b0414..81ca87b0414 100644
--- a/ndb/tools/ndbsql/Makefile
+++ b/ndb/tools/old_dirs/ndbsql/Makefile
diff --git a/ndb/tools/select_all/Makefile b/ndb/tools/old_dirs/select_all/Makefile
index e14e411b3a5..e14e411b3a5 100644
--- a/ndb/tools/select_all/Makefile
+++ b/ndb/tools/old_dirs/select_all/Makefile
diff --git a/ndb/tools/select_count/Makefile b/ndb/tools/old_dirs/select_count/Makefile
index 35a53c6b046..35a53c6b046 100644
--- a/ndb/tools/select_count/Makefile
+++ b/ndb/tools/old_dirs/select_count/Makefile
diff --git a/ndb/tools/src/counterviewer/CounterViewer.java b/ndb/tools/old_dirs/src/counterviewer/CounterViewer.java
index 317c1c75e28..317c1c75e28 100644
--- a/ndb/tools/src/counterviewer/CounterViewer.java
+++ b/ndb/tools/old_dirs/src/counterviewer/CounterViewer.java
diff --git a/ndb/tools/select_all/select_all.cpp b/ndb/tools/select_all.cpp
index 34f63a095bb..34f63a095bb 100644
--- a/ndb/tools/select_all/select_all.cpp
+++ b/ndb/tools/select_all.cpp
diff --git a/ndb/tools/select_count.cpp b/ndb/tools/select_count.cpp
new file mode 100644
index 00000000000..cae91feb378
--- /dev/null
+++ b/ndb/tools/select_count.cpp
@@ -0,0 +1,199 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+
+#include <NdbOut.hpp>
+
+#include <NdbApi.hpp>
+#include <NdbMain.h>
+#include <NDBT.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+#include <UtilTransactions.hpp>
+
+static int
+select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
+ int parallelism,
+ int* count_rows,
+ UtilTransactions::ScanLock lock,
+ NdbConnection* pBuddyTrans=0);
+
+int main(int argc, const char** argv){
+ const char* _dbname = "TEST_DB";
+ int _parallelism = 240;
+ int _help = 0;
+ int _lock = 0;
+
+ struct getargs args[] = {
+ { "database", 'd', arg_string, &_dbname, "dbname",
+ "Name of database table is in"},
+ { "parallelism", 's', arg_integer, &_parallelism, "parallelism", "parallelism" },
+ { "usage", '?', arg_flag, &_help, "Print help", "" },
+ { "lock", 'l', arg_integer, &_lock,
+ "Read(0), Read-hold(1), Exclusive(2)", "lock"}
+
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "tabname1 ... tabnameN\n"\
+ "This program will count the number of records in tables\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) ||
+ argv[optind] == NULL || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ // Connect to Ndb
+ Ndb MyNdb(_dbname);
+
+ if(MyNdb.init() != 0){
+ ERR(MyNdb.getNdbError());
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ // Connect to Ndb and wait for it to become ready
+ while(MyNdb.waitUntilReady() != 0)
+ ndbout << "Waiting for ndb to become ready..." << endl;
+
+ for(int i = optind; i<argc; i++){
+ // Check if table exists in db
+ const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]);
+ if(pTab == NULL){
+ ndbout << " Table " << argv[i] << " does not exist!" << endl;
+ continue;
+ }
+
+ int rows = 0;
+ if (select_count(&MyNdb, pTab, _parallelism, &rows,
+ (UtilTransactions::ScanLock)_lock) != 0){
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ ndbout << rows << " records in table " << argv[i] << endl;
+ }
+ return NDBT_ProgramExit(NDBT_OK);
+}
+
+int
+select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
+ int parallelism,
+ int* count_rows,
+ UtilTransactions::ScanLock lock,
+ NdbConnection* pBuddyTrans){
+
+ int retryAttempt = 0;
+ const int retryMax = 100;
+ int check;
+ NdbConnection *pTrans;
+ NdbOperation *pOp;
+
+ while (true){
+
+ if (retryAttempt >= retryMax){
+ g_info << "ERROR: has retried this operation " << retryAttempt
+ << " times, failing!" << endl;
+ return NDBT_FAILED;
+ }
+
+ pTrans = pNdb->hupp(pBuddyTrans);
+ if (pTrans == NULL) {
+ const NdbError err = pNdb->getNdbError();
+
+ if (err.status == NdbError::TemporaryError){
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ continue;
+ }
+ ERR(err);
+ return NDBT_FAILED;
+ }
+ pOp = pTrans->getNdbOperation(pTab->getName());
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ switch(lock){
+ case UtilTransactions::SL_ReadHold:
+ check = pOp->openScanReadHoldLock(parallelism);
+ break;
+ case UtilTransactions::SL_Exclusive:
+ check = pOp->openScanExclusive(parallelism);
+ break;
+ case UtilTransactions::SL_Read:
+ default:
+ check = pOp->openScanRead(parallelism);
+ }
+
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pTrans->executeScan();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ eof = pTrans->nextScanResult();
+
+ while(eof == 0){
+ rows++;
+ eof = pTrans->nextScanResult();
+ }
+ if (eof == -1) {
+ const NdbError err = pTrans->getNdbError();
+
+ if (err.status == NdbError::TemporaryError){
+ pNdb->closeTransaction(pTrans);
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ continue;
+ }
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ pNdb->closeTransaction(pTrans);
+
+ if (count_rows != NULL){
+ *count_rows = rows;
+ }
+
+ return NDBT_OK;
+ }
+ return NDBT_FAILED;
+}
+
+
diff --git a/ndb/tools/select_count/select_count.cpp b/ndb/tools/select_count/select_count.cpp
deleted file mode 100644
index b1513ad4135..00000000000
--- a/ndb/tools/select_count/select_count.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#include <ndb_global.h>
-
-#include <NdbOut.hpp>
-
-#include <NdbApi.hpp>
-#include <NdbMain.h>
-#include <NDBT.hpp>
-#include <NdbSleep.h>
-#include <getarg.h>
-#include <UtilTransactions.hpp>
-
-
-int main(int argc, const char** argv){
- const char* _dbname = "TEST_DB";
- int _parallelism = 240;
- int _help = 0;
- int _lock = 0;
-
- struct getargs args[] = {
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"},
- { "parallelism", 's', arg_integer, &_parallelism, "parallelism", "parallelism" },
- { "usage", '?', arg_flag, &_help, "Print help", "" },
- { "lock", 'l', arg_integer, &_lock,
- "Read(0), Read-hold(1), Exclusive(2)", "lock"}
-
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "tabname1 ... tabnameN\n"\
- "This program will count the number of records in tables\n";
-
- if(getarg(args, num_args, argc, argv, &optind) ||
- argv[optind] == NULL || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
-
- // Connect to Ndb
- Ndb MyNdb(_dbname);
-
- if(MyNdb.init() != 0){
- ERR(MyNdb.getNdbError());
- return NDBT_ProgramExit(NDBT_FAILED);
- }
-
- // Connect to Ndb and wait for it to become ready
- while(MyNdb.waitUntilReady() != 0)
- ndbout << "Waiting for ndb to become ready..." << endl;
-
- for(int i = optind; i<argc; i++){
- // Check if table exists in db
- const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]);
- if(pTab == NULL){
- ndbout << " Table " << argv[i] << " does not exist!" << endl;
- continue;
- }
-
- int rows = 0;
- UtilTransactions utilTrans(*pTab);
- if (utilTrans.selectCount(&MyNdb, _parallelism, &rows,
- (UtilTransactions::ScanLock)_lock) != 0){
- return NDBT_ProgramExit(NDBT_FAILED);
- }
-
- ndbout << rows << " records in table " << argv[i] << endl;
- }
- return NDBT_ProgramExit(NDBT_OK);
-}
-
-
-
diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp
new file mode 100644
index 00000000000..7ce2739a157
--- /dev/null
+++ b/ndb/tools/waiter.cpp
@@ -0,0 +1,299 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <mgmapi.h>
+#include <string.h>
+#include <NdbMain.h>
+#include <NdbOut.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+#include <kernel/ndb_limits.h>
+#include "../src/common/mgmcommon/LocalConfig.hpp"
+
+#include <NDBT.hpp>
+
+int
+waitClusterStarted(const char* _addr, unsigned int _timeout= 120);
+
+int main(int argc, const char** argv){
+
+ const char* _hostName = NULL;
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "hostname:port\n"\
+ "This program will connect to the mgmsrv of a NDB cluster.\n"\
+ "It will then wait for all nodes to be started\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+ char buf[255];
+ _hostName = argv[optind];
+
+ if (_hostName == NULL){
+ LocalConfig lcfg;
+ if(!lcfg.init())
+ {
+ lcfg.printError();
+ lcfg.printUsage();
+ g_err << "Error parsing local config file" << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ for (int i = 0; i<lcfg.items; i++)
+ {
+ MgmtSrvrId * m = lcfg.ids[i];
+
+ switch(m->type){
+ case MgmId_TCP:
+ snprintf(buf, 255, "%s:%d", m->data.tcp.remoteHost, m->data.tcp.port);
+ _hostName = buf;
+ break;
+ case MgmId_File:
+ break;
+ default:
+ break;
+ }
+ if (_hostName != NULL)
+ break;
+ }
+ if (_hostName == NULL)
+ {
+ g_err << "No management servers configured in local config file" << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ }
+
+ if (waitClusterStarted(_hostName) != 0)
+ return NDBT_ProgramExit(NDBT_FAILED);
+
+ return NDBT_ProgramExit(NDBT_OK);
+}
+
+#define MGMERR(h) \
+ ndbout << "latest_error="<<ndb_mgm_get_latest_error(h) \
+ << ", line="<<ndb_mgm_get_latest_error_line(h) \
+ << endl;
+
+NdbMgmHandle handle= NULL;
+
+Vector<ndb_mgm_node_state> ndbNodes;
+Vector<ndb_mgm_node_state> mgmNodes;
+Vector<ndb_mgm_node_state> apiNodes;
+
+int
+getStatus(){
+ int retries = 0;
+ struct ndb_mgm_cluster_state * status;
+ struct ndb_mgm_node_state * node;
+
+ ndbNodes.clear();
+ mgmNodes.clear();
+ apiNodes.clear();
+
+ while(retries < 10){
+ status = ndb_mgm_get_status(handle);
+ if (status == NULL){
+ ndbout << "status==NULL, retries="<<retries<<endl;
+ MGMERR(handle);
+ retries++;
+ continue;
+ }
+ for (int i = 0; i < status->no_of_nodes; i++){
+ node = &status->node_states[i];
+ switch(node->node_type){
+ case NDB_MGM_NODE_TYPE_NDB:
+ ndbNodes.push_back(*node);
+ break;
+ case NDB_MGM_NODE_TYPE_MGM:
+ mgmNodes.push_back(*node);
+ break;
+ case NDB_MGM_NODE_TYPE_API:
+ apiNodes.push_back(*node);
+ break;
+ default:
+ if(node->node_status == NDB_MGM_NODE_STATUS_UNKNOWN ||
+ node->node_status == NDB_MGM_NODE_STATUS_NO_CONTACT){
+ retries++;
+ ndbNodes.clear();
+ mgmNodes.clear();
+ apiNodes.clear();
+ free(status);
+ status = NULL;
+ i = status->no_of_nodes;
+
+ ndbout << "kalle"<< endl;
+ break;
+ }
+ abort();
+ break;
+ }
+ }
+ if(status == 0){
+ ndbout << "status == 0" << endl;
+ continue;
+ }
+ free(status);
+ return 0;
+ }
+
+ g_err << "getStatus failed" << endl;
+ return -1;
+}
+
+int
+waitClusterStarted(const char* _addr, unsigned int _timeout)
+{
+ ndb_mgm_node_status _status = NDB_MGM_NODE_STATUS_STARTED;
+ int _startphase = -1;
+
+ int _nodes[MAX_NDB_NODES];
+ int _num_nodes = 0;
+
+ handle = ndb_mgm_create_handle();
+ if (handle == NULL){
+ g_err << "handle == NULL" << endl;
+ return -1;
+ }
+ g_info << "Connecting to mgmsrv at " << _addr << endl;
+ if (ndb_mgm_connect(handle, _addr) == -1) {
+ MGMERR(handle);
+ g_err << "Connection to " << _addr << " failed" << endl;
+ return -1;
+ }
+
+ if (getStatus() != 0)
+ return -1;
+
+ // Collect all nodes into nodes
+ for (size_t i = 0; i < ndbNodes.size(); i++){
+ _nodes[i] = ndbNodes[i].node_id;
+ _num_nodes++;
+ }
+
+ unsigned int attempts = 0;
+ unsigned int resetAttempts = 0;
+ const unsigned int MAX_RESET_ATTEMPTS = 10;
+ bool allInState = false;
+ while (allInState == false){
+ if (_timeout > 0 && attempts > _timeout){
+ /**
+ * Timeout has expired waiting for the nodes to enter
+ * the state we want
+ */
+ bool waitMore = false;
+ /**
+ * Make special check if we are waiting for
+ * cluster to become started
+ */
+ if(_status == NDB_MGM_NODE_STATUS_STARTED){
+ waitMore = true;
+ /**
+ * First check if any node is not starting
+ * then it's no idea to wait anymore
+ */
+ for (size_t n = 0; n < ndbNodes.size(); n++){
+ if (ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTED &&
+ ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTING)
+ waitMore = false;
+
+ }
+ }
+
+ if (!waitMore || resetAttempts > MAX_RESET_ATTEMPTS){
+ g_err << "waitNodeState("
+ << ndb_mgm_get_node_status_string(_status)
+ <<", "<<_startphase<<")"
+ << " timeout after " << attempts <<" attemps" << endl;
+ return -1;
+ }
+
+ g_err << "waitNodeState("
+ << ndb_mgm_get_node_status_string(_status)
+ <<", "<<_startphase<<")"
+ << " resetting number of attempts "
+ << resetAttempts << endl;
+ attempts = 0;
+ resetAttempts++;
+
+ }
+
+ allInState = true;
+ if (getStatus() != 0){
+ g_err << "getStatus != 0" << endl;
+ return -1;
+ }
+
+ // ndbout << "waitNodeState; _num_nodes = " << _num_nodes << endl;
+ // for (int i = 0; i < _num_nodes; i++)
+ // ndbout << " node["<<i<<"] =" <<_nodes[i] << endl;
+
+ for (int i = 0; i < _num_nodes; i++){
+ ndb_mgm_node_state* ndbNode = NULL;
+ for (size_t n = 0; n < ndbNodes.size(); n++){
+ if (ndbNodes[n].node_id == _nodes[i])
+ ndbNode = &ndbNodes[n];
+ }
+
+ if(ndbNode == NULL){
+ allInState = false;
+ continue;
+ }
+
+ g_info << "State node " << ndbNode->node_id << " "
+ << ndb_mgm_get_node_status_string(ndbNode->node_status)<< endl;
+
+ assert(ndbNode != NULL);
+
+ if(_status == NDB_MGM_NODE_STATUS_STARTING &&
+ ((ndbNode->node_status == NDB_MGM_NODE_STATUS_STARTING &&
+ ndbNode->start_phase >= _startphase) ||
+ (ndbNode->node_status == NDB_MGM_NODE_STATUS_STARTED)))
+ continue;
+
+ if (_status == NDB_MGM_NODE_STATUS_STARTING){
+ g_info << "status = "
+ << ndb_mgm_get_node_status_string(ndbNode->node_status)
+ <<", start_phase="<<ndbNode->start_phase<<endl;
+ if (ndbNode->node_status != _status) {
+ if (ndbNode->node_status < _status)
+ allInState = false;
+ else
+ g_info << "node_status(" << ndbNode->node_status
+ <<") != _status("<<_status<<")"<<endl;
+ } else if (ndbNode->start_phase < _startphase)
+ allInState = false;
+ } else {
+ if (ndbNode->node_status != _status)
+ allInState = false;
+ }
+ }
+ g_info << "Waiting for cluster enter state"
+ << ndb_mgm_get_node_status_string(_status)<< endl;
+ NdbSleep_SecSleep(1);
+ attempts++;
+ }
+ return 0;
+}
diff --git a/netware/BUILD/compile-linux-tools b/netware/BUILD/compile-linux-tools
index 886f866d674..70f07be649e 100755
--- a/netware/BUILD/compile-linux-tools
+++ b/netware/BUILD/compile-linux-tools
@@ -29,7 +29,7 @@ rm -f */*.linux
./configure --without-innodb --without-docs
# build tools only
-make clean config.h
+make clean all-local
(cd dbug; make libdbug.a)
(cd strings; make libmystrings.a)
(cd mysys; make libmysys.a)
@@ -43,6 +43,8 @@ make clean config.h
(cd extra; make comp_err)
(cd libmysql; make conf_to_src)
(cd libmysql_r; make conf_to_src)
+# so the file will be linked
+(cd sql; make sql_yacc.cc)
(cd sql; make gen_lex_hash)
(cd strings; make conf_to_src)
diff --git a/netware/BUILD/compile-netware-standard b/netware/BUILD/compile-netware-standard
index a21ea16a445..76a776a1da3 100755
--- a/netware/BUILD/compile-netware-standard
+++ b/netware/BUILD/compile-netware-standard
@@ -15,6 +15,7 @@ suffix="standard"
extra_configs=" \
--with-innodb \
--enable-thread-safe-client \
+ --with-archive-storage-engine \
"
. $path/compile-netware-END
diff --git a/netware/BUILD/mwenv b/netware/BUILD/mwenv
index 6f818b6f7a3..0acfd3aaf8f 100755
--- a/netware/BUILD/mwenv
+++ b/netware/BUILD/mwenv
@@ -1,13 +1,13 @@
#! /bin/sh
-# WINE_BUILD_DIR, BUILD_DIR, and VERSION must be correct before compiling
+# F:/mydev, /home/kp/mydev, and 4.0.21 must be correct before compiling
# This values are normally changed by the nwbootstrap script
# the default is "F:/mydev"
-export MYDEV="WINE_BUILD_DIR"
+export MYDEV="F:/mydev"
-export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV;$MYDEV/zlib-1.1.4"
-export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.1.4;$MYDEV/mysql-VERSION/netware/BUILD"
+export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.1.4;$MYDEV"
+export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.1.4;$MYDEV/openssl;$MYDEV/mysql-VERSION/netware/BUILD"
export MWNWx86LibraryFiles="libcpre.o;libc.imp;netware.imp;mwcrtl.lib;mwcpp.lib;libz.a;neb.imp;zPublics.imp;knetware.imp"
export WINEPATH="$MYDEV/mw/bin"
@@ -19,11 +19,10 @@ export AR='mwldnlm'
export AR_FLAGS='-type library -o'
export AS='mwasmnlm'
export CC='mwccnlm -gccincludes'
-export CFLAGS='-align 8 -proc 686 -relax_pointers -dialect c'
+export CFLAGS='-O3 -align 8 -proc 686 -relax_pointers -dialect c'
export CXX='mwccnlm -gccincludes'
-export CXXFLAGS='-align 8 -proc 686 -relax_pointers -dialect c++ -bool on -wchar_t on -D_WCHAR_T'
+export CXXFLAGS='-O3 -align 8 -proc 686 -relax_pointers -dialect c++ -bool on -wchar_t on -D_WCHAR_T'
export LD='mwldnlm'
export LDFLAGS='-entry _LibCPrelude -exit _LibCPostlude -map -flags pseudopreemption'
export RANLIB=:
export STRIP=:
-
diff --git a/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap
index f54775bf054..25e843c87e3 100755
--- a/netware/BUILD/nwbootstrap
+++ b/netware/BUILD/nwbootstrap
@@ -171,6 +171,16 @@ do
rm $file.org
done
+# create the libmysql.imp file in netware folder from libmysql/libmysql.def
+# file
+echo "generating llibmysql.imp file..."
+awk 'BEGIN{x=0;} x==1 {print $1;next} /EXPORTS/{x=1}' libmysql/libmysql.def > netware/libmysql.imp
+
+# create the libmysql.imp file in netware folder from libmysql/libmysql.def file
+echo "generating llibmysql.imp file..."
+awk 'BEGIN{x=0;} x==1 {print $1;next} /EXPORTS/{x=1}' libmysql/libmysql.def > netware/libmysql.imp
+
+
# build linux tools
echo "compiling linux tools..."
./netware/BUILD/compile-linux-tools
@@ -183,5 +193,3 @@ then
fi
echo "done"
-
-
diff --git a/netware/Makefile.am b/netware/Makefile.am
index 1f0277ef20e..2467270f27b 100644
--- a/netware/Makefile.am
+++ b/netware/Makefile.am
@@ -14,7 +14,10 @@
# 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_NETWARE
INCLUDES = -I$(srcdir)/../include -I../include -I..
+LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
+ ../dbug/libdbug.a ../strings/libmystrings.a
bin_PROGRAMS = mysqld_safe mysql_install_db mysql_test_run libmysql
mysqld_safe_SOURCES= mysqld_safe.c my_manage.c
mysql_install_db_SOURCES= mysql_install_db.c my_manage.c
@@ -43,7 +46,31 @@ link_sources:
org=`echo $$f | sed -e 's/.*\/\(.*\)/\1/g'`; \
@LN_CP_F@ $(srcdir)/$$org $(srcdir)/../$$f; \
done;
-
+else
+EXTRA_DIST= comp_err.def init_db.sql install_test_db.ncf \
+ isamchk.def isamlog.def libmysql.def libmysql.imp \
+ libmysqlmain.c my_manage.c my_manage.h \
+ my_print_defaults.def myisam_ftdump.def myisamchk.def \
+ myisamlog.def myisampack.def mysql.def mysql.xdc \
+ mysql_fix_privilege_tables.pl mysql_install.def \
+ mysql_install_db.c mysql_install_db.def \
+ mysql_secure_installation.pl mysql_test_run.c \
+ mysql_test_run.def mysql_waitpid.def mysqladmin.def \
+ mysqlbinlog.def mysqlcheck.def mysqld.def \
+ mysqld_safe.c mysqld_safe.def mysqldump.def mysqlimport.def \
+ mysqlshow.def mysqltest.def pack_isam.def perror.def \
+ replace.def resolve_stack_dump.def resolveip.def test_db.sql \
+ static_init_db.sql \
+ BUILD/apply-patch BUILD/compile-AUTOTOOLS \
+ BUILD/compile-linux-tools BUILD/compile-netware-END \
+ BUILD/compile-netware-START BUILD/compile-netware-all\
+ BUILD/compile-netware-debug BUILD/compile-netware-max \
+ BUILD/compile-netware-max-debug BUILD/compile-netware-src \
+ BUILD/compile-netware-standard BUILD/create-patch \
+ BUILD/cron-build BUILD/crontab BUILD/knetware.imp \
+ BUILD/mwasmnlm BUILD/mwccnlm BUILD/mwenv BUILD/mwldnlm \
+ BUILD/nwbootstrap BUILD/openssl.imp BUILD/save-patch
+endif
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/netware/init_db.sql b/netware/init_db.sql
index 52e08333a93..5e7ace0779b 100644
--- a/netware/init_db.sql
+++ b/netware/init_db.sql
@@ -28,3 +28,16 @@ CREATE TABLE help_topic (help_topic_id int unsigned NOT NULL, name varchar(64) N
CREATE TABLE help_category (help_category_id smallint unsigned NOT NULL, name varchar(64) NOT NULL, parent_category_id smallint unsigned null, url varchar(128) NOT NULL, primary key (help_category_id), unique index (name)) comment='help categories';
CREATE TABLE help_keyword (help_keyword_id int unsigned NOT NULL, name varchar(64) NOT NULL, primary key (help_keyword_id), unique index (name)) comment='help keywords';
CREATE TABLE help_relation (help_topic_id int unsigned NOT NULL references help_topic, help_keyword_id int unsigned NOT NULL references help_keyword, primary key (help_keyword_id, help_topic_id)) comment='keyword-topic relation';
+
+CREATE TABLE time_zone_name (Name char(64) NOT NULL,Time_zone_id int unsigned NOT NULL,PRIMARY KEY Name (Name)) DEFAULT CHARACTER SET latin1 comment='Time zone names';
+INSERT INTO time_zone_name (Name, Time_Zone_id) VALUES ('MET', 1), ('UTC', 2), ('Universal', 2), ('Europe/Moscow',3), ('leap/Europe/Moscow',4);
+
+CREATE TABLE time_zone (Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') DEFAULT 'N' NOT NULL,PRIMARY KEY TzId (Time_zone_id)) DEFAULT CHARACTER SET latin1 comment='Time zones';
+INSERT INTO time_zone (Time_zone_id, Use_leap_seconds) VALUES (1,'N'), (2,'N'), (3,'N'), (4,'Y');
+CREATE TABLE time_zone_transition (Time_zone_id int unsigned NOT NULL,Transition_time bigint signed NOT NULL,Transition_type_id int unsigned NOT NULL,PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time)) DEFAULT CHARACTER SET latin1 comment='Time zone transitions';
+INSERT INTO time_zone_transition (Time_zone_id, Transition_time, Transition_type_id) VALUES(1, -1693706400, 0) ,(1, -1680483600, 1),(1, -1663455600, 2) ,(1, -1650150000, 3),(1, -1632006000, 2) ,(1, -1618700400, 3),(1, -938905200, 2) ,(1, -857257200, 3),(1, -844556400, 2) ,(1, -828226800, 3),(1, -812502000, 2) ,(1, -796777200, 3),(1, 228877200, 2) ,(1, 243997200, 3),(1, 260326800, 2) ,(1, 276051600, 3),(1, 291776400, 2) ,(1, 307501200, 3),(1, 323830800, 2) ,(1, 338950800, 3),(1, 354675600, 2) ,(1, 370400400, 3),(1, 386125200, 2) ,(1, 401850000, 3),(1, 417574800, 2) ,(1, 433299600, 3),(1, 449024400, 2) ,(1, 465354000, 3),(1, 481078800, 2) ,(1, 496803600, 3),(1, 512528400, 2) ,(1, 528253200, 3),(1, 543978000, 2) ,(1, 559702800, 3),(1, 575427600, 2) ,(1, 591152400, 3),(1, 606877200, 2) ,(1, 622602000, 3),(1, 638326800, 2) ,(1, 654656400, 3),(1, 670381200, 2) ,(1, 686106000, 3),(1, 701830800, 2) ,(1, 717555600, 3) ,(1, 733280400, 2) ,(1, 749005200, 3) ,(1, 764730000, 2) ,(1, 780454800, 3) ,(1, 796179600, 2) ,(1, 811904400, 3) ,(1, 828234000, 2) ,(1, 846378000, 3) ,(1, 859683600, 2) ,(1, 877827600, 3) ,(1, 891133200, 2) ,(1, 909277200, 3) ,(1, 922582800, 2) ,(1, 941331600, 3) ,(1, 954032400, 2) ,(1, 972781200, 3) ,(1, 985482000, 2) ,(1, 1004230800, 3) ,(1, 1017536400, 2) ,(1, 1035680400, 3) ,(1, 1048986000, 2) ,(1, 1067130000, 3) ,(1, 1080435600, 2) ,(1, 1099184400, 3) ,(1, 1111885200, 2) ,(1, 1130634000, 3) ,(1, 1143334800, 2) ,(1, 1162083600, 3) ,(1, 1174784400, 2) ,(1, 1193533200, 3) ,(1, 1206838800, 2) ,(1, 1224982800, 3) ,(1, 1238288400, 2) ,(1, 1256432400, 3) ,(1, 1269738000, 2) ,(1, 1288486800, 3) ,(1, 1301187600, 2) ,(1, 1319936400, 3) ,(1, 1332637200, 2) ,(1, 1351386000, 3) ,(1, 1364691600, 2) ,(1, 1382835600, 3) ,(1, 1396141200, 2) ,(1, 1414285200, 3) ,(1, 1427590800, 2) ,(1, 1445734800, 3) ,(1, 1459040400, 2) ,(1, 1477789200, 3) ,(1, 1490490000, 2) ,(1, 1509238800, 3) ,(1, 1521939600, 2) ,(1, 1540688400, 3) ,(1, 1553994000, 2) ,(1, 1572138000, 3) ,(1, 1585443600, 2) ,(1, 1603587600, 3) ,(1, 1616893200, 2) ,(1, 1635642000, 3) ,(1, 1648342800, 2) ,(1, 1667091600, 3) ,(1, 1679792400, 2) ,(1, 1698541200, 3) ,(1, 1711846800, 2) ,(1, 1729990800, 3) ,(1, 1743296400, 2) ,(1, 1761440400, 3) ,(1, 1774746000, 2) ,(1, 1792890000, 3) ,(1, 1806195600, 2) ,(1, 1824944400, 3) ,(1, 1837645200, 2) ,(1, 1856394000, 3) ,(1, 1869094800, 2) ,(1, 1887843600, 3) ,(1, 1901149200, 2) ,(1, 1919293200, 3) ,(1, 1932598800, 2) ,(1, 1950742800, 3) ,(1, 1964048400, 2) ,(1, 1982797200, 3) ,(1, 1995498000, 2) ,(1, 2014246800, 3) ,(1, 2026947600, 2) ,(1, 2045696400, 3) ,(1, 2058397200, 2) ,(1, 2077146000, 3) ,(1, 2090451600, 2) ,(1, 2108595600, 3) ,(1, 2121901200, 2) ,(1, 2140045200, 3) ,(3, -1688265000, 2) ,(3, -1656819048, 1) ,(3, -1641353448, 2) ,(3, -1627965048, 3) ,(3, -1618716648, 1) ,(3, -1596429048, 3) ,(3, -1593829848, 5) ,(3, -1589860800, 4) ,(3, -1542427200, 5) ,(3, -1539493200, 6) ,(3, -1525323600, 5) ,(3, -1522728000, 4) ,(3, -1491188400, 7) ,(3, -1247536800, 4) ,(3, 354920400, 5) ,(3, 370728000, 4) ,(3, 386456400, 5) ,(3, 402264000, 4) ,(3, 417992400, 5) ,(3, 433800000, 4) ,(3, 449614800, 5) ,(3, 465346800, 8) ,(3, 481071600, 9) ,(3, 496796400, 8) ,(3, 512521200, 9) ,(3, 528246000, 8) ,(3, 543970800, 9) ,(3, 559695600, 8) ,(3, 575420400, 9) ,(3, 591145200, 8) ,(3, 606870000, 9) ,(3, 622594800, 8) ,(3, 638319600, 9) ,(3, 654649200, 8) ,(3, 670374000, 10) ,(3, 686102400, 11) ,(3, 695779200, 8) ,(3, 701812800, 5) ,(3, 717534000, 4) ,(3, 733273200, 9) ,(3, 748998000, 8) ,(3, 764722800, 9) ,(3, 780447600, 8) ,(3, 796172400, 9) ,(3, 811897200, 8) ,(3, 828226800, 9) ,(3, 846370800, 8) ,(3, 859676400, 9) ,(3, 877820400, 8) ,(3, 891126000, 9) ,(3, 909270000, 8) ,(3, 922575600, 9) ,(3, 941324400, 8) ,(3, 954025200, 9) ,(3, 972774000, 8) ,(3, 985474800, 9) ,(3, 1004223600, 8) ,(3, 1017529200, 9) ,(3, 1035673200, 8) ,(3, 1048978800, 9) ,(3, 1067122800, 8) ,(3, 1080428400, 9) ,(3, 1099177200, 8) ,(3, 1111878000, 9) ,(3, 1130626800, 8) ,(3, 1143327600, 9) ,(3, 1162076400, 8) ,(3, 1174777200, 9) ,(3, 1193526000, 8) ,(3, 1206831600, 9) ,(3, 1224975600, 8) ,(3, 1238281200, 9) ,(3, 1256425200, 8) ,(3, 1269730800, 9) ,(3, 1288479600, 8) ,(3, 1301180400, 9) ,(3, 1319929200, 8) ,(3, 1332630000, 9) ,(3, 1351378800, 8) ,(3, 1364684400, 9) ,(3, 1382828400, 8) ,(3, 1396134000, 9) ,(3, 1414278000, 8) ,(3, 1427583600, 9) ,(3, 1445727600, 8) ,(3, 1459033200, 9) ,(3, 1477782000, 8) ,(3, 1490482800, 9) ,(3, 1509231600, 8) ,(3, 1521932400, 9) ,(3, 1540681200, 8) ,(3, 1553986800, 9) ,(3, 1572130800, 8) ,(3, 1585436400, 9) ,(3, 1603580400, 8) ,(3, 1616886000, 9) ,(3, 1635634800, 8) ,(3, 1648335600, 9) ,(3, 1667084400, 8) ,(3, 1679785200, 9) ,(3, 1698534000, 8) ,(3, 1711839600, 9) ,(3, 1729983600, 8) ,(3, 1743289200, 9) ,(3, 1761433200, 8) ,(3, 1774738800, 9) ,(3, 1792882800, 8) ,(3, 1806188400, 9) ,(3, 1824937200, 8) ,(3, 1837638000, 9) ,(3, 1856386800, 8) ,(3, 1869087600, 9) ,(3, 1887836400, 8) ,(3, 1901142000, 9) ,(3, 1919286000, 8) ,(3, 1932591600, 9) ,(3, 1950735600, 8) ,(3, 1964041200, 9) ,(3, 1982790000, 8) ,(3, 1995490800, 9) ,(3, 2014239600, 8) ,(3, 2026940400, 9) ,(3, 2045689200, 8) ,(3, 2058390000, 9) ,(3, 2077138800, 8) ,(3, 2090444400, 9) ,(3, 2108588400, 8) ,(3, 2121894000, 9) ,(3, 2140038000, 8) ,(4, -1688265000, 2) ,(4, -1656819048, 1) ,(4, -1641353448, 2) ,(4, -1627965048, 3) ,(4, -1618716648, 1) ,(4, -1596429048, 3) ,(4, -1593829848, 5) ,(4, -1589860800, 4) ,(4, -1542427200, 5) ,(4, -1539493200, 6) ,(4, -1525323600, 5) ,(4, -1522728000, 4) ,(4, -1491188400, 7) ,(4, -1247536800, 4) ,(4, 354920409, 5) ,(4, 370728010, 4) ,(4, 386456410, 5) ,(4, 402264011, 4) ,(4, 417992411, 5) ,(4, 433800012, 4) ,(4, 449614812, 5) ,(4, 465346812, 8) ,(4, 481071612, 9) ,(4, 496796413, 8) ,(4, 512521213, 9) ,(4, 528246013, 8) ,(4, 543970813, 9) ,(4, 559695613, 8) ,(4, 575420414, 9) ,(4, 591145214, 8) ,(4, 606870014, 9) ,(4, 622594814, 8) ,(4, 638319615, 9) ,(4, 654649215, 8) ,(4, 670374016, 10) ,(4, 686102416, 11) ,(4, 695779216, 8) ,(4, 701812816, 5) ,(4, 717534017, 4) ,(4, 733273217, 9) ,(4, 748998018, 8) ,(4, 764722818, 9) ,(4, 780447619, 8) ,(4, 796172419, 9) ,(4, 811897219, 8) ,(4, 828226820, 9) ,(4, 846370820, 8) ,(4, 859676420, 9) ,(4, 877820421, 8) ,(4, 891126021, 9) ,(4, 909270021, 8) ,(4, 922575622, 9) ,(4, 941324422, 8) ,(4, 954025222, 9) ,(4, 972774022, 8) ,(4, 985474822, 9) ,(4, 1004223622, 8) ,(4, 1017529222, 9) ,(4, 1035673222, 8) ,(4, 1048978822, 9) ,(4, 1067122822, 8) ,(4, 1080428422, 9) ,(4, 1099177222, 8) ,(4, 1111878022, 9) ,(4, 1130626822, 8) ,(4, 1143327622, 9) ,(4, 1162076422, 8) ,(4, 1174777222, 9) ,(4, 1193526022, 8) ,(4, 1206831622, 9) ,(4, 1224975622, 8) ,(4, 1238281222, 9) ,(4, 1256425222, 8) ,(4, 1269730822, 9) ,(4, 1288479622, 8) ,(4, 1301180422, 9) ,(4, 1319929222, 8) ,(4, 1332630022, 9) ,(4, 1351378822, 8) ,(4, 1364684422, 9) ,(4, 1382828422, 8) ,(4, 1396134022, 9) ,(4, 1414278022, 8) ,(4, 1427583622, 9) ,(4, 1445727622, 8) ,(4, 1459033222, 9) ,(4, 1477782022, 8) ,(4, 1490482822, 9) ,(4, 1509231622, 8) ,(4, 1521932422, 9) ,(4, 1540681222, 8) ,(4, 1553986822, 9) ,(4, 1572130822, 8) ,(4, 1585436422, 9) ,(4, 1603580422, 8) ,(4, 1616886022, 9) ,(4, 1635634822, 8) ,(4, 1648335622, 9) ,(4, 1667084422, 8) ,(4, 1679785222, 9) ,(4, 1698534022, 8) ,(4, 1711839622, 9) ,(4, 1729983622, 8) ,(4, 1743289222, 9) ,(4, 1761433222, 8) ,(4, 1774738822, 9) ,(4, 1792882822, 8) ,(4, 1806188422, 9) ,(4, 1824937222, 8) ,(4, 1837638022, 9) ,(4, 1856386822, 8) ,(4, 1869087622, 9) ,(4, 1887836422, 8) ,(4, 1901142022, 9) ,(4, 1919286022, 8) ,(4, 1932591622, 9) ,(4, 1950735622, 8) ,(4, 1964041222, 9) ,(4, 1982790022, 8) ,(4, 1995490822, 9) ,(4, 2014239622, 8) ,(4, 2026940422, 9) ,(4, 2045689222, 8) ,(4, 2058390022, 9) ,(4, 2077138822, 8) ,(4, 2090444422, 9) ,(4, 2108588422, 8) ,(4, 2121894022, 9) ,(4, 2140038022, 8);
+
+CREATE TABLE time_zone_transition_type (Time_zone_id int unsigned NOT NULL,Transition_type_id int unsigned NOT NULL,Offset int signed DEFAULT 0 NOT NULL,Is_DST tinyint unsigned DEFAULT 0 NOT NULL,Abbreviation char(8) DEFAULT '' NOT NULL,PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id)) DEFAULT CHARACTER SET latin1 comment='Time zone transition types';
+INSERT INTO time_zone_transition_type (Time_zone_id,Transition_type_id, Offset, Is_DST, Abbreviation) VALUES(1, 0, 7200, 1, 'MEST') ,(1, 1, 3600, 0, 'MET'),(1, 2, 7200, 1, 'MEST') ,(1, 3, 3600, 0, 'MET'),(2, 0, 0, 0, 'UTC'),(3, 0, 9000, 0, 'MMT') ,(3, 1, 12648, 1, 'MST'),(3, 2, 9048, 0, 'MMT') ,(3, 3, 16248, 1, 'MDST'),(3, 4, 10800, 0, 'MSK') ,(3, 5, 14400, 1, 'MSD'),(3, 6, 18000, 1, 'MSD') ,(3, 7, 7200, 0, 'EET'),(3, 8, 10800, 0, 'MSK') ,(3, 9, 14400, 1, 'MSD'),(3, 10, 10800, 1, 'EEST') ,(3, 11, 7200, 0, 'EET'),(4, 0, 9000, 0, 'MMT') ,(4, 1, 12648, 1, 'MST'),(4, 2, 9048, 0, 'MMT') ,(4, 3, 16248, 1, 'MDST'),(4, 4, 10800, 0, 'MSK') ,(4, 5, 14400, 1, 'MSD'),(4, 6, 18000, 1, 'MSD') ,(4, 7, 7200, 0, 'EET'),(4, 8, 10800, 0, 'MSK') ,(4, 9, 14400, 1, 'MSD'),(4, 10, 10800, 1, 'EEST') ,(4, 11, 7200, 0, 'EET');
+CREATE TABLE time_zone_leap_second (Transition_time bigint signed NOT NULL,Correction int signed NOT NULL,PRIMARY KEY TranTime (Transition_time)) DEFAULT CHARACTER SET latin1 comment='Leap seconds information for time zones';
+INSERT INTO time_zone_leap_second (Transition_time, Correction) VALUES (78796800, 1) ,(94694401, 2) ,(126230402, 3),(157766403, 4) ,(189302404, 5) ,(220924805, 6),(252460806, 7) ,(283996807, 8) ,(315532808, 9),(362793609, 10) ,(394329610, 11) ,(425865611, 12),(489024012, 13) ,(567993613, 14) ,(631152014, 15),(662688015, 16) ,(709948816, 17) ,(741484817, 18),(773020818, 19) ,(820454419, 20) ,(867715220, 21),(915148821, 22);
diff --git a/netware/my_manage.c b/netware/my_manage.c
index f5aa3163431..29514837837 100644
--- a/netware/my_manage.c
+++ b/netware/my_manage.c
@@ -200,11 +200,11 @@ int wait_for_server_start(char *bin_dir, char *user, char *password, int port,ch
add_arg(&al, "--password=%s", password);
add_arg(&al, "--silent");
- /** Not supported on NetWare
+#ifdef NOT_USED
add_arg(&al, "-O");
add_arg(&al, "connect_timeout=10");
add_arg(&al, "-w");
- **/
+#endif
add_arg(&al, "--host=localhost");
add_arg(&al, "ping");
@@ -475,4 +475,3 @@ void get_basedir(char *argv0, char *basedir)
strcpy(basedir, temp);
}
}
-
diff --git a/netware/mysql_fix_privilege_tables.pl b/netware/mysql_fix_privilege_tables.pl
index fd5bc11dde1..c0a428eff0f 100644
--- a/netware/mysql_fix_privilege_tables.pl
+++ b/netware/mysql_fix_privilege_tables.pl
@@ -1,16 +1,16 @@
#-----------------------------------------------------------------------------
# Copyright (C) 2002 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
@@ -19,7 +19,7 @@
#-----------------------------------------------------------------------------
# This notice applies to changes, created by or for Novell, Inc.,
# to preexisting works for which notices appear elsewhere in this file.
-
+
# Copyright (c) 2003 Novell, Inc. All Rights Reserved.
# This program is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#-----------------------------------------------------------------------------
-use strict;
+#use strict;
use Mysql;
print "MySQL Fix Privilege Tables Script\n\n";
@@ -63,12 +63,27 @@ my $conn = Mysql->connect("localhost", "mysql", "root", $password)
|| die "Unable to connect to MySQL.";
print "OK, successfully used the password, moving on...\n\n";
-
-
+
+
#-----------------------------------------------------------------------------
# MySQL 4.0.2
#-----------------------------------------------------------------------------
+#-- Detect whether or not we had the Grant_priv column
+print "Fixing privileges for old tables...\n";
+$conn->query("SET \@hadGrantPriv:=0;");
+$conn->query("SELECT \@hadGrantPriv:=1 FROM user WHERE Grant_priv LIKE '%';");
+
+#--- Fix privileges for old tables
+$conn->query("UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE \@hadGrantPriv = 0;");
+$conn->query("UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE \@hadGrantPriv = 0;");
+$conn->query("UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE \@hadGrantPriv = 0;");
+
+
+# Detect whether we had Show_db_priv
+$conn->query("SET \@hadShowDbPriv:=0;");
+$conn->query("SELECT \@hadShowDbPriv:=1 FROM user WHERE Show_db_priv LIKE '%';");
+
print "Adding new fields used by MySQL 4.0.2 to the privilege tables...\n";
print "NOTE: You can ignore any Duplicate column errors.\n";
$conn->query(" \
@@ -81,9 +96,11 @@ ADD Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv, \
ADD Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Execute_priv, \
ADD Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_slave_priv; \
") && $conn->query(" \
-UPDATE user SET show_db_priv=select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>''; \
+UPDATE user SET show_db_priv=select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>''AND \@hadShowDbPriv = 0; \
");
+#-- The above statement converts privileges so that users have similar privileges as before
+
#-----------------------------------------------------------------------------
# MySQL 4.0 Limitations
#-----------------------------------------------------------------------------
@@ -97,6 +114,22 @@ ADD max_updates int(11) unsigned NOT NULL AFTER max_questions, \
ADD max_connections int(11) unsigned NOT NULL AFTER max_updates; \
");
+#-- Change the password column to suite the new password hashing used
+#-- in 4.1.1 onward
+$conn->query("ALTER TABLE user change Password Password char(41) binary not null;");
+
+#-- The second alter changes ssl_type to new 4.0.2 format
+#-- Adding columns needed by GRANT .. REQUIRE (openssl)"
+print "Adding new fields to use in ssl authentication...\n";
+
+$conn->query(" \
+ALTER TABLE user \
+ADD ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL, \
+ADD ssl_cipher BLOB NOT NULL, \
+ADD x509_issuer BLOB NOT NULL, \
+ADD x509_subject BLOB NOT NULL; \
+");
+
#-----------------------------------------------------------------------------
# MySQL 4.0 DB and Host privs
#-----------------------------------------------------------------------------
@@ -115,6 +148,77 @@ ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, \
ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL; \
");
+#
+# Change the Table_name column to be of char(64) which was char(60) by mistake till now.
+#
+$conn->query("alter table tables_priv change Table_name Table_name char(64) binary DEFAULT '' NOT NULL;");
+
+
+#
+# Create some possible missing tables
+#
+print "Adding online help tables...\n";
+
+$conn->query(" \
+CREATE TABLE IF NOT EXISTS help_topic ( \
+help_topic_id int unsigned not null, \
+name varchar(64) not null, \
+help_category_id smallint unsigned not null, \
+description text not null, \
+example text not null, \
+url varchar(128) not null, \
+primary key (help_topic_id), unique index (name) \
+) comment='help topics'; \
+");
+
+$conn->query(" \
+CREATE TABLE IF NOT EXISTS help_category ( \
+help_category_id smallint unsigned not null, \
+name varchar(64) not null, \
+parent_category_id smallint unsigned null, \
+url varchar(128) not null, \
+primary key (help_category_id), \
+unique index (name) \
+) comment='help categories'; \
+");
+
+$conn->query(" \
+CREATE TABLE IF NOT EXISTS help_relation ( \
+help_topic_id int unsigned not null references help_topic, \
+help_keyword_id int unsigned not null references help_keyword, \
+primary key (help_keyword_id, help_topic_id) \
+) comment='keyword-topic relation'; \
+");
+
+$conn->query(" \
+CREATE TABLE IF NOT EXISTS help_keyword ( \
+help_keyword_id int unsigned not null, \
+name varchar(64) not null, \
+primary key (help_keyword_id), \
+unique index (name) \
+) comment='help keywords'; \
+");
+
+
+#
+# Filling the help tables with contents.
+#
+print "Filling online help tables with contents...\n";
+# Generate the path for "fill_help_tables.sql" file which is in different folder.
+$fill_help_table=$0;
+$fill_help_table =~ s/scripts[\\\/]mysql_fix_privilege_tables.pl/support-files\\fill_help_tables.sql/;
+
+#read all content from the sql file which contains recordsfor help tables.
+open(fileIN,$fill_help_table) or die("Cannot open $fill_help_table: $!");
+@logData = <fileIN>;
+close(fileIN);
+foreach $line (@logData) {
+# if the line is not empty, insert a record in the table.
+ if( ! ($line =~ /^\s*$/) ) {
+ $conn->query("$line");
+ }
+}
+
#-----------------------------------------------------------------------------
# done
#-----------------------------------------------------------------------------
@@ -122,4 +226,3 @@ ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL; \
print "\n\nAll done!\n\n";
print "Thanks for using MySQL!\n\n";
-
diff --git a/netware/mysql_test_run.c b/netware/mysql_test_run.c
index 06d5e5985c1..a69c5015968 100644
--- a/netware/mysql_test_run.c
+++ b/netware/mysql_test_run.c
@@ -16,22 +16,15 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
+#include <my_global.h>
+#include <m_string.h>
#include <dirent.h>
-#include <string.h>
#include <screen.h>
#include <nks/vm.h>
#include <ctype.h>
#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
#include <sys/mode.h>
-
-#include "my_config.h"
#include "my_manage.h"
-
/******************************************************************************
macros
@@ -148,11 +141,12 @@ int read_option(char *, char *);
void run_test(char *);
void setup(char *);
void vlog(char *, va_list);
-void log(char *, ...);
+void log_msg(char *, ...);
void log_info(char *, ...);
void log_error(char *, ...);
void log_errno(char *, ...);
void die(char *);
+char *str_tok(char *string, const char *delim);
/******************************************************************************
@@ -165,21 +159,21 @@ void report_stats()
{
if (total_fail == 0)
{
- log("\nAll %d test(s) were successful.\n", total_test);
+ log_msg("\nAll %d test(s) were successful.\n", total_test);
}
else
{
double percent = ((double)total_pass / total_test) * 100;
- log("\nFailed %u/%u test(s), %.02f%% successful.\n",
+ log_msg("\nFailed %u/%u test(s), %.02f%% successful.\n",
total_fail, total_test, percent);
- log("\nThe .out and .err files in %s may give you some\n", result_dir);
- log("hint of what when wrong.\n");
- log("\nIf you want to report this error, please first read the documentation\n");
- log("at: http://www.mysql.com/doc/M/y/MySQL_test_suite.html\n");
+ log_msg("\nThe .out and .err files in %s may give you some\n", result_dir);
+ log_msg("hint of what when wrong.\n");
+ log_msg("\nIf you want to report this error, please first read the documentation\n");
+ log_msg("at: http://www.mysql.com/doc/M/y/MySQL_test_suite.html\n");
}
- log("\n%.02f total minutes elapsed in the test cases\n\n", total_time / 60);
+ log_msg("\n%.02f total minutes elapsed in the test cases\n\n", total_time / 60);
}
/******************************************************************************
@@ -244,6 +238,7 @@ void mysql_install_db()
mkdir(temp, S_IRWXU);
// create subdirectories
+ log_msg("Creating test-suite folders...\n");
snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir);
mkdir(temp, S_IRWXU);
snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir);
@@ -262,7 +257,9 @@ void mysql_install_db()
mkdir(temp, S_IRWXU);
// install databases
+ log_msg("Creating test databases for master... \n");
install_db(master_dir);
+ log_msg("Creating test databases for slave... \n");
install_db(slave_dir);
}
@@ -346,6 +343,9 @@ 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);
+#ifdef DEBUG //only for debug builds
+ add_arg(&al, "--debug");
+#endif
if (use_openssl)
{
@@ -370,33 +370,28 @@ void start_master()
if (master_opt[0] != NULL)
{
char *p;
- char *temp;
-
- p = (char *)strtok(master_opt, " \t");
- if ((temp = strstr(p, "timezone")) == NULL)
+ p = (char *)str_tok(master_opt, " \t");
+ if (!strstr(master_opt, "timezone"))
{
- while(p)
+ while (p)
{
add_arg(&al, "%s", p);
- p = (char *)strtok(NULL, " \t");
+ p = (char *)str_tok(NULL, " \t");
}
}
- else
- {
- //do nothing
- }
}
// remove the pid file if it exists
remove(master_pid);
// spawn
- if ((err = spawn(mysqld_file, &al, FALSE, NULL, master_out, master_err)) == 0)
+ if ((err= spawn(mysqld_file, &al, FALSE, NULL, master_out, master_err)) == 0)
{
sleep_until_file_exists(master_pid);
- if ((err = wait_for_server_start(bin_dir, user, password, master_port,mysql_tmp_dir)) == 0)
+ if ((err = wait_for_server_start(bin_dir, user, password, master_port,
+ mysql_tmp_dir)) == 0)
{
master_running = TRUE;
}
@@ -467,11 +462,11 @@ void start_slave()
snprintf(temp, PATH_MAX, "%s/master.info", slave_dir);
fp = fopen(temp, "wb+");
- fputs("master-bin.001\n", fp);
+ fputs("master-bin.000001\n", fp);
fputs("4\n", fp);
fputs("127.0.0.1\n", fp);
fputs("replicate\n", fp);
- fputs("aaaaaaaaaaaaaaabthispartofthepasswordisnotused\n", fp);
+ fputs("aaaaaaaaaaaaaaab\n", fp);
fputs("9306\n", fp);
fputs("1\n", fp);
fputs("0\n", fp);
@@ -521,6 +516,9 @@ void start_slave()
add_arg(&al, "--master-retry-count=10");
add_arg(&al, "-O");
add_arg(&al, "slave_net_timeout=10");
+#ifdef DEBUG //only for debug builds
+ add_arg(&al, "--debug");
+#endif
if (use_openssl)
{
@@ -534,13 +532,13 @@ void start_slave()
{
char *p;
- p = (char *)strtok(slave_master_info, " \t");
+ p = (char *)str_tok(slave_master_info, " \t");
while(p)
{
add_arg(&al, "%s", p);
- p = (char *)strtok(NULL, " \t");
+ p = (char *)str_tok(NULL, " \t");
}
}
else
@@ -567,13 +565,13 @@ void start_slave()
{
char *p;
- p = (char *)strtok(slave_opt, " \t");
+ p = (char *)str_tok(slave_opt, " \t");
while(p)
{
add_arg(&al, "%s", p);
- p = (char *)strtok(NULL, " \t");
+ p = (char *)str_tok(NULL, " \t");
}
}
@@ -585,18 +583,22 @@ void start_slave()
{
sleep_until_file_exists(slave_pid);
- if ((err = wait_for_server_start(bin_dir, user, password, slave_port,mysql_tmp_dir)) == 0)
+ if ((err = wait_for_server_start(bin_dir, user, password, slave_port,
+ mysql_tmp_dir)) == 0)
{
slave_running = TRUE;
+
}
else
{
log_error("The slave server went down early.");
+
}
}
else
{
log_error("Unable to start slave server.");
+
}
// free args
@@ -636,7 +638,8 @@ void stop_slave()
if (!slave_running) return;
// stop
- if ((err = stop_server(bin_dir, user, password, slave_port, slave_pid,mysql_tmp_dir)) == 0)
+ if ((err = stop_server(bin_dir, user, password, slave_port, slave_pid,
+ mysql_tmp_dir)) == 0)
{
slave_running = FALSE;
}
@@ -660,7 +663,8 @@ void stop_master()
// running?
if (!master_running) return;
- if ((err = stop_server(bin_dir, user, password, master_port, master_pid,mysql_tmp_dir)) == 0)
+ if ((err = stop_server(bin_dir, user, password, master_port, master_pid,
+ mysql_tmp_dir)) == 0)
{
master_running = FALSE;
}
@@ -697,6 +701,7 @@ void mysql_stop()
******************************************************************************/
void mysql_restart()
{
+ log_info("Restarting the MySQL server(s): %u", ++restarts);
mysql_stop();
@@ -758,6 +763,12 @@ int read_option(char *opt_file, char *opt)
strcat(opt, temp);
}
+ // Check for double backslash and replace it with single bakslash
+ if ((p = strstr(opt, "\\\\")) != NULL)
+ {
+ /* bmove is guranteed to work byte by byte */
+ bmove(p, p+1, strlen(p+1));
+ }
}
else
{
@@ -786,20 +797,16 @@ void run_test(char *test)
int flag = FALSE;
struct stat info;
- // single test?
-// if (!single_test)
- {
- // skip tests in the skip list
- snprintf(temp, PATH_MAX, " %s ", test);
- skip = (strindex(skip_test, temp) != NULL);
- if( skip == FALSE )
- ignore = (strindex(ignore_test, temp) != NULL);
- }
+ // skip tests in the skip list
+ snprintf(temp, PATH_MAX, " %s ", test);
+ skip = (strindex(skip_test, temp) != NULL);
+ if (skip == FALSE)
+ ignore = (strindex(ignore_test, temp) != NULL);
- if(ignore)
+ if (ignore)
{
// show test
- log("%-46s ", test);
+ log_msg("%-46s ", test);
// ignore
rstr = TEST_IGNORE;
@@ -837,7 +844,7 @@ void run_test(char *test)
if (stat(test_file, &info))
{
snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, TEST_SUFFIX);
- if(access(test_file,0))
+ if (access(test_file,0))
{
printf("Invalid test name %s, %s file not found\n",test,test_file);
return;
@@ -881,7 +888,7 @@ void run_test(char *test)
sleep(1);
// show test
- log("%-46s ", test);
+ log_msg("%-46s ", test);
// args
init_args(&al);
@@ -953,7 +960,7 @@ void run_test(char *test)
else // early skips
{
// show test
- log("%-46s ", test);
+ log_msg("%-46s ", test);
// skip
rstr = TEST_SKIP;
@@ -961,7 +968,7 @@ void run_test(char *test)
}
// result
- log("%10.06f %-14s\n", elapsed, rstr);
+ log_msg("%10.06f %-14s\n", elapsed, rstr);
}
/******************************************************************************
@@ -990,7 +997,7 @@ void vlog(char *format, va_list ap)
Log the message.
******************************************************************************/
-void log(char *format, ...)
+void log_msg(char *format, ...)
{
va_list ap;
@@ -1014,9 +1021,9 @@ void log_info(char *format, ...)
va_start(ap, format);
- log("-- INFO : ");
+ log_msg("-- INFO : ");
vlog(format, ap);
- log("\n");
+ log_msg("\n");
va_end(ap);
}
@@ -1034,9 +1041,9 @@ void log_error(char *format, ...)
va_start(ap, format);
- log("-- ERROR: ");
+ log_msg("-- ERROR: ");
vlog(format, ap);
- log("\n");
+ log_msg("\n");
va_end(ap);
}
@@ -1054,9 +1061,9 @@ void log_errno(char *format, ...)
va_start(ap, format);
- log("-- ERROR: (%003u) ", errno);
+ log_msg("-- ERROR: (%003u) ", errno);
vlog(format, ap);
- log("\n");
+ log_msg("\n");
va_end(ap);
}
@@ -1087,8 +1094,7 @@ void die(char *msg)
void setup(char *file)
{
char temp[PATH_MAX];
- char mysqldump_load[PATH_MAX*2],mysqlbinlog_load[PATH_MAX*2];
-
+ char file_path[PATH_MAX*2];
char *p;
// set the timezone for the timestamp test
@@ -1145,13 +1151,16 @@ void setup(char *file)
strcpy(temp, strlwr(skip_test));
snprintf(skip_test, PATH_MAX, " %s ", temp);
- snprintf(mysqlbinlog_load,PATH_MAX*2,"%s/mysqlbinlog --no-defaults --local-load=%s",bin_dir,mysql_tmp_dir);
- snprintf(mysqldump_load,PATH_MAX*2,"%s/mysqldump --no-defaults -uroot --port=%d",bin_dir,master_port);
// environment
setenv("MYSQL_TEST_DIR", mysql_test_dir, 1);
- setenv("MYSQL_DUMP", mysqldump_load, 1);
- setenv("MYSQL_BINLOG", mysqlbinlog_load, 1);
+ snprintf(file_path, PATH_MAX*2, "%s/mysqldump --no-defaults -u root --port=%u", bin_dir, master_port);
+ setenv("MYSQL_DUMP", file_path, 1);
+ snprintf(file_path, PATH_MAX*2, "%s/mysqlbinlog --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir);
+ setenv("MYSQL_BINLOG", file_path, 1);
setenv("MASTER_MYPORT", "9306", 1);
+ setenv("SLAVE_MYPORT", "9307", 1);
+ setenv("MYSQL_TCP_PORT", "3306", 1);
+
}
/******************************************************************************
@@ -1165,20 +1174,22 @@ int main(int argc, char **argv)
// setup
setup(argv[0]);
- /* The --ignore option is comma saperated list of test cases to skip and should
- * be very first command line option to the test suite.
- * The usage is now:
- * mysql_test_run --ignore=test1,test2 test3 test4
- * where test1 and test2 are test cases to ignore
- * and test3 and test4 are test cases to run. */
- if( argc >= 2 && !strnicmp(argv[1], "--ignore=", sizeof("--ignore=")-1) )
+ /* The --ignore option is comma saperated list of test cases to skip and
+ should be very first command line option to the test suite.
+
+ The usage is now:
+ mysql_test_run --ignore=test1,test2 test3 test4
+ where test1 and test2 are test cases to ignore
+ and test3 and test4 are test cases to run.
+ */
+ if (argc >= 2 && !strnicmp(argv[1], "--ignore=", sizeof("--ignore=")-1))
{
char *temp, *token;
- temp=strdup(strchr(argv[1],'=') + 1);
- for(token=strtok(temp, ","); token != NULL; token=strtok(NULL, ","))
+ temp= strdup(strchr(argv[1],'=') + 1);
+ for (token=str_tok(temp, ","); token != NULL; token=str_tok(NULL, ","))
{
- if( strlen(ignore_test) + strlen(token) + 2 <= PATH_MAX-1 )
- sprintf( ignore_test+strlen(ignore_test), " %s ", token);
+ if (strlen(ignore_test) + strlen(token) + 2 <= PATH_MAX-1)
+ sprintf(ignore_test+strlen(ignore_test), " %s ", token);
else
{
free(temp);
@@ -1189,18 +1200,18 @@ int main(int argc, char **argv)
is_ignore_list = 1;
}
// header
- log("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE);
+ log_msg("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE);
- log("Initializing Tests...\n");
+ log_msg("Initializing Tests...\n");
// install test databases
mysql_install_db();
- log("Starting Tests...\n");
+ log_msg("Starting Tests...\n");
- log("\n");
- log(HEADER);
- log(DASH);
+ log_msg("\n");
+ log_msg(HEADER);
+ log_msg(DASH);
if ( argc > 1 + is_ignore_list )
{
@@ -1255,10 +1266,10 @@ int main(int argc, char **argv)
// stop server
mysql_stop();
- log(DASH);
- log("\n");
+ log_msg(DASH);
+ log_msg("\n");
- log("Ending Tests...\n");
+ log_msg("Ending Tests...\n");
// report stats
report_stats();
@@ -1272,3 +1283,113 @@ int main(int argc, char **argv)
return 0;
}
+/*
+ Synopsis:
+ This function breaks the string into a sequence of tokens. The difference
+ between this function and strtok is that it respects the quoted string i.e.
+ it skips any delimiter character within the quoted part of the string.
+ It return tokens by eliminating quote character. It modifies the input string
+ passed. It will work with whitespace delimeter but may not work properly with
+ other delimeter. If the delimeter will contain any quote character, then
+ function will not tokenize and will return null string.
+ e.g. if input string is
+ --init-slave="set global max_connections=500" --skip-external-locking
+ then the output will two string i.e.
+ --init-slave=set global max_connections=500
+ --skip-external-locking
+
+Arguments:
+ string: input string
+ delim: set of delimiter character
+Output:
+ return the null terminated token of NULL.
+*/
+
+
+char *str_tok(char *string, const char *delim)
+{
+ char *token; /* current token received from strtok */
+ char *qt_token; /* token delimeted by the matching pair of quote */
+ /*
+ if there are any quote chars found in the token then this variable
+ will hold the concatenated string to return to the caller
+ */
+ char *ptr_token=NULL;
+ /* pointer to the quote character in the token from strtok */
+ char *ptr_quote=NULL;
+
+ /* See if the delimeter contains any quote character */
+ if (strchr(delim,'\'') || strchr(delim,'\"'))
+ return NULL;
+
+ /* repeate till we are getting some token from strtok */
+ while ((token = (char*)strtok(string, delim) ) != NULL)
+ {
+ /*
+ make the input string NULL so that next time onward strtok can
+ be called with NULL input string.
+ */
+ string = NULL;
+
+ /* check if the current token contain double quote character*/
+ if ((ptr_quote = (char*)strchr(token,'\"')) != NULL)
+ {
+ /*
+ get the matching the matching double quote in the remaining
+ input string
+ */
+ qt_token = (char*)strtok(NULL,"\"");
+ }
+ /* check if the current token contain single quote character*/
+ else if ((ptr_quote = (char*)strchr(token,'\'')) != NULL)
+ {
+ /*
+ get the matching the matching single quote in the remaining
+ input string
+ */
+ qt_token = (char*)strtok(NULL,"\'");
+ }
+
+ /*
+ if the current token does not contains any quote character then
+ return to the caller.
+ */
+ if (ptr_quote == NULL)
+ {
+ /*
+ if there is any earlier token i.e. ptr_token then append the
+ current token in it and return it else return the current
+ token directly
+ */
+ return ptr_token ? strcat(ptr_token,token) : token;
+ }
+
+ /*
+ remove the quote character i.e. make NULL so that the token will
+ be devided in two part and later both part can be concatenated
+ and hence quote will be removed
+ */
+ *ptr_quote= 0;
+
+ /* check if ptr_token has been initialized or not */
+ if (ptr_token == NULL)
+ {
+ /* initialize the ptr_token with current token */
+ ptr_token= token;
+ /* copy entire string between matching pair of quote*/
+ sprintf(ptr_token+strlen(ptr_token),"%s %s", ptr_quote+1, qt_token);
+ }
+ else
+ {
+ /*
+ copy the current token and entire string between matching pair
+ of quote
+ */
+ sprintf(ptr_token+strlen(ptr_token),"%s%s %s", token, ptr_quote+1,
+ qt_token );
+ }
+ }
+
+ /* return the concatenated token */
+ return ptr_token;
+}
diff --git a/netware/mysqld_safe.c b/netware/mysqld_safe.c
index a815497ac0f..a307b52bb7e 100644
--- a/netware/mysqld_safe.c
+++ b/netware/mysqld_safe.c
@@ -1,20 +1,20 @@
/*
- Copyright (c) 2003 Novell, Inc. All Rights Reserved.
+ Copyright (c) 2003 Novell, Inc. All Rights Reserved.
- 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.
+ 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
+ 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 <stdlib.h>
#include <stdio.h>
@@ -32,7 +32,7 @@
/******************************************************************************
global variables
-
+
******************************************************************************/
char autoclose;
char basedir[PATH_MAX];
@@ -47,37 +47,38 @@ char mysqld[PATH_MAX];
char hostname[PATH_MAX];
char default_option[PATH_MAX];
-FILE *log_fd = NULL;
+FILE *log_fd= NULL;
/******************************************************************************
prototypes
-
+
******************************************************************************/
void usage(void);
void vlog(char *, va_list);
void log(char *, ...);
-void start_defaults(int, char*[]);
+void start_defaults(int, char *[]);
void finish_defaults();
void read_defaults(arg_list_t *);
-void parse_args(int, char*[]);
-void get_options(int, char*[]);
+void parse_args(int, char *[]);
+void get_options(int, char *[]);
void check_data_vol();
void check_setup();
void check_tables();
-void mysql_start(int, char*[]);
+void mysql_start(int, char *[]);
+void parse_setvar(char *arg);
/******************************************************************************
functions
-
+
******************************************************************************/
/******************************************************************************
usage()
-
+
Show usage.
******************************************************************************/
@@ -85,7 +86,7 @@ void usage(void)
{
// keep the screen up
setscreenmode(SCR_NO_MODE);
-
+
puts("\
\n\
usage: mysqld_safe [options]\n\
@@ -106,14 +107,14 @@ options:\n\
--mysqld=<file> Use the <file> MySQL daemon.\n\
\n\
");
-
+
exit(-1);
}
/******************************************************************************
vlog()
-
+
Log the message.
******************************************************************************/
@@ -121,7 +122,7 @@ void vlog(char *format, va_list ap)
{
vfprintf(stdout, format, ap);
fflush(stdout);
-
+
if (log_fd)
{
vfprintf(log_fd, format, ap);
@@ -132,25 +133,25 @@ void vlog(char *format, va_list ap)
/******************************************************************************
log()
-
+
Log the message.
******************************************************************************/
void log(char *format, ...)
{
va_list ap;
-
+
va_start(ap, format);
vlog(format, ap);
-
+
va_end(ap);
}
/******************************************************************************
start_defaults()
-
+
Start setting the defaults.
******************************************************************************/
@@ -158,30 +159,30 @@ void start_defaults(int argc, char *argv[])
{
struct stat buf;
int i;
-
+
// default options
- static char *default_options[] =
+ static char *default_options[]=
{
- "--no-defaults",
- "--defaults-file=",
- "--defaults-extra-file=",
- NULL
+ "--no-defaults",
+ "--defaults-file=",
+ "--defaults-extra-file=",
+ NULL
};
-
+
// autoclose
- autoclose = FALSE;
-
+ autoclose= FALSE;
+
// basedir
get_basedir(argv[0], basedir);
-
+
// check-tables
- checktables = FALSE;
-
+ checktables= FALSE;
+
// hostname
- if (gethostname(hostname,PATH_MAX) < 0)
+ if (gethostname(hostname, PATH_MAX) < 0)
{
// default
- strcpy(hostname,"mysql");
+ strcpy(hostname, "mysql");
}
// address
@@ -189,30 +190,30 @@ void start_defaults(int argc, char *argv[])
// port
snprintf(port, PATH_MAX, "3306");
-
+
// default option
- default_option[0] = NULL;
- for (i=0; (argc > 1) && default_options[i]; i++)
- {
- if(!strnicmp(argv[1], default_options[i], strlen(default_options[i])))
- {
- strncpy(default_option, argv[1], PATH_MAX);
- break;
- }
- }
-
+ default_option[0]= NULL;
+ for (i= 0; (argc > 1) && default_options[i]; i++)
+ {
+ if (!strnicmp(argv[1], default_options[i], strlen(default_options[i])))
+ {
+ strncpy(default_option, argv[1], PATH_MAX);
+ break;
+ }
+ }
+
// set after basedir is established
- datadir[0] = NULL;
- pid_file[0] = NULL;
- err_log[0] = NULL;
- safe_log[0] = NULL;
- mysqld[0] = NULL;
+ datadir[0]= NULL;
+ pid_file[0]= NULL;
+ err_log[0]= NULL;
+ safe_log[0]= NULL;
+ mysqld[0]= NULL;
}
/******************************************************************************
finish_defaults()
-
+
Finish settig the defaults.
******************************************************************************/
@@ -220,22 +221,27 @@ void finish_defaults()
{
struct stat buf;
int i;
-
+
// datadir
- if (!datadir[0]) snprintf(datadir, PATH_MAX, "%s/data", basedir);
-
+ if (!datadir[0])
+ snprintf(datadir, PATH_MAX, "%s/data", basedir);
+
// pid-file
- if (!pid_file[0]) snprintf(pid_file, PATH_MAX, "%s/%s.pid", datadir, hostname);
-
+ if (!pid_file[0])
+ snprintf(pid_file, PATH_MAX, "%s/%s.pid", datadir, hostname);
+
// err-log
- if (!err_log[0]) snprintf(err_log, PATH_MAX, "%s/%s.err", datadir, hostname);
+ if (!err_log[0])
+ snprintf(err_log, PATH_MAX, "%s/%s.err", datadir, hostname);
// safe-log
- if (!safe_log[0]) snprintf(safe_log, PATH_MAX, "%s/%s.safe", datadir, hostname);
+ if (!safe_log[0])
+ snprintf(safe_log, PATH_MAX, "%s/%s.safe", datadir, hostname);
// mysqld
- if (!mysqld[0]) snprintf(mysqld, PATH_MAX, "%s/bin/mysqld-max", basedir);
-
+ if (!mysqld[0])
+ snprintf(mysqld, PATH_MAX, "%s/bin/mysqld-max", basedir);
+
if (stat(mysqld, &buf))
{
snprintf(mysqld, PATH_MAX, "%s/bin/mysqld", basedir);
@@ -245,7 +251,7 @@ void finish_defaults()
/******************************************************************************
read_defaults()
-
+
Read the defaults.
******************************************************************************/
@@ -256,64 +262,66 @@ void read_defaults(arg_list_t *pal)
char mydefaults[PATH_MAX];
char line[PATH_MAX];
FILE *fp;
-
- // defaults output file
- snprintf(defaults_file, PATH_MAX, "%s/bin/defaults.out", basedir);
- remove(defaults_file);
- // mysqladmin file
+ // defaults output file
+ snprintf(defaults_file, PATH_MAX, "%s/bin/defaults.out", basedir);
+ remove(defaults_file);
+
+ // mysqladmin file
snprintf(mydefaults, PATH_MAX, "%s/bin/my_print_defaults", basedir);
-
+
// args
init_args(&al);
add_arg(&al, mydefaults);
- if (default_option[0]) add_arg(&al, default_option);
+ if (default_option[0])
+ add_arg(&al, default_option);
add_arg(&al, "mysqld");
add_arg(&al, "server");
add_arg(&al, "mysqld_safe");
add_arg(&al, "safe_mysqld");
- spawn(mydefaults, &al, TRUE, NULL, defaults_file, NULL);
+ spawn(mydefaults, &al, TRUE, NULL, defaults_file, NULL);
free_args(&al);
- // gather defaults
- if((fp = fopen(defaults_file, "r")) != NULL)
- {
- while(fgets(line, PATH_MAX, fp))
- {
+ // gather defaults
+ if ((fp= fopen(defaults_file, "r")) != NULL)
+ {
+ while (fgets(line, PATH_MAX, fp))
+ {
char *p;
-
+
// remove end-of-line character
- if ((p = strrchr(line, '\n')) != NULL) *p = '\0';
-
+ if ((p= strrchr(line, '\n')) != NULL)
+ *p= '\0';
+
// add the option as an argument
- add_arg(pal, line);
- }
-
- fclose(fp);
- }
-
- // remove file
- remove(defaults_file);
+ add_arg(pal, line);
+ }
+
+ fclose(fp);
+ }
+
+ // remove file
+ remove(defaults_file);
}
/******************************************************************************
parse_args()
-
+
Get the options.
******************************************************************************/
void parse_args(int argc, char *argv[])
{
- int index = 0;
+ int index= 0;
int c;
-
+
// parse options
enum opts
{
- OPT_BASEDIR = 0xFF,
+ OPT_BASEDIR= 0xFF,
OPT_DATADIR,
OPT_PID_FILE,
OPT_BIND_ADDRESS,
@@ -321,74 +329,79 @@ void parse_args(int argc, char *argv[])
OPT_ERR_LOG,
OPT_SAFE_LOG,
OPT_MYSQLD,
- OPT_HELP
+ OPT_HELP,
+ OPT_SETVAR
};
-
- static struct option options[] =
+
+ static struct option options[]=
{
- {"autoclose", no_argument, &autoclose, TRUE},
- {"basedir", required_argument, 0, OPT_BASEDIR},
- {"check-tables", no_argument, &checktables, TRUE},
- {"datadir", required_argument, 0, OPT_DATADIR},
- {"pid-file", required_argument, 0, OPT_PID_FILE},
- {"bind-address", required_argument, 0, OPT_BIND_ADDRESS},
- {"port", required_argument, 0, OPT_PORT},
- {"err-log", required_argument, 0, OPT_ERR_LOG},
- {"safe-log", required_argument, 0, OPT_SAFE_LOG},
- {"mysqld", required_argument, 0, OPT_MYSQLD},
- {"help", no_argument, 0, OPT_HELP},
- {0, 0, 0, 0}
+ {"autoclose", no_argument, &autoclose, TRUE},
+ {"basedir", required_argument, 0, OPT_BASEDIR},
+ {"check-tables", no_argument, &checktables, TRUE},
+ {"datadir", required_argument, 0, OPT_DATADIR},
+ {"pid-file", required_argument, 0, OPT_PID_FILE},
+ {"bind-address", required_argument, 0, OPT_BIND_ADDRESS},
+ {"port", required_argument, 0, OPT_PORT},
+ {"err-log", required_argument, 0, OPT_ERR_LOG},
+ {"safe-log", required_argument, 0, OPT_SAFE_LOG},
+ {"mysqld", required_argument, 0, OPT_MYSQLD},
+ {"help", no_argument, 0, OPT_HELP},
+ {"set-variable", required_argument, 0, OPT_SETVAR},
+ {0, 0, 0, 0}
};
-
+
// we have to reset getopt_long because we use it multiple times
- optind = 1;
-
+ optind= 1;
+
// turn off error reporting
- opterr = 0;
-
- while ((c = getopt_long(argc, argv, "b:h:P:", options, &index)) >= 0)
+ opterr= 0;
+
+ while ((c= getopt_long(argc, argv, "b:h:P:", options, &index)) >= 0)
{
- switch (c)
- {
+ switch (c) {
case OPT_BASEDIR:
case 'b':
strcpy(basedir, optarg);
break;
-
+
case OPT_DATADIR:
case 'h':
strcpy(datadir, optarg);
break;
-
+
case OPT_PID_FILE:
strcpy(pid_file, optarg);
break;
-
+
case OPT_BIND_ADDRESS:
strcpy(address, optarg);
break;
-
+
case OPT_PORT:
case 'P':
strcpy(port, optarg);
break;
-
+
case OPT_ERR_LOG:
strcpy(err_log, optarg);
break;
-
+
case OPT_SAFE_LOG:
strcpy(safe_log, optarg);
break;
-
+
case OPT_MYSQLD:
strcpy(mysqld, optarg);
break;
-
+
+ case OPT_SETVAR:
+ parse_setvar(optarg);
+ break;
+
case OPT_HELP:
usage();
break;
-
+
default:
// ignore
break;
@@ -396,17 +409,37 @@ void parse_args(int argc, char *argv[])
}
}
+/*
+ parse_setvar(char *arg)
+ Pasrsing for port just to display the port num on the mysqld_safe screen
+*/
+void parse_setvar(char *arg)
+{
+ char *pos;
+
+ if ((pos= strindex(arg, "port")))
+ {
+ for (; *pos && *pos != '='; pos++);
+ if (*pos)
+ strcpy(port, pos + 1);
+ }
+}
+
+/******************************************************************************
+
+
+
/******************************************************************************
get_options()
-
+
Get the options.
******************************************************************************/
void get_options(int argc, char *argv[])
{
arg_list_t al;
-
+
// start defaults
start_defaults(argc, argv);
@@ -416,10 +449,10 @@ void get_options(int argc, char *argv[])
read_defaults(&al);
parse_args(al.argc, al.argv);
free_args(&al);
-
+
// command-line arguments
parse_args(argc, argv);
-
+
// finish defaults
finish_defaults();
}
@@ -427,7 +460,7 @@ void get_options(int argc, char *argv[])
/******************************************************************************
check_data_vol()
-
+
Check the database volume.
******************************************************************************/
@@ -437,23 +470,23 @@ void check_data_vol()
struct volume_info vol;
char buff[PATH_MAX];
char *p;
-
+
// clear struct
memset(&vol, 0, sizeof(vol));
-
+
// find volume name
strcpy(buff, datadir);
- if (p = strchr(buff, ':'))
+ if (p= strchr(buff, ':'))
{
// terminate after volume name
- *p = 0;
+ *p= 0;
}
else
{
// assume SYS volume
strcpy(buff, "SYS");
}
-
+
// retrieve information
netware_vol_info_from_name(&vol, buff);
@@ -467,25 +500,25 @@ void check_data_vol()
/******************************************************************************
check_setup()
-
+
Check the current setup.
******************************************************************************/
void check_setup()
{
- struct stat info;
+ struct stat info;
char temp[PATH_MAX];
-
+
// remove any current pid_file
- if (!stat(pid_file, &info) && (remove(pid_file) < 0))
- {
+ if (!stat(pid_file, &info) && (remove(pid_file) < 0))
+ {
log("ERROR: Unable to remove current pid file!\n\n");
exit(-1);
- }
-
- // check the data volume
+ }
+
+ // check the data volume
check_data_vol();
-
+
// check for a database
snprintf(temp, PATH_MAX, "%s/mysql/host.frm", datadir);
if (stat(temp, &info))
@@ -498,7 +531,7 @@ void check_setup()
/******************************************************************************
check_tables()
-
+
Check the database tables.
******************************************************************************/
@@ -506,21 +539,21 @@ void check_tables()
{
arg_list_t al;
char mycheck[PATH_MAX];
- char table[PATH_MAX];
- char db[PATH_MAX];
- DIR *datadir_entry, *db_entry, *table_entry;
-
- // status
+ char table[PATH_MAX];
+ char db[PATH_MAX];
+ DIR *datadir_entry, *db_entry, *table_entry;
+
+ // status
log("checking tables...\n");
-
+
// list databases
- if ((datadir_entry = opendir(datadir)) == NULL)
- {
- return;
- }
+ if ((datadir_entry= opendir(datadir)) == NULL)
+ {
+ return;
+ }
- while((db_entry = readdir(datadir_entry)) != NULL)
- {
+ while ((db_entry= readdir(datadir_entry)) != NULL)
+ {
if (db_entry->d_name[0] == '.')
{
// Skip
@@ -529,184 +562,191 @@ void check_tables()
{
// create long db name
snprintf(db, PATH_MAX, "%s/%s", datadir, db_entry->d_name);
-
+
// list tables
- if ((db_entry = opendir(db)) == NULL)
+ if ((db_entry= opendir(db)) == NULL)
{
- continue;
+ continue;
}
-
- while((table_entry = readdir(db_entry)) != NULL)
+
+ while ((table_entry= readdir(db_entry)) != NULL)
{
- // create long table name
- snprintf(table, PATH_MAX, "%s/%s", db, strlwr(table_entry->d_name));
-
- if (strindex(table, ".myi"))
- {
- // ** myisamchk
-
- // mysqladmin file
- snprintf(mycheck, PATH_MAX, "%s/bin/myisamchk", basedir);
-
- // args
- init_args(&al);
- add_arg(&al, mycheck);
- add_arg(&al, "--silent");
- add_arg(&al, "--force");
- add_arg(&al, "--fast");
- add_arg(&al, "--medium-check");
- add_arg(&al, "-O");
- add_arg(&al, "key_buffer=64M");
- add_arg(&al, "-O");
- add_arg(&al, "sort_buffer=64M");
- add_arg(&al, table);
-
- spawn(mycheck, &al, TRUE, NULL, NULL, NULL);
-
- free_args(&al);
- }
- else if (strindex(table, ".ism"))
- {
- // ** isamchk
-
- // mysqladmin file
- snprintf(mycheck, PATH_MAX, "%s/bin/isamchk", basedir);
-
- // args
- init_args(&al);
- add_arg(&al, mycheck);
- add_arg(&al, "--silent");
- add_arg(&al, "--force");
- add_arg(&al, "-O");
- add_arg(&al, "sort_buffer=64M");
- add_arg(&al, table);
-
- spawn(mycheck, &al, TRUE, NULL, NULL, NULL);
-
- free_args(&al);
- }
+ // create long table name
+ snprintf(table, PATH_MAX, "%s/%s", db, strlwr(table_entry->d_name));
+
+ if (strindex(table, ".myi"))
+ {
+ // ** myisamchk
+
+ // mysqladmin file
+ snprintf(mycheck, PATH_MAX, "%s/bin/myisamchk", basedir);
+
+ // args
+ init_args(&al);
+ add_arg(&al, mycheck);
+ add_arg(&al, "--silent");
+ add_arg(&al, "--force");
+ add_arg(&al, "--fast");
+ add_arg(&al, "--medium-check");
+ add_arg(&al, "-O");
+ add_arg(&al, "key_buffer=64M");
+ add_arg(&al, "-O");
+ add_arg(&al, "sort_buffer=64M");
+ add_arg(&al, table);
+
+ spawn(mycheck, &al, TRUE, NULL, NULL, NULL);
+
+ free_args(&al);
+ }
+ else if (strindex(table, ".ism"))
+ {
+ // ** isamchk
+
+ // mysqladmin file
+ snprintf(mycheck, PATH_MAX, "%s/bin/isamchk", basedir);
+
+ // args
+ init_args(&al);
+ add_arg(&al, mycheck);
+ add_arg(&al, "--silent");
+ add_arg(&al, "--force");
+ add_arg(&al, "-O");
+ add_arg(&al, "sort_buffer=64M");
+ add_arg(&al, table);
+
+ spawn(mycheck, &al, TRUE, NULL, NULL, NULL);
+
+ free_args(&al);
+ }
}
}
- }
+ }
}
/******************************************************************************
mysql_start()
-
+
Start the mysql server.
******************************************************************************/
void mysql_start(int argc, char *argv[])
{
- arg_list_t al;
- int i, j, err;
- struct stat info;
- time_t cal;
- struct tm lt;
- char stamp[PATH_MAX];
- char skip;
-
+ arg_list_t al;
+ int i, j, err;
+ struct stat info;
+ time_t cal;
+ struct tm lt;
+ char stamp[PATH_MAX];
+ char skip;
+
// private options
- static char *private_options[] =
+ static char *private_options[]=
{
- "--autoclose",
+ "--autoclose",
"--check-tables",
"--help",
- "--err-log=",
- "--mysqld=",
- NULL
+ "--err-log=",
+ "--mysqld=",
+ NULL
};
-
- // args
- init_args(&al);
- add_arg(&al, "%s", mysqld);
-
- // parent args
- for(i = 1; i < argc; i++)
- {
- skip = FALSE;
-
+
+ // args
+ init_args(&al);
+ add_arg(&al, "%s", mysqld);
+
+ // parent args
+ for (i= 1; i < argc; i++)
+ {
+ skip= FALSE;
+
// skip private arguments
- for (j=0; private_options[j]; j++)
+ for (j= 0; private_options[j]; j++)
{
- if(!strnicmp(argv[i], private_options[j], strlen(private_options[j])))
+ if (!strnicmp(argv[i], private_options[j], strlen(private_options[j])))
{
- skip = TRUE;
- break;
+ skip= TRUE;
+ consoleprintf("The argument skipped is %s\n", argv[i]);
+ break;
}
}
-
- if (!skip) add_arg(&al, "%s", argv[i]);
- }
-
+
+ if (!skip)
+ {
+ add_arg(&al, "%s", argv[i]);
+ consoleprintf("The final argument is %s\n", argv[i]);
+ }
+ }
// spawn
- do
- {
- // check the database tables
- if (checktables) check_tables();
-
- // status
+ do
+ {
+ // check the database tables
+ if (checktables)
+ check_tables();
+
+ // status
time(&cal);
localtime_r(&cal, &lt);
strftime(stamp, PATH_MAX, "%d %b %Y %H:%M:%S", &lt);
log("mysql started : %s\n", stamp);
-
- // spawn mysqld
- spawn(mysqld, &al, TRUE, NULL, NULL, err_log);
- }
- while (!stat(pid_file, &info));
-
- // status
+
+ // spawn mysqld
+ spawn(mysqld, &al, TRUE, NULL, NULL, err_log);
+ }
+ while (!stat(pid_file, &info));
+
+ // status
time(&cal);
localtime_r(&cal, &lt);
strftime(stamp, PATH_MAX, "%d %b %Y %H:%M:%S", &lt);
log("mysql stopped : %s\n\n", stamp);
-
- // free args
- free_args(&al);
+
+ // free args
+ free_args(&al);
}
/******************************************************************************
main()
-
+
******************************************************************************/
int main(int argc, char **argv)
{
- char temp[PATH_MAX];
-
+ char temp[PATH_MAX];
+
// get the options
- get_options(argc, argv);
+ get_options(argc, argv);
// keep the screen up
- if (!autoclose) setscreenmode(SCR_NO_MODE);
-
+ if (!autoclose)
+ setscreenmode(SCR_NO_MODE);
+
// create log file
- log_fd = fopen(safe_log, "w+");
-
+ log_fd= fopen(safe_log, "w+");
+
// header
log("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE);
-
- // status
- log("address : %s\n", address);
- log("port : %s\n", port);
+
+ // status
+ log("address : %s\n", address);
+ log("port : %s\n", port);
log("daemon : %s\n", mysqld);
- log("base directory : %s\n", basedir);
- log("data directory : %s\n", datadir);
- log("pid file : %s\n", pid_file);
- log("error file : %s\n", err_log);
- log("log file : %s\n", safe_log);
+ log("base directory : %s\n", basedir);
+ log("data directory : %s\n", datadir);
+ log("pid file : %s\n", pid_file);
+ log("error file : %s\n", err_log);
+ log("log file : %s\n", safe_log);
log("\n");
-
+
// check setup
check_setup();
-
+
// start the MySQL server
- mysql_start(argc, argv);
-
- // close log file
- if (log_fd) fclose(log_fd);
-
+ mysql_start(argc, argv);
+
+ // close log file
+ if (log_fd)
+ fclose(log_fd);
+
return 0;
}
diff --git a/netware/static_init_db.sql b/netware/static_init_db.sql
index 63ee623dac4..e9fb92f4a97 100644
--- a/netware/static_init_db.sql
+++ b/netware/static_init_db.sql
@@ -10,7 +10,7 @@ INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y',
CREATE TABLE host (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db)) comment='Host privileges; Merged with database privileges';
-CREATE TABLE user (Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(45) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') DEFAULT 'N' NOT NULL, File_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User)) comment='Users and global privileges';
+CREATE TABLE user (Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') DEFAULT 'N' NOT NULL, File_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User)) comment='Users and global privileges';
INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
INSERT INTO user VALUES ('','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
@@ -20,7 +20,7 @@ INSERT INTO user (host,user) values ('','');
CREATE TABLE func (name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') NOT NULL, PRIMARY KEY (name)) comment='User defined functions';
-CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(60) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp(14), Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor)) comment='Table privileges';
+CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp(14), Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor)) comment='Table privileges';
CREATE TABLE columns_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp(14), Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name)) comment='Column privileges';
diff --git a/regex/regcomp.c b/regex/regcomp.c
index b939429e16e..31899609e3c 100644
--- a/regex/regcomp.c
+++ b/regex/regcomp.c
@@ -884,7 +884,7 @@ int ch;
register char *oldend = p->end;
char bracket[3];
- assert(othercase(ch) != ch); /* p_bracket() would recurse */
+ assert(othercase(p->charset, ch) != ch); /* p_bracket() would recurse */
p->next = bracket;
p->end = bracket+2;
bracket[0] = ch;
diff --git a/scripts/fill_func_tables.sh b/scripts/fill_func_tables.sh
index 459afee2fe1..459afee2fe1 100755..100644
--- a/scripts/fill_func_tables.sh
+++ b/scripts/fill_func_tables.sh
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index 341726fd89b..9c76c5a51f3 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -103,7 +103,7 @@ BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \
isam/isamchk$BS isam/pack_isam$BS \
myisam/myisamchk$BS myisam/myisampack$BS myisam/myisamlog$BS \
myisam/myisam_ftdump$BS \
- sql/mysqld$BS \
+ sql/mysqld$BS sql/mysql_tzinfo_to_sql$BS \
client/mysql$BS client/mysqlshow$BS client/mysqladmin$BS \
client/mysqldump$BS client/mysqlimport$BS \
client/mysqltest$BS client/mysqlcheck$BS \
@@ -197,14 +197,6 @@ fi
$CP support-files/* $BASE/support-files
$CP scripts/*.sql $BASE/share
-if [ $BASE_SYSTEM = "netware" ] ; then
- rm -f $BASE/support-files/magic \
- $BASE/support-files/mysql.server \
- $BASE/support-files/mysql*.spec \
- $BASE/support-files/mysql-log-rotate \
- $BASE/support-files/binary-configure
-fi
-
$CP -r sql/share/* $MYSQL_SHARE
rm -f $MYSQL_SHARE/Makefile* $MYSQL_SHARE/*/*.OLD
@@ -241,10 +233,24 @@ rm -f $BASE/bin/Makefile* $BASE/bin/*.in $BASE/bin/*.sh $BASE/bin/mysql_install_
#
+# Copy system dependent files
+#
+if [ $BASE_SYSTEM = "netware" ] ; then
+ cp ./netware/static_init_db.sql ./netware/init_db.sql
+ ./scripts/fill_help_tables < ./Docs/manual.texi >> ./netware/init_db.sql
+fi
+
+#
# Remove system dependent files
#
if [ $BASE_SYSTEM = "netware" ] ; then
- rm -f $BASE/MySQLEULA.txt
+ rm -f $BASE/support-files/magic \
+ $BASE/support-files/mysql.server \
+ $BASE/support-files/mysql*.spec \
+ $BASE/support-files/mysql-log-rotate \
+ $BASE/support-files/binary-configure \
+ $BASE/INSTALL-BINARY \
+ $BASE/MySQLEULA.txt
else
rm -f $BASE/README.NW
fi
@@ -263,14 +269,14 @@ fi
# NDB Cluster
if [ x$NDBCLUSTER = x1 ]; then
- if [ ! -f ndb/BinDist.sh ]; then
- echo "Missing ndb/BinDist.sh"; exit 1
- fi
- mkdir $BASE/ndb || exit 1
- # assume we have cpio..
- if (cd ndb && sh BinDist.sh | cpio -pdm $BASE/ndb); then :; else
- echo "Copy failed - missing files in ndb/BinDist.sh ?"; exit 1
- fi
+ ( cd ndb ; make DESTDIR=$BASE/ndb-stage install )
+ ( cd mysql-test/ndb ; make DESTDIR=$BASE/ndb-stage install )
+ $CP $BASE/ndb-stage@bindir@/* $BASE/bin/.
+ $CP $BASE/ndb-stage@libexecdir@/* $BASE/bin/.
+ $CP $BASE/ndb-stage@pkglibdir@/* $BASE/lib/.
+ $CP -r $BASE/ndb-stage@pkgincludedir@/ndb $BASE/lib/.
+ $CP -r $BASE/ndb-stage@prefix@/mysql-test/ndb $BASE/mysql-test/. || exit 1
+ rm -rf $BASE/ndb-stage
fi
# Change the distribution to a long descriptive name
@@ -349,9 +355,6 @@ if [ $BASE_SYSTEM != "netware" ] ; then
echo "Compressing archive"
rm -f $NEW_NAME.tar.gz
gzip -9 $NEW_NAME.tar
- echo "Removing temporary directory"
- rm -r -f $BASE
-
echo "$NEW_NAME.tar.gz created"
else
@@ -362,9 +365,8 @@ else
cd $TMP
if test -e "$SOURCE/$NEW_NAME.zip"; then rm $SOURCE/$NEW_NAME.zip; fi
zip -r $SOURCE/$NEW_NAME.zip $NEW_NAME
- echo "Removing temporary directory"
- rm -r -f $BASE
-
echo "$NEW_NAME.zip created"
fi
+echo "Removing temporary directory"
+rm -r -f $BASE
diff --git a/scripts/make_win_binary_distribution.sh b/scripts/make_win_binary_distribution.sh
index e5893c1eb1e..9b2cc2d7d22 100644
--- a/scripts/make_win_binary_distribution.sh
+++ b/scripts/make_win_binary_distribution.sh
@@ -110,6 +110,9 @@ print_debug "Copying sql-bench to $DIRNAME/bench"
mkdir $DIRNAME/bench
cp -fr sql-bench/* $DIRNAME/bench
+print_debug "Copying support-files to $DIRNAME"
+cp support-files/* $DIRNAME
+
# Files for bin
for i in client_release/* client_debug/mysqld.exe lib_release/libmySQL.dll
do
@@ -124,7 +127,7 @@ do
cp $i $DIRNAME/include
done
-# Windows users are used to having dbug.h
+# Windows users are used to having dbug.h ?
cp include/my_dbug.h $DIRNAME/include/dbug.h
# Libraries found in lib_release and lib_debug
diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh
index 68ba488f3d5..eaaf219afc4 100755..100644
--- a/scripts/make_win_src_distribution.sh
+++ b/scripts/make_win_src_distribution.sh
@@ -161,13 +161,16 @@ vreplace()
done
}
-for d in 4.0.XX-gpl 4.0.XX-pro 4.0.XX-classic
-do
- cd $BASE/InstallShield/$d/String\ Tables/0009-English
- vreplace value.shl
- cd ../../Setup\ Files/Compressed\ Files/Language\ Independent/OS\ Independent
- vreplace infolist.txt
-done
+if test -d $BASE/InstallShield
+then
+ for d in 4.1.XX-gpl 4.1.XX-pro 4.1.XX-classic
+ do
+ cd $BASE/InstallShield/$d/String\ Tables/0009-English
+ vreplace value.shl
+ cd ../../Setup\ Files/Compressed\ Files/Language\ Independent/OS\ Independent
+ vreplace infolist.txt
+ done
+fi
#
# Move all error message files to root directory
@@ -288,6 +291,12 @@ do
done
#
+# support files
+#
+mkdir $BASE/support-files
+cp support-files/*.cnf $BASE/support-files
+
+#
# Raw dirs from source tree
#
@@ -302,10 +311,11 @@ do
done
#
-# Fix some windows files
+# Fix some windows files to avoid compiler warnings
#
-./extra/replace std:: "" -- $BASE/sql/sql_yacc.cpp
+./extra/replace std:: "" < $BASE/sql/sql_yacc.cpp | sed '/^ *switch (yytype)$/ { N; /\n *{$/ { N; /\n *default:$/ { N; /\n *break;$/ { N; /\n *}$/ d; };};};} ' > $BASE/sql/sql_yacc.cpp-new
+mv $BASE/sql/sql_yacc.cpp-new $BASE/sql/sql_yacc.cpp
unix_to_dos $BASE/README
mv $BASE/README $BASE/README.txt
@@ -316,7 +326,7 @@ mv $BASE/README $BASE/README.txt
if [ -d $BASE/SSL/SCCS ]
then
- find $BASE -type d -name SCCS | xargs rm -r -f
+ find $BASE/ -type d -name SCCS -printf " \"%p\"" | xargs rm -r -f
fi
#
diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh
index 287e1cf11dc..87f49107a40 100644
--- a/scripts/mysql_create_system_tables.sh
+++ b/scripts/mysql_create_system_tables.sh
@@ -39,6 +39,8 @@ c_hc=""
c_hr=""
c_hk=""
i_ht=""
+c_tzn="" c_tz="" c_tzt="" c_tztt="" c_tzls=""
+i_tzn="" i_tz="" i_tzt="" i_tztt="" i_tzls=""
c_p=""
# Check for old tables
@@ -153,12 +155,15 @@ then
i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);"
if test "$windows" = "0"
then
- i_u="$i_u
+ i_u="$i_u
INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
INSERT INTO user (host,user) values ('$hostname','');
INSERT INTO user (host,user) values ('localhost','');"
else
- i_u="INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);"
+ i_u="$i_u
+ INSERT INTO user VALUES ('%','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+ INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+ INSERT INTO user VALUES ('%','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0);"
fi
fi
fi
@@ -286,6 +291,332 @@ then
c_hr="$c_hr comment='keyword-topic relation';"
fi
+if test ! -f $mdata/time_zone_name.frm
+then
+ if test "$1" = "verbose" ; then
+ echo "Preparing time_zone_name table" 1>&2;
+ fi
+
+ c_tzn="$c_tzn CREATE TABLE time_zone_name ("
+ c_tzn="$c_tzn Name char(64) NOT NULL,"
+ c_tzn="$c_tzn Time_zone_id int unsigned NOT NULL,"
+ c_tzn="$c_tzn PRIMARY KEY Name (Name)"
+ c_tzn="$c_tzn ) DEFAULT CHARACTER SET latin1"
+ c_tzn="$c_tzn comment='Time zone names';"
+
+ if test "$1" = "test"
+ then
+ i_tzn="$i_tzn INSERT INTO time_zone_name (Name, Time_Zone_id) VALUES"
+ i_tzn="$i_tzn ('MET', 1), ('UTC', 2), ('Universal', 2), "
+ i_tzn="$i_tzn ('Europe/Moscow',3), ('leap/Europe/Moscow',4);"
+ fi
+fi
+
+if test ! -f $mdata/time_zone.frm
+then
+ if test "$1" = "verbose" ; then
+ echo "Preparing time_zone table" 1>&2;
+ fi
+
+ c_tz="$c_tz CREATE TABLE time_zone ("
+ c_tz="$c_tz Time_zone_id int unsigned NOT NULL auto_increment,"
+ c_tz="$c_tz Use_leap_seconds enum('Y','N') DEFAULT 'N' NOT NULL,"
+ c_tz="$c_tz PRIMARY KEY TzId (Time_zone_id)"
+ c_tz="$c_tz ) DEFAULT CHARACTER SET latin1"
+ c_tz="$c_tz comment='Time zones';"
+
+ if test "$1" = "test"
+ then
+ i_tz="$i_tz INSERT INTO time_zone (Time_zone_id, Use_leap_seconds)"
+ i_tz="$i_tz VALUES (1,'N'), (2,'N'), (3,'N'), (4,'Y');"
+ fi
+fi
+
+if test ! -f $mdata/time_zone_transition.frm
+then
+ if test "$1" = "verbose" ; then
+ echo "Preparing time_zone_transition table" 1>&2;
+ fi
+
+ c_tzt="$c_tzt CREATE TABLE time_zone_transition ("
+ c_tzt="$c_tzt Time_zone_id int unsigned NOT NULL,"
+ c_tzt="$c_tzt Transition_time bigint signed NOT NULL,"
+ c_tzt="$c_tzt Transition_type_id int unsigned NOT NULL,"
+ c_tzt="$c_tzt PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time)"
+ c_tzt="$c_tzt ) DEFAULT CHARACTER SET latin1"
+ c_tzt="$c_tzt comment='Time zone transitions';"
+
+ if test "$1" = "test"
+ then
+ i_tzt="$i_tzt INSERT INTO time_zone_transition"
+ i_tzt="$i_tzt (Time_zone_id, Transition_time, Transition_type_id)"
+ i_tzt="$i_tzt VALUES"
+ i_tzt="$i_tzt (1, -1693706400, 0) ,(1, -1680483600, 1)"
+ i_tzt="$i_tzt ,(1, -1663455600, 2) ,(1, -1650150000, 3)"
+ i_tzt="$i_tzt ,(1, -1632006000, 2) ,(1, -1618700400, 3)"
+ i_tzt="$i_tzt ,(1, -938905200, 2) ,(1, -857257200, 3)"
+ i_tzt="$i_tzt ,(1, -844556400, 2) ,(1, -828226800, 3)"
+ i_tzt="$i_tzt ,(1, -812502000, 2) ,(1, -796777200, 3)"
+ i_tzt="$i_tzt ,(1, 228877200, 2) ,(1, 243997200, 3)"
+ i_tzt="$i_tzt ,(1, 260326800, 2) ,(1, 276051600, 3)"
+ i_tzt="$i_tzt ,(1, 291776400, 2) ,(1, 307501200, 3)"
+ i_tzt="$i_tzt ,(1, 323830800, 2) ,(1, 338950800, 3)"
+ i_tzt="$i_tzt ,(1, 354675600, 2) ,(1, 370400400, 3)"
+ i_tzt="$i_tzt ,(1, 386125200, 2) ,(1, 401850000, 3)"
+ i_tzt="$i_tzt ,(1, 417574800, 2) ,(1, 433299600, 3)"
+ i_tzt="$i_tzt ,(1, 449024400, 2) ,(1, 465354000, 3)"
+ i_tzt="$i_tzt ,(1, 481078800, 2) ,(1, 496803600, 3)"
+ i_tzt="$i_tzt ,(1, 512528400, 2) ,(1, 528253200, 3)"
+ i_tzt="$i_tzt ,(1, 543978000, 2) ,(1, 559702800, 3)"
+ i_tzt="$i_tzt ,(1, 575427600, 2) ,(1, 591152400, 3)"
+ i_tzt="$i_tzt ,(1, 606877200, 2) ,(1, 622602000, 3)"
+ i_tzt="$i_tzt ,(1, 638326800, 2) ,(1, 654656400, 3)"
+ i_tzt="$i_tzt ,(1, 670381200, 2) ,(1, 686106000, 3)"
+ i_tzt="$i_tzt ,(1, 701830800, 2) ,(1, 717555600, 3)"
+ i_tzt="$i_tzt ,(1, 733280400, 2) ,(1, 749005200, 3)"
+ i_tzt="$i_tzt ,(1, 764730000, 2) ,(1, 780454800, 3)"
+ i_tzt="$i_tzt ,(1, 796179600, 2) ,(1, 811904400, 3)"
+ i_tzt="$i_tzt ,(1, 828234000, 2) ,(1, 846378000, 3)"
+ i_tzt="$i_tzt ,(1, 859683600, 2) ,(1, 877827600, 3)"
+ i_tzt="$i_tzt ,(1, 891133200, 2) ,(1, 909277200, 3)"
+ i_tzt="$i_tzt ,(1, 922582800, 2) ,(1, 941331600, 3)"
+ i_tzt="$i_tzt ,(1, 954032400, 2) ,(1, 972781200, 3)"
+ i_tzt="$i_tzt ,(1, 985482000, 2) ,(1, 1004230800, 3)"
+ i_tzt="$i_tzt ,(1, 1017536400, 2) ,(1, 1035680400, 3)"
+ i_tzt="$i_tzt ,(1, 1048986000, 2) ,(1, 1067130000, 3)"
+ i_tzt="$i_tzt ,(1, 1080435600, 2) ,(1, 1099184400, 3)"
+ i_tzt="$i_tzt ,(1, 1111885200, 2) ,(1, 1130634000, 3)"
+ i_tzt="$i_tzt ,(1, 1143334800, 2) ,(1, 1162083600, 3)"
+ i_tzt="$i_tzt ,(1, 1174784400, 2) ,(1, 1193533200, 3)"
+ i_tzt="$i_tzt ,(1, 1206838800, 2) ,(1, 1224982800, 3)"
+ i_tzt="$i_tzt ,(1, 1238288400, 2) ,(1, 1256432400, 3)"
+ i_tzt="$i_tzt ,(1, 1269738000, 2) ,(1, 1288486800, 3)"
+ i_tzt="$i_tzt ,(1, 1301187600, 2) ,(1, 1319936400, 3)"
+ i_tzt="$i_tzt ,(1, 1332637200, 2) ,(1, 1351386000, 3)"
+ i_tzt="$i_tzt ,(1, 1364691600, 2) ,(1, 1382835600, 3)"
+ i_tzt="$i_tzt ,(1, 1396141200, 2) ,(1, 1414285200, 3)"
+ i_tzt="$i_tzt ,(1, 1427590800, 2) ,(1, 1445734800, 3)"
+ i_tzt="$i_tzt ,(1, 1459040400, 2) ,(1, 1477789200, 3)"
+ i_tzt="$i_tzt ,(1, 1490490000, 2) ,(1, 1509238800, 3)"
+ i_tzt="$i_tzt ,(1, 1521939600, 2) ,(1, 1540688400, 3)"
+ i_tzt="$i_tzt ,(1, 1553994000, 2) ,(1, 1572138000, 3)"
+ i_tzt="$i_tzt ,(1, 1585443600, 2) ,(1, 1603587600, 3)"
+ i_tzt="$i_tzt ,(1, 1616893200, 2) ,(1, 1635642000, 3)"
+ i_tzt="$i_tzt ,(1, 1648342800, 2) ,(1, 1667091600, 3)"
+ i_tzt="$i_tzt ,(1, 1679792400, 2) ,(1, 1698541200, 3)"
+ i_tzt="$i_tzt ,(1, 1711846800, 2) ,(1, 1729990800, 3)"
+ i_tzt="$i_tzt ,(1, 1743296400, 2) ,(1, 1761440400, 3)"
+ i_tzt="$i_tzt ,(1, 1774746000, 2) ,(1, 1792890000, 3)"
+ i_tzt="$i_tzt ,(1, 1806195600, 2) ,(1, 1824944400, 3)"
+ i_tzt="$i_tzt ,(1, 1837645200, 2) ,(1, 1856394000, 3)"
+ i_tzt="$i_tzt ,(1, 1869094800, 2) ,(1, 1887843600, 3)"
+ i_tzt="$i_tzt ,(1, 1901149200, 2) ,(1, 1919293200, 3)"
+ i_tzt="$i_tzt ,(1, 1932598800, 2) ,(1, 1950742800, 3)"
+ i_tzt="$i_tzt ,(1, 1964048400, 2) ,(1, 1982797200, 3)"
+ i_tzt="$i_tzt ,(1, 1995498000, 2) ,(1, 2014246800, 3)"
+ i_tzt="$i_tzt ,(1, 2026947600, 2) ,(1, 2045696400, 3)"
+ i_tzt="$i_tzt ,(1, 2058397200, 2) ,(1, 2077146000, 3)"
+ i_tzt="$i_tzt ,(1, 2090451600, 2) ,(1, 2108595600, 3)"
+ i_tzt="$i_tzt ,(1, 2121901200, 2) ,(1, 2140045200, 3)"
+ i_tzt="$i_tzt ,(3, -1688265000, 2) ,(3, -1656819048, 1)"
+ i_tzt="$i_tzt ,(3, -1641353448, 2) ,(3, -1627965048, 3)"
+ i_tzt="$i_tzt ,(3, -1618716648, 1) ,(3, -1596429048, 3)"
+ i_tzt="$i_tzt ,(3, -1593829848, 5) ,(3, -1589860800, 4)"
+ i_tzt="$i_tzt ,(3, -1542427200, 5) ,(3, -1539493200, 6)"
+ i_tzt="$i_tzt ,(3, -1525323600, 5) ,(3, -1522728000, 4)"
+ i_tzt="$i_tzt ,(3, -1491188400, 7) ,(3, -1247536800, 4)"
+ i_tzt="$i_tzt ,(3, 354920400, 5) ,(3, 370728000, 4)"
+ i_tzt="$i_tzt ,(3, 386456400, 5) ,(3, 402264000, 4)"
+ i_tzt="$i_tzt ,(3, 417992400, 5) ,(3, 433800000, 4)"
+ i_tzt="$i_tzt ,(3, 449614800, 5) ,(3, 465346800, 8)"
+ i_tzt="$i_tzt ,(3, 481071600, 9) ,(3, 496796400, 8)"
+ i_tzt="$i_tzt ,(3, 512521200, 9) ,(3, 528246000, 8)"
+ i_tzt="$i_tzt ,(3, 543970800, 9) ,(3, 559695600, 8)"
+ i_tzt="$i_tzt ,(3, 575420400, 9) ,(3, 591145200, 8)"
+ i_tzt="$i_tzt ,(3, 606870000, 9) ,(3, 622594800, 8)"
+ i_tzt="$i_tzt ,(3, 638319600, 9) ,(3, 654649200, 8)"
+ i_tzt="$i_tzt ,(3, 670374000, 10) ,(3, 686102400, 11)"
+ i_tzt="$i_tzt ,(3, 695779200, 8) ,(3, 701812800, 5)"
+ i_tzt="$i_tzt ,(3, 717534000, 4) ,(3, 733273200, 9)"
+ i_tzt="$i_tzt ,(3, 748998000, 8) ,(3, 764722800, 9)"
+ i_tzt="$i_tzt ,(3, 780447600, 8) ,(3, 796172400, 9)"
+ i_tzt="$i_tzt ,(3, 811897200, 8) ,(3, 828226800, 9)"
+ i_tzt="$i_tzt ,(3, 846370800, 8) ,(3, 859676400, 9)"
+ i_tzt="$i_tzt ,(3, 877820400, 8) ,(3, 891126000, 9)"
+ i_tzt="$i_tzt ,(3, 909270000, 8) ,(3, 922575600, 9)"
+ i_tzt="$i_tzt ,(3, 941324400, 8) ,(3, 954025200, 9)"
+ i_tzt="$i_tzt ,(3, 972774000, 8) ,(3, 985474800, 9)"
+ i_tzt="$i_tzt ,(3, 1004223600, 8) ,(3, 1017529200, 9)"
+ i_tzt="$i_tzt ,(3, 1035673200, 8) ,(3, 1048978800, 9)"
+ i_tzt="$i_tzt ,(3, 1067122800, 8) ,(3, 1080428400, 9)"
+ i_tzt="$i_tzt ,(3, 1099177200, 8) ,(3, 1111878000, 9)"
+ i_tzt="$i_tzt ,(3, 1130626800, 8) ,(3, 1143327600, 9)"
+ i_tzt="$i_tzt ,(3, 1162076400, 8) ,(3, 1174777200, 9)"
+ i_tzt="$i_tzt ,(3, 1193526000, 8) ,(3, 1206831600, 9)"
+ i_tzt="$i_tzt ,(3, 1224975600, 8) ,(3, 1238281200, 9)"
+ i_tzt="$i_tzt ,(3, 1256425200, 8) ,(3, 1269730800, 9)"
+ i_tzt="$i_tzt ,(3, 1288479600, 8) ,(3, 1301180400, 9)"
+ i_tzt="$i_tzt ,(3, 1319929200, 8) ,(3, 1332630000, 9)"
+ i_tzt="$i_tzt ,(3, 1351378800, 8) ,(3, 1364684400, 9)"
+ i_tzt="$i_tzt ,(3, 1382828400, 8) ,(3, 1396134000, 9)"
+ i_tzt="$i_tzt ,(3, 1414278000, 8) ,(3, 1427583600, 9)"
+ i_tzt="$i_tzt ,(3, 1445727600, 8) ,(3, 1459033200, 9)"
+ i_tzt="$i_tzt ,(3, 1477782000, 8) ,(3, 1490482800, 9)"
+ i_tzt="$i_tzt ,(3, 1509231600, 8) ,(3, 1521932400, 9)"
+ i_tzt="$i_tzt ,(3, 1540681200, 8) ,(3, 1553986800, 9)"
+ i_tzt="$i_tzt ,(3, 1572130800, 8) ,(3, 1585436400, 9)"
+ i_tzt="$i_tzt ,(3, 1603580400, 8) ,(3, 1616886000, 9)"
+ i_tzt="$i_tzt ,(3, 1635634800, 8) ,(3, 1648335600, 9)"
+ i_tzt="$i_tzt ,(3, 1667084400, 8) ,(3, 1679785200, 9)"
+ i_tzt="$i_tzt ,(3, 1698534000, 8) ,(3, 1711839600, 9)"
+ i_tzt="$i_tzt ,(3, 1729983600, 8) ,(3, 1743289200, 9)"
+ i_tzt="$i_tzt ,(3, 1761433200, 8) ,(3, 1774738800, 9)"
+ i_tzt="$i_tzt ,(3, 1792882800, 8) ,(3, 1806188400, 9)"
+ i_tzt="$i_tzt ,(3, 1824937200, 8) ,(3, 1837638000, 9)"
+ i_tzt="$i_tzt ,(3, 1856386800, 8) ,(3, 1869087600, 9)"
+ i_tzt="$i_tzt ,(3, 1887836400, 8) ,(3, 1901142000, 9)"
+ i_tzt="$i_tzt ,(3, 1919286000, 8) ,(3, 1932591600, 9)"
+ i_tzt="$i_tzt ,(3, 1950735600, 8) ,(3, 1964041200, 9)"
+ i_tzt="$i_tzt ,(3, 1982790000, 8) ,(3, 1995490800, 9)"
+ i_tzt="$i_tzt ,(3, 2014239600, 8) ,(3, 2026940400, 9)"
+ i_tzt="$i_tzt ,(3, 2045689200, 8) ,(3, 2058390000, 9)"
+ i_tzt="$i_tzt ,(3, 2077138800, 8) ,(3, 2090444400, 9)"
+ i_tzt="$i_tzt ,(3, 2108588400, 8) ,(3, 2121894000, 9)"
+ i_tzt="$i_tzt ,(3, 2140038000, 8)"
+ i_tzt="$i_tzt ,(4, -1688265000, 2) ,(4, -1656819048, 1)"
+ i_tzt="$i_tzt ,(4, -1641353448, 2) ,(4, -1627965048, 3)"
+ i_tzt="$i_tzt ,(4, -1618716648, 1) ,(4, -1596429048, 3)"
+ i_tzt="$i_tzt ,(4, -1593829848, 5) ,(4, -1589860800, 4)"
+ i_tzt="$i_tzt ,(4, -1542427200, 5) ,(4, -1539493200, 6)"
+ i_tzt="$i_tzt ,(4, -1525323600, 5) ,(4, -1522728000, 4)"
+ i_tzt="$i_tzt ,(4, -1491188400, 7) ,(4, -1247536800, 4)"
+ i_tzt="$i_tzt ,(4, 354920409, 5) ,(4, 370728010, 4)"
+ i_tzt="$i_tzt ,(4, 386456410, 5) ,(4, 402264011, 4)"
+ i_tzt="$i_tzt ,(4, 417992411, 5) ,(4, 433800012, 4)"
+ i_tzt="$i_tzt ,(4, 449614812, 5) ,(4, 465346812, 8)"
+ i_tzt="$i_tzt ,(4, 481071612, 9) ,(4, 496796413, 8)"
+ i_tzt="$i_tzt ,(4, 512521213, 9) ,(4, 528246013, 8)"
+ i_tzt="$i_tzt ,(4, 543970813, 9) ,(4, 559695613, 8)"
+ i_tzt="$i_tzt ,(4, 575420414, 9) ,(4, 591145214, 8)"
+ i_tzt="$i_tzt ,(4, 606870014, 9) ,(4, 622594814, 8)"
+ i_tzt="$i_tzt ,(4, 638319615, 9) ,(4, 654649215, 8)"
+ i_tzt="$i_tzt ,(4, 670374016, 10) ,(4, 686102416, 11)"
+ i_tzt="$i_tzt ,(4, 695779216, 8) ,(4, 701812816, 5)"
+ i_tzt="$i_tzt ,(4, 717534017, 4) ,(4, 733273217, 9)"
+ i_tzt="$i_tzt ,(4, 748998018, 8) ,(4, 764722818, 9)"
+ i_tzt="$i_tzt ,(4, 780447619, 8) ,(4, 796172419, 9)"
+ i_tzt="$i_tzt ,(4, 811897219, 8) ,(4, 828226820, 9)"
+ i_tzt="$i_tzt ,(4, 846370820, 8) ,(4, 859676420, 9)"
+ i_tzt="$i_tzt ,(4, 877820421, 8) ,(4, 891126021, 9)"
+ i_tzt="$i_tzt ,(4, 909270021, 8) ,(4, 922575622, 9)"
+ i_tzt="$i_tzt ,(4, 941324422, 8) ,(4, 954025222, 9)"
+ i_tzt="$i_tzt ,(4, 972774022, 8) ,(4, 985474822, 9)"
+ i_tzt="$i_tzt ,(4, 1004223622, 8) ,(4, 1017529222, 9)"
+ i_tzt="$i_tzt ,(4, 1035673222, 8) ,(4, 1048978822, 9)"
+ i_tzt="$i_tzt ,(4, 1067122822, 8) ,(4, 1080428422, 9)"
+ i_tzt="$i_tzt ,(4, 1099177222, 8) ,(4, 1111878022, 9)"
+ i_tzt="$i_tzt ,(4, 1130626822, 8) ,(4, 1143327622, 9)"
+ i_tzt="$i_tzt ,(4, 1162076422, 8) ,(4, 1174777222, 9)"
+ i_tzt="$i_tzt ,(4, 1193526022, 8) ,(4, 1206831622, 9)"
+ i_tzt="$i_tzt ,(4, 1224975622, 8) ,(4, 1238281222, 9)"
+ i_tzt="$i_tzt ,(4, 1256425222, 8) ,(4, 1269730822, 9)"
+ i_tzt="$i_tzt ,(4, 1288479622, 8) ,(4, 1301180422, 9)"
+ i_tzt="$i_tzt ,(4, 1319929222, 8) ,(4, 1332630022, 9)"
+ i_tzt="$i_tzt ,(4, 1351378822, 8) ,(4, 1364684422, 9)"
+ i_tzt="$i_tzt ,(4, 1382828422, 8) ,(4, 1396134022, 9)"
+ i_tzt="$i_tzt ,(4, 1414278022, 8) ,(4, 1427583622, 9)"
+ i_tzt="$i_tzt ,(4, 1445727622, 8) ,(4, 1459033222, 9)"
+ i_tzt="$i_tzt ,(4, 1477782022, 8) ,(4, 1490482822, 9)"
+ i_tzt="$i_tzt ,(4, 1509231622, 8) ,(4, 1521932422, 9)"
+ i_tzt="$i_tzt ,(4, 1540681222, 8) ,(4, 1553986822, 9)"
+ i_tzt="$i_tzt ,(4, 1572130822, 8) ,(4, 1585436422, 9)"
+ i_tzt="$i_tzt ,(4, 1603580422, 8) ,(4, 1616886022, 9)"
+ i_tzt="$i_tzt ,(4, 1635634822, 8) ,(4, 1648335622, 9)"
+ i_tzt="$i_tzt ,(4, 1667084422, 8) ,(4, 1679785222, 9)"
+ i_tzt="$i_tzt ,(4, 1698534022, 8) ,(4, 1711839622, 9)"
+ i_tzt="$i_tzt ,(4, 1729983622, 8) ,(4, 1743289222, 9)"
+ i_tzt="$i_tzt ,(4, 1761433222, 8) ,(4, 1774738822, 9)"
+ i_tzt="$i_tzt ,(4, 1792882822, 8) ,(4, 1806188422, 9)"
+ i_tzt="$i_tzt ,(4, 1824937222, 8) ,(4, 1837638022, 9)"
+ i_tzt="$i_tzt ,(4, 1856386822, 8) ,(4, 1869087622, 9)"
+ i_tzt="$i_tzt ,(4, 1887836422, 8) ,(4, 1901142022, 9)"
+ i_tzt="$i_tzt ,(4, 1919286022, 8) ,(4, 1932591622, 9)"
+ i_tzt="$i_tzt ,(4, 1950735622, 8) ,(4, 1964041222, 9)"
+ i_tzt="$i_tzt ,(4, 1982790022, 8) ,(4, 1995490822, 9)"
+ i_tzt="$i_tzt ,(4, 2014239622, 8) ,(4, 2026940422, 9)"
+ i_tzt="$i_tzt ,(4, 2045689222, 8) ,(4, 2058390022, 9)"
+ i_tzt="$i_tzt ,(4, 2077138822, 8) ,(4, 2090444422, 9)"
+ i_tzt="$i_tzt ,(4, 2108588422, 8) ,(4, 2121894022, 9)"
+ i_tzt="$i_tzt ,(4, 2140038022, 8);"
+ fi
+fi
+
+if test ! -f $mdata/time_zone_transition_type.frm
+then
+ if test "$1" = "verbose" ; then
+ echo "Preparing time_zone_transition_type table" 1>&2;
+ fi
+
+ c_tztt="$c_tztt CREATE TABLE time_zone_transition_type ("
+ c_tztt="$c_tztt Time_zone_id int unsigned NOT NULL,"
+ c_tztt="$c_tztt Transition_type_id int unsigned NOT NULL,"
+ c_tztt="$c_tztt Offset int signed DEFAULT 0 NOT NULL,"
+ c_tztt="$c_tztt Is_DST tinyint unsigned DEFAULT 0 NOT NULL,"
+ c_tztt="$c_tztt Abbreviation char(8) DEFAULT '' NOT NULL,"
+ c_tztt="$c_tztt PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id)"
+ c_tztt="$c_tztt ) DEFAULT CHARACTER SET latin1"
+ c_tztt="$c_tztt comment='Time zone transition types';"
+
+ if test "$1" = "test"
+ then
+ i_tztt="$i_tztt INSERT INTO time_zone_transition_type (Time_zone_id,"
+ i_tztt="$i_tztt Transition_type_id, Offset, Is_DST, Abbreviation) VALUES"
+ i_tztt="$i_tztt (1, 0, 7200, 1, 'MEST') ,(1, 1, 3600, 0, 'MET')"
+ i_tztt="$i_tztt ,(1, 2, 7200, 1, 'MEST') ,(1, 3, 3600, 0, 'MET')"
+ i_tztt="$i_tztt ,(2, 0, 0, 0, 'UTC')"
+ i_tztt="$i_tztt ,(3, 0, 9000, 0, 'MMT') ,(3, 1, 12648, 1, 'MST')"
+ i_tztt="$i_tztt ,(3, 2, 9048, 0, 'MMT') ,(3, 3, 16248, 1, 'MDST')"
+ i_tztt="$i_tztt ,(3, 4, 10800, 0, 'MSK') ,(3, 5, 14400, 1, 'MSD')"
+ i_tztt="$i_tztt ,(3, 6, 18000, 1, 'MSD') ,(3, 7, 7200, 0, 'EET')"
+ i_tztt="$i_tztt ,(3, 8, 10800, 0, 'MSK') ,(3, 9, 14400, 1, 'MSD')"
+ i_tztt="$i_tztt ,(3, 10, 10800, 1, 'EEST') ,(3, 11, 7200, 0, 'EET')"
+ i_tztt="$i_tztt ,(4, 0, 9000, 0, 'MMT') ,(4, 1, 12648, 1, 'MST')"
+ i_tztt="$i_tztt ,(4, 2, 9048, 0, 'MMT') ,(4, 3, 16248, 1, 'MDST')"
+ i_tztt="$i_tztt ,(4, 4, 10800, 0, 'MSK') ,(4, 5, 14400, 1, 'MSD')"
+ i_tztt="$i_tztt ,(4, 6, 18000, 1, 'MSD') ,(4, 7, 7200, 0, 'EET')"
+ i_tztt="$i_tztt ,(4, 8, 10800, 0, 'MSK') ,(4, 9, 14400, 1, 'MSD')"
+ i_tztt="$i_tztt ,(4, 10, 10800, 1, 'EEST') ,(4, 11, 7200, 0, 'EET');"
+ fi
+fi
+
+if test ! -f $mdata/time_zone_leap_second.frm
+then
+ if test "$1" = "verbose" ; then
+ echo "Preparing time_zone_leap_second table" 1>&2;
+ fi
+
+ c_tzls="$c_tzls CREATE TABLE time_zone_leap_second ("
+ c_tzls="$c_tzls Transition_time bigint signed NOT NULL,"
+ c_tzls="$c_tzls Correction int signed NOT NULL,"
+ c_tzls="$c_tzls PRIMARY KEY TranTime (Transition_time)"
+ c_tzls="$c_tzls ) DEFAULT CHARACTER SET latin1"
+ c_tzls="$c_tzls comment='Leap seconds information for time zones';"
+
+ if test "$1" = "test"
+ then
+ i_tzls="$i_tzls INSERT INTO time_zone_leap_second "
+ i_tzls="$i_tzls (Transition_time, Correction) VALUES "
+ i_tzls="$i_tzls (78796800, 1) ,(94694401, 2) ,(126230402, 3)"
+ i_tzls="$i_tzls ,(157766403, 4) ,(189302404, 5) ,(220924805, 6)"
+ i_tzls="$i_tzls ,(252460806, 7) ,(283996807, 8) ,(315532808, 9)"
+ i_tzls="$i_tzls ,(362793609, 10) ,(394329610, 11) ,(425865611, 12)"
+ i_tzls="$i_tzls ,(489024012, 13) ,(567993613, 14) ,(631152014, 15)"
+ i_tzls="$i_tzls ,(662688015, 16) ,(709948816, 17) ,(741484817, 18)"
+ i_tzls="$i_tzls ,(773020818, 19) ,(820454419, 20) ,(867715220, 21)"
+ i_tzls="$i_tzls ,(915148821, 22);"
+ fi
+fi
+
if test ! -f $mdata/proc.frm
then
c_p="$c_p CREATE TABLE proc ("
@@ -352,6 +683,17 @@ $c_hc
$c_hr
$c_hk
+$c_tzn
+$i_tzn
+$c_tz
+$i_tz
+$c_tzt
+$i_tzt
+$c_tztt
+$i_tztt
+$c_tzls
+$i_tzls
+
$c_p
END_OF_DATA
diff --git a/scripts/mysql_find_rows.sh b/scripts/mysql_find_rows.sh
index 3d7bad3323e..91ffc326e16 100644
--- a/scripts/mysql_find_rows.sh
+++ b/scripts/mysql_find_rows.sh
@@ -16,7 +16,7 @@ usage() if ($opt_help || $opt_Information);
$query=$search=$database=$set=""; $eoq=0;
while (<>)
{
- next if (length($query) == 0 && /^\#/); # Skipp comments
+ next if (length($query) == 0 && /^\#/); # Skip comments
$query.=search($_);
if ($eoq)
{
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index 69bf2bebaa8..f3c5c009f1c 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -102,7 +102,7 @@ then
fi
cmd="$bindir/mysql -f --user=$user --host=$host"
-if test -z "$password" ; then
+if test ! -z "$password" ; then
cmd="$cmd --password=$password"
fi
if test ! -z "$port"; then
@@ -118,13 +118,14 @@ then
cmd="cat"
fi
-# Find where mysql_fix_privilege_tables.sql is located
+# Find where first mysql_fix_privilege_tables.sql is located
for i in $basedir/support-files $basedir/share $basedir/share/mysql \
$basedir/scripts @pkgdatadir@ . ./scripts
do
if test -f $i/$file
then
pkgdatadir=$i
+ break
fi
done
@@ -154,7 +155,7 @@ s_echo ""
if test $verbose = 1
then
s_echo "You can safely ignore all 'Duplicate column' and 'Unknown column' errors"
- s_echo "as this just means that your tables where already up to date."
+ s_echo "because these just mean that your tables are already up to date."
s_echo "This script is safe to run even if your tables are already up to date!"
s_echo ""
fi
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index 0feab0ac7d0..83b802ee567 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -2,7 +2,7 @@
-- for MySQL 4.0.
-- You can safely ignore all 'Duplicate column' and 'Unknown column' errors"
--- as this just means that your tables where already up to date.
+-- because these just mean that your tables are already up to date.
-- This script is safe to run even if your tables are already up to date!
-- On unix, you should use the mysql_fix_privilege_tables script to execute
@@ -181,6 +181,45 @@ unique index (name)
) comment='help keywords';
#
+# Create missing time zone related tables
+#
+
+CREATE TABLE IF NOT EXISTS time_zone_name (
+Name char(64) NOT NULL,
+Time_zone_id int unsigned NOT NULL,
+PRIMARY KEY Name (Name)
+) DEFAULT CHARACTER SET latin1 comment='Time zone names';
+
+CREATE TABLE IF NOT EXISTS time_zone (
+Time_zone_id int unsigned NOT NULL auto_increment,
+Use_leap_seconds enum('Y','N') DEFAULT 'N' NOT NULL,
+PRIMARY KEY TzId (Time_zone_id)
+) DEFAULT CHARACTER SET latin1 comment='Time zones';
+
+CREATE TABLE IF NOT EXISTS time_zone_transition (
+Time_zone_id int unsigned NOT NULL,
+Transition_time bigint signed NOT NULL,
+Transition_type_id int unsigned NOT NULL,
+PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time)
+) DEFAULT CHARACTER SET latin1 comment='Time zone transitions';
+
+CREATE TABLE IF NOT EXISTS time_zone_transition_type (
+Time_zone_id int unsigned NOT NULL,
+Transition_type_id int unsigned NOT NULL,
+Offset int signed DEFAULT 0 NOT NULL,
+Is_DST tinyint unsigned DEFAULT 0 NOT NULL,
+Abbreviation char(8) DEFAULT '' NOT NULL,
+PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id)
+) DEFAULT CHARACTER SET latin1 comment='Time zone transition types';
+
+CREATE TABLE IF NOT EXISTS time_zone_leap_second (
+Transition_time bigint signed NOT NULL,
+Correction int signed NOT NULL,
+PRIMARY KEY TranTime (Transition_time)
+) DEFAULT CHARACTER SET latin1 comment='Leap seconds information for time zones';
+
+
+#
# Create proc table if it doesn't exists
#
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index abde6ecbe73..aa5b99aebcc 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -10,6 +10,7 @@
in_rpm=0
windows=0
defaults=""
+user=""
tmp_file=/tmp/mysql_install_db.$$
case "$1" in
@@ -34,7 +35,11 @@ parse_arguments() {
--force) force=1 ;;
--basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
--ldata=*|--datadir=*) ldata=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
- --user=*) user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --user=*)
+ # Note that the user will be passed to mysqld so that it runs
+ # as 'user' (crucial e.g. if log-bin=/some_other_path/
+ # where a chown of datadir won't help)
+ user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
--skip-name-resolve) ip_only=1 ;;
--verbose) verbose=1 ;;
--rpm) in_rpm=1 ;;
@@ -155,7 +160,7 @@ then
resolved=`$bindir/resolveip localhost 2>&1`
if [ $? -ne 0 ]
then
- echo "Neither host '$hostname' and 'localhost' could not be looked up with"
+ echo "Neither host '$hostname' nor 'localhost' could be looked up with"
echo "$bindir/resolveip"
echo "Please configure the 'hostname' command to return a correct hostname."
echo "If you want to solve this at a later stage, restart this script with"
@@ -198,13 +203,17 @@ else
create_option="real"
fi
+if test -n "$user"; then
+ args="$args --user=$user"
+fi
+
if test "$in_rpm" -eq 0 -a "$windows" -eq 0
then
echo "Installing all prepared tables"
fi
mysqld_install_cmd_line="$mysqld $defaults $mysqld_opt --bootstrap \
--skip-grant-tables --basedir=$basedir --datadir=$ldata --skip-innodb \
---skip-bdb $args"
+--skip-bdb $args --max_allowed_packet=8M"
if $scriptdir/mysql_create_system_tables $create_option $mdata $hostname $windows \
| eval "$mysqld_install_cmd_line"
then
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 779438e75c3..7b77bf449cd 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -43,13 +43,7 @@ parse_arguments() {
--basedir=*) MY_BASEDIR_VERSION=`echo "$arg" | sed -e "s;--basedir=;;"` ;;
--datadir=*) DATADIR=`echo "$arg" | sed -e "s;--datadir=;;"` ;;
--pid-file=*) pid_file=`echo "$arg" | sed -e "s;--pid-file=;;"` ;;
- --user=*)
- if test $SET_USER -eq 0
- then
- user=`echo "$arg" | sed -e "s;--[^=]*=;;"`
- fi
- SET_USER=1
- ;;
+ --user=*) user=`echo "$arg" | sed -e "s;--[^=]*=;;"` ; SET_USER=1 ;;
# these two might have been set in a [mysqld_safe] section of my.cnf
# they are added to mysqld command line to override settings from my.cnf
diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh
index 905e7ee65be..1f5ba707f05 100644
--- a/sql-bench/server-cfg.sh
+++ b/sql-bench/server-cfg.sh
@@ -184,6 +184,14 @@ sub new
$self->{'transactions'} = 1; # Transactions enabled
}
if (defined($main::opt_create_options) &&
+ $main::opt_create_options =~ /type=ndb/i)
+ {
+ $self->{'transactions'} = 1; # Transactions enabled
+ $limits{'max_columns'} = 90; # Max number of columns in table
+ $limits{'max_tables'} = 32; # No comments
+ $limits{'working_blobs'} = 0; # NDB tables can't handle BLOB's
+ }
+ if (defined($main::opt_create_options) &&
$main::opt_create_options =~ /type=bdb/i)
{
$self->{'transactions'} = 1; # Transactions enabled
diff --git a/sql-common/Makefile.am b/sql-common/Makefile.am
index 1f397c0ea87..6bd42d70e4f 100644
--- a/sql-common/Makefile.am
+++ b/sql-common/Makefile.am
@@ -15,7 +15,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## Process this file with automake to create Makefile.in
-EXTRA_DIST = client.c pack.c
+EXTRA_DIST = client.c pack.c my_time.c
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/sql-common/client.c b/sql-common/client.c
index 02fb1964eaa..3aaa9f23665 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -39,6 +39,10 @@
#include "mysql.h"
+/* Remove client convenience wrappers */
+#undef max_allowed_packet
+#undef net_buffer_length
+
#ifdef EMBEDDED_LIBRARY
#undef MYSQL_SERVER
@@ -63,7 +67,6 @@ my_bool net_flush(NET *net);
#include "mysqld_error.h"
#include "errmsg.h"
#include <violite.h>
-#include <assert.h>
#if defined(THREAD) && !defined(__WIN__)
#include <my_pthread.h> /* because of signal() */
#endif /* defined(THREAD) && !defined(__WIN__) */
@@ -445,13 +448,13 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) !=
WAIT_OBJECT_0)
{
- error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR;
+ error_allow = CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR;
goto err;
}
/* Get number of connection */
connect_number = uint4korr(handle_connect_map);/*WAX2*/
- p= int2str(connect_number, connect_number_char, 10);
+ p= int10_to_str(connect_number, connect_number_char, 10);
/*
The name of event and file-mapping events create agree next rule:
@@ -751,6 +754,58 @@ static my_bool is_NT(void)
}
#endif
+
+#ifdef CHECK_LICENSE
+/*
+ Check server side variable 'license'.
+ If the variable does not exist or does not contain 'Commercial',
+ we're talking to non-commercial server from commercial client.
+ SYNOPSIS
+ check_license()
+ RETURN VALUE
+ 0 success
+ !0 network error or the server is not commercial.
+ Error code is saved in mysql->net.last_errno.
+*/
+
+static int check_license(MYSQL *mysql)
+{
+ MYSQL_ROW row;
+ MYSQL_RES *res;
+ NET *net= &mysql->net;
+ static const char query[]= "SELECT @@license";
+ static const char required_license[]= STRINGIFY_ARG(LICENSE);
+
+ if (mysql_real_query(mysql, query, sizeof(query)-1))
+ {
+ if (net->last_errno == ER_UNKNOWN_SYSTEM_VARIABLE)
+ {
+ net->last_errno= CR_WRONG_LICENSE;
+ sprintf(net->last_error, ER(net->last_errno), required_license);
+ }
+ return 1;
+ }
+ if (!(res= mysql_use_result(mysql)))
+ return 1;
+ row= mysql_fetch_row(res);
+ /*
+ If no rows in result set, or column value is NULL (none of these
+ two is ever true for server variables now), or column value
+ mismatch, set wrong license error.
+ */
+ if (!net->last_errno &&
+ (!row || !row[0] ||
+ strncmp(row[0], required_license, sizeof(required_license))))
+ {
+ net->last_errno= CR_WRONG_LICENSE;
+ sprintf(net->last_error, ER(net->last_errno), required_license);
+ }
+ mysql_free_result(res);
+ return net->last_errno;
+}
+#endif /* CHECK_LICENSE */
+
+
/**************************************************************************
Shut down connection
**************************************************************************/
@@ -1681,7 +1736,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno);
goto error;
}
- memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length);
+ memcpy(&sock_addr.sin_addr, hp->h_addr,
+ min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length));
my_gethostbyname_r_free();
}
sock_addr.sin_port = (ushort) htons((ushort) port);
@@ -1783,40 +1839,39 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
}
/* Set character set */
- if (mysql->options.charset_name)
+ if (!mysql->options.charset_name &&
+ !(mysql->options.charset_name=
+ my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
+ goto error;
+
{
const char *save= charsets_dir;
if (mysql->options.charset_dir)
charsets_dir=mysql->options.charset_dir;
mysql->charset=get_charset_by_csname(mysql->options.charset_name,
- MY_CS_PRIMARY,
- MYF(MY_WME));
+ MY_CS_PRIMARY, MYF(MY_WME));
charsets_dir= save;
-
- if (!mysql->charset)
- {
- net->last_errno=CR_CANT_READ_CHARSET;
- strmov(net->sqlstate, unknown_sqlstate);
- if (mysql->options.charset_dir)
- my_snprintf(net->last_error, sizeof(net->last_error)-1,
- ER(net->last_errno),
- mysql->options.charset_name,
- mysql->options.charset_dir);
- else
- {
- char cs_dir_name[FN_REFLEN];
- get_charsets_dir(cs_dir_name);
- my_snprintf(net->last_error, sizeof(net->last_error)-1,
- ER(net->last_errno),
- mysql->options.charset_name,
- cs_dir_name);
- }
- goto error;
- }
}
- else
+
+ if (!mysql->charset)
{
- mysql->charset= default_charset_info;
+ net->last_errno=CR_CANT_READ_CHARSET;
+ strmov(net->sqlstate, unknown_sqlstate);
+ if (mysql->options.charset_dir)
+ my_snprintf(net->last_error, sizeof(net->last_error)-1,
+ ER(net->last_errno),
+ mysql->options.charset_name,
+ mysql->options.charset_dir);
+ else
+ {
+ char cs_dir_name[FN_REFLEN];
+ get_charsets_dir(cs_dir_name);
+ my_snprintf(net->last_error, sizeof(net->last_error)-1,
+ ER(net->last_errno),
+ mysql->options.charset_name,
+ cs_dir_name);
+ }
+ goto error;
}
@@ -1996,10 +2051,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
goto error;
}
-
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
+#ifdef CHECK_LICENSE
+ if (check_license(mysql))
+ goto error;
+#endif
+
if (db && mysql_select_db(mysql,db))
goto error;
@@ -2469,7 +2528,7 @@ mysql_fetch_row(MYSQL_RES *res)
{
set_mysql_error(mysql,
res->unbuffered_fetch_cancelled ?
- CR_FETCH_CANCELLED : CR_COMMANDS_OUT_OF_SYNC,
+ CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
unknown_sqlstate);
}
else if (!(read_one_row(mysql, res->field_count, res->row, res->lengths)))
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
new file mode 100644
index 00000000000..46c84ac9ba7
--- /dev/null
+++ b/sql-common/my_time.c
@@ -0,0 +1,561 @@
+/* Copyright (C) 2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_time.h>
+#include <m_string.h>
+#include <m_ctype.h>
+
+ulonglong log_10_int[20]=
+{
+ 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL,
+ ULL(100000000), ULL(1000000000), ULL(10000000000), ULL(100000000000),
+ ULL(1000000000000), ULL(10000000000000), ULL(100000000000000),
+ ULL(1000000000000000), ULL(10000000000000000), ULL(100000000000000000),
+ ULL(1000000000000000000), ULL(10000000000000000000)
+};
+
+
+/* Position for YYYY-DD-MM HH-MM-DD.FFFFFF AM in default format */
+
+static uchar internal_format_positions[]=
+{0, 1, 2, 3, 4, 5, 6, (uchar) 255};
+
+static char time_separator=':';
+
+/*
+ Convert a timestamp string to a MYSQL_TIME value.
+
+ SYNOPSIS
+ str_to_datetime()
+ str String to parse
+ length Length of string
+ l_time Date is stored here
+ flags Bitmap of following items
+ TIME_FUZZY_DATE Set if we should allow partial dates
+ TIME_DATETIME_ONLY Set if we only allow full datetimes.
+ was_cut Set to 1 if value was cut during conversion or to 0
+ otherwise.
+
+ DESCRIPTION
+ At least the following formats are recogniced (based on number of digits)
+ YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS
+ YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS
+ YYYYMMDDTHHMMSS where T is a the character T (ISO8601)
+ Also dates where all parts are zero are allowed
+
+ The second part may have an optional .###### fraction part.
+
+ NOTES
+ This function should work with a format position vector as long as the
+ following things holds:
+ - All date are kept together and all time parts are kept together
+ - Date and time parts must be separated by blank
+ - Second fractions must come after second part and be separated
+ by a '.'. (The second fractions are optional)
+ - AM/PM must come after second fractions (or after seconds if no fractions)
+ - Year must always been specified.
+ - If time is before date, then we will use datetime format only if
+ the argument consist of two parts, separated by space.
+ Otherwise we will assume the argument is a date.
+ - The hour part must be specified in hour-minute-second order.
+
+ RETURN VALUES
+ MYSQL_TIMESTAMP_NONE String wasn't a timestamp, like
+ [DD [HH:[MM:[SS]]]].fraction.
+ l_time is not changed.
+ MYSQL_TIMESTAMP_DATE DATE string (YY MM and DD parts ok)
+ MYSQL_TIMESTAMP_DATETIME Full timestamp
+ MYSQL_TIMESTAMP_ERROR Timestamp with wrong values.
+ All elements in l_time is set to 0
+*/
+
+#define MAX_DATE_PARTS 8
+
+enum enum_mysql_timestamp_type
+str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
+ uint flags, int *was_cut)
+{
+ uint field_length, year_length, digits, i, number_of_fields;
+ uint date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
+ uint add_hours= 0, start_loop;
+ ulong not_zero_date, allow_space;
+ bool is_internal_format;
+ const char *pos, *last_field_pos;
+ const char *end=str+length;
+ const uchar *format_position;
+ bool found_delimitier= 0, found_space= 0;
+ uint frac_pos, frac_len;
+ DBUG_ENTER("str_to_datetime");
+ DBUG_PRINT("ENTER",("str: %.*s",length,str));
+
+ LINT_INIT(field_length);
+ LINT_INIT(year_length);
+ LINT_INIT(last_field_pos);
+
+ *was_cut= 0;
+
+ /* Skip space at start */
+ for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
+ ;
+ if (str == end || ! my_isdigit(&my_charset_latin1, *str))
+ {
+ *was_cut= 1;
+ DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
+ }
+
+ is_internal_format= 0;
+ /* This has to be changed if want to activate different timestamp formats */
+ format_position= internal_format_positions;
+
+ /*
+ Calculate number of digits in first part.
+ If length= 8 or >= 14 then year is of format YYYY.
+ (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS)
+ */
+ for (pos=str; pos != end && my_isdigit(&my_charset_latin1,*pos) ; pos++)
+ ;
+
+ digits= (uint) (pos-str);
+ start_loop= 0; /* Start of scan loop */
+ date_len[format_position[0]]= 0; /* Length of year field */
+ if (pos == end)
+ {
+ /* Found date in internal format (only numbers like YYYYMMDD) */
+ year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
+ field_length=year_length-1;
+ is_internal_format= 1;
+ format_position= internal_format_positions;
+ }
+ else
+ {
+ if (format_position[0] >= 3) /* If year is after HHMMDD */
+ {
+ /*
+ If year is not in first part then we have to determinate if we got
+ a date field or a datetime field.
+ We do this by checking if there is two numbers separated by
+ space in the input.
+ */
+ while (pos < end && !my_isspace(&my_charset_latin1, *pos))
+ pos++;
+ while (pos < end && !my_isdigit(&my_charset_latin1, *pos))
+ pos++;
+ if (pos == end)
+ {
+ if (flags & TIME_DATETIME_ONLY)
+ {
+ *was_cut= 1;
+ DBUG_RETURN(MYSQL_TIMESTAMP_NONE); /* Can't be a full datetime */
+ }
+ /* Date field. Set hour, minutes and seconds to 0 */
+ date[0]= date[1]= date[2]= date[3]= date[4]= 0;
+ start_loop= 5; /* Start with first date part */
+ }
+ }
+ }
+
+ /*
+ Only allow space in the first "part" of the datetime field and:
+ - after days, part seconds
+ - before and after AM/PM (handled by code later)
+
+ 2003-03-03 20:00:20 AM
+ 20:00:20.000000 AM 03-03-2000
+ */
+ i= max((uint) format_position[0], (uint) format_position[1]);
+ set_if_bigger(i, (uint) format_position[2]);
+ allow_space= ((1 << i) | (1 << format_position[6]));
+ allow_space&= (1 | 2 | 4 | 8);
+
+ not_zero_date= 0;
+ for (i = start_loop;
+ i < MAX_DATE_PARTS-1 && str != end &&
+ my_isdigit(&my_charset_latin1,*str);
+ i++)
+ {
+ const char *start= str;
+ ulong tmp_value= (uint) (uchar) (*str++ - '0');
+ while (str != end && my_isdigit(&my_charset_latin1,str[0]) &&
+ (!is_internal_format || field_length--))
+ {
+ tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0');
+ str++;
+ }
+ date_len[i]= (uint) (str - start);
+ if (tmp_value > 999999) /* Impossible date part */
+ {
+ *was_cut= 1;
+ DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
+ }
+ date[i]=tmp_value;
+ not_zero_date|= tmp_value;
+
+ /* Length-1 of next field */
+ field_length= format_position[i+1] == 0 ? 3 : 1;
+
+ if ((last_field_pos= str) == end)
+ {
+ i++; /* Register last found part */
+ break;
+ }
+ /* Allow a 'T' after day to allow CCYYMMDDT type of fields */
+ if (i == format_position[2] && *str == 'T')
+ {
+ str++; /* ISO8601: CCYYMMDDThhmmss */
+ continue;
+ }
+ if (i == format_position[5]) /* Seconds */
+ {
+ if (*str == '.') /* Followed by part seconds */
+ {
+ str++;
+ field_length= 5; /* 5 digits after first (=6) */
+ }
+ continue;
+
+ /* No part seconds */
+ date[++i]= 0;
+ }
+ while (str != end &&
+ (my_ispunct(&my_charset_latin1,*str) ||
+ my_isspace(&my_charset_latin1,*str)))
+ {
+ if (my_isspace(&my_charset_latin1,*str))
+ {
+ if (!(allow_space & (1 << i)))
+ {
+ *was_cut= 1;
+ DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
+ }
+ found_space= 1;
+ }
+ str++;
+ found_delimitier= 1; /* Should be a 'normal' date */
+ }
+ /* Check if next position is AM/PM */
+ if (i == format_position[6]) /* Seconds, time for AM/PM */
+ {
+ i++; /* Skip AM/PM part */
+ if (format_position[7] != 255) /* If using AM/PM */
+ {
+ if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
+ {
+ if (str[0] == 'p' || str[0] == 'P')
+ add_hours= 12;
+ else if (str[0] != 'a' || str[0] != 'A')
+ continue; /* Not AM/PM */
+ str+= 2; /* Skip AM/PM */
+ /* Skip space after AM/PM */
+ while (str != end && my_isspace(&my_charset_latin1,*str))
+ str++;
+ }
+ }
+ }
+ last_field_pos= str;
+ }
+ if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY))
+ {
+ *was_cut= 1;
+ DBUG_RETURN(MYSQL_TIMESTAMP_NONE); /* Can't be a datetime */
+ }
+
+ str= last_field_pos;
+
+ number_of_fields= i - start_loop;
+ while (i < MAX_DATE_PARTS)
+ {
+ date_len[i]= 0;
+ date[i++]= 0;
+ }
+
+ if (!is_internal_format)
+ {
+ year_length= date_len[(uint) format_position[0]];
+ if (!year_length) /* Year must be specified */
+ {
+ *was_cut= 1;
+ DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
+ }
+
+ l_time->year= date[(uint) format_position[0]];
+ l_time->month= date[(uint) format_position[1]];
+ l_time->day= date[(uint) format_position[2]];
+ l_time->hour= date[(uint) format_position[3]];
+ l_time->minute= date[(uint) format_position[4]];
+ l_time->second= date[(uint) format_position[5]];
+
+ frac_pos= (uint) format_position[6];
+ frac_len= date_len[frac_pos];
+ if (frac_len < 6)
+ date[frac_pos]*= (uint) log_10_int[6 - frac_len];
+ l_time->second_part= date[frac_pos];
+
+ if (format_position[7] != (uchar) 255)
+ {
+ if (l_time->hour > 12)
+ {
+ *was_cut= 1;
+ goto err;
+ }
+ l_time->hour= l_time->hour%12 + add_hours;
+ }
+ }
+ else
+ {
+ l_time->year= date[0];
+ l_time->month= date[1];
+ l_time->day= date[2];
+ l_time->hour= date[3];
+ l_time->minute= date[4];
+ l_time->second= date[5];
+ if (date_len[6] < 6)
+ date[6]*= (uint) log_10_int[6 - date_len[6]];
+ l_time->second_part=date[6];
+ }
+ l_time->neg= 0;
+
+ if (year_length == 2 && i >= format_position[1] && i >=format_position[2] &&
+ (l_time->month || l_time->day))
+ l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);
+
+ if (number_of_fields < 3 || l_time->month > 12 ||
+ l_time->day > 31 || l_time->hour > 23 ||
+ l_time->minute > 59 || l_time->second > 59 ||
+ (!(flags & TIME_FUZZY_DATE) && (l_time->month == 0 || l_time->day == 0)))
+ {
+ /* Only give warning for a zero date if there is some garbage after */
+ if (!not_zero_date) /* If zero date */
+ {
+ for (; str != end ; str++)
+ {
+ if (!my_isspace(&my_charset_latin1, *str))
+ {
+ not_zero_date= 1; /* Give warning */
+ break;
+ }
+ }
+ }
+ if (not_zero_date)
+ *was_cut= 1;
+ goto err;
+ }
+
+ l_time->time_type= (number_of_fields <= 3 ?
+ MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);
+
+ for (; str != end ; str++)
+ {
+ if (!my_isspace(&my_charset_latin1,*str))
+ {
+ *was_cut= 1;
+ break;
+ }
+ }
+
+ DBUG_RETURN(l_time->time_type=
+ (number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE :
+ MYSQL_TIMESTAMP_DATETIME));
+
+err:
+ bzero((char*) l_time, sizeof(*l_time));
+ DBUG_RETURN(MYSQL_TIMESTAMP_ERROR);
+}
+
+
+/*
+ Convert a time string to a TIME struct.
+
+ SYNOPSIS
+ str_to_time()
+ str A string in full TIMESTAMP format or
+ [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS,
+ [M]MSS or [S]S
+ There may be an optional [.second_part] after seconds
+ length Length of str
+ l_time Store result here
+ was_cut Set to 1 if value was cut during conversion or to 0
+ otherwise.
+
+ NOTES
+ Because of the extra days argument, this function can only
+ work with times where the time arguments are in the above order.
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
+ int *was_cut)
+{
+ long date[5],value;
+ const char *end=str+length, *end_of_days;
+ bool found_days,found_hours;
+ uint state;
+
+ l_time->neg=0;
+ *was_cut= 0;
+ for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
+ length--;
+ if (str != end && *str == '-')
+ {
+ l_time->neg=1;
+ str++;
+ length--;
+ }
+ if (str == end)
+ return 1;
+
+ /* Check first if this is a full TIMESTAMP */
+ if (length >= 12)
+ { /* Probably full timestamp */
+ enum enum_mysql_timestamp_type
+ res= str_to_datetime(str, length, l_time,
+ (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), was_cut);
+ if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR)
+ return res == MYSQL_TIMESTAMP_ERROR;
+ /* We need to restore was_cut flag since str_to_datetime can modify it */
+ *was_cut= 0;
+ }
+
+ /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
+ for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
+ value=value*10L + (long) (*str - '0');
+
+ /* Skip all space after 'days' */
+ end_of_days= str;
+ for (; str != end && my_isspace(&my_charset_latin1, str[0]) ; str++)
+ ;
+
+ LINT_INIT(state);
+ found_days=found_hours=0;
+ if ((uint) (end-str) > 1 && str != end_of_days &&
+ my_isdigit(&my_charset_latin1, *str))
+ { /* Found days part */
+ date[0]= value;
+ state= 1; /* Assume next is hours */
+ found_days= 1;
+ }
+ else if ((end-str) > 1 && *str == time_separator &&
+ my_isdigit(&my_charset_latin1, str[1]))
+ {
+ date[0]=0; /* Assume we found hours */
+ date[1]=value;
+ state=2;
+ found_hours=1;
+ str++; /* skip ':' */
+ }
+ else
+ {
+ /* String given as one number; assume HHMMSS format */
+ date[0]= 0;
+ date[1]= value/10000;
+ date[2]= value/100 % 100;
+ date[3]= value % 100;
+ state=4;
+ goto fractional;
+ }
+
+ /* Read hours, minutes and seconds */
+ for (;;)
+ {
+ for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
+ value=value*10L + (long) (*str - '0');
+ date[state++]=value;
+ if (state == 4 || (end-str) < 2 || *str != time_separator ||
+ !my_isdigit(&my_charset_latin1,str[1]))
+ break;
+ str++; /* Skip time_separator (':') */
+ }
+
+ if (state != 4)
+ { /* Not HH:MM:SS */
+ /* Fix the date to assume that seconds was given */
+ if (!found_hours && !found_days)
+ {
+ bmove_upp((char*) (date+4), (char*) (date+state),
+ sizeof(long)*(state-1));
+ bzero((char*) date, sizeof(long)*(4-state));
+ }
+ else
+ bzero((char*) (date+state), sizeof(long)*(4-state));
+ }
+
+fractional:
+ /* Get fractional second part */
+ if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
+ {
+ uint field_length=5;
+ str++; value=(uint) (uchar) (*str - '0');
+ while (++str != end &&
+ my_isdigit(&my_charset_latin1,str[0]) &&
+ field_length--)
+ value=value*10 + (uint) (uchar) (*str - '0');
+ if (field_length)
+ value*= (long) log_10_int[field_length];
+ date[4]=value;
+ }
+ else
+ date[4]=0;
+
+ if (internal_format_positions[7] != 255)
+ {
+ /* Read a possible AM/PM */
+ while (str != end && my_isspace(&my_charset_latin1, *str))
+ str++;
+ if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
+ {
+ if (str[0] == 'p' || str[0] == 'P')
+ {
+ str+= 2;
+ date[1]= date[1]%12 + 12;
+ }
+ else if (str[0] == 'a' || str[0] == 'A')
+ str+=2;
+ }
+ }
+
+ /* Some simple checks */
+ if (date[2] >= 60 || date[3] >= 60)
+ {
+ *was_cut= 1;
+ return 1;
+ }
+ l_time->year= 0; /* For protocol::store_time */
+ l_time->month= 0;
+ l_time->day= date[0];
+ l_time->hour= date[1];
+ l_time->minute= date[2];
+ l_time->second= date[3];
+ l_time->second_part= date[4];
+ l_time->time_type= MYSQL_TIMESTAMP_TIME;
+
+ /* Check if there is garbage at end of the TIME specification */
+ if (str != end)
+ {
+ do
+ {
+ if (!my_isspace(&my_charset_latin1,*str))
+ {
+ *was_cut= 1;
+ break;
+ }
+ } while (++str != end);
+ }
+ return 0;
+}
+
+
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 828456c4510..a1eada6e3d2 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -27,6 +27,7 @@ WRAPLIBS= @WRAPLIBS@
SUBDIRS = share
libexec_PROGRAMS = mysqld
noinst_PROGRAMS = gen_lex_hash
+bin_PROGRAMS = mysql_tzinfo_to_sql
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
LDADD = @isam_libs@ \
../myisam/libmyisam.a \
@@ -57,8 +58,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
lex.h lex_symbol.h sql_acl.h sql_crypt.h \
log_event.h sql_repl.h slave.h \
stacktrace.h sql_sort.h sql_cache.h set_var.h \
- spatial.h gstream.h client_settings.h \
- examples/ha_example.h \
+ spatial.h gstream.h client_settings.h tzfile.h \
+ tztime.h examples/ha_example.h examples/ha_archive.h \
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
parse_file.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc \
@@ -90,11 +91,14 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
client.c sql_client.cc mini_client_errors.c pack.c\
stacktrace.c repl_failsafe.h repl_failsafe.cc \
gstream.cc spatial.cc sql_help.cc protocol_cursor.cc \
- examples/ha_example.cc \
+ tztime.cc my_time.c \
+ examples/ha_example.cc examples/ha_archive.cc \
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
sp_cache.cc parse_file.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
+mysql_tzinfo_to_sql_SOURCES = mysql_tzinfo_to_sql.cc
+mysql_tzinfo_to_sql_LDADD = $(LDADD) $(CXXLDFLAGS)
DEFS = -DMYSQL_SERVER \
-DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
@@ -106,17 +110,26 @@ BUILT_SOURCES = sql_yacc.cc sql_yacc.h
EXTRA_DIST = udf_example.cc $(BUILT_SOURCES)
AM_YFLAGS = -d
-link_sources:
+mysql_tzinfo_to_sql.cc:
+ rm -f mysql_tzinfo_to_sql.cc
+ @LN_CP_F@ tztime.cc mysql_tzinfo_to_sql.cc
+
+link_sources: mysql_tzinfo_to_sql.cc
rm -f mini_client_errors.c
@LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c
rm -f pack.c
@LN_CP_F@ ../sql-common/pack.c pack.c
rm -f client.c
@LN_CP_F@ ../sql-common/client.c client.c
+ 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 $<
+
# Try to get better dependencies for the grammar. Othervise really bad
# things like different grammars for different pars of MySQL can
# happen if you are unlucky.
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc
new file mode 100644
index 00000000000..e052a819ef8
--- /dev/null
+++ b/sql/examples/ha_archive.cc
@@ -0,0 +1,586 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef __GNUC__
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include <mysql_priv.h>
+
+#ifdef HAVE_ARCHIVE_DB
+#include "ha_archive.h"
+
+/*
+ First, if you want to understand storage engines you should look at
+ ha_example.cc and ha_example.h.
+ This example was written as a test case for a customer who needed
+ a storage engine without indexes that could compress data very well.
+ So, welcome to a completely compressed storage engine. This storage
+ engine only does inserts. No replace, deletes, or updates. All reads are
+ complete table scans. Compression is done through gzip (bzip compresses
+ better, but only marginally, if someone asks I could add support for
+ it too, but beaware that it costs a lot more in CPU time then gzip).
+
+ We keep a file pointer open for each instance of ha_archive for each read
+ but for writes we keep one open file handle just for that. We flush it
+ only if we have a read occur. gzip handles compressing lots of records
+ at once much better then doing lots of little records between writes.
+ It is possible to not lock on writes but this would then mean we couldn't
+ handle bulk inserts as well (that is if someone was trying to read at
+ the same time since we would want to flush).
+
+ No attempts at durability are made. You can corrupt your data.
+
+ For performance as far as table scans go it is quite fast. I don't have
+ good numbers but locally it has out performed both Innodb and MyISAM. For
+ Innodb the question will be if the table can be fit into the buffer
+ pool. For MyISAM its a question of how much the file system caches the
+ MyISAM file. With enough free memory MyISAM is faster. Its only when the OS
+ doesn't have enough memory to cache entire table that archive turns out
+ to be any faster. For writes it is always a bit slower then MyISAM. It has no
+ internal limits though for row length.
+
+ Examples between MyISAM (packed) and Archive.
+
+ Table with 76695844 identical rows:
+ 29680807 a_archive.ARZ
+ 920350317 a.MYD
+
+
+ Table with 8991478 rows (all of Slashdot's comments):
+ 1922964506 comment_archive.ARZ
+ 2944970297 comment_text.MYD
+
+
+ TODO:
+ Add bzip optional support.
+ Allow users to set compression level.
+ Add truncate table command.
+ Implement versioning, should be easy.
+ Implement optimize so we can fix broken tables.
+ Allow for errors, find a way to mark bad rows.
+ See if during an optimize you can make the table smaller.
+ Talk to the gzip guys, come up with a writable format so that updates are doable
+ without switching to a block method.
+ Add optional feature so that rows can be flushed at interval (which will cause less
+ compression but may speed up ordered searches).
+
+ -Brian
+*/
+
+/* Variables for archive share methods */
+pthread_mutex_t archive_mutex;
+static HASH archive_open_tables;
+static int archive_init= 0;
+
+/* The file extension */
+#define ARZ ".ARZ"
+
+/*
+ Used for hash table that tracks open tables.
+*/
+static byte* archive_get_key(ARCHIVE_SHARE *share,uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length=share->table_name_length;
+ return (byte*) share->table_name;
+}
+
+
+/*
+ Example of simple lock controls.
+ See ha_example.cc for a description.
+*/
+static ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table)
+{
+ ARCHIVE_SHARE *share;
+ uint length;
+ char *tmp_name;
+
+ if (!archive_init)
+ {
+ /* Hijack a mutex for init'ing the storage engine */
+ pthread_mutex_lock(&LOCK_mysql_create_db);
+ if (!archive_init)
+ {
+ archive_init++;
+ VOID(pthread_mutex_init(&archive_mutex,MY_MUTEX_INIT_FAST));
+ (void) hash_init(&archive_open_tables,system_charset_info,32,0,0,
+ (hash_get_key) archive_get_key,0,0);
+ }
+ pthread_mutex_unlock(&LOCK_mysql_create_db);
+ }
+ pthread_mutex_lock(&archive_mutex);
+ length=(uint) strlen(table_name);
+
+ if (!(share=(ARCHIVE_SHARE*) hash_search(&archive_open_tables,
+ (byte*) table_name,
+ length)))
+ {
+ if (!(share=(ARCHIVE_SHARE *)
+ my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
+ &share, sizeof(*share),
+ &tmp_name, length+1,
+ NullS)))
+ {
+ pthread_mutex_unlock(&archive_mutex);
+ return NULL;
+ }
+
+ share->use_count=0;
+ share->table_name_length=length;
+ share->table_name=tmp_name;
+ fn_format(share->data_file_name,table_name,"",ARZ,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
+ strmov(share->table_name,table_name);
+ /*
+ It is expensive to open and close the data files and since you can't have
+ a gzip file that can be both read and written we keep a writer open
+ that is shared amoung all open tables.
+ */
+ if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
+ goto error;
+ if (my_hash_insert(&archive_open_tables, (byte*) share))
+ goto error;
+ thr_lock_init(&share->lock);
+ if (pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST))
+ goto error2;
+ }
+ share->use_count++;
+ pthread_mutex_unlock(&archive_mutex);
+
+ return share;
+
+error2:
+ thr_lock_delete(&share->lock);
+ /* We close, but ignore errors since we already have errors */
+ (void)gzclose(share->archive_write);
+error:
+ pthread_mutex_unlock(&archive_mutex);
+ my_free((gptr) share, MYF(0));
+
+ return NULL;
+}
+
+
+/*
+ Free lock controls.
+ See ha_example.cc for a description.
+*/
+static int free_share(ARCHIVE_SHARE *share)
+{
+ int rc= 0;
+ pthread_mutex_lock(&archive_mutex);
+ if (!--share->use_count)
+ {
+ hash_delete(&archive_open_tables, (byte*) share);
+ thr_lock_delete(&share->lock);
+ pthread_mutex_destroy(&share->mutex);
+ my_free((gptr) share, MYF(0));
+ if (gzclose(share->archive_write) == Z_ERRNO)
+ rc= -1;
+ }
+ pthread_mutex_unlock(&archive_mutex);
+
+ return rc;
+}
+
+
+/*
+ We just implement one additional file extension.
+*/
+const char **ha_archive::bas_ext() const
+{ static const char *ext[]= { ARZ, NullS }; return ext; }
+
+
+/*
+ When opening a file we:
+ Create/get our shared structure.
+ Init out lock.
+ We open the file we will read from.
+ Set the size of ref_length.
+*/
+int ha_archive::open(const char *name, int mode, uint test_if_locked)
+{
+ DBUG_ENTER("ha_archive::open");
+
+ if (!(share= get_share(name, table)))
+ DBUG_RETURN(1);
+ thr_lock_data_init(&share->lock,&lock,NULL);
+
+ if ((archive= gzopen(share->data_file_name, "rb")) == NULL)
+ {
+ (void)free_share(share); //We void since we already have an error
+ DBUG_RETURN(-1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Closes the file. We first close this storage engines file handle to the
+ archive and then remove our reference count to the table (and possibly
+ free it as well).
+ */
+int ha_archive::close(void)
+{
+ DBUG_ENTER("ha_archive::close");
+ int rc= 0;
+ if (gzclose(archive) == Z_ERRNO)
+ rc =-1;
+ rc |= free_share(share);
+ DBUG_RETURN(rc);
+}
+
+
+/*
+ We create our data file here. The format is pretty simple. The first bytes in
+ any file are the version number. Currently we do nothing with this, but in
+ the future this gives us the ability to figure out version if we change the
+ format at all. After the version we starting writing our rows. Unlike other
+ storage engines we do not "pack" our data. Since we are about to do a general
+ compression, packing would just be a waste of CPU time. If the table has blobs
+ they are written after the row in the order of creation.
+ So to read a row we:
+ Read the version
+ Read the record and copy it into buf
+ Loop through any blobs and read them
+ */
+int ha_archive::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info)
+{
+ File create_file;
+ char name_buff[FN_REFLEN];
+ size_t written;
+ DBUG_ENTER("ha_archive::create");
+
+ if ((create_file= my_create(fn_format(name_buff,name,"",ARZ,MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
+ O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+ DBUG_RETURN(-1);
+ if ((archive= gzdopen(create_file, "ab")) == NULL)
+ {
+ delete_table(name);
+ DBUG_RETURN(-1);
+ }
+ version= ARCHIVE_VERSION;
+ written= gzwrite(archive, &version, sizeof(version));
+ if (written == 0 || written != sizeof(version))
+ {
+ delete_table(name);
+ DBUG_RETURN(-1);
+ }
+ if (gzclose(archive))
+ {
+ delete_table(name);
+ DBUG_RETURN(-1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+/*
+ Look at ha_archive::open() for an explanation of the row format.
+ Here we just write out the row.
+*/
+int ha_archive::write_row(byte * buf)
+{
+ char *pos;
+ z_off_t written;
+ DBUG_ENTER("ha_archive::write_row");
+
+ statistic_increment(ha_write_count,&LOCK_status);
+ if (table->timestamp_default_now)
+ update_timestamp(buf+table->timestamp_default_now-1);
+ written= gzwrite(share->archive_write, buf, table->reclength);
+ share->dirty= true;
+ if (written == 0 || written != table->reclength)
+ DBUG_RETURN(-1);
+
+ for (Field_blob **field=table->blob_field ; *field ; field++)
+ {
+ char *ptr;
+ uint32 size= (*field)->get_length();
+
+ (*field)->get_ptr(&ptr);
+ written= gzwrite(share->archive_write, ptr, (unsigned)size);
+ if (written == 0 || written != size)
+ DBUG_RETURN(-1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ All calls that need to scan the table start with this method. If we are told
+ that it is a table scan we rewind the file to the beginning, otherwise
+ we assume the position will be set.
+*/
+int ha_archive::rnd_init(bool scan)
+{
+ DBUG_ENTER("ha_archive::rnd_init");
+ int read; // gzread() returns int, and we use this to check the header
+
+ /* We rewind the file so that we can read from the beginning if scan */
+ if(scan)
+ {
+ records= 0;
+ if (gzrewind(archive))
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ }
+
+ /*
+ If dirty, we lock, and then reset/flush the data.
+ I found that just calling gzflush() doesn't always work.
+ */
+ if (share->dirty == true)
+ {
+ pthread_mutex_lock(&share->mutex);
+ if (share->dirty == true)
+ {
+/* I was having problems with OSX, but it worked for 10.3 so I am wrapping this with and ifdef */
+#ifdef BROKEN_GZFLUSH
+ gzclose(share->archive_write);
+ if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
+ {
+ pthread_mutex_unlock(&share->mutex);
+ DBUG_RETURN(-1);
+ }
+#else
+ gzflush(share->archive_write, Z_SYNC_FLUSH);
+#endif
+ share->dirty= false;
+ }
+ pthread_mutex_unlock(&share->mutex);
+ }
+
+ /*
+ At the moment we just check the size of version to make sure the header is
+ intact.
+ */
+ if (scan)
+ {
+ read= gzread(archive, &version, sizeof(version));
+ if (read == 0 || read != sizeof(version))
+ DBUG_RETURN(-1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ This is the method that is used to read a row. It assumes that the row is
+ positioned where you want it.
+*/
+int ha_archive::get_row(byte *buf)
+{
+ int read; // Bytes read, gzread() returns int
+ char *last;
+ size_t total_blob_length= 0;
+ DBUG_ENTER("ha_archive::get_row");
+
+ read= gzread(archive, buf, table->reclength);
+
+ /* If we read nothing we are at the end of the file */
+ if (read == 0)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ /* If the record is the wrong size, the file is probably damaged */
+ if (read != table->reclength)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
+ /* Calculate blob length, we use this for our buffer */
+ for (Field_blob **field=table->blob_field; *field ; field++)
+ total_blob_length += (*field)->get_length();
+
+ /* Adjust our row buffer if we need be */
+ buffer.alloc(total_blob_length);
+ last= (char *)buffer.ptr();
+
+ /* Loop through our blobs and read them */
+ for (Field_blob **field=table->blob_field; *field ; field++)
+ {
+ size_t size= (*field)->get_length();
+ read= gzread(archive, last, size);
+ if (read == 0 || read != size)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ (*field)->set_ptr(size, last);
+ last += size;
+ }
+ DBUG_RETURN(0);
+}
+
+/*
+ Called during ORDER BY. Its position is either from being called sequentially
+ or by having had ha_archive::rnd_pos() called before it is called.
+*/
+int ha_archive::rnd_next(byte *buf)
+{
+ DBUG_ENTER("ha_archive::rnd_next");
+ int rc;
+
+ statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ current_position= gztell(archive);
+ rc= get_row(buf);
+ if (!(HA_ERR_END_OF_FILE == rc))
+ records++;
+
+ DBUG_RETURN(rc);
+}
+
+
+/*
+ Thanks to the table flag HA_REC_NOT_IN_SEQ this will be called after
+ each call to ha_archive::rnd_next() if an ordering of the rows is
+ needed.
+*/
+void ha_archive::position(const byte *record)
+{
+ DBUG_ENTER("ha_archive::position");
+ ha_store_ptr(ref, ref_length, current_position);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ This is called after a table scan for each row if the results of the scan need
+ to be ordered. It will take *pos and use it to move the cursor in the file so
+ that the next row that is called is the correctly ordered row.
+*/
+int ha_archive::rnd_pos(byte * buf, byte *pos)
+{
+ DBUG_ENTER("ha_archive::rnd_pos");
+ statistic_increment(ha_read_rnd_count,&LOCK_status);
+ current_position= ha_get_ptr(pos, ref_length);
+ z_off_t seek= gzseek(archive, current_position, SEEK_SET);
+
+ DBUG_RETURN(get_row(buf));
+}
+
+/******************************************************************************
+
+ Everything below here is default, please look at ha_example.cc for
+ descriptions.
+
+ ******************************************************************************/
+
+int ha_archive::update_row(const byte * old_data, byte * new_data)
+{
+
+ DBUG_ENTER("ha_archive::update_row");
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+}
+
+int ha_archive::delete_row(const byte * buf)
+{
+ DBUG_ENTER("ha_archive::delete_row");
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+}
+
+int ha_archive::index_read(byte * buf, const byte * key,
+ uint key_len __attribute__((unused)),
+ enum ha_rkey_function find_flag
+ __attribute__((unused)))
+{
+ DBUG_ENTER("ha_archive::index_read");
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+}
+
+int ha_archive::index_read_idx(byte * buf, uint index, const byte * key,
+ uint key_len __attribute__((unused)),
+ enum ha_rkey_function find_flag
+ __attribute__((unused)))
+{
+ DBUG_ENTER("ha_archive::index_read_idx");
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+}
+
+
+int ha_archive::index_next(byte * buf)
+{
+ DBUG_ENTER("ha_archive::index_next");
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+}
+
+int ha_archive::index_prev(byte * buf)
+{
+ DBUG_ENTER("ha_archive::index_prev");
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+}
+
+int ha_archive::index_first(byte * buf)
+{
+ DBUG_ENTER("ha_archive::index_first");
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+}
+
+int ha_archive::index_last(byte * buf)
+{
+ DBUG_ENTER("ha_archive::index_last");
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+}
+
+
+void ha_archive::info(uint flag)
+{
+ DBUG_ENTER("ha_archive::info");
+
+ /* This is a lie, but you don't want the optimizer to see zero or 1 */
+ if (records < 2)
+ records= 2;
+
+ DBUG_VOID_RETURN;
+}
+
+int ha_archive::extra(enum ha_extra_function operation)
+{
+ DBUG_ENTER("ha_archive::extra");
+ DBUG_RETURN(0);
+}
+
+int ha_archive::reset(void)
+{
+ DBUG_ENTER("ha_archive::reset");
+ DBUG_RETURN(0);
+}
+
+
+int ha_archive::external_lock(THD *thd, int lock_type)
+{
+ DBUG_ENTER("ha_archive::external_lock");
+ DBUG_RETURN(0);
+}
+
+THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
+ THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type)
+{
+ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
+ lock.type=lock_type;
+ *to++= &lock;
+ return to;
+}
+
+ha_rows ha_archive::records_in_range(int inx,
+ const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag)
+{
+ DBUG_ENTER("ha_archive::records_in_range ");
+ DBUG_RETURN(records); // HA_ERR_WRONG_COMMAND
+}
+#endif /* HAVE_ARCHIVE_DB */
diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h
new file mode 100644
index 00000000000..03e296d0eae
--- /dev/null
+++ b/sql/examples/ha_archive.h
@@ -0,0 +1,120 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef __GNUC__
+#pragma interface /* gcc class implementation */
+#endif
+
+#include <zlib.h>
+
+/*
+ Please read ha_archive.cc first. If you are looking for more general
+ answers on how storage engines work, look at ha_example.cc and
+ ha_example.h.
+*/
+
+typedef struct st_archive_share {
+ char *table_name;
+ char data_file_name[FN_REFLEN];
+ uint table_name_length,use_count;
+ pthread_mutex_t mutex;
+ THR_LOCK lock;
+ gzFile archive_write; /* Archive file we are working with */
+ bool dirty; /* Flag for if a flush should occur */
+} ARCHIVE_SHARE;
+
+/*
+ Version for file format.
+ 1 - Initial Version
+*/
+#define ARCHIVE_VERSION 1
+
+class ha_archive: public handler
+{
+ THR_LOCK_DATA lock; /* MySQL lock */
+ ARCHIVE_SHARE *share; /* Shared lock info */
+ gzFile archive; /* Archive file we are working with */
+ z_off_t current_position; /* The position of the row we just read */
+ byte byte_buffer[IO_SIZE]; /* Initial buffer for our string */
+ String buffer; /* Buffer used for blob storage */
+ unsigned int version; /* Used for recording version */
+
+public:
+ ha_archive(TABLE *table): handler(table)
+ {
+ /* Set our original buffer from pre-allocated memory */
+ buffer.set(byte_buffer, IO_SIZE, system_charset_info);
+
+ /* The size of the offset value we will use for position() */
+ ref_length = sizeof(z_off_t);
+ }
+ ~ha_archive()
+ {
+ }
+ const char *table_type() const { return "ARCHIVE"; }
+ const char *index_type(uint inx) { return "NONE"; }
+ const char **bas_ext() const;
+ ulong table_flags() const
+ {
+ return (HA_REC_NOT_IN_SEQ | HA_NOT_EXACT_COUNT | HA_NO_AUTO_INCREMENT |
+ HA_FILE_BASED);
+ }
+ ulong index_flags(uint idx, uint part) const
+ {
+ return 0;
+ }
+ /*
+ Have to put something here, there is no real limit as far as
+ archive is concerned.
+ */
+ uint max_supported_record_length() const { return UINT_MAX; }
+ /*
+ Called in test_quick_select to determine if indexes should be used.
+ */
+ virtual double scan_time() { return (double) (records) / 20.0+10; }
+ /* The next method will never be called */
+ virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; }
+ int open(const char *name, int mode, uint test_if_locked);
+ int close(void);
+ int write_row(byte * buf);
+ int update_row(const byte * old_data, byte * new_data);
+ int delete_row(const byte * buf);
+ int index_read(byte * buf, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_read_idx(byte * buf, uint idx, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_next(byte * buf);
+ int index_prev(byte * buf);
+ int index_first(byte * buf);
+ int index_last(byte * buf);
+ int rnd_init(bool scan=1);
+ int rnd_next(byte *buf);
+ int rnd_pos(byte * buf, byte *pos);
+ int get_row(byte *buf);
+ void position(const byte *record);
+ void info(uint);
+ int extra(enum ha_extra_function operation);
+ int reset(void);
+ int external_lock(THD *thd, int lock_type);
+ ha_rows records_in_range(int inx, const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag);
+ int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
+
+ THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type);
+};
diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc
index 2d17caf1a83..097abd48e05 100644
--- a/sql/examples/ha_example.cc
+++ b/sql/examples/ha_example.cc
@@ -14,24 +14,24 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*
- ha_example is a stubbed storage engine. It does nothing at this point. It
- will let you create/open/delete tables but that is all. You can enable it
+/*
+ ha_example is a stubbed storage engine. It does nothing at this point. It
+ will let you create/open/delete tables but that is all. You can enable it
in your buld by doing the following during your build process:
./configure --with-example-storage-engine
-
+
Once this is done mysql will let you create tables with:
CREATE TABLE A (...) ENGINE=EXAMPLE;
The example is setup to use table locks. It implements an example "SHARE"
- that is inserted into a hash by table name. You can use this to store
+ that is inserted into a hash by table name. You can use this to store
information of state that any example handler object will be able to see
if it is using the same table.
- Please read the object definition in ha_example.h before reading the rest
+ Please read the object definition in ha_example.h before reading the rest
if this file.
- To get an idea of what occurs here is an example select that would do a
+ To get an idea of what occurs here is an example select that would do a
scan of an entire table:
ha_example::store_lock
ha_example::external_lock
@@ -50,13 +50,13 @@
ha_example::rnd_next
ha_example::extra
ENUM HA_EXTRA_NO_CACHE End cacheing of records (def)
- ha_example::external_lock
+ ha_example::external_lock
ha_example::extra
ENUM HA_EXTRA_RESET Reset database to after open
- In the above example has 9 row called before rnd_next signalled that it was
- at the end of its data. In the above example the table was already opened
- (or you would have seen a call to ha_example::open(). Calls to
+ In the above example has 9 row called before rnd_next signalled that it was
+ at the end of its data. In the above example the table was already opened
+ (or you would have seen a call to ha_example::open(). Calls to
ha_example::extra() are hints as to what will be occuring to the request.
Happy coding!
@@ -92,7 +92,7 @@ static byte* example_get_key(EXAMPLE_SHARE *share,uint *length,
/*
Example of simple lock controls. The "share" it creates is structure we will
pass to each example handler. Do you have to have one of these? Well, you have
- pieces that are used for locking, and they are needed to function.
+ pieces that are used for locking, and they are needed to function.
*/
static EXAMPLE_SHARE *get_share(const char *table_name, TABLE *table)
{
@@ -130,7 +130,7 @@ static EXAMPLE_SHARE *get_share(const char *table_name, TABLE *table)
my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
&share, sizeof(*share),
&tmp_name, length+1,
- NullS)))
+ NullS)))
{
pthread_mutex_unlock(&example_mutex);
return NULL;
@@ -161,7 +161,7 @@ error:
}
-/*
+/*
Free lock controls. We call this whenever we close a table. If the table had
the last reference to the share then we free memory associated with it.
*/
@@ -182,7 +182,7 @@ static int free_share(EXAMPLE_SHARE *share)
/*
- If frm_error() is called then we will use this to to find out what file extentions
+ If frm_error() is called then we will use this to to find out what file extentions
exist for the storage engine. This is also used by the default rename_table and
delete_table method in handler.cc.
*/
@@ -190,10 +190,10 @@ const char **ha_example::bas_ext() const
{ static const char *ext[]= { NullS }; return ext; }
-/*
+/*
Used for opening tables. The name will be the name of the file.
A table is opened when it needs to be opened. For instance
- when a request comes in for a select on the table (tables are not
+ when a request comes in for a select on the table (tables are not
open and closed for each request, they are cached).
Called from handler.cc by handler::ha_open(). The server opens all tables by
@@ -212,12 +212,12 @@ int ha_example::open(const char *name, int mode, uint test_if_locked)
/*
- Closes a table. We call the free_share() function to free any resources
+ Closes a table. We call the free_share() function to free any resources
that we have allocated in the "shared" structure.
Called from sql_base.cc, sql_select.cc, and table.cc.
In sql_select.cc it is only used to close up temporary tables or during
- the process where a temporary table is converted over to being a
+ the process where a temporary table is converted over to being a
myisam table.
For sql_base.cc look at close_data_tables().
*/
@@ -230,7 +230,7 @@ int ha_example::close(void)
/*
write_row() inserts a row. No extra() hint is given currently if a bulk load
- is happeneding. buf() is a byte array of data. You can use the field
+ is happeneding. buf() is a byte array of data. You can use the field
information to extract the data from the native byte array type.
Example of this would be:
for (Field **field=table->field ; *field ; field++)
@@ -238,20 +238,20 @@ int ha_example::close(void)
...
}
- See ha_tina.cc for an example of extracting all of the data as strings.
+ See ha_tina.cc for an example of extracting all of the data as strings.
ha_berekly.cc has an example of how to store it intact by "packing" it
for ha_berkeley's own native storage type.
See the note for update_row() on auto_increments and timestamps. This
case also applied to write_row().
- Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
+ Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
*/
int ha_example::write_row(byte * buf)
{
DBUG_ENTER("ha_example::write_row");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -274,7 +274,7 @@ int ha_example::update_row(const byte * old_data, byte * new_data)
{
DBUG_ENTER("ha_example::update_row");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -282,8 +282,8 @@ int ha_example::update_row(const byte * old_data, byte * new_data)
This will delete a row. buf will contain a copy of the row to be deleted.
The server will call this right after the current row has been called (from
either a previous rnd_nexT() or index call).
- If you keep a pointer to the last row or can access a primary key it will
- make doing the deletion quite a bit easier.
+ If you keep a pointer to the last row or can access a primary key it will
+ make doing the deletion quite a bit easier.
Keep in mind that the server does no guarentee consecutive deletions. ORDER BY
clauses can be used.
@@ -294,7 +294,7 @@ int ha_example::update_row(const byte * old_data, byte * new_data)
int ha_example::delete_row(const byte * buf)
{
DBUG_ENTER("ha_example::delete_row");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -309,7 +309,7 @@ int ha_example::index_read(byte * buf, const byte * key,
__attribute__((unused)))
{
DBUG_ENTER("ha_example::index_read");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -323,7 +323,7 @@ int ha_example::index_read_idx(byte * buf, uint index, const byte * key,
__attribute__((unused)))
{
DBUG_ENTER("ha_example::index_read_idx");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -333,7 +333,7 @@ int ha_example::index_read_idx(byte * buf, uint index, const byte * key,
int ha_example::index_next(byte * buf)
{
DBUG_ENTER("ha_example::index_next");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -343,40 +343,40 @@ int ha_example::index_next(byte * buf)
int ha_example::index_prev(byte * buf)
{
DBUG_ENTER("ha_example::index_prev");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
/*
index_first() asks for the first key in the index.
- Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
+ Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
and sql_select.cc.
*/
int ha_example::index_first(byte * buf)
{
DBUG_ENTER("ha_example::index_first");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
/*
index_last() asks for the last key in the index.
- Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
+ Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
and sql_select.cc.
*/
int ha_example::index_last(byte * buf)
{
DBUG_ENTER("ha_example::index_last");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
-/*
+/*
rnd_init() is called when the system wants the storage engine to do a table
- scan.
- See the example in the introduction at the top of this file to see when
+ scan.
+ See the example in the introduction at the top of this file to see when
rnd_init() is called.
Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc,
@@ -385,11 +385,16 @@ int ha_example::index_last(byte * buf)
int ha_example::rnd_init(bool scan)
{
DBUG_ENTER("ha_example::rnd_init");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
+int ha_example::rnd_end()
+{
+ DBUG_ENTER("ha_example::rnd_end");
+ DBUG_RETURN(0);
+}
-/*
+/*
This is called for each row of the table scan. When you run out of records
you should return HA_ERR_END_OF_FILE. Fill buff up with the row information.
The Field structure for the table is the key to getting data into buf
@@ -415,8 +420,8 @@ int ha_example::rnd_next(byte *buf)
the size needed to store current_position. ref is just a byte array
that the server will maintain. If you are using offsets to mark rows, then
current_position should be the offset. If it is a primary key like in
- BDB, then it needs to be a primary key.
-
+ BDB, then it needs to be a primary key.
+
Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc.
*/
void ha_example::position(const byte *record)
@@ -436,7 +441,7 @@ void ha_example::position(const byte *record)
int ha_example::rnd_pos(byte * buf, byte *pos)
{
DBUG_ENTER("ha_example::rnd_pos");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -449,9 +454,9 @@ int ha_example::rnd_pos(byte * buf, byte *pos)
if (records < 2)
records = 2;
The reason is that the server will optimize for cases of only a single
- record. If in a table scan you don't know the number of records
+ record. If in a table scan you don't know the number of records
it will probably be better to set records to two so you can return
- as many records as you need.
+ as many records as you need.
Along with records a few more variables you may wish to set are:
records
deleted
@@ -518,9 +523,9 @@ int ha_example::reset(void)
/*
Used to delete all rows in a table. Both for cases of truncate and
for cases where the optimizer realizes that all rows will be
- removed as a result of a SQL statement.
+ removed as a result of a SQL statement.
- Called from item_sum.cc by Item_func_group_concat::clear(),
+ Called from item_sum.cc by Item_func_group_concat::clear(),
Item_sum_count_distinct::clear(), and Item_func_group_concat::clear().
Called from sql_delete.cc by mysql_delete().
Called from sql_select.cc by JOIN::reinit().
@@ -529,12 +534,12 @@ int ha_example::reset(void)
int ha_example::delete_all_rows()
{
DBUG_ENTER("ha_example::delete_all_rows");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
-/*
- First you should go read the section "locking functions for mysql" in
+/*
+ First you should go read the section "locking functions for mysql" in
lock.cc to understand this.
This create a lock on the table. If you are implementing a storage engine
that can handle transacations look at ha_berkely.cc to see how you will
@@ -564,7 +569,7 @@ int ha_example::external_lock(THD *thd, int lock_type)
lock (if we don't want to use MySQL table locks at all) or add locks
for many tables (like we do when we are using a MERGE handler).
- Berkeley DB for example changes all WRITE locks to TL_WRITE_ALLOW_WRITE
+ Berkeley DB for example changes all WRITE locks to TL_WRITE_ALLOW_WRITE
(which signals that we are doing WRITES, but we are still allowing other
reader's and writer's.
@@ -591,11 +596,15 @@ THR_LOCK_DATA **ha_example::store_lock(THD *thd,
}
/*
- Used to delete a table. By the time delete_table() has been called all
+ Used to delete a table. By the time delete_table() has been called all
opened references to this table will have been closed (and your globally
- shared references released. The variable name will just be the name of
+ shared references released. The variable name will just be the name of
the table. You will need to remove any files you have created at this point.
+ If you do not implement this, the default delete_table() is called from
+ handler.cc and it will delete all files with the file extentions returned
+ by bas_ext().
+
Called from handler.cc by delete_table and ha_create_table(). Only used
during create if the table_flag HA_DROP_BEFORE_CREATE was specified for
the storage engine.
@@ -610,15 +619,19 @@ int ha_example::delete_table(const char *name)
/*
Renames a table from one name to another from alter table call.
+ If you do not implement this, the default rename_table() is called from
+ handler.cc and it will delete all files with the file extentions returned
+ by bas_ext().
+
Called from sql_table.cc by mysql_rename_table().
*/
int ha_example::rename_table(const char * from, const char * to)
{
DBUG_ENTER("ha_example::rename_table ");
- DBUG_RETURN(HA_ERR_NOT_IMPLEMENTED);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
-/*
+/*
Given a starting key, and an ending key estimate the number of rows that
will exist between the two. end_key may be empty which in case determine
if start_key matches any rows.
@@ -636,14 +649,14 @@ ha_rows ha_example::records_in_range(uint inx, key_range *min_key,
/*
create() is called to create a database. The variable name will have the name
of the table. When create() is called you do not need to worry about opening
- the table. Also, the FRM file will have already been created so adjusting
+ the table. Also, the FRM file will have already been created so adjusting
create_info will not do you any good. You can overwrite the frm file at this
- point if you wish to change the table definition, but there are no methods
+ point if you wish to change the table definition, but there are no methods
currently provided for doing that.
Called from handle.cc by ha_create_table().
*/
-int ha_example::create(const char *name, TABLE *table_arg,
+int ha_example::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
DBUG_ENTER("ha_example::create");
diff --git a/sql/examples/ha_example.h b/sql/examples/ha_example.h
index 2228f04284a..dc8f265c16e 100644
--- a/sql/examples/ha_example.h
+++ b/sql/examples/ha_example.h
@@ -14,13 +14,17 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*
+/*
Please read ha_exmple.cc before reading this file.
Please keep in mind that the example storage engine implements all methods
that are required to be implemented. handler.h has a full list of methods
that you can implement.
*/
+#ifdef __GNUC__
+#pragma interface /* gcc class implementation */
+#endif
+
/*
EXAMPLE_SHARE is a structure that will be shared amoung all open handlers
The example implements the minimum of what you will probably need.
@@ -44,56 +48,68 @@ public:
ha_example(TABLE *table): handler(table)
{
}
- ~ha_example()
+ ~ha_example()
{
}
/* The name that will be used for display purposes */
- const char *table_type() const { return "EXAMPLE"; }
- /* The name of the index type that will be used for display */
- const char *index_type(uint inx) { return "NONE"; }
+ const char *table_type() const { return "EXAMPLE"; }
+ /*
+ The name of the index type that will be used for display
+ don't implement this method unless you really have indexes
+ */
+ const char *index_type(uint inx) { return "HASH"; }
const char **bas_ext() const;
- /*
- This is a list of flags that says what the storage engine
+ /*
+ This is a list of flags that says what the storage engine
implements. The current table flags are documented in
- table_flags.
+ handler.h
*/
ulong table_flags() const
{
return 0;
}
- /*
- This is a list of flags that says how the storage engine
+ /*
+ This is a list of flags that says how the storage engine
implements indexes. The current index flags are documented in
- handler.h. If you do not implement indexes, just return zero
+ handler.h. If you do not implement indexes, just return zero
here.
*/
- ulong index_flags(uint inx) const
+ ulong index_flags(uint inx, uint part) const
{
return 0;
}
- /*
+ /*
unireg.cc will call the following to make sure that the storage engine can
handle the data it is about to send.
+
+ Return *real* limits of your storage engine here. MySQL will do
+ min(your_limits, MySQL_limits) automatically
+
+ There is no need to implement ..._key_... methods if you don't suport
+ indexes.
*/
- uint max_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_keys() const { return 0; }
- uint max_key_parts() const { return 0; }
- uint max_key_length() const { return 0; }
+ uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
+ uint max_supported_keys() const { return 0; }
+ uint max_supported_key_parts() const { return 0; }
+ uint max_supported_key_length() const { return 0; }
/*
Called in test_quick_select to determine if indexes should be used.
*/
virtual double scan_time() { return (double) (records+deleted) / 20.0+10; }
- /*
+ /*
The next method will never be called if you do not implement indexes.
*/
virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; }
- virtual bool fast_key_read() { return 1;}
- /*
+ /*
Everything below are methods that we implment in ha_example.cc.
+
+ Most of these methods are not obligatory, skip them and
+ MySQL will treat them as not implemented
*/
- int open(const char *name, int mode, uint test_if_locked);
- int close(void);
+ int open(const char *name, int mode, uint test_if_locked); // required
+ int close(void); // required
+
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
@@ -105,21 +121,32 @@ public:
int index_prev(byte * buf);
int index_first(byte * buf);
int index_last(byte * buf);
- int rnd_init(bool scan=1);
- int rnd_next(byte *buf);
- int rnd_pos(byte * buf, byte *pos);
- void position(const byte *record);
- void info(uint);
+ /*
+ unlike index_init(), rnd_init() can be called two times
+ without rnd_end() in between (it only makes sense if scan=1).
+ then the second call should prepare for the new table scan
+ (e.g if rnd_init allocates the cursor, second call should
+ position it to the start of the table, no need to deallocate
+ and allocate it again
+ */
+ int rnd_init(bool scan); //required
+ int rnd_end();
+ int rnd_next(byte *buf); //required
+ int rnd_pos(byte * buf, byte *pos); //required
+ void position(const byte *record); //required
+ void info(uint); //required
+
int extra(enum ha_extra_function operation);
int reset(void);
- int external_lock(THD *thd, int lock_type);
+ int external_lock(THD *thd, int lock_type); //required
int delete_all_rows(void);
ha_rows records_in_range(uint inx, key_range *min_key,
key_range *max_key);
int delete_table(const char *from);
int rename_table(const char * from, const char * to);
- int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
+ int create(const char *name, TABLE *form,
+ HA_CREATE_INFO *create_info); //required
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
- enum thr_lock_type lock_type);
+ enum thr_lock_type lock_type); //required
};
diff --git a/sql/field.cc b/sql/field.cc
index df9b4f84ae7..2d3729817b7 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -398,8 +398,8 @@ bool Field::get_date(TIME *ltime,uint fuzzydate)
char buff[40];
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
- str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) <=
- TIMESTAMP_DATETIME_ERROR)
+ str_to_datetime_with_warn(res->ptr(), res->length(),
+ ltime, fuzzydate) <= MYSQL_TIMESTAMP_ERROR)
return 1;
return 0;
}
@@ -409,7 +409,7 @@ bool Field::get_time(TIME *ltime)
char buff[40];
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
- str_to_time(res->ptr(),res->length(),ltime))
+ str_to_time_with_warn(res->ptr(), res->length(), ltime))
return 1;
return 0;
}
@@ -433,7 +433,7 @@ void Field::store_time(TIME *ltime,timestamp_type type)
bool Field::optimize_range(uint idx)
{
- return !test(table->file->index_flags(idx) & HA_WRONG_ASCII_ORDER);
+ return test(table->file->index_flags(idx) & HA_READ_RANGE);
}
/****************************************************************************
@@ -462,7 +462,7 @@ void Field_decimal::overflow(bool negative)
uint len=field_length;
char *to=ptr, filler= '9';
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
if (negative)
{
if (!unsigned_flag)
@@ -546,7 +546,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
char *left_wall,*right_wall;
char tmp_char;
/*
- To remember if current_thd->cuted_fields has already been incremented,
+ To remember if table->in_use->cuted_fields has already been incremented,
to do that only once
*/
bool is_cuted_fields_incr=0;
@@ -572,7 +572,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
from++;
if (from == end)
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
is_cuted_fields_incr=1;
}
else if (*from == '+' || *from == '-') // Found some sign ?
@@ -642,13 +642,13 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
it makes the code easer to read.
*/
- if (current_thd->count_cuted_fields)
+ if (table->in_use->count_cuted_fields)
{
// Skip end spaces
for (;from != end && my_isspace(&my_charset_bin, *from); from++) ;
if (from != end) // If still something left, warn
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
is_cuted_fields_incr=1;
}
}
@@ -794,7 +794,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
/*
Write digits of the frac_% parts ;
- Depending on current_thd->count_cutted_fields, we may also want
+ Depending on table->in_use->count_cutted_fields, we may also want
to know if some non-zero tail of these parts will
be truncated (for example, 0.002->0.00 will generate a warning,
while 0.000->0.00 will not)
@@ -812,7 +812,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
{
if (pos == right_wall)
{
- if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
+ if (table->in_use->count_cuted_fields && !is_cuted_fields_incr)
break; // Go on below to see if we lose non zero digits
return 0;
}
@@ -826,7 +826,8 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
if (tmp_char != '0') // Losing a non zero digit ?
{
if (!is_cuted_fields_incr)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_TRUNCATED, 1);
return 0;
}
continue;
@@ -843,7 +844,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
if (tmp_char != '0') // Losing a non zero digit ?
{
if (!is_cuted_fields_incr)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
return 0;
}
continue;
@@ -1061,18 +1062,18 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
if (tmp < 0)
{
tmp=0; /* purecov: inspected */
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (tmp > 255)
{
tmp= 255;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error= 1;
}
}
@@ -1081,18 +1082,18 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
if (tmp < -128)
{
tmp= -128;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (tmp >= 128)
{
tmp= 127;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error= 1;
}
}
@@ -1110,13 +1111,13 @@ int Field_tiny::store(double nr)
if (nr < 0.0)
{
*ptr=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > 255.0)
{
*ptr=(char) 255;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1127,13 +1128,13 @@ int Field_tiny::store(double nr)
if (nr < -128.0)
{
*ptr= (char) -128;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > 127.0)
{
*ptr=127;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1150,13 +1151,13 @@ int Field_tiny::store(longlong nr)
if (nr < 0L)
{
*ptr=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > 255L)
{
*ptr= (char) 255;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1167,13 +1168,13 @@ int Field_tiny::store(longlong nr)
if (nr < -128L)
{
*ptr= (char) -128;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > 127L)
{
*ptr=127;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1265,18 +1266,18 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
if (tmp < 0)
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (tmp > (uint16) ~0)
{
tmp=(uint16) ~0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error= 1;
}
}
@@ -1285,18 +1286,18 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
if (tmp < INT_MIN16)
{
tmp= INT_MIN16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (tmp > INT_MAX16)
{
tmp=INT_MAX16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error= 1;
}
}
@@ -1322,13 +1323,13 @@ int Field_short::store(double nr)
if (nr < 0)
{
res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (double) (uint16) ~0)
{
res=(int16) (uint16) ~0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1339,13 +1340,13 @@ int Field_short::store(double nr)
if (nr < (double) INT_MIN16)
{
res=INT_MIN16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (double) INT_MAX16)
{
res=INT_MAX16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1371,13 +1372,13 @@ int Field_short::store(longlong nr)
if (nr < 0L)
{
res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (longlong) (uint16) ~0)
{
res=(int16) (uint16) ~0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1388,13 +1389,13 @@ int Field_short::store(longlong nr)
if (nr < INT_MIN16)
{
res=INT_MIN16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > INT_MAX16)
{
res=INT_MAX16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1540,18 +1541,18 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
if (tmp < 0)
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (tmp >= (long) (1L << 24))
{
tmp=(long) (1L << 24)-1L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error= 1;
}
}
@@ -1560,18 +1561,18 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
if (tmp < INT_MIN24)
{
tmp= INT_MIN24;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (tmp > INT_MAX24)
{
tmp=INT_MAX24;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error= 1;
}
}
@@ -1590,14 +1591,14 @@ int Field_medium::store(double nr)
if (nr < 0)
{
int3store(ptr,0);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr >= (double) (long) (1L << 24))
{
uint32 tmp=(uint32) (1L << 24)-1L;
int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1609,14 +1610,14 @@ int Field_medium::store(double nr)
{
long tmp=(long) INT_MIN24;
int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (double) INT_MAX24)
{
long tmp=(long) INT_MAX24;
int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1633,14 +1634,14 @@ int Field_medium::store(longlong nr)
if (nr < 0L)
{
int3store(ptr,0);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr >= (longlong) (long) (1L << 24))
{
long tmp=(long) (1L << 24)-1L;;
int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1652,14 +1653,14 @@ int Field_medium::store(longlong nr)
{
long tmp=(long) INT_MIN24;
int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (longlong) INT_MAX24)
{
long tmp=(long) INT_MAX24;
int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1771,10 +1772,10 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
else
tmp=my_strntol(cs,from,len,10,&end,&error);
if (error ||
- (from+len != end && current_thd->count_cuted_fields &&
+ (from+len != end && table->in_use->count_cuted_fields &&
!test_if_int(from,len,end,cs)))
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error= 1;
}
#ifdef WORDS_BIGENDIAN
@@ -1799,13 +1800,13 @@ int Field_long::store(double nr)
if (nr < 0)
{
res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (double) (ulong) ~0L)
{
res=(int32) (uint32) ~0L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1816,13 +1817,13 @@ int Field_long::store(double nr)
if (nr < (double) INT_MIN32)
{
res=(int32) INT_MIN32;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (double) INT_MAX32)
{
res=(int32) INT_MAX32;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1844,18 +1845,26 @@ int Field_long::store(longlong nr)
{
int error= 0;
int32 res;
+
+ /*
+ This assert has nothing to do with this method per se, it was put here
+ only because it is one of the best places for catching places there its
+ condition is broken.
+ */
+ DBUG_ASSERT(table->in_use == current_thd);
+
if (unsigned_flag)
{
if (nr < 0)
{
res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr >= (LL(1) << 32))
{
res=(int32) (uint32) ~0L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1866,13 +1875,13 @@ int Field_long::store(longlong nr)
if (nr < (longlong) INT_MIN32)
{
res=(int32) INT_MIN32;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (longlong) INT_MAX32)
{
res=(int32) INT_MAX32;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1905,6 +1914,8 @@ double Field_long::val_real(void)
longlong Field_long::val_int(void)
{
int32 j;
+ /* See the comment in Field_long::store(long long) */
+ DBUG_ASSERT(table->in_use == current_thd);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
j=sint4korr(ptr);
@@ -2029,10 +2040,10 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
else
tmp=my_strntoll(cs,from,len,10,&end,&error);
if (error ||
- (from+len != end && current_thd->count_cuted_fields &&
+ (from+len != end && table->in_use->count_cuted_fields &&
!test_if_int(from,len,end,cs)))
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error= 1;
}
#ifdef WORDS_BIGENDIAN
@@ -2057,13 +2068,13 @@ int Field_longlong::store(double nr)
if (nr < 0)
{
res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr >= (double) ~ (ulonglong) 0)
{
res= ~(longlong) 0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -2074,13 +2085,13 @@ int Field_longlong::store(double nr)
if (nr <= (double) LONGLONG_MIN)
{
res=(longlong) LONGLONG_MIN;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr >= (double) LONGLONG_MAX)
{
res=(longlong) LONGLONG_MAX;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -2251,10 +2262,10 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
int error;
char *end;
double nr= my_strntod(cs,(char*) from,len,&end,&error);
- if (error || ((uint) (end-from) != len && current_thd->count_cuted_fields))
+ if (error || ((uint) (end-from) != len && table->in_use->count_cuted_fields))
{
error= 1;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
}
Field_float::store(nr);
return error;
@@ -2270,13 +2281,13 @@ int Field_float::store(double nr)
{
j= 0;
set_null();
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (unsigned_flag && nr < 0)
{
j= 0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -2300,13 +2311,13 @@ int Field_float::store(double nr)
if (nr < -max_value)
{
j= (float)-max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > max_value)
{
j= (float)max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -2331,7 +2342,7 @@ int Field_float::store(longlong nr)
float j= (float) nr;
if (unsigned_flag && j < 0)
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
j=0;
error= 1;
}
@@ -2553,10 +2564,10 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
int error;
char *end;
double nr= my_strntod(cs,(char*) from, len, &end, &error);
- if (error || ((uint) (end-from) != len && current_thd->count_cuted_fields))
+ if (error || ((uint) (end-from) != len && table->in_use->count_cuted_fields))
{
error= 1;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
}
Field_double::store(nr);
return error;
@@ -2571,13 +2582,13 @@ int Field_double::store(double nr)
{
nr= 0;
set_null();
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (unsigned_flag && nr < 0)
{
nr= 0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -2597,13 +2608,13 @@ int Field_double::store(double nr)
if (nr < -max_value)
{
nr= -max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > max_value)
{
nr= max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
}
@@ -2626,7 +2637,7 @@ int Field_double::store(longlong nr)
int error= 0;
if (unsigned_flag && j < 0)
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
j=0;
}
@@ -2900,7 +2911,39 @@ void Field_timestamp::set_timestamp_offsets()
int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
{
- long tmp=(long) str_to_timestamp(from,len);
+ TIME l_time;
+ my_time_t tmp= 0;
+ int error;
+ bool have_smth_to_conv;
+ bool in_dst_time_gap;
+ THD *thd= table->in_use;
+
+ have_smth_to_conv= (str_to_datetime(from, len, &l_time, 0, &error) >
+ MYSQL_TIMESTAMP_ERROR);
+
+ if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED,
+ from, len, MYSQL_TIMESTAMP_DATETIME, 1);
+
+ if (have_smth_to_conv)
+ {
+ if (!(tmp= TIME_to_timestamp(thd, &l_time, &in_dst_time_gap)))
+ {
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ from, len, MYSQL_TIMESTAMP_DATETIME, !error);
+
+ error= 1;
+ }
+ else if (in_dst_time_gap)
+ {
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_INVALID_TIMESTAMP,
+ from, len, MYSQL_TIMESTAMP_DATETIME, !error);
+ error= 1;
+ }
+ }
+
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -2909,7 +2952,7 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
else
#endif
longstore(ptr,tmp);
- return 0;
+ return error;
}
int Field_timestamp::store(double nr)
@@ -2917,8 +2960,10 @@ int Field_timestamp::store(double nr)
int error= 0;
if (nr < 0 || nr > 99991231235959.0)
{
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ nr, MYSQL_TIMESTAMP_DATETIME);
nr= 0; // Avoid overflow on buff
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
error= 1;
}
error|= Field_timestamp::store((longlong) rint(nr));
@@ -2926,96 +2971,37 @@ int Field_timestamp::store(double nr)
}
-/*
- Convert a datetime of formats YYMMDD, YYYYMMDD or YYMMDDHHMSS to
- YYYYMMDDHHMMSS. The high date '99991231235959' is checked before this
- function.
-*/
-
-static longlong fix_datetime(longlong nr, TIME *time_res,
- const char *field_name, bool *error)
-{
- long part1,part2;
-
- *error= 0;
- if (nr == LL(0) || nr >= LL(10000101000000))
- goto ok;
- if (nr < 101)
- goto err;
- if (nr <= (YY_PART_YEAR-1)*10000L+1231L)
- {
- nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069
- goto ok;
- }
- if (nr < (YY_PART_YEAR)*10000L+101L)
- goto err;
- if (nr <= 991231L)
- {
- nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999
- goto ok;
- }
- if (nr < 10000101L)
- goto err;
- if (nr <= 99991231L)
- {
- nr= nr*1000000L;
- goto ok;
- }
- if (nr < 101000000L)
- goto err;
- if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959))
- {
- nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069
- goto ok;
- }
- if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000))
- goto err;
- if (nr <= LL(991231235959))
- nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999
-
- ok:
- part1=(long) (nr/LL(1000000));
- part2=(long) (nr - (longlong) part1*LL(1000000));
- time_res->year= (int) (part1/10000L); part1%=10000L;
- time_res->month= (int) part1 / 100;
- time_res->day= (int) part1 % 100;
- time_res->hour= (int) (part2/10000L); part2%=10000L;
- time_res->minute=(int) part2 / 100;
- time_res->second=(int) part2 % 100;
-
- if (time_res->year <= 9999 && time_res->month <= 12 &&
- time_res->day <= 31 && time_res->hour <= 23 &&
- time_res->minute <= 59 && time_res->second <= 59)
- return nr;
-
- err:
- THD *thd= current_thd;
- if (thd->count_cuted_fields)
- {
- thd->cuted_fields++;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
- field_name, thd->row_count);
- }
- *error= 1;
- return LL(0);
-}
-
-
int Field_timestamp::store(longlong nr)
{
TIME l_time;
- time_t timestamp= 0;
- bool error;
+ my_time_t timestamp= 0;
+ int error;
+ bool in_dst_time_gap;
+ THD *thd= table->in_use;
- if ((nr= fix_datetime(nr, &l_time, field_name, &error)))
+ if (number_to_TIME(nr, &l_time, 0, &error))
{
- long not_used;
-
- if (!(timestamp= my_gmt_sec(&l_time, &not_used)))
- goto err;
- }
+ if (!(timestamp= TIME_to_timestamp(thd, &l_time, &in_dst_time_gap)))
+ {
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ nr, MYSQL_TIMESTAMP_DATETIME, 1);
+ error= 1;
+ }
+ if (in_dst_time_gap)
+ {
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_INVALID_TIMESTAMP,
+ nr, MYSQL_TIMESTAMP_DATETIME, !error);
+ error= 1;
+ }
+ }
+ else if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_TRUNCATED,
+ nr, MYSQL_TIMESTAMP_DATETIME, 1);
+
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -3024,12 +3010,8 @@ int Field_timestamp::store(longlong nr)
else
#endif
longstore(ptr,(uint32) timestamp);
+
return error;
-
-err:
- longstore(ptr,(uint32) 0);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
- return 1;
}
@@ -3040,12 +3022,9 @@ double Field_timestamp::val_real(void)
longlong Field_timestamp::val_int(void)
{
- int part_time;
uint32 temp;
- time_t time_arg;
- struct tm *l_time;
- longlong res;
- struct tm tm_tmp;
+ TIME time_tmp;
+ THD *thd= table->in_use;
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -3056,32 +3035,21 @@ longlong Field_timestamp::val_int(void)
if (temp == 0L) // No time
return(0); /* purecov: inspected */
- time_arg=(time_t) temp;
- localtime_r(&time_arg,&tm_tmp);
- l_time=&tm_tmp;
-
- part_time= l_time->tm_year % 100;
- res= ((longlong) (part_time+ ((part_time < YY_PART_YEAR) ? 2000 : 1900))*
- LL(10000000000));
- part_time= l_time->tm_mon+1;
- res+= (longlong) part_time * LL(100000000);
- part_time=l_time->tm_mday;
- res+= (longlong) ((long) part_time * 1000000L);
- part_time=l_time->tm_hour;
- res+= (longlong) (part_time * 10000L);
- part_time=l_time->tm_min;
- res+= (longlong) (part_time * 100);
- part_time=l_time->tm_sec;
- return res+part_time;
+
+ thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, (my_time_t)temp);
+ thd->time_zone_used= 1;
+
+ return time_tmp.year * LL(10000000000) + time_tmp.month * LL(100000000) +
+ time_tmp.day * 1000000L + time_tmp.hour * 10000L +
+ time_tmp.minute * 100 + time_tmp.second;
}
String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
{
uint32 temp, temp2;
- time_t time_arg;
- struct tm *l_time;
- struct tm tm_tmp;
+ TIME time_tmp;
+ THD *thd= table->in_use;
char *to;
val_buffer->alloc(field_length+1);
@@ -3101,11 +3069,11 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
return val_ptr;
}
val_buffer->set_charset(&my_charset_bin); // Safety
- time_arg=(time_t) temp;
- localtime_r(&time_arg,&tm_tmp);
- l_time=&tm_tmp;
+
+ thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,(my_time_t)temp);
+ thd->time_zone_used= 1;
- temp= l_time->tm_year % 100;
+ temp= time_tmp.year % 100;
if (temp < YY_PART_YEAR)
{
*to++= '2';
@@ -3120,27 +3088,27 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= '-';
- temp=l_time->tm_mon+1;
+ temp=time_tmp.month;
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= '-';
- temp=l_time->tm_mday;
+ temp=time_tmp.day;
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= ' ';
- temp=l_time->tm_hour;
+ temp=time_tmp.hour;
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= ':';
- temp=l_time->tm_min;
+ temp=time_tmp.minute;
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= ':';
- temp=l_time->tm_sec;
+ temp=time_tmp.second;
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
@@ -3152,6 +3120,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
bool Field_timestamp::get_date(TIME *ltime, uint fuzzydate)
{
long temp;
+ THD *thd= table->in_use;
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
temp=uint4korr(ptr);
@@ -3166,19 +3135,8 @@ bool Field_timestamp::get_date(TIME *ltime, uint fuzzydate)
}
else
{
- struct tm tm_tmp;
- time_t time_arg= (time_t) temp;
- localtime_r(&time_arg,&tm_tmp);
- struct tm *start= &tm_tmp;
- ltime->year= start->tm_year+1900;
- ltime->month= start->tm_mon+1;
- ltime->day= start->tm_mday;
- ltime->hour= start->tm_hour;
- ltime->minute= start->tm_min;
- ltime->second= start->tm_sec;
- ltime->second_part= 0;
- ltime->neg= 0;
- ltime->time_type=TIMESTAMP_DATETIME;
+ thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)temp);
+ thd->time_zone_used= 1;
}
return 0;
}
@@ -3245,7 +3203,7 @@ void Field_timestamp::sql_type(String &res) const
void Field_timestamp::set_time()
{
- long tmp= (long) current_thd->query_start();
+ long tmp= (long) table->in_use->query_start();
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -3267,25 +3225,35 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
{
TIME ltime;
long tmp;
- int error= 0;
- if (str_to_time(from,len,&ltime))
+ int error;
+
+ if (str_to_time(from, len, &ltime, &error))
{
tmp=0L;
error= 1;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED,
+ from, len, MYSQL_TIMESTAMP_TIME, 1);
}
else
{
+ if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_TRUNCATED,
+ from, len, MYSQL_TIMESTAMP_TIME, 1);
+
if (ltime.month)
ltime.day=0;
tmp=(ltime.day*24L+ltime.hour)*10000L+(ltime.minute*100+ltime.second);
if (tmp > 8385959)
{
tmp=8385959;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ from, len, MYSQL_TIMESTAMP_TIME, !error);
error= 1;
}
}
+
if (ltime.neg)
tmp= -tmp;
error |= Field_time::store((longlong) tmp);
@@ -3300,13 +3268,15 @@ int Field_time::store(double nr)
if (nr > 8385959.0)
{
tmp=8385959L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
error= 1;
}
else if (nr < -8385959.0)
{
tmp= -8385959L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
error= 1;
}
else
@@ -3317,7 +3287,9 @@ int Field_time::store(double nr)
if (tmp % 100 > 59 || tmp/100 % 100 > 59)
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE, nr,
+ MYSQL_TIMESTAMP_TIME);
error= 1;
}
}
@@ -3333,13 +3305,17 @@ int Field_time::store(longlong nr)
if (nr > (longlong) 8385959L)
{
tmp=8385959L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE, nr,
+ MYSQL_TIMESTAMP_TIME, 1);
error= 1;
}
else if (nr < (longlong) -8385959L)
{
tmp= -8385959L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE, nr,
+ MYSQL_TIMESTAMP_TIME, 1);
error= 1;
}
else
@@ -3348,7 +3324,9 @@ int Field_time::store(longlong nr)
if (tmp % 100 > 59 || tmp/100 % 100 > 59)
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE, nr,
+ MYSQL_TIMESTAMP_TIME, 1);
error= 1;
}
}
@@ -3395,6 +3373,39 @@ String *Field_time::val_str(String *val_buffer,
}
+/*
+ Normally we would not consider 'time' as a vaild date, but we allow
+ get_date() here to be able to do things like
+ DATE_FORMAT(time, "%l.%i %p")
+*/
+
+bool Field_time::get_date(TIME *ltime, uint fuzzydate)
+{
+ long tmp;
+ if (!fuzzydate)
+ {
+ push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ ER(ER_WARN_DATA_OUT_OF_RANGE), field_name,
+ table->in_use->row_count);
+ return 1;
+ }
+ tmp=(long) sint3korr(ptr);
+ ltime->neg=0;
+ if (tmp < 0)
+ {
+ ltime->neg= 1;
+ tmp=-tmp;
+ }
+ ltime->hour=tmp/10000;
+ tmp-=ltime->hour*10000;
+ ltime->minute= tmp/100;
+ ltime->second= tmp % 100;
+ ltime->year= ltime->month= ltime->day= ltime->second_part= 0;
+ return 0;
+}
+
+
bool Field_time::get_time(TIME *ltime)
{
long tmp=(long) sint3korr(ptr);
@@ -3410,7 +3421,7 @@ bool Field_time::get_time(TIME *ltime)
ltime->minute= (int) tmp/100;
ltime->second= (int) tmp % 100;
ltime->second_part=0;
- ltime->time_type= TIMESTAMP_TIME;
+ ltime->time_type= MYSQL_TIMESTAMP_TIME;
return 0;
}
@@ -3460,11 +3471,11 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155)
{
*ptr=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
- if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
if (nr != 0 || len != 4)
{
if (nr < YY_PART_YEAR)
@@ -3493,7 +3504,7 @@ int Field_year::store(longlong nr)
if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155)
{
*ptr=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
if (nr != 0 || field_length != 4) // 0000 -> 0; 00 -> 2000
@@ -3557,15 +3568,20 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
{
TIME l_time;
uint32 tmp;
- int error= 0;
- if (str_to_TIME(from,len,&l_time,1) <= TIMESTAMP_DATETIME_ERROR)
+ int error;
+
+ if (str_to_datetime(from, len, &l_time, 1, &error) <= MYSQL_TIMESTAMP_ERROR)
{
tmp=0;
error= 1;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
}
else
tmp=(uint32) l_time.year*10000L + (uint32) (l_time.month*100+l_time.day);
+
+ if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED,
+ from, len, MYSQL_TIMESTAMP_DATE, 1);
+
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -3587,7 +3603,9 @@ int Field_date::store(double nr)
if (nr < 0.0 || nr > 99991231.0)
{
tmp=0L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ nr, MYSQL_TIMESTAMP_DATE);
error= 1;
}
else
@@ -3613,7 +3631,9 @@ int Field_date::store(longlong nr)
if (nr < 0 || nr > LL(99991231))
{
tmp=0L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ nr, MYSQL_TIMESTAMP_DATE, 0);
error= 1;
}
else
@@ -3740,15 +3760,19 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
{
TIME l_time;
long tmp;
- int error= 0;
- if (str_to_TIME(from,len,&l_time,1) <= TIMESTAMP_DATETIME_ERROR)
+ int error;
+ if (str_to_datetime(from, len, &l_time, 1, &error) <= MYSQL_TIMESTAMP_ERROR)
{
tmp=0L;
error= 1;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
}
else
tmp= l_time.day + l_time.month*32 + l_time.year*16*32;
+
+ if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED,
+ from, len, MYSQL_TIMESTAMP_DATE, 1);
+
int3store(ptr,tmp);
return error;
}
@@ -3758,7 +3782,8 @@ int Field_newdate::store(double nr)
if (nr < 0.0 || nr > 99991231235959.0)
{
(void) Field_newdate::store((longlong) -1);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_TRUNCATED, nr, MYSQL_TIMESTAMP_DATE);
return 1;
}
else
@@ -3775,7 +3800,9 @@ int Field_newdate::store(longlong nr)
if (nr < 0L || nr > 99991231L)
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE, nr,
+ MYSQL_TIMESTAMP_DATE, 1);
error= 1;
}
else
@@ -3793,7 +3820,9 @@ int Field_newdate::store(longlong nr)
if (month > 12 || day > 31)
{
tmp=0L; // Don't allow date to change
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE, nr,
+ MYSQL_TIMESTAMP_DATE, 1);
error= 1;
}
else
@@ -3806,12 +3835,12 @@ int Field_newdate::store(longlong nr)
void Field_newdate::store_time(TIME *ltime,timestamp_type type)
{
long tmp;
- if (type == TIMESTAMP_DATE || type == TIMESTAMP_DATETIME)
+ if (type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME)
tmp=ltime->year*16*32+ltime->month*32+ltime->day;
else
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
}
int3store(ptr,tmp);
}
@@ -3870,7 +3899,7 @@ bool Field_newdate::get_date(TIME *ltime,uint fuzzydate)
ltime->day= tmp & 31;
ltime->month= (tmp >> 5) & 15;
ltime->year= (tmp >> 9);
- ltime->time_type=TIMESTAMP_DATE;
+ ltime->time_type= MYSQL_TIMESTAMP_DATE;
ltime->hour= ltime->minute= ltime->second= ltime->second_part= ltime->neg= 0;
return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0;
}
@@ -3910,12 +3939,18 @@ void Field_newdate::sql_type(String &res) const
int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
{
- longlong tmp=str_to_datetime(from,len,1);
- if (tmp < 0)
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
- tmp= 0;
- }
+ TIME time_tmp;
+ int error;
+ ulonglong tmp= 0;
+
+ if (str_to_datetime(from, len, &time_tmp, 1, &error) > MYSQL_TIMESTAMP_ERROR)
+ tmp= TIME_to_ulonglong_datetime(&time_tmp);
+
+ if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ from, len, MYSQL_TIMESTAMP_DATETIME, 1);
+
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -3924,7 +3959,7 @@ int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
else
#endif
longlongstore(ptr,tmp);
- return 0;
+ return error;
}
@@ -3933,8 +3968,10 @@ int Field_datetime::store(double nr)
int error= 0;
if (nr < 0.0 || nr > 99991231235959.0)
{
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ nr, MYSQL_TIMESTAMP_DATETIME);
nr=0.0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
error= 1;
}
error |= Field_datetime::store((longlong) rint(nr));
@@ -3945,9 +3982,16 @@ int Field_datetime::store(double nr)
int Field_datetime::store(longlong nr)
{
TIME not_used;
- bool error;
+ int error;
+ longlong initial_nr= nr;
- nr= fix_datetime(nr, &not_used, field_name, &error);
+ nr= number_to_TIME(nr, &not_used, 1, &error);
+
+ if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_TRUNCATED, initial_nr,
+ MYSQL_TIMESTAMP_DATETIME, 1);
+
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -3963,13 +4007,13 @@ int Field_datetime::store(longlong nr)
void Field_datetime::store_time(TIME *ltime,timestamp_type type)
{
longlong tmp;
- if (type == TIMESTAMP_DATE || type == TIMESTAMP_DATETIME)
+ if (type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME)
tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*LL(1000000)+
(ltime->hour*10000L+ltime->minute*100+ltime->second));
else
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -4062,7 +4106,7 @@ bool Field_datetime::get_date(TIME *ltime, uint fuzzydate)
part1=(uint32) (tmp/LL(1000000));
part2=(uint32) (tmp - (ulonglong) part1*LL(1000000));
- ltime->time_type= TIMESTAMP_DATETIME;
+ ltime->time_type= MYSQL_TIMESTAMP_DATETIME;
ltime->neg= 0;
ltime->second_part= 0;
ltime->second= (int) (part2%100);
@@ -4146,7 +4190,10 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
char buff[80];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
uint copy_length;
-
+
+ /* See the comment for Field_long::store(long long) */
+ DBUG_ASSERT(table->in_use == current_thd);
+
/* Convert character set if nesessary */
if (String::needs_conversion(length, cs, field_charset, &not_used))
{
@@ -4168,7 +4215,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
field_charset->cset->fill(field_charset,ptr+copy_length,
field_length-copy_length,' ');
- if ((copy_length < length) && current_thd->count_cuted_fields)
+ if ((copy_length < length) && table->in_use->count_cuted_fields)
{ // Check if we loosed some info
const char *end=from+length;
from+= copy_length;
@@ -4176,7 +4223,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
MY_SEQ_SPACES);
if (from != end)
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error=1;
}
}
@@ -4224,6 +4271,8 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
uint length= field_charset->cset->lengthsp(field_charset, ptr, field_length);
+ /* See the comment for Field_long::store(long long) */
+ DBUG_ASSERT(table->in_use == current_thd);
val_ptr->set((const char*) ptr, length, field_charset);
return val_ptr;
}
@@ -4242,9 +4291,8 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr)
(const uchar*) b_ptr,
field_length);
}
- return field_charset->coll->strnncoll(field_charset,
- (const uchar*) a_ptr, field_length,
- (const uchar*) b_ptr, field_length);
+ return my_strnncoll(field_charset,(const uchar*) a_ptr, field_length,
+ (const uchar*) b_ptr, field_length);
}
void Field_string::sort_string(char *to,uint length)
@@ -4352,7 +4400,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
if (length > field_length)
{
length=field_length;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error= 1;
}
memcpy(ptr+HA_KEY_BLOB_LENGTH,from,length);
@@ -4636,6 +4684,42 @@ uint32 Field_blob::get_length(const char *pos)
}
+/*
+ Put a blob length field into a record buffer.
+
+ SYNOPSIS
+ Field_blob::put_length()
+ pos Pointer into the record buffer.
+ length The length value to put.
+
+ DESCRIPTION
+ Depending on the maximum length of a blob, its length field is
+ put into 1 to 4 bytes. This is a property of the blob object,
+ described by 'packlength'.
+
+ RETURN
+ nothing
+*/
+
+void Field_blob::put_length(char *pos, uint32 length)
+{
+ switch (packlength) {
+ case 1:
+ *pos= (char) length;
+ break;
+ case 2:
+ int2store(pos, length);
+ break;
+ case 3:
+ int3store(pos, length);
+ break;
+ case 4:
+ int4store(pos, length);
+ break;
+ }
+}
+
+
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
{
if (!length)
@@ -4670,7 +4754,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
min(length, copy_length),
copy_length);
if (copy_length < length)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
Field_blob::store_length(copy_length);
if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH)
@@ -5010,6 +5094,50 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
return to+length;
}
+
+/*
+ Unpack a blob key into a record buffer.
+
+ SYNOPSIS
+ Field_blob::unpack_key()
+ to Pointer into the record buffer.
+ from Pointer to the packed key.
+ max_length Key length limit from key description.
+
+ DESCRIPTION
+ A blob key has a maximum size of 64K-1.
+ In its packed form, the length field is one or two bytes long,
+ depending on 'max_length'.
+ Depending on the maximum length of a blob, its length field is
+ put into 1 to 4 bytes. This is a property of the blob object,
+ described by 'packlength'.
+ Blobs are internally stored apart from the record buffer, which
+ contains a pointer to the blob buffer.
+
+ RETURN
+ Pointer into 'from' past the last byte copied from packed key.
+*/
+
+const char *Field_blob::unpack_key(char *to, const char *from, uint max_length)
+{
+ /* get length of the blob key */
+ uint32 length= *((uchar*) from++);
+ if (max_length > 255)
+ length+= (*((uchar*) from++)) << 8;
+
+ /* put the length into the record buffer */
+ put_length(to, length);
+
+ /* put the address of the blob buffer or NULL */
+ if (length)
+ memcpy_fixed(to + packlength, &from, sizeof(from));
+ else
+ bzero(to + packlength, sizeof(from));
+
+ /* point to first byte of next field in 'from' */
+ return from + length;
+}
+
/* Create a packed key that will be used for storage from a MySQL key */
char *Field_blob::pack_key_from_key_image(char *to, const char *from,
@@ -5229,11 +5357,11 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
if (err || end != from+length || tmp > typelib->count)
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
}
}
else
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
}
store_type((ulonglong) tmp);
return err;
@@ -5251,7 +5379,7 @@ int Field_enum::store(longlong nr)
int error= 0;
if ((uint) nr > typelib->count || nr == 0)
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
nr=0;
error=1;
}
@@ -5407,11 +5535,11 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
tmp > (ulonglong) (((longlong) 1 << typelib->count) - (longlong) 1))
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
}
}
else if (got_warning)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
store_type(tmp);
return err;
}
@@ -5424,7 +5552,7 @@ int Field_set::store(longlong nr)
(longlong) 1))
{
nr&= (longlong) (((longlong) 1 << typelib->count) - (longlong) 1);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
error=1;
}
store_type((ulonglong) nr);
@@ -5803,13 +5931,148 @@ create_field::create_field(Field *old_field,Field *orig_field)
/* Warning handling */
-void Field::set_warning(const uint level, const uint code)
+
+/*
+ Produce warning or note about data saved into field
+
+ SYNOPSYS
+ set_warning()
+ level - level of message (Note/Warning/Error)
+ code - error code of message to be produced
+ cuted_increment - whenever we should increase cut fields count or not
+
+ NOTE
+ This function won't produce warning and increase cut fields counter
+ if count_cuted_fields == FIELD_CHECK_IGNORE for current thread.
+
+ RETURN VALUE
+ true - if count_cuted_fields == FIELD_CHECK_IGNORE
+ false - otherwise
+*/
+bool
+Field::set_warning(const uint level, const uint code, int cuted_increment)
{
- THD *thd= current_thd;
+ THD *thd= table->in_use;
if (thd->count_cuted_fields)
{
- thd->cuted_fields++;
- push_warning_printf(thd, (MYSQL_ERROR::enum_warning_level) level,
- code, ER(code), field_name, thd->row_count);
+ thd->cuted_fields+= cuted_increment;
+ push_warning_printf(thd, (MYSQL_ERROR::enum_warning_level) level,
+ code, ER(code), field_name, thd->row_count);
+ return 0;
+ }
+ return 1;
+}
+
+
+/*
+ Produce warning or note about datetime string data saved into field
+
+ SYNOPSYS
+ set_warning()
+ level - level of message (Note/Warning/Error)
+ code - error code of message to be produced
+ str - string value which we tried to save
+ str_len - length of string which we tried to save
+ ts_type - type of datetime value (datetime/date/time)
+ cuted_increment - whenever we should increase cut fields count or not
+
+ NOTE
+ This function will always produce some warning but won't increase cut
+ fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current
+ thread.
+*/
+void
+Field::set_datetime_warning(const uint level, const uint code,
+ const char *str, uint str_length,
+ timestamp_type ts_type, int cuted_increment)
+{
+ if (set_warning(level, code, cuted_increment))
+ make_truncated_value_warning(table->in_use, str, str_length, ts_type);
+}
+
+
+/*
+ Produce warning or note about integer datetime value saved into field
+
+ SYNOPSYS
+ set_warning()
+ level - level of message (Note/Warning/Error)
+ code - error code of message to be produced
+ nr - numeric value which we tried to save
+ ts_type - type of datetime value (datetime/date/time)
+ cuted_increment - whenever we should increase cut fields count or not
+
+ NOTE
+ This function will always produce some warning but won't increase cut
+ fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current
+ thread.
+*/
+void
+Field::set_datetime_warning(const uint level, const uint code,
+ longlong nr, timestamp_type ts_type,
+ int cuted_increment)
+{
+ if (set_warning(level, code, cuted_increment))
+ {
+ 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,
+ ts_type);
+ }
+}
+
+
+/*
+ Produce warning or note about double datetime data saved into field
+
+ SYNOPSYS
+ set_warning()
+ level - level of message (Note/Warning/Error)
+ code - error code of message to be produced
+ nr - double value which we tried to save
+ ts_type - type of datetime value (datetime/date/time)
+
+ NOTE
+ This function will always produce some warning but won't increase cut
+ fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current
+ thread.
+*/
+void
+Field::set_datetime_warning(const uint level, const uint code,
+ double nr, timestamp_type ts_type)
+{
+ if (set_warning(level, code, 1))
+ {
+ /* DBL_DIG is enough to print '-[digits].E+###' */
+ char str_nr[DBL_DIG + 8];
+ uint str_len= my_sprintf(str_nr, (str_nr, "%g", nr));
+ make_truncated_value_warning(table->in_use, str_nr, str_len, ts_type);
+ }
+}
+
+/*
+ maximum possible display length for blob
+
+ SYNOPSIS
+ Field_blob::max_length()
+
+ RETURN
+ length
+*/
+uint32 Field_blob::max_length()
+{
+ switch (packlength)
+ {
+ case 1:
+ return 255;
+ case 2:
+ return 65535;
+ case 3:
+ return 16777215;
+ case 4:
+ return (uint32) 4294967295U;
+ default:
+ DBUG_ASSERT(0); // we should never go here
+ return 0;
}
}
diff --git a/sql/field.h b/sql/field.h
index 002a7228164..a2fe77e18a3 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -45,6 +45,10 @@ public:
char *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is
+ /*
+ Note that you can use table->in_use as replacement for current_thd member
+ only inside of val_*() and store() members (e.g. you can't use it in cons)
+ */
struct st_table *table; // Pointer for table
struct st_table *orig_table; // Pointer to original table
const char *table_name,*field_name;
@@ -247,6 +251,10 @@ public:
{
return pack(to,from,max_length);
}
+ virtual const char *unpack_key(char* to, const char *from, uint max_length)
+ {
+ return unpack(to,from);
+ }
virtual uint packed_col_length(const char *to, uint length)
{ return length;}
virtual uint max_packed_col_length(uint max_length)
@@ -264,9 +272,20 @@ public:
virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; }
virtual bool has_charset(void) const { return FALSE; }
virtual void set_charset(CHARSET_INFO *charset) { }
- void set_warning(const unsigned int level, const unsigned int code);
+ bool set_warning(const unsigned int level, const unsigned int code,
+ int cuted_increment);
+ void set_datetime_warning(const uint level, const uint code,
+ const char *str, uint str_len,
+ timestamp_type ts_type, int cuted_increment);
+ void set_datetime_warning(const uint level, const uint code,
+ longlong nr, timestamp_type ts_type,
+ int cuted_increment);
+ void set_datetime_warning(const uint level, const uint code,
+ double nr, timestamp_type ts_type);
virtual field_cast_enum field_cast_type()= 0;
bool field_cast_compatible(field_cast_enum type);
+ /* maximum possible display length */
+ virtual uint32 max_length()= 0;
friend bool reopen_table(THD *,struct st_table *,bool);
friend int cre_myisam(my_string name, register TABLE *form, uint options,
ulonglong auto_increment_value);
@@ -336,6 +355,7 @@ public:
CHARSET_INFO *charset(void) const { return field_charset; }
void set_charset(CHARSET_INFO *charset) { field_charset=charset; }
bool binary() const { return field_charset->state & MY_CS_BINSORT ? 1 : 0; }
+ uint32 max_length() { return field_length; }
friend class create_field;
};
@@ -366,6 +386,7 @@ public:
void overflow(bool negative);
bool zero_pack() const { return 0; }
void sql_type(String &str) const;
+ uint32 max_length() { return field_length; }
field_cast_enum field_cast_type() { return FIELD_CAST_DECIMAL; }
};
@@ -397,6 +418,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 1; }
void sql_type(String &str) const;
+ uint32 max_length() { return 4; }
field_cast_enum field_cast_type() { return FIELD_CAST_TINY; }
};
@@ -433,6 +455,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 2; }
void sql_type(String &str) const;
+ uint32 max_length() { return 6; }
field_cast_enum field_cast_type() { return FIELD_CAST_SHORT; }
};
@@ -464,6 +487,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; }
void sql_type(String &str) const;
+ uint32 max_length() { return 8; }
field_cast_enum field_cast_type() { return FIELD_CAST_MEDIUM; }
};
@@ -500,6 +524,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; }
void sql_type(String &str) const;
+ uint32 max_length() { return 11; }
field_cast_enum field_cast_type() { return FIELD_CAST_LONG; }
};
@@ -539,6 +564,7 @@ public:
uint32 pack_length() const { return 8; }
void sql_type(String &str) const;
bool store_for_compare() { return 1; }
+ uint32 max_length() { return 20; }
field_cast_enum field_cast_type() { return FIELD_CAST_LONGLONG; }
};
#endif
@@ -573,6 +599,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(float); }
void sql_type(String &str) const;
+ uint32 max_length() { return 24; }
field_cast_enum field_cast_type() { return FIELD_CAST_FLOAT; }
};
@@ -607,6 +634,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(double); }
void sql_type(String &str) const;
+ uint32 max_length() { return 53; }
field_cast_enum field_cast_type() { return FIELD_CAST_DOUBLE; }
};
@@ -637,6 +665,7 @@ public:
uint32 pack_length() const { return 0; }
void sql_type(String &str) const;
uint size_of() const { return sizeof(*this); }
+ uint32 max_length() { return 4; }
field_cast_enum field_cast_type() { return FIELD_CAST_NULL; }
};
@@ -800,6 +829,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ bool get_date(TIME *ltime, uint fuzzydate);
bool send_binary(Protocol *protocol);
bool get_time(TIME *ltime);
int cmp(const char *,const char*);
@@ -991,6 +1021,7 @@ public:
inline uint32 get_length(uint row_offset=0)
{ return get_length(ptr+row_offset); }
uint32 get_length(const char *ptr);
+ void put_length(char *pos, uint32 length);
inline void get_ptr(char **str)
{
memcpy_fixed(str,ptr+packlength,sizeof(char*));
@@ -1023,6 +1054,7 @@ public:
const char *unpack(char *to, const char *from);
char *pack_key(char *to, const char *from, uint max_length);
char *pack_key_from_key_image(char* to, const char *from, uint max_length);
+ const char *unpack_key(char* to, const char *from, uint max_length);
int pack_cmp(const char *a, const char *b, uint key_length);
int pack_cmp(const char *b, uint key_length);
uint packed_col_length(const char *col_ptr, uint length);
@@ -1034,6 +1066,7 @@ public:
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
field_cast_enum field_cast_type() { return FIELD_CAST_BLOB; }
+ uint32 max_length();
};
#ifdef HAVE_SPATIAL
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 0974c552364..e98068ef974 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -121,7 +121,8 @@ set_field_to_null(Field *field)
field->reset();
if (current_thd->count_cuted_fields == CHECK_FIELD_WARN)
{
- field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,ER_WARN_DATA_TRUNCATED);
+ field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_TRUNCATED, 1);
return 0;
}
if (!current_thd->no_errors)
@@ -178,7 +179,8 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions)
}
if (current_thd->count_cuted_fields == CHECK_FIELD_WARN)
{
- field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,ER_WARN_NULL_TO_NOTNULL);
+ field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_NULL_TO_NOTNULL, 1);
return 0;
}
if (!current_thd->no_errors)
@@ -229,7 +231,7 @@ static void do_copy_not_null(Copy_field *copy)
if (*copy->from_null_ptr & copy->from_bit)
{
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED);
+ ER_WARN_DATA_TRUNCATED, 1);
copy->to_field->reset();
}
else
@@ -329,7 +331,7 @@ static void do_cut_string(Copy_field *copy)
if (!my_isspace(system_charset_info, *ptr)) // QQ: ucs incompatible
{
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED);
+ ER_WARN_DATA_TRUNCATED, 1);
break;
}
}
@@ -350,7 +352,7 @@ static void do_varstring(Copy_field *copy)
length=copy->to_length-2;
if (current_thd->count_cuted_fields)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED);
+ ER_WARN_DATA_TRUNCATED, 1);
}
int2store(copy->to_ptr,length);
memcpy(copy->to_ptr+2, copy->from_ptr,length);
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 1a1547a9d67..fe2b3850197 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -341,7 +341,7 @@ static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count)
{
my_free((char*) tmp, MYF(0));
tmp=0;
- }
+ }
}
DBUG_RETURN(tmp);
}
@@ -384,7 +384,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
if (sort_form->key_read) // QQ Can be removed after the reset
file->extra(HA_EXTRA_KEYREAD); // QQ is removed
next_pos=(byte*) 0; /* Find records in sequence */
- file->rnd_init();
+ file->ha_rnd_init(1);
file->extra_opt(HA_EXTRA_CACHE,
current_thd->variables.read_buff_size);
}
@@ -439,7 +439,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
{
DBUG_PRINT("info",("Sort killed by user"));
(void) file->extra(HA_EXTRA_NO_CACHE);
- file->rnd_end();
+ file->ha_rnd_end();
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
}
if (error == 0)
@@ -469,7 +469,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
else
{
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
- file->rnd_end();
+ if (!next_pos)
+ file->ha_rnd_end();
}
DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos));
@@ -877,7 +878,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
if (param->not_killable)
{
killed= &not_killable;
- not_killable=THD::NOT_KILLED;
+ not_killable= THD::NOT_KILLED;
}
error=0;
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 69a4635b7af..e25640280a3 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -442,7 +442,6 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
return 0; // Identical keys
}
-
int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
{
char name_buff[FN_REFLEN];
@@ -725,8 +724,8 @@ void ha_berkeley::unpack_key(char *record, DBT *key, uint index)
}
record[key_part->null_offset]&= ~key_part->null_bit;
}
- pos= (char*) key_part->field->unpack(record + key_part->field->offset(),
- pos);
+ pos= (char*) key_part->field->unpack_key(record + key_part->field->offset(),
+ pos, key_part->length);
}
}
@@ -843,8 +842,8 @@ int ha_berkeley::write_row(byte * record)
else
{
DB_TXN *sub_trans = transaction;
- /* Don't use sub transactions in temporary tables (in_use == 0) */
- ulong thd_options = table->in_use ? table->in_use->options : 0;
+ /* Don't use sub transactions in temporary tables */
+ ulong thd_options = table->tmp_table == NO_TMP_TABLE ? table->in_use->options : 0;
for (uint retry=0 ; retry < berkeley_trans_retry ; retry++)
{
key_map changed_keys(0);
@@ -1067,7 +1066,7 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
DBT prim_key, key, old_prim_key;
int error;
DB_TXN *sub_trans;
- ulong thd_options = table->in_use ? table->in_use->options : 0;
+ ulong thd_options = table->tmp_table == NO_TMP_TABLE ? table->in_use->options : 0;
bool primary_key_changed;
DBUG_ENTER("update_row");
LINT_INIT(error);
@@ -1260,7 +1259,7 @@ int ha_berkeley::delete_row(const byte * record)
int error;
DBT row, prim_key;
key_map keys=table->keys_in_use;
- ulong thd_options = table->in_use ? table->in_use->options : 0;
+ ulong thd_options = table->tmp_table == NO_TMP_TABLE ? table->in_use->options : 0;
DBUG_ENTER("delete_row");
statistic_increment(ha_delete_count,&LOCK_status);
@@ -1350,6 +1349,7 @@ int ha_berkeley::index_end()
error=cursor->c_close(cursor);
cursor=0;
}
+ active_index=MAX_KEY;
DBUG_RETURN(error);
}
@@ -1411,7 +1411,7 @@ int ha_berkeley::index_read_idx(byte * buf, uint keynr, const byte * key,
statistic_increment(ha_read_key_count,&LOCK_status);
DBUG_ENTER("index_read_idx");
current_row.flags=DB_DBT_REALLOC;
- active_index= (uint) -1;
+ active_index=MAX_KEY;
DBUG_RETURN(read_row(key_file[keynr]->get(key_file[keynr], transaction,
pack_key(&last_key, keynr, key_buff, key,
key_len),
@@ -1482,7 +1482,7 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
bzero((char*) &row, sizeof(row));
error= read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV),
(char*) buf, active_index, &row, &last_key, 1);
- }
+ }
DBUG_RETURN(error);
}
@@ -1630,20 +1630,51 @@ int ha_berkeley::rnd_pos(byte * buf, byte *pos)
statistic_increment(ha_read_rnd_count,&LOCK_status);
DBUG_ENTER("ha_berkeley::rnd_pos");
- active_index= (uint) -1; // Don't delete via cursor
+ active_index= MAX_KEY;
DBUG_RETURN(read_row(file->get(file, transaction,
get_pos(&db_pos, pos),
&current_row, 0),
(char*) buf, primary_key, &current_row, (DBT*) 0, 0));
}
+/*
+ Set a reference to the current record in (ref,ref_length).
+
+ SYNOPSIS
+ ha_berkeley::position()
+ record The current record buffer
+
+ DESCRIPTION
+ The BDB handler stores the primary key in (ref,ref_length).
+ There is either an explicit primary key, or an implicit (hidden)
+ primary key.
+ During open(), 'ref_length' is calculated as the maximum primary
+ key length. When an actual key is shorter than that, the rest of
+ the buffer must be cleared out. The row cannot be identified, if
+ garbage follows behind the end of the key. There is no length
+ field for the current key, so that the whole ref_length is used
+ for comparison.
+
+ RETURN
+ nothing
+*/
+
void ha_berkeley::position(const byte *record)
{
DBT key;
+ DBUG_ENTER("ha_berkeley::position");
if (hidden_primary_key)
+ {
+ DBUG_ASSERT(ref_length == BDB_HIDDEN_PRIMARY_KEY_LENGTH);
memcpy_fixed(ref, (char*) current_ident, BDB_HIDDEN_PRIMARY_KEY_LENGTH);
+ }
else
+ {
create_key(&key, primary_key, (char*) ref, record);
+ if (key.size < ref_length)
+ bzero(ref + key.size, ref_length - key.size);
+ }
+ DBUG_VOID_RETURN;
}
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index 1d7d29de979..3213a81fadf 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -87,24 +87,25 @@ class ha_berkeley: public handler
public:
ha_berkeley(TABLE *table): handler(table), alloc_ptr(0),rec_buff(0), file(0),
- int_table_flags(HA_REC_NOT_IN_SEQ |
- HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER | HA_FAST_KEY_READ |
- HA_NULL_KEY | HA_BLOB_KEY | HA_NOT_EXACT_COUNT |
- HA_PRIMARY_KEY_IN_READ_INDEX | HA_DROP_BEFORE_CREATE |
- HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX |
- HA_KEY_READ_WRONG_STR | HA_FILE_BASED),
- changed_rows(0),last_dup_key((uint) -1),version(0),using_ignore(0)
- {
- }
+ int_table_flags(HA_REC_NOT_IN_SEQ | HA_FAST_KEY_READ |
+ HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_NOT_EXACT_COUNT |
+ HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED |
+ HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX),
+ changed_rows(0),last_dup_key((uint) -1),version(0),using_ignore(0) {}
~ha_berkeley() {}
const char *table_type() const { return "BerkeleyDB"; }
+ ulong index_flags(uint idx, uint part) const
+ {
+ ulong flags=HA_READ_NEXT | HA_READ_PREV;
+ if (part == (uint)~0 ||
+ table->key_info[idx].key_part[part].field->key_type() != HA_KEYTYPE_TEXT)
+ flags|= HA_READ_ORDER | HA_KEYREAD_ONLY | HA_READ_RANGE;
+ return flags;
+ }
const char *index_type(uint key_number) { return "BTREE"; }
const char **bas_ext() const;
ulong table_flags(void) const { return int_table_flags; }
- uint max_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_keys() const { return MAX_KEY-1; }
- uint max_key_parts() const { return MAX_REF_PARTS; }
- uint max_key_length() const { return MAX_KEY_LENGTH; }
+ uint max_supported_keys() const { return MAX_KEY-1; }
uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; }
ha_rows estimate_number_of_rows();
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
@@ -128,7 +129,7 @@ class ha_berkeley: public handler
int index_prev(byte * buf);
int index_first(byte * buf);
int index_last(byte * buf);
- int rnd_init(bool scan=1);
+ int rnd_init(bool scan);
int rnd_end();
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index c375614ac95..cc828b6e6b2 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -111,6 +111,7 @@ int ha_heap::delete_row(const byte * buf)
int ha_heap::index_read(byte * buf, const byte * key, uint key_len,
enum ha_rkey_function find_flag)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_key_count, &LOCK_status);
int error = heap_rkey(file,buf,active_index, key, key_len, find_flag);
table->status = error ? STATUS_NOT_FOUND : 0;
@@ -119,6 +120,7 @@ int ha_heap::index_read(byte * buf, const byte * key, uint key_len,
int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_key_count, &LOCK_status);
int error= heap_rkey(file, buf, active_index, key, key_len,
HA_READ_PREFIX_LAST);
@@ -137,6 +139,7 @@ int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
int ha_heap::index_next(byte * buf)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_next_count,&LOCK_status);
int error=heap_rnext(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -145,6 +148,7 @@ int ha_heap::index_next(byte * buf)
int ha_heap::index_prev(byte * buf)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_prev_count,&LOCK_status);
int error=heap_rprev(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -153,6 +157,7 @@ int ha_heap::index_prev(byte * buf)
int ha_heap::index_first(byte * buf)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_first_count,&LOCK_status);
int error=heap_rfirst(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -161,6 +166,7 @@ int ha_heap::index_first(byte * buf)
int ha_heap::index_last(byte * buf)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_last_count,&LOCK_status);
int error=heap_rlast(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index ebca52265b0..9d0b9999300 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -40,21 +40,18 @@ class ha_heap: public handler
const char **bas_ext() const;
ulong table_flags() const
{
- return (HA_READ_RND_SAME | HA_FAST_KEY_READ | HA_KEYPOS_TO_RNDPOS |
- HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ);
+ return (HA_FAST_KEY_READ | HA_NO_BLOBS | HA_NULL_IN_KEY |
+ HA_REC_NOT_IN_SEQ | HA_READ_RND_SAME |
+ HA_CAN_INSERT_DELAYED);
}
- ulong index_flags(uint inx) const
+ ulong index_flags(uint inx, uint part) const
{
return ((table->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
- (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER) :
- (HA_ONLY_WHOLE_INDEX | HA_WRONG_ASCII_ORDER |
- HA_NOT_READ_PREFIX_LAST));
+ HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE :
+ HA_ONLY_WHOLE_INDEX);
}
const key_map *keys_to_use_for_scanning() { return &btree_keys; }
- uint max_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_keys() const { return MAX_KEY; }
- uint max_key_parts() const { return MAX_REF_PARTS; }
- uint max_key_length() const { return HA_MAX_REC_LENGTH; }
+ uint max_supported_keys() const { return MAX_KEY; }
double scan_time() { return (double) (records+deleted) / 20.0+10; }
double read_time(uint index, uint ranges, ha_rows rows)
{ return (double) rows / 20.0+1; }
@@ -75,7 +72,7 @@ class ha_heap: public handler
int index_prev(byte * buf);
int index_first(byte * buf);
int index_last(byte * buf);
- int rnd_init(bool scan=1);
+ int rnd_init(bool scan);
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index f870cbab1c3..9f14e22ce38 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -66,6 +66,7 @@ extern "C" {
#include "../innobase/include/trx0roll.h"
#include "../innobase/include/trx0trx.h"
#include "../innobase/include/trx0sys.h"
+#include "../innobase/include/mtr0mtr.h"
#include "../innobase/include/row0ins.h"
#include "../innobase/include/row0mysql.h"
#include "../innobase/include/row0sel.h"
@@ -103,7 +104,7 @@ are determined in innobase_init below: */
char* innobase_data_home_dir = NULL;
char* innobase_data_file_path = NULL;
char* innobase_log_group_home_dir = NULL;
-char* innobase_log_arch_dir = NULL;
+char* innobase_log_arch_dir = NULL;/* unused */
/* The following has a misleading name: starting from 4.0.5, this also
affects Windows: */
char* innobase_unix_file_flush_method = NULL;
@@ -112,7 +113,7 @@ char* innobase_unix_file_flush_method = NULL;
values */
uint innobase_flush_log_at_trx_commit = 1;
-my_bool innobase_log_archive = FALSE;
+my_bool innobase_log_archive = FALSE;/* unused */
my_bool innobase_use_native_aio = FALSE;
my_bool innobase_fast_shutdown = TRUE;
my_bool innobase_file_per_table = FALSE;
@@ -406,7 +407,7 @@ innobase_mysql_print_thd(
May 14, 2004 probably no race any more,
but better be safe */
}
-
+
/* Use strmake to reduce the timeframe
for a race, compared to fwrite() */
i= (uint) (strmake(buf, s, len) - buf);
@@ -841,7 +842,8 @@ innobase_init(void)
if (!innobase_log_group_home_dir) {
innobase_log_group_home_dir = default_path;
}
-
+
+#ifdef UNIV_LOG_ARCHIVE
/* Since innodb_log_arch_dir has no relevance under MySQL,
starting from 4.0.6 we always set it the same as
innodb_log_group_home_dir: */
@@ -849,6 +851,7 @@ innobase_init(void)
innobase_log_arch_dir = innobase_log_group_home_dir;
srv_arch_dir = innobase_log_arch_dir;
+#endif /* UNIG_LOG_ARCHIVE */
ret = (bool)
srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
@@ -870,7 +873,9 @@ innobase_init(void)
srv_n_log_files = (ulint) innobase_log_files_in_group;
srv_log_file_size = (ulint) innobase_log_file_size;
+#ifdef UNIV_LOG_ARCHIVE
srv_log_archive_on = (ulint) innobase_log_archive;
+#endif /* UNIV_LOG_ARCHIVE */
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit;
@@ -1433,9 +1438,6 @@ ha_innobase::open(
last_query_id = (ulong)-1;
- active_index = 0;
- active_index_before_scan = (uint)-1; /* undefined value */
-
if (!(share=get_share(name))) {
DBUG_RETURN(1);
@@ -1579,15 +1581,6 @@ ha_innobase::open(
DBUG_RETURN(0);
}
-/*********************************************************************
-Does nothing. */
-
-void
-ha_innobase::initialize(void)
-/*=========================*/
-{
-}
-
/**********************************************************************
Closes a handle to an InnoDB table. */
@@ -1745,7 +1738,12 @@ innobase_mysql_cmp(
}
}
- ret = my_strnncoll(charset,
+ /* Starting from 4.1.3, we use strnncollsp() in comparisons of
+ non-latin1_swedish_ci strings. NOTE that the collation order
+ changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
+ having indexes on such data need to rebuild their tables! */
+
+ ret = charset->coll->strnncollsp(charset,
a, a_length,
b, b_length);
if (ret < 0) {
@@ -2655,7 +2653,7 @@ ha_innobase::index_end(void)
{
int error = 0;
DBUG_ENTER("index_end");
-
+ active_index=MAX_KEY;
DBUG_RETURN(error);
}
@@ -3126,8 +3124,6 @@ ha_innobase::rnd_init(
/* Store the active index value so that we can restore the original
value after a scan */
- active_index_before_scan = active_index;
-
if (prebuilt->clust_index_was_generated) {
err = change_active_index(MAX_KEY);
} else {
@@ -3147,19 +3143,7 @@ ha_innobase::rnd_end(void)
/*======================*/
/* out: 0 or error number */
{
- /* Restore the old active_index back; MySQL may assume that a table
- scan does not change active_index. We only restore the value if
- MySQL has called rnd_init before: sometimes MySQL seems to call
- rnd_end WITHOUT calling rnd_init. */
-
- if (active_index_before_scan != (uint)-1) {
-
- change_active_index(active_index_before_scan);
-
- active_index_before_scan = (uint)-1;
- }
-
- return(index_end());
+ return(index_end());
}
/*********************************************************************
@@ -4331,9 +4315,8 @@ ha_innobase::analyze(
}
/**************************************************************************
-This is currently mapped to ::analyze. A better option would be to map this
-to "ALTER TABLE tablename TYPE=InnoDB", which seems to rebuild the table in
-MySQL. */
+This is mapped to "ALTER TABLE tablename TYPE=InnoDB", which rebuilds
+the table in MySQL. */
int
ha_innobase::optimize(
@@ -4341,7 +4324,7 @@ ha_innobase::optimize(
THD* thd, /* in: connection thread handle */
HA_CHECK_OPT* check_opt) /* in: currently ignored */
{
- return(ha_innobase::analyze(thd, check_opt));
+ return(HA_ADMIN_TRY_ALTER);
}
/***********************************************************************
@@ -4664,7 +4647,22 @@ ha_innobase::start_stmt(
prepared for an update of a row */
prebuilt->select_lock_type = LOCK_X;
- }
+ } else {
+ if (thd->lex->sql_command == SQLCOM_SELECT
+ && thd->lex->lock_option == TL_READ) {
+
+ /* For other than temporary tables, we obtain
+ no lock for consistent read (plain SELECT) */
+
+ prebuilt->select_lock_type = LOCK_NONE;
+ } else {
+ /* Not a consistent read: use LOCK_X as the
+ select_lock_type value (TODO: how could we know
+ whether it should be LOCK_S, LOCK_X, or LOCK_NONE?) */
+
+ prebuilt->select_lock_type = LOCK_X;
+ }
+ }
/* Set the MySQL flag to mark that there is an active transaction */
thd->transaction.all.innodb_active_trans = 1;
@@ -5044,7 +5042,7 @@ ha_innobase::store_lock(
/***********************************************************************
This function initializes the auto-inc counter if it has not been
initialized yet. This function does not change the value of the auto-inc
-counter if it already has been initialized. In parameter ret returns
+counter if it already has been initialized. In paramete ret returns
the value of the auto-inc counter. */
int
@@ -5170,6 +5168,39 @@ ha_innobase::get_auto_increment()
return(nr);
}
+/***********************************************************************
+This function stores binlog offset and flushes logs */
+
+void
+innobase_store_binlog_offset_and_flush_log(
+/*=============================*/
+ char *binlog_name, /* in: binlog name */
+ longlong offset /* in: binlog offset */
+)
+{
+ mtr_t mtr;
+
+ assert(binlog_name != NULL);
+
+ /* Start a mini-transaction */
+ mtr_start_noninline(&mtr);
+
+ /* Update the latest MySQL binlog name and offset info
+ in trx sys header */
+
+ trx_sys_update_mysql_binlog_offset(
+ binlog_name,
+ offset,
+ TRX_SYS_MYSQL_LOG_INFO, &mtr);
+
+ /* Commits the mini-transaction */
+ mtr_commit(&mtr);
+
+ /* Syncronous flush of the log buffer to disk */
+ log_buffer_flush_to_disk();
+}
+
+
int
ha_innobase::cmp_ref(
const mysql_byte *ref1,
@@ -5218,4 +5249,18 @@ ha_innobase::cmp_ref(
return 0;
}
+char *ha_innobase::get_mysql_bin_log_name()
+{
+ return trx_sys_mysql_bin_log_name;
+}
+
+ulonglong ha_innobase::get_mysql_bin_log_pos()
+{
+ /*
+ trx... is ib_longlong, which is a typedef for a 64-bit integer (__int64 or
+ longlong) so it's ok to cast it to ulonglong.
+ */
+ return trx_sys_mysql_bin_log_pos;
+}
+
#endif /* HAVE_INNOBASE_DB */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index a8f9750c3d4..0a86f4adf3c 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -61,20 +61,11 @@ class ha_innobase: public handler
ulong start_of_scan; /* this is set to 1 when we are
starting a table scan but have not
yet fetched any row, else 0 */
- uint active_index_before_scan;
- /* since a table scan in InnoDB is
- always done through an index, a table
- scan may change active_index; but
- MySQL may assume that active_index
- after a table scan is the same as
- before; we store the value here so
- that we can restore the value after
- a scan */
uint last_match_mode;/* match mode of the latest search:
ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
or undefined */
longlong auto_inc_counter_for_this_stat;
- ulong max_row_length(const byte *buf);
+ ulong max_supported_row_length(const byte *buf);
uint store_key_val_for_row(uint keynr, char* buff, uint buff_len,
const byte* record);
@@ -87,13 +78,10 @@ class ha_innobase: public handler
public:
ha_innobase(TABLE *table): handler(table),
int_table_flags(HA_REC_NOT_IN_SEQ |
- HA_KEYPOS_TO_RNDPOS |
- HA_LASTKEY_ORDER |
- HA_NULL_KEY | HA_FAST_KEY_READ |
- HA_BLOB_KEY |
+ HA_NULL_IN_KEY | HA_FAST_KEY_READ |
+ HA_CAN_INDEX_BLOBS |
HA_CAN_SQL_HANDLER |
HA_NOT_EXACT_COUNT |
- HA_NO_WRITE_DELAYED |
HA_PRIMARY_KEY_IN_READ_INDEX |
HA_TABLE_SCAN_ON_INDEX),
last_dup_key((uint) -1),
@@ -106,14 +94,12 @@ class ha_innobase: public handler
const char *index_type(uint key_number) { return "BTREE"; }
const char** bas_ext() const;
ulong table_flags() const { return int_table_flags; }
- ulong index_flags(uint idx) const
+ ulong index_flags(uint idx, uint part) const
{
- return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER |
- HA_KEY_READ_ONLY);
+ return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE |
+ HA_KEYREAD_ONLY);
}
- uint max_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_keys() const { return MAX_KEY; }
- uint max_key_parts() const { return MAX_REF_PARTS; }
+ uint max_supported_keys() const { return MAX_KEY; }
/* An InnoDB page must store >= 2 keys;
a secondary key record must also contain the
primary key value:
@@ -121,15 +107,12 @@ class ha_innobase: public handler
less than 1 / 4 of page size which is 16 kB;
but currently MySQL does not work with keys
whose size is > MAX_KEY_LENGTH */
- uint max_key_length() const { return((MAX_KEY_LENGTH <= 3500) ?
- MAX_KEY_LENGTH : 3500);}
- uint max_key_part_length() { return((MAX_KEY_LENGTH <= 3500) ?
- MAX_KEY_LENGTH : 3500);}
+ uint max_supported_key_length() const { return 3500; }
+ uint max_supported_key_part_length() const { return 3500; }
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
bool has_transactions() { return 1;}
int open(const char *name, int mode, uint test_if_locked);
- void initialize(void);
int close(void);
double scan_time();
double read_time(uint index, uint ranges, ha_rows rows);
@@ -151,7 +134,7 @@ class ha_innobase: public handler
int index_first(byte * buf);
int index_last(byte * buf);
- int rnd_init(bool scan=1);
+ int rnd_init(bool scan);
int rnd_end();
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
@@ -183,6 +166,8 @@ class ha_innobase: public handler
void init_table_handle_for_HANDLER();
longlong get_auto_increment();
uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; }
+ static char *get_mysql_bin_log_name();
+ static ulonglong get_mysql_bin_log_pos();
bool primary_key_is_clustered() { return true; }
int cmp_ref(const byte *ref1, const byte *ref2);
};
@@ -241,3 +226,5 @@ int innodb_show_status(THD* thd);
my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
uint full_name_len);
void innobase_release_temporary_latches(void* innobase_tid);
+
+void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
diff --git a/sql/ha_isam.h b/sql/ha_isam.h
index 8a887ababde..521946a17b5 100644
--- a/sql/ha_isam.h
+++ b/sql/ha_isam.h
@@ -32,19 +32,20 @@ class ha_isam: public handler
public:
ha_isam(TABLE *table)
:handler(table), file(0),
- int_table_flags(HA_READ_RND_SAME | HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
- HA_KEY_READ_WRONG_STR | HA_DUPP_POS |
- HA_NOT_DELETE_WITH_CACHE | HA_FILE_BASED)
+ int_table_flags(HA_READ_RND_SAME |
+ HA_DUPP_POS | HA_NOT_DELETE_WITH_CACHE | HA_FILE_BASED)
{}
~ha_isam() {}
+ ulong index_flags(uint idx, uint part) const
+ { return HA_READ_NEXT; } // but no HA_READ_PREV here!!!
const char *table_type() const { return "ISAM"; }
const char *index_type(uint key_number) { return "BTREE"; }
const char **bas_ext() const;
ulong table_flags() const { return int_table_flags; }
- uint max_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_keys() const { return N_MAXKEY; }
- uint max_key_parts() const { return N_MAXKEY_SEG; }
- uint max_key_length() const { return N_MAX_KEY_LENGTH; }
+ uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
+ uint max_supported_keys() const { return N_MAXKEY; }
+ uint max_supported_key_parts() const { return N_MAXKEY_SEG; }
+ uint max_supported_key_length() const { return N_MAX_KEY_LENGTH; }
uint min_record_length(uint options) const;
bool low_byte_first() const { return 0; }
@@ -62,11 +63,10 @@ class ha_isam: public handler
int index_prev(byte * buf);
int index_first(byte * buf);
int index_last(byte * buf);
- int rnd_init(bool scan=1);
+ int rnd_init(bool scan);
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
- my_off_t row_position() { return nisam_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
int external_lock(THD *thd, int lock_type);
diff --git a/sql/ha_isammrg.h b/sql/ha_isammrg.h
index 289277a9dac..166a96cf9e4 100644
--- a/sql/ha_isammrg.h
+++ b/sql/ha_isammrg.h
@@ -32,14 +32,11 @@ class ha_isammrg: public handler
~ha_isammrg() {}
const char *table_type() const { return "MRG_ISAM"; }
const char **bas_ext() const;
- ulong table_flags() const { return (HA_READ_RND_SAME | HA_KEYPOS_TO_RNDPOS |
+ ulong table_flags() const { return (HA_READ_RND_SAME |
HA_REC_NOT_IN_SEQ | HA_FILE_BASED); }
- ulong index_flags(uint idx) const { return HA_NOT_READ_PREFIX_LAST; }
+ ulong index_flags(uint idx, uint part) const { DBUG_ASSERT(0); return 0; }
- uint max_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_keys() const { return 0; }
- uint max_key_parts() const { return 0; }
- uint max_key_length() const { return 0; }
+ uint max_supported_keys() const { return 0; }
bool low_byte_first() const { return 0; }
uint min_record_length(uint options) const;
@@ -56,11 +53,10 @@ class ha_isammrg: public handler
int index_prev(byte * buf);
int index_first(byte * buf);
int index_last(byte * buf);
- int rnd_init(bool scan=1);
+ int rnd_init(bool scan);
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
- my_off_t row_position() { return mrg_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
int external_lock(THD *thd, int lock_type);
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 0c43b1f263e..f7e966a9d16 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -60,13 +60,11 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
DBUG_PRINT(msg_type,("message: %s",msgbuf));
-#ifndef EMBEDDED_LIBRARY
- if (thd->net.vio == 0)
+ if (!thd->vio_ok())
{
sql_print_error(msgbuf);
return;
}
-#endif
if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
T_AUTO_REPAIR))
@@ -1006,8 +1004,10 @@ bool ha_myisam::check_and_repair(THD *thd)
{
int error=0;
int marked_crashed;
+ char *old_query;
+ uint old_query_length;
HA_CHECK_OPT check_opt;
- DBUG_ENTER("ha_myisam::auto_check_and_repair");
+ DBUG_ENTER("ha_myisam::check_and_repair");
check_opt.init();
check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
@@ -1015,7 +1015,15 @@ bool ha_myisam::check_and_repair(THD *thd)
if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
check_opt.flags|=T_QUICK;
sql_print_error("Warning: Checking table: '%s'",table->path);
- if ((marked_crashed=mi_is_crashed(file)) || check(thd, &check_opt))
+
+ old_query= thd->query;
+ old_query_length= thd->query_length;
+ pthread_mutex_lock(&LOCK_thread_count);
+ thd->query= table->real_name;
+ thd->query_length= strlen(table->real_name);
+ pthread_mutex_unlock(&LOCK_thread_count);
+
+ if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
{
sql_print_error("Warning: Recovering table: '%s'",table->path);
check_opt.flags=
@@ -1026,6 +1034,10 @@ bool ha_myisam::check_and_repair(THD *thd)
if (repair(thd, &check_opt))
error=1;
}
+ pthread_mutex_lock(&LOCK_thread_count);
+ thd->query= old_query;
+ thd->query_length= old_query_length;
+ pthread_mutex_unlock(&LOCK_thread_count);
DBUG_RETURN(error);
}
@@ -1052,6 +1064,7 @@ int ha_myisam::delete_row(const byte * buf)
int ha_myisam::index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_key_count,&LOCK_status);
int error=mi_rkey(file,buf,active_index, key, key_len, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -1069,6 +1082,7 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_key_count,&LOCK_status);
int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -1077,6 +1091,7 @@ int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len)
int ha_myisam::index_next(byte * buf)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_next_count,&LOCK_status);
int error=mi_rnext(file,buf,active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -1085,6 +1100,7 @@ int ha_myisam::index_next(byte * buf)
int ha_myisam::index_prev(byte * buf)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_prev_count,&LOCK_status);
int error=mi_rprev(file,buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -1093,6 +1109,7 @@ int ha_myisam::index_prev(byte * buf)
int ha_myisam::index_first(byte * buf)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_first_count,&LOCK_status);
int error=mi_rfirst(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -1101,6 +1118,7 @@ int ha_myisam::index_first(byte * buf)
int ha_myisam::index_last(byte * buf)
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_last_count,&LOCK_status);
int error=mi_rlast(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -1111,6 +1129,7 @@ int ha_myisam::index_next_same(byte * buf,
const byte *key __attribute__((unused)),
uint length __attribute__((unused)))
{
+ DBUG_ASSERT(inited==INDEX);
statistic_increment(ha_read_next_count,&LOCK_status);
int error=mi_rnext_same(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index 77887220903..ef3f00577dd 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -44,10 +44,10 @@ class ha_myisam: public handler
public:
ha_myisam(TABLE *table): handler(table), file(0),
- int_table_flags(HA_READ_RND_SAME | HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
- HA_NULL_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
- HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY |
- HA_FILE_BASED | HA_HAS_GEOMETRY),
+ int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
+ HA_DUPP_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
+ HA_FILE_BASED | HA_CAN_GEOMETRY | HA_READ_RND_SAME |
+ HA_CAN_INSERT_DELAYED),
can_enable_indexes(1)
{}
~ha_myisam() {}
@@ -55,17 +55,15 @@ class ha_myisam: public handler
const char *index_type(uint key_number);
const char **bas_ext() const;
ulong table_flags() const { return int_table_flags; }
- ulong index_flags(uint inx) const
+ ulong index_flags(uint inx, uint part) const
{
- ulong flags=(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER);
- return (flags | ((table->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
- 0 : HA_KEY_READ_ONLY));
+ return ((table->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
+ 0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
+ HA_READ_ORDER | HA_KEYREAD_ONLY);
}
- uint max_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_keys() const { return MI_MAX_KEY; }
- uint max_key_parts() const { return MAX_REF_PARTS; }
- uint max_key_length() const { return MI_MAX_KEY_LENGTH; }
- uint max_key_part_length() { return MI_MAX_KEY_LENGTH; }
+ uint max_supported_keys() const { return MI_MAX_KEY; }
+ uint max_supported_key_length() const { return MI_MAX_KEY_LENGTH; }
+ uint max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
uint checksum() const;
int open(const char *name, int mode, uint test_if_locked);
@@ -94,12 +92,11 @@ class ha_myisam: public handler
FT_INFO *ft_init_ext(uint flags, uint inx,const byte *key, uint keylen)
{ return ft_init_search(flags,file,inx,(byte*) key,keylen, table->record[0]); }
int ft_read(byte *buf);
- int rnd_init(bool scan=1);
+ int rnd_init(bool scan);
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
int restart_rnd_next(byte *buf, byte *pos);
void position(const byte *record);
- my_off_t row_position() { return mi_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index fd36c78202d..995cfe9ad4a 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -34,21 +34,20 @@ class ha_myisammrg: public handler
const char **bas_ext() const;
ulong table_flags() const
{
- return (HA_REC_NOT_IN_SEQ | HA_READ_RND_SAME | HA_AUTO_PART_KEY |
- HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
- HA_NULL_KEY | HA_BLOB_KEY | HA_FILE_BASED);
+ return (HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_READ_RND_SAME |
+ HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_FILE_BASED |
+ HA_CAN_INSERT_DELAYED);
}
- ulong index_flags(uint inx) const
+ ulong index_flags(uint inx, uint part) const
{
- ulong flags=(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER);
- return (flags | ((table->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
- 0 : HA_KEY_READ_ONLY));
+ return ((table->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
+ 0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
+ HA_READ_ORDER | HA_KEYREAD_ONLY);
}
- uint max_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_keys() const { return MI_MAX_KEY; }
- uint max_key_parts() const { return MAX_REF_PARTS; }
- uint max_key_length() const { return MAX_KEY_LENGTH; }
- virtual double scan_time()
+ uint max_supported_keys() const { return MI_MAX_KEY; }
+ uint max_supported_key_length() const { return MI_MAX_KEY_LENGTH; }
+ uint max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
+ double scan_time()
{ return ulonglong2double(data_file_length) / IO_SIZE + file->tables; }
int open(const char *name, int mode, uint test_if_locked);
@@ -66,12 +65,11 @@ class ha_myisammrg: public handler
int index_first(byte * buf);
int index_last(byte * buf);
int index_next_same(byte *buf, const byte *key, uint keylen);
- int rnd_init(bool scan=1);
+ int rnd_init(bool scan);
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
- my_off_t row_position() { return myrg_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 21056ef4a8f..d499218a8c3 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -20,12 +20,6 @@
NDB Cluster
*/
-/*
- TODO
- After CREATE DATABASE gör discover på alla tabeller i den databasen
-
-*/
-
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
@@ -45,8 +39,13 @@
// Default value for parallelism
static const int parallelism= 240;
+// Default value for max number of transactions
+// createable against NDB from this handler
+static const int max_transactions = 256;
+
#define NDB_HIDDEN_PRIMARY_KEY_LENGTH 8
+
#define ERR_PRINT(err) \
DBUG_PRINT("error", ("Error: %d message: %s", err.code, err.message))
@@ -64,6 +63,8 @@ typedef NdbDictionary::Dictionary NDBDICT;
bool ndbcluster_inited= false;
+static Ndb* g_ndb= NULL;
+
// Handler synchronization
pthread_mutex_t ndbcluster_mutex;
@@ -95,7 +96,22 @@ static const err_code_mapping err_map[]=
{ 630, HA_ERR_FOUND_DUPP_KEY },
{ 893, HA_ERR_FOUND_DUPP_UNIQUE },
{ 721, HA_ERR_TABLE_EXIST },
+ { 4244, HA_ERR_TABLE_EXIST },
{ 241, HA_ERR_OLD_METADATA },
+
+ { 266, HA_ERR_LOCK_WAIT_TIMEOUT },
+ { 274, HA_ERR_LOCK_WAIT_TIMEOUT },
+ { 296, HA_ERR_LOCK_WAIT_TIMEOUT },
+ { 297, HA_ERR_LOCK_WAIT_TIMEOUT },
+ { 237, HA_ERR_LOCK_WAIT_TIMEOUT },
+
+ { 623, HA_ERR_RECORD_FILE_FULL },
+ { 624, HA_ERR_RECORD_FILE_FULL },
+ { 625, HA_ERR_RECORD_FILE_FULL },
+ { 826, HA_ERR_RECORD_FILE_FULL },
+ { 827, HA_ERR_RECORD_FILE_FULL },
+ { 832, HA_ERR_RECORD_FILE_FULL },
+
{ -1, -1 }
};
@@ -144,6 +160,28 @@ int ha_ndbcluster::ndb_err(NdbConnection *trans)
/*
+ Override the default get_error_message in order to add the
+ error message of NDB
+ */
+
+bool ha_ndbcluster::get_error_message(int error,
+ String *buf)
+{
+ DBUG_ENTER("ha_ndbcluster::get_error_message");
+ DBUG_PRINT("enter", ("error: %d", error));
+
+ if (!m_ndb)
+ DBUG_RETURN(false);
+
+ const NdbError err= m_ndb->getNdbError(error);
+ bool temporary= err.status==NdbError::TemporaryError;
+ buf->set(err.message, strlen(err.message), &my_charset_bin);
+ DBUG_PRINT("exit", ("message: %s, temporary: %d", buf->ptr(), temporary));
+ DBUG_RETURN(temporary);
+}
+
+
+/*
Instruct NDB to set the value of the hidden primary key
*/
@@ -297,7 +335,7 @@ int ha_ndbcluster::get_metadata(const char *path)
const NDBTAB *tab;
const void *data, *pack_data;
const char **key_name;
- uint ndb_columns, mysql_columns, length, pack_length, i;
+ uint ndb_columns, mysql_columns, length, pack_length;
int error;
DBUG_ENTER("get_metadata");
DBUG_PRINT("enter", ("m_tabname: %s, path: %s", m_tabname, path));
@@ -353,60 +391,111 @@ int ha_ndbcluster::get_metadata(const char *path)
// All checks OK, lets use the table
m_table= (void*)tab;
- for (i= 0; i < MAX_KEY; i++)
- m_indextype[i]= UNDEFINED_INDEX;
+ DBUG_RETURN(build_index_list());
+}
+int ha_ndbcluster::build_index_list()
+{
+ char *name;
+ const char *index_name;
+ static const char* unique_suffix= "$unique";
+ uint i, name_len;
+ DBUG_ENTER("build_index_list");
+
// Save information about all known indexes
- for (i= 0; i < table->keys; i++)
- m_indextype[i] = get_index_type_from_table(i);
-
- DBUG_RETURN(0);
+ for (uint i= 0; i < table->keys; i++)
+ {
+ NDB_INDEX_TYPE idx_type= get_index_type_from_table(i);
+ m_indextype[i]= idx_type;
+
+ if (idx_type == UNIQUE_ORDERED_INDEX || idx_type == UNIQUE_INDEX)
+ {
+ index_name= get_index_name(i);
+ name_len= strlen(index_name)+strlen(unique_suffix)+1;
+ // Create name for unique index by appending "$unique";
+ if (!(name= my_malloc(name_len, MYF(MY_WME))))
+ DBUG_RETURN(2);
+ strxnmov(name, name_len, index_name, unique_suffix, NullS);
+ m_unique_index_name[i]= name;
+ DBUG_PRINT("info", ("Created unique index name: %s for index %d",
+ name, i));
+ }
+ }
+ DBUG_RETURN(0);
}
+
+
/*
Decode the type of an index from information
provided in table object
*/
-NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint index_no) const
+NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const
{
- if (index_no == table->primary_key)
- return PRIMARY_KEY_INDEX;
+ bool is_hash_index= (table->key_info[inx].algorithm == HA_KEY_ALG_HASH);
+ if (inx == table->primary_key)
+ return is_hash_index ? PRIMARY_KEY_INDEX : PRIMARY_KEY_ORDERED_INDEX;
else
- return ((table->key_info[index_no].flags & HA_NOSAME) ?
- UNIQUE_INDEX :
+ return ((table->key_info[inx].flags & HA_NOSAME) ?
+ (is_hash_index ? UNIQUE_INDEX : UNIQUE_ORDERED_INDEX) :
ORDERED_INDEX);
}
-
+
void ha_ndbcluster::release_metadata()
{
+ uint i;
+
DBUG_ENTER("release_metadata");
DBUG_PRINT("enter", ("m_tabname: %s", m_tabname));
m_table= NULL;
+ // Release index list
+ for (i= 0; i < MAX_KEY; i++)
+ {
+ if (m_unique_index_name[i])
+ my_free((char*)m_unique_index_name[i], MYF(0));
+ m_unique_index_name[i]= NULL;
+ }
+
DBUG_VOID_RETURN;
}
+NdbCursorOperation::LockMode get_ndb_lock_type(enum thr_lock_type type)
+{
+ return (type == TL_WRITE_ALLOW_WRITE) ?
+ NdbCursorOperation::LM_Exclusive : NdbCursorOperation::LM_Read;
+}
+
static const ulong index_type_flags[]=
{
/* UNDEFINED_INDEX */
0,
/* PRIMARY_KEY_INDEX */
- HA_ONLY_WHOLE_INDEX |
- HA_WRONG_ASCII_ORDER |
- HA_NOT_READ_PREFIX_LAST,
+ HA_ONLY_WHOLE_INDEX,
+
+ /* PRIMARY_KEY_ORDERED_INDEX */
+ /*
+ Enable HA_KEYREAD_ONLY when "sorted" indexes are supported,
+ thus ORDERD BY clauses can be optimized by reading directly
+ through the index.
+ */
+ // HA_KEYREAD_ONLY |
+ HA_READ_NEXT |
+ HA_READ_RANGE,
/* UNIQUE_INDEX */
- HA_ONLY_WHOLE_INDEX |
- HA_WRONG_ASCII_ORDER |
- HA_NOT_READ_PREFIX_LAST,
+ HA_ONLY_WHOLE_INDEX,
+
+ /* UNIQUE_ORDERED_INDEX */
+ HA_READ_NEXT |
+ HA_READ_RANGE,
/* ORDERED_INDEX */
HA_READ_NEXT |
- HA_READ_PREV |
- HA_NOT_READ_AFTER_KEY
+ HA_READ_RANGE,
};
static const int index_flags_size= sizeof(index_type_flags)/sizeof(ulong);
@@ -416,6 +505,11 @@ inline const char* ha_ndbcluster::get_index_name(uint idx_no) const
return table->keynames.type_names[idx_no];
}
+inline const char* ha_ndbcluster::get_unique_index_name(uint idx_no) const
+{
+ return m_unique_index_name[idx_no];
+}
+
inline NDB_INDEX_TYPE ha_ndbcluster::get_index_type(uint idx_no) const
{
DBUG_ASSERT(idx_no < MAX_KEY);
@@ -430,9 +524,10 @@ inline NDB_INDEX_TYPE ha_ndbcluster::get_index_type(uint idx_no) const
flags depending on the type of the index.
*/
-inline ulong ha_ndbcluster::index_flags(uint idx_no) const
+inline ulong ha_ndbcluster::index_flags(uint idx_no, uint part) const
{
DBUG_ENTER("index_flags");
+ DBUG_PRINT("info", ("idx_no: %d", idx_no));
DBUG_ASSERT(get_index_type_from_table(idx_no) < index_flags_size);
DBUG_RETURN(index_type_flags[get_index_type_from_table(idx_no)]);
}
@@ -457,6 +552,24 @@ int ha_ndbcluster::set_primary_key(NdbOperation *op, const byte *key)
}
+int ha_ndbcluster::set_primary_key_from_old_data(NdbOperation *op, const byte *old_data)
+{
+ KEY* key_info= table->key_info + table->primary_key;
+ KEY_PART_INFO* key_part= key_info->key_part;
+ KEY_PART_INFO* end= key_part+key_info->key_parts;
+ DBUG_ENTER("set_primary_key_from_old_data");
+
+ for (; key_part != end; key_part++)
+ {
+ Field* field= key_part->field;
+ if (set_ndb_key(op, field,
+ key_part->fieldnr-1, old_data+key_part->offset))
+ ERR_RETURN(op->getNdbError());
+ }
+ DBUG_RETURN(0);
+}
+
+
int ha_ndbcluster::set_primary_key(NdbOperation *op)
{
DBUG_ENTER("set_primary_key");
@@ -550,7 +663,6 @@ int ha_ndbcluster::unique_index_read(const byte *key,
uint key_len, byte *buf)
{
NdbConnection *trans= m_active_trans;
- const char *index_name;
NdbIndexOperation *op;
THD *thd= current_thd;
byte *key_ptr;
@@ -560,9 +672,10 @@ int ha_ndbcluster::unique_index_read(const byte *key,
DBUG_ENTER("unique_index_read");
DBUG_PRINT("enter", ("key_len: %u, index: %u", key_len, active_index));
DBUG_DUMP("key", (char*)key, key_len);
+ DBUG_PRINT("enter", ("name: %s", get_unique_index_name(active_index)));
- index_name= get_index_name(active_index);
- if (!(op= trans->getNdbIndexOperation(index_name, m_tabname)) ||
+ if (!(op= trans->getNdbIndexOperation(get_unique_index_name(active_index),
+ m_tabname)) ||
op->readTuple() != 0)
ERR_RETURN(trans->getNdbError());
@@ -608,25 +721,64 @@ int ha_ndbcluster::unique_index_read(const byte *key,
}
/*
- Get the next record of a started scan
+ Get the next record of a started scan. Try to fetch
+ it locally from NdbApi cached records if possible,
+ otherwise ask NDB for more.
+
+ NOTE
+ If this is a update/delete make sure to not contact
+ NDB before any pending ops have been sent to NDB.
+
*/
inline int ha_ndbcluster::next_result(byte *buf)
{
+ int check;
NdbConnection *trans= m_active_trans;
NdbResultSet *cursor= m_active_cursor;
DBUG_ENTER("next_result");
-
- if (cursor->nextResult() == 0)
- {
- // One more record found
- unpack_record(buf);
- table->status= 0;
- DBUG_RETURN(0);
- }
+
+ if (!cursor)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ /*
+ If this an update or delete, call nextResult with false
+ to process any records already cached in NdbApi
+ */
+ bool contact_ndb = m_lock.type != TL_WRITE_ALLOW_WRITE;
+ do {
+ DBUG_PRINT("info", ("Call nextResult, contact_ndb: %d", contact_ndb));
+ check= cursor->nextResult(contact_ndb);
+ if (check == 0)
+ {
+ // One more record found
+ DBUG_PRINT("info", ("One more record found"));
+ unpack_record(buf);
+ table->status= 0;
+ DBUG_RETURN(0);
+ }
+ else if (check == 1 || check == 2)
+ {
+ // 1: No more records
+ // 2: No more cached records
+
+ /*
+ Before fetching more rows and releasing lock(s),
+ all pending update or delete operations should
+ be sent to NDB
+ */
+ DBUG_PRINT("info", ("ops_pending: %d", ops_pending));
+ if (ops_pending && (trans->execute(NoCommit) != 0))
+ DBUG_RETURN(ndb_err(trans));
+ ops_pending= 0;
+
+ contact_ndb= (check == 2);
+ }
+ } while (check == 2);
+
table->status= STATUS_NOT_FOUND;
- if (ndb_err(trans))
- ERR_RETURN(trans->getNdbError());
+ if (check == -1)
+ DBUG_RETURN(ndb_err(trans));
// No more records
DBUG_PRINT("info", ("No more records"));
@@ -635,155 +787,135 @@ inline int ha_ndbcluster::next_result(byte *buf)
/*
- Read record(s) from NDB using ordered index scan
+ Set bounds for a ordered index scan, use key_range
*/
-int ha_ndbcluster::ordered_index_scan(const byte *key, uint key_len,
- byte *buf,
- enum ha_rkey_function find_flag)
-{
- uint no_fields= table->fields;
- uint tot_len, i;
- NdbConnection *trans= m_active_trans;
- NdbResultSet *cursor= m_active_cursor;
- NdbScanOperation *op;
- const char *bound_str= NULL;
- const char *index_name;
- NdbOperation::BoundType bound_type = NdbOperation::BoundEQ;
- bool can_be_handled_by_ndb= FALSE;
+int ha_ndbcluster::set_bounds(NdbOperation *op,
+ const key_range *key,
+ int bound)
+{
+ uint i, tot_len;
byte *key_ptr;
- KEY *key_info;
- THD* thd = current_thd;
- DBUG_ENTER("ordered_index_scan");
- DBUG_PRINT("enter", ("index: %u", active_index));
- DBUG_PRINT("enter", ("Starting new ordered scan on %s", m_tabname));
-
- index_name= get_index_name(active_index);
- if (!(op= trans->getNdbScanOperation(index_name, m_tabname)))
- ERR_RETURN(trans->getNdbError());
- if (!(cursor= op->readTuples(parallelism)))
- ERR_RETURN(trans->getNdbError());
- m_active_cursor= cursor;
-
- switch (find_flag) {
- case HA_READ_KEY_EXACT: /* Find first record else error */
- bound_str= "HA_READ_KEY_EXACT";
- bound_type= NdbOperation::BoundEQ;
- can_be_handled_by_ndb= TRUE;
- break;
- case HA_READ_KEY_OR_NEXT: /* Record or next record */
- bound_str= "HA_READ_KEY_OR_NEXT";
- bound_type= NdbOperation::BoundLE;
- can_be_handled_by_ndb= TRUE;
- break;
- case HA_READ_KEY_OR_PREV: /* Record or previous */
- bound_str= "HA_READ_KEY_OR_PREV";
- bound_type= NdbOperation::BoundGE;
- can_be_handled_by_ndb= TRUE;
- break;
- case HA_READ_AFTER_KEY: /* Find next rec. after key-record */
- bound_str= "HA_READ_AFTER_KEY";
- bound_type= NdbOperation::BoundLT;
- can_be_handled_by_ndb= TRUE;
- break;
- case HA_READ_BEFORE_KEY: /* Find next rec. before key-record */
- bound_str= "HA_READ_BEFORE_KEY";
- bound_type= NdbOperation::BoundGT;
- can_be_handled_by_ndb= TRUE;
- break;
- case HA_READ_PREFIX: /* Key which as same prefix */
- bound_str= "HA_READ_PREFIX";
- break;
- case HA_READ_PREFIX_LAST: /* Last key with the same prefix */
- bound_str= "HA_READ_PREFIX_LAST";
- break;
- case HA_READ_PREFIX_LAST_OR_PREV:
- /* Last or prev key with the same prefix */
- bound_str= "HA_READ_PREFIX_LAST_OR_PREV";
- break;
- default:
- bound_str= "UNKNOWN";
- break;
- }
- DBUG_PRINT("info", ("find_flag: %s, bound_type: %d,"
- "can_be_handled_by_ndb: %d",
- bound_str, bound_type, can_be_handled_by_ndb));
- if (!can_be_handled_by_ndb)
- DBUG_RETURN(1);
-
+ KEY* key_info= table->key_info + active_index;
+ KEY_PART_INFO* key_part= key_info->key_part;
+ KEY_PART_INFO* end= key_part+key_info->key_parts;
+
+ DBUG_ENTER("set_bounds");
+ DBUG_PRINT("enter", ("bound: %d", bound));
+ DBUG_PRINT("enter", ("key_parts: %d", key_info->key_parts));
+ DBUG_PRINT("enter", ("key->length: %d", key->length));
+ DBUG_PRINT("enter", ("key->flag: %d", key->flag));
+
// Set bounds using key data
tot_len= 0;
- key_ptr= (byte *) key;
- key_info= table->key_info + active_index;
- for (i= 0; i < key_info->key_parts; i++)
+ key_ptr= (byte *) key->key;
+ for (; key_part != end; key_part++)
{
- Field* field= key_info->key_part[i].field;
+ Field* field= key_part->field;
uint32 field_len= field->pack_length();
- DBUG_PRINT("info", ("Set index bound on %s",
+ tot_len+= field_len;
+
+ const char* bounds[]= {"LE", "LT", "GE", "GT", "EQ"};
+ DBUG_ASSERT(bound >= 0 && bound <= 4);
+ DBUG_PRINT("info", ("Set Bound%s on %s",
+ bounds[bound],
field->field_name));
DBUG_DUMP("key", (char*)key_ptr, field_len);
-
+
if (op->setBound(field->field_name,
- bound_type,
+ bound,
key_ptr,
field_len) != 0)
ERR_RETURN(op->getNdbError());
key_ptr+= field_len;
- tot_len+= field_len;
- if (tot_len >= key_len)
+
+ if (tot_len >= key->length)
+ break;
+
+ /*
+ Only one bound which is not EQ can be set
+ so if this bound was not EQ, bail out and make
+ a best effort attempt
+ */
+ if (bound != NdbOperation::BoundEQ)
break;
}
-
- // Define attributes to read
- for (i= 0; i < no_fields; i++)
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Start ordered index scan in NDB
+*/
+
+int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
+ const key_range *end_key,
+ bool sorted, byte* buf)
+{
+ NdbConnection *trans= m_active_trans;
+ NdbResultSet *cursor;
+ NdbScanOperation *op;
+ const char *index_name;
+
+ DBUG_ENTER("ordered_index_scan");
+ DBUG_PRINT("enter", ("index: %u, sorted: %d", active_index, sorted));
+ DBUG_PRINT("enter", ("Starting new ordered scan on %s", m_tabname));
+
+ index_name= get_index_name(active_index);
+ if (!(op= trans->getNdbScanOperation(index_name, m_tabname)))
+ ERR_RETURN(trans->getNdbError());
+ if (!(cursor= op->readTuples(parallelism, get_ndb_lock_type(m_lock.type))))
+ ERR_RETURN(trans->getNdbError());
+ m_active_cursor= cursor;
+
+ if (start_key &&
+ set_bounds(op, start_key,
+ (start_key->flag == HA_READ_KEY_EXACT) ?
+ NdbOperation::BoundEQ :
+ (start_key->flag == HA_READ_AFTER_KEY) ?
+ NdbOperation::BoundLT :
+ NdbOperation::BoundLE))
+ DBUG_RETURN(1);
+
+ if (end_key)
{
- Field *field= table->field[i];
- if ((thd->query_id == field->query_id) ||
- (field->flags & PRI_KEY_FLAG))
- {
- if (get_ndb_value(op, i, field->ptr))
- ERR_RETURN(op->getNdbError());
- }
- else
+ if (start_key && start_key->flag == HA_READ_KEY_EXACT)
{
- m_value[i]= NULL;
+ DBUG_PRINT("info", ("start_key is HA_READ_KEY_EXACT ignoring end_key"));
}
+ else if (set_bounds(op, end_key,
+ (end_key->flag == HA_READ_AFTER_KEY) ?
+ NdbOperation::BoundGE :
+ NdbOperation::BoundGT))
+ DBUG_RETURN(1);
}
-
- if (table->primary_key == MAX_KEY)
- {
- DBUG_PRINT("info", ("Getting hidden key"));
- // Scanning table with no primary key
- int hidden_no= no_fields;
-#ifndef DBUG_OFF
- const NDBTAB *tab= (NDBTAB *) m_table;
- if (!tab->getColumn(hidden_no))
- DBUG_RETURN(1);
-#endif
- if (get_ndb_value(op, hidden_no, NULL))
- ERR_RETURN(op->getNdbError());
- }
-
- if (trans->execute(NoCommit) != 0)
- DBUG_RETURN(ndb_err(trans));
- DBUG_PRINT("exit", ("Scan started successfully"));
- DBUG_RETURN(next_result(buf));
+ DBUG_RETURN(define_read_attrs(buf, op));
}
-#if 0
/*
- Read record(s) from NDB using full table scan with filter
+ Start a filtered scan in NDB.
+
+ NOTE
+ This function is here as an example of how to start a
+ filtered scan. It should be possible to replace full_table_scan
+ with this function and make a best effort attempt
+ at filtering out the irrelevant data by converting the "items"
+ into interpreted instructions.
+ This would speed up table scans where there is a limiting WHERE clause
+ that doesn't match any index in the table.
+
*/
int ha_ndbcluster::filtered_scan(const byte *key, uint key_len,
byte *buf,
enum ha_rkey_function find_flag)
{
- uint no_fields= table->fields;
NdbConnection *trans= m_active_trans;
- NdbResultSet *cursor= m_active_cursor;
+ NdbResultSet *cursor;
+ NdbScanOperation *op;
DBUG_ENTER("filtered_scan");
DBUG_PRINT("enter", ("key_len: %u, index: %u",
@@ -791,12 +923,10 @@ int ha_ndbcluster::filtered_scan(const byte *key, uint key_len,
DBUG_DUMP("key", (char*)key, key_len);
DBUG_PRINT("info", ("Starting a new filtered scan on %s",
m_tabname));
- NdbScanOperation *op= trans->getNdbScanOperation(m_tabname);
- if (!op)
+
+ if (!(op= trans->getNdbScanOperation(m_tabname)))
ERR_RETURN(trans->getNdbError());
-
- cursor= op->readTuples(parallelism);
- if (!cursor)
+ if (!(cursor= op->readTuples(parallelism, get_ndb_lock_type(m_lock.type))))
ERR_RETURN(trans->getNdbError());
m_active_cursor= cursor;
@@ -845,66 +975,49 @@ int ha_ndbcluster::filtered_scan(const byte *key, uint key_len,
sf.end();
}
- // Define attributes to read
- for (uint field_no= 0; field_no < no_fields; field_no++)
- {
- Field *field= table->field[field_no];
-
- // Read attribute
- DBUG_PRINT("get", ("%d: %s", field_no, field->field_name));
- if (get_ndb_value(op, field_no, field->ptr))
- ERR_RETURN(op->getNdbError());
- }
-
- if (table->primary_key == MAX_KEY)
- {
- DBUG_PRINT("info", ("Getting hidden key"));
- // Scanning table with no primary key
- int hidden_no= no_fields;
-#ifndef DBUG_OFF
- const NDBTAB *tab= (NDBTAB *) m_table;
- if (!tab->getColumn(hidden_no))
- DBUG_RETURN(1);
-#endif
- if (get_ndb_value(op, hidden_no, NULL))
- ERR_RETURN(op->getNdbError());
- }
-
- if (trans->execute(NoCommit) != 0)
- DBUG_RETURN(ndb_err(trans));
- DBUG_PRINT("exit", ("Scan started successfully"));
- DBUG_RETURN(next_result(buf));
+ DBUG_RETURN(define_read_attrs(buf, op));
}
-#endif
/*
- Read records from NDB using full table scan
+ Start full table scan in NDB
*/
int ha_ndbcluster::full_table_scan(byte *buf)
{
uint i;
- THD *thd= current_thd;
- NdbConnection *trans= m_active_trans;
NdbResultSet *cursor;
NdbScanOperation *op;
+ NdbConnection *trans= m_active_trans;
DBUG_ENTER("full_table_scan");
DBUG_PRINT("enter", ("Starting new scan on %s", m_tabname));
if (!(op=trans->getNdbScanOperation(m_tabname)))
ERR_RETURN(trans->getNdbError());
- if (!(cursor= op->readTuples(parallelism)))
+ if (!(cursor= op->readTuples(parallelism, get_ndb_lock_type(m_lock.type))))
ERR_RETURN(trans->getNdbError());
m_active_cursor= cursor;
-
+ DBUG_RETURN(define_read_attrs(buf, op));
+}
+
+
+inline
+int ha_ndbcluster::define_read_attrs(byte* buf, NdbOperation* op)
+{
+ uint i;
+ THD *thd= current_thd;
+ NdbConnection *trans= m_active_trans;
+
+ DBUG_ENTER("define_read_attrs");
+
// Define attributes to read
for (i= 0; i < table->fields; i++)
{
Field *field= table->field[i];
if ((thd->query_id == field->query_id) ||
- (field->flags & PRI_KEY_FLAG))
+ (field->flags & PRI_KEY_FLAG) ||
+ retrieve_all_fields)
{
if (get_ndb_value(op, i, field->ptr))
ERR_RETURN(op->getNdbError());
@@ -991,8 +1104,17 @@ int ha_ndbcluster::write_row(byte *record)
to NoCommit the transaction between each row.
Find out how this is detected!
*/
- if (trans->execute(NoCommit) != 0)
- DBUG_RETURN(ndb_err(trans));
+ rows_inserted++;
+ if ((rows_inserted == rows_to_insert) ||
+ ((rows_inserted % bulk_insert_rows) == 0))
+ {
+ // Send rows to NDB
+ DBUG_PRINT("info", ("Sending inserts to NDB, "\
+ "rows_inserted:%d, bulk_insert_rows: %d",
+ rows_inserted, bulk_insert_rows));
+ if (trans->execute(NoCommit) != 0)
+ DBUG_RETURN(ndb_err(trans));
+ }
DBUG_RETURN(0);
}
@@ -1039,6 +1161,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
{
THD *thd= current_thd;
NdbConnection *trans= m_active_trans;
+ NdbResultSet* cursor= m_active_cursor;
NdbOperation *op;
uint i;
DBUG_ENTER("update_row");
@@ -1047,49 +1170,66 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
if (table->timestamp_on_update_now)
update_timestamp(new_data+table->timestamp_on_update_now-1);
- if (!(op= trans->getNdbOperation(m_tabname)) ||
- op->updateTuple() != 0)
- ERR_RETURN(trans->getNdbError());
-
- if (table->primary_key == MAX_KEY)
- {
- // This table has no primary key, use "hidden" primary key
- DBUG_PRINT("info", ("Using hidden key"));
-
- // Require that the PK for this record has previously been
- // read into m_value
- uint no_fields= table->fields;
- NdbRecAttr* rec= m_value[no_fields];
- DBUG_ASSERT(rec);
- DBUG_DUMP("key", (char*)rec->aRef(), NDB_HIDDEN_PRIMARY_KEY_LENGTH);
-
- if (set_hidden_key(op, no_fields, rec->aRef()))
- ERR_RETURN(op->getNdbError());
- }
- else
+ /* Check for update of primary key and return error */
+ if ((table->primary_key != MAX_KEY) &&
+ (key_cmp(table->primary_key, old_data, new_data)))
+ DBUG_RETURN(HA_ERR_UNSUPPORTED);
+
+ if (cursor)
{
- /* Check for update of primary key and return error */
- if (key_cmp(table->primary_key, old_data, new_data))
- DBUG_RETURN(HA_ERR_UNSUPPORTED);
-
- int res;
- if ((res= set_primary_key(op, old_data + table->null_bytes)))
- DBUG_RETURN(res);
+ /*
+ We are scanning records and want to update the record
+ that was just found, call updateTuple on the cursor
+ to take over the lock to a new update operation
+ And thus setting the primary key of the record from
+ the active record in cursor
+ */
+ DBUG_PRINT("info", ("Calling updateTuple on cursor"));
+ if (!(op= cursor->updateTuple()))
+ ERR_RETURN(trans->getNdbError());
+ ops_pending++;
+ }
+ else
+ {
+ if (!(op= trans->getNdbOperation(m_tabname)) ||
+ op->updateTuple() != 0)
+ ERR_RETURN(trans->getNdbError());
+
+ if (table->primary_key == MAX_KEY)
+ {
+ // This table has no primary key, use "hidden" primary key
+ DBUG_PRINT("info", ("Using hidden key"));
+
+ // Require that the PK for this record has previously been
+ // read into m_value
+ uint no_fields= table->fields;
+ NdbRecAttr* rec= m_value[no_fields];
+ DBUG_ASSERT(rec);
+ DBUG_DUMP("key", (char*)rec->aRef(), NDB_HIDDEN_PRIMARY_KEY_LENGTH);
+
+ if (set_hidden_key(op, no_fields, rec->aRef()))
+ ERR_RETURN(op->getNdbError());
+ }
+ else
+ {
+ int res;
+ if ((res= set_primary_key_from_old_data(op, old_data)))
+ DBUG_RETURN(res);
+ }
}
// Set non-key attribute(s)
for (i= 0; i < table->fields; i++)
{
-
Field *field= table->field[i];
if ((thd->query_id == field->query_id) &&
(!(field->flags & PRI_KEY_FLAG)) &&
set_ndb_value(op, field, i))
ERR_RETURN(op->getNdbError());
}
-
+
// Execute update operation
- if (trans->execute(NoCommit) != 0)
+ if (!cursor && trans->execute(NoCommit) != 0)
DBUG_RETURN(ndb_err(trans));
DBUG_RETURN(0);
@@ -1103,39 +1243,61 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
int ha_ndbcluster::delete_row(const byte *record)
{
NdbConnection *trans= m_active_trans;
+ NdbResultSet* cursor= m_active_cursor;
NdbOperation *op;
DBUG_ENTER("delete_row");
statistic_increment(ha_delete_count,&LOCK_status);
- if (!(op=trans->getNdbOperation(m_tabname)) ||
- op->deleteTuple() != 0)
- ERR_RETURN(trans->getNdbError());
-
- if (table->primary_key == MAX_KEY)
+ if (cursor)
{
- // This table has no primary key, use "hidden" primary key
- DBUG_PRINT("info", ("Using hidden key"));
- uint no_fields= table->fields;
- NdbRecAttr* rec= m_value[no_fields];
- DBUG_ASSERT(rec != NULL);
+ /*
+ We are scanning records and want to update the record
+ that was just found, call deleteTuple on the cursor
+ to take over the lock to a new update operation
+ And thus setting the primary key of the record from
+ the active record in cursor
+ */
+ DBUG_PRINT("info", ("Calling deleteTuple on cursor"));
+ if (cursor->deleteTuple() != 0)
+ ERR_RETURN(trans->getNdbError());
+ ops_pending++;
- if (set_hidden_key(op, no_fields, rec->aRef()))
- ERR_RETURN(op->getNdbError());
- }
- else
+ // If deleting from cursor, NoCommit will be handled in next_result
+ DBUG_RETURN(0);
+ }
+ else
{
- int res;
- if ((res= set_primary_key(op)))
- return res;
+
+ if (!(op=trans->getNdbOperation(m_tabname)) ||
+ op->deleteTuple() != 0)
+ ERR_RETURN(trans->getNdbError());
+
+ if (table->primary_key == MAX_KEY)
+ {
+ // This table has no primary key, use "hidden" primary key
+ DBUG_PRINT("info", ("Using hidden key"));
+ uint no_fields= table->fields;
+ NdbRecAttr* rec= m_value[no_fields];
+ DBUG_ASSERT(rec != NULL);
+
+ if (set_hidden_key(op, no_fields, rec->aRef()))
+ ERR_RETURN(op->getNdbError());
+ }
+ else
+ {
+ int res;
+ if ((res= set_primary_key(op)))
+ return res;
+ }
}
-
+
// Execute delete operation
if (trans->execute(NoCommit) != 0)
DBUG_RETURN(ndb_err(trans));
DBUG_RETURN(0);
}
-
+
/*
Unpack a record read from NDB
@@ -1223,6 +1385,7 @@ void ha_ndbcluster::print_results()
switch (col->getType()) {
case NdbDictionary::Column::Blob:
+ case NdbDictionary::Column::Clob:
case NdbDictionary::Column::Undefined:
fprintf(DBUG_FILE, "Unknown type: %d", col->getType());
break;
@@ -1337,7 +1500,7 @@ int ha_ndbcluster::index_init(uint index)
int ha_ndbcluster::index_end()
{
DBUG_ENTER("index_end");
- DBUG_RETURN(rnd_end());
+ DBUG_RETURN(close_scan());
}
@@ -1348,28 +1511,12 @@ int ha_ndbcluster::index_read(byte *buf,
DBUG_ENTER("index_read");
DBUG_PRINT("enter", ("active_index: %u, key_len: %u, find_flag: %d",
active_index, key_len, find_flag));
-
- int error= 1;
- statistic_increment(ha_read_key_count, &LOCK_status);
- switch (get_index_type(active_index)){
- case PRIMARY_KEY_INDEX:
- error= pk_read(key, key_len, buf);
- break;
-
- case UNIQUE_INDEX:
- error= unique_index_read(key, key_len, buf);
- break;
-
- case ORDERED_INDEX:
- error= ordered_index_scan(key, key_len, buf, find_flag);
- break;
-
- default:
- case UNDEFINED_INDEX:
- break;
- }
- DBUG_RETURN(error);
+ key_range start_key;
+ start_key.key= key;
+ start_key.length= key_len;
+ start_key.flag= find_flag;
+ DBUG_RETURN(read_range_first(&start_key, NULL, false, true));
}
@@ -1391,11 +1538,7 @@ int ha_ndbcluster::index_next(byte *buf)
int error = 1;
statistic_increment(ha_read_next_count,&LOCK_status);
- if (get_index_type(active_index) == PRIMARY_KEY_INDEX)
- error= HA_ERR_END_OF_FILE;
- else
- error = next_result(buf);
- DBUG_RETURN(error);
+ DBUG_RETURN(next_result(buf));
}
@@ -1423,6 +1566,62 @@ int ha_ndbcluster::index_last(byte *buf)
}
+int ha_ndbcluster::read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted)
+{
+ KEY* key_info;
+ int error= 1;
+ byte* buf= table->record[0];
+ DBUG_ENTER("ha_ndbcluster::read_range_first");
+ DBUG_PRINT("info", ("eq_range: %d, sorted: %d", eq_range, sorted));
+
+ if (m_active_cursor)
+ close_scan();
+
+ switch (get_index_type(active_index)){
+ case PRIMARY_KEY_ORDERED_INDEX:
+ case PRIMARY_KEY_INDEX:
+ key_info= table->key_info + active_index;
+ if (start_key &&
+ start_key->length == key_info->key_length &&
+ start_key->flag == HA_READ_KEY_EXACT)
+ {
+ error= pk_read(start_key->key, start_key->length, buf);
+ DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error);
+ }
+ break;
+ case UNIQUE_ORDERED_INDEX:
+ case UNIQUE_INDEX:
+ key_info= table->key_info + active_index;
+ if (start_key &&
+ start_key->length == key_info->key_length &&
+ start_key->flag == HA_READ_KEY_EXACT)
+ {
+ error= unique_index_read(start_key->key, start_key->length, buf);
+ DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error);
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ // Start the ordered index scan and fetch the first row
+ error= ordered_index_scan(start_key, end_key, sorted,
+ buf);
+
+ DBUG_RETURN(error);
+}
+
+
+int ha_ndbcluster::read_range_next()
+{
+ DBUG_ENTER("ha_ndbcluster::read_range_next");
+ DBUG_RETURN(next_result(table->record[0]));
+}
+
+
int ha_ndbcluster::rnd_init(bool scan)
{
NdbResultSet *cursor= m_active_cursor;
@@ -1435,19 +1634,23 @@ int ha_ndbcluster::rnd_init(bool scan)
DBUG_RETURN(0);
}
+int ha_ndbcluster::close_scan()
+{
+ NdbResultSet *cursor= m_active_cursor;
+ DBUG_ENTER("close_scan");
+
+ if (!cursor)
+ DBUG_RETURN(1);
+
+ cursor->close();
+ m_active_cursor= NULL;
+ DBUG_RETURN(0);
+}
int ha_ndbcluster::rnd_end()
{
- NdbResultSet *cursor= m_active_cursor;
DBUG_ENTER("rnd_end");
-
- if (cursor)
- {
- DBUG_PRINT("info", ("Closing the cursor"));
- cursor->close();
- m_active_cursor= NULL;
- }
- DBUG_RETURN(0);
+ DBUG_RETURN(close_scan());
}
@@ -1455,12 +1658,10 @@ int ha_ndbcluster::rnd_next(byte *buf)
{
DBUG_ENTER("rnd_next");
statistic_increment(ha_read_rnd_next_count, &LOCK_status);
- int error = 1;
+
if (!m_active_cursor)
- error = full_table_scan(buf);
- else
- error = next_result(buf);
- DBUG_RETURN(error);
+ DBUG_RETURN(full_table_scan(buf));
+ DBUG_RETURN(next_result(buf));
}
@@ -1654,6 +1855,7 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
where field->query_id is the same as
the current query id */
DBUG_PRINT("info", ("HA_EXTRA_RETRIEVE_ALL_COLS"));
+ retrieve_all_fields= TRUE;
break;
case HA_EXTRA_PREPARE_FOR_DELETE:
DBUG_PRINT("info", ("HA_EXTRA_PREPARE_FOR_DELETE"));
@@ -1679,6 +1881,53 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
DBUG_RETURN(0);
}
+/*
+ Start of an insert, remember number of rows to be inserted, it will
+ be used in write_row and get_autoincrement to send an optimal number
+ of rows in each roundtrip to the server
+
+ SYNOPSIS
+ rows number of rows to insert, 0 if unknown
+
+*/
+
+void ha_ndbcluster::start_bulk_insert(ha_rows rows)
+{
+ int bytes, batch;
+ const NDBTAB *tab= (NDBTAB *) m_table;
+
+ DBUG_ENTER("start_bulk_insert");
+ DBUG_PRINT("enter", ("rows: %d", rows));
+
+ rows_inserted= 0;
+ rows_to_insert= rows;
+
+ /*
+ Calculate how many rows that should be inserted
+ per roundtrip to NDB. This is done in order to minimize the
+ number of roundtrips as much as possible. However performance will
+ degrade if too many bytes are inserted, thus it's limited by this
+ calculation.
+ */
+ const int bytesperbatch = 8192;
+ bytes= 12 + tab->getRowSizeInBytes() + 4 * tab->getNoOfColumns();
+ batch= bytesperbatch/bytes;
+ batch= batch == 0 ? 1 : batch;
+ DBUG_PRINT("info", ("batch: %d, bytes: %d", batch, bytes));
+ bulk_insert_rows= batch;
+
+ DBUG_VOID_RETURN;
+}
+
+/*
+ End of an insert
+ */
+int ha_ndbcluster::end_bulk_insert()
+{
+ DBUG_ENTER("end_bulk_insert");
+ DBUG_RETURN(0);
+}
+
int ha_ndbcluster::extra_opt(enum ha_extra_function operation, ulong cache_size)
{
@@ -1708,7 +1957,7 @@ const char **ha_ndbcluster::bas_ext() const
double ha_ndbcluster::scan_time()
{
- return rows2double(records/3);
+ return rows2double(records*1000);
}
@@ -1740,6 +1989,8 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd,
m_lock.type=lock_type;
}
*to++= &m_lock;
+
+ DBUG_PRINT("exit", ("lock_type: %d", lock_type));
DBUG_RETURN(to);
}
@@ -1788,6 +2039,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
if (lock_type != F_UNLCK)
{
+ DBUG_PRINT("info", ("lock_type != F_UNLCK"));
if (!thd->transaction.ndb_lock_count++)
{
PRINT_OPTION_FLAGS(thd);
@@ -1853,10 +2105,14 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
(NdbConnection*)thd->transaction.all.ndb_tid:
(NdbConnection*)thd->transaction.stmt.ndb_tid;
DBUG_ASSERT(m_active_trans);
-
+
+ // Start of transaction
+ retrieve_all_fields= FALSE;
+ ops_pending= 0;
}
else
{
+ DBUG_PRINT("info", ("lock_type == F_UNLCK"));
if (!--thd->transaction.ndb_lock_count)
{
DBUG_PRINT("trans", ("Last external_lock"));
@@ -1904,6 +2160,10 @@ int ha_ndbcluster::start_stmt(THD *thd)
thd->transaction.stmt.ndb_tid= trans;
}
m_active_trans= trans;
+
+ // Start of statement
+ retrieve_all_fields= FALSE;
+ ops_pending= 0;
DBUG_RETURN(error);
}
@@ -2041,9 +2301,8 @@ int ha_ndbcluster::create(const char *name,
NdbDictionary::Column::Type ndb_type;
NDBCOL col;
uint pack_length, length, i;
- int res;
const void *data, *pack_data;
- const char **key_name= form->keynames.type_names;
+ const char **key_names= form->keynames.type_names;
char name2[FN_HEADLEN];
DBUG_ENTER("create");
@@ -2086,13 +2345,11 @@ int ha_ndbcluster::create(const char *name,
col.setPrimaryKey(field->flags & PRI_KEY_FLAG);
if (field->flags & AUTO_INCREMENT_FLAG)
{
- DBUG_PRINT("info", ("Found auto_increment key"));
col.setAutoIncrement(TRUE);
- ulonglong value = info->auto_increment_value ?
- info->auto_increment_value -1 :
- (ulonglong) 0;
- DBUG_PRINT("info", ("initial value=%ld", value));
-// col.setInitialAutIncValue(value);
+ ulonglong value= info->auto_increment_value ?
+ info->auto_increment_value -1 : (ulonglong) 0;
+ DBUG_PRINT("info", ("Autoincrement key, initial: %d", value));
+ col.setAutoIncrementInitialValue(value);
}
else
col.setAutoIncrement(false);
@@ -2132,65 +2389,86 @@ int ha_ndbcluster::create(const char *name,
DBUG_PRINT("info", ("Table %s/%s created successfully",
m_dbname, m_tabname));
- // Fetch table from NDB, check that it exists
- const NDBTAB *tab2= dict->getTable(m_tabname);
- if (tab2 == NULL)
- {
- const NdbError err= dict->getNdbError();
- ERR_PRINT(err);
- my_errno= ndb_to_mysql_error(&err);
+ if ((my_errno= build_index_list()))
DBUG_RETURN(my_errno);
- }
// Create secondary indexes
- for (i= 0; i < form->keys; i++)
+ KEY* key_info= form->key_info;
+ const char** key_name= key_names;
+ for (i= 0; i < form->keys; i++, key_info++, key_name++)
{
- DBUG_PRINT("info", ("Found index %u: %s", i, key_name[i]));
- if (i == form->primary_key)
- {
- DBUG_PRINT("info", ("Skipping it, PK already created"));
- continue;
- }
-
- DBUG_PRINT("info", ("Creating index %u: %s", i, key_name[i]));
- res= create_index(key_name[i],
- form->key_info + i);
- switch(res){
- case 0:
- // OK
+ int error= 0;
+ DBUG_PRINT("info", ("Index %u: %s", i, *key_name));
+
+ switch (get_index_type_from_table(i)){
+
+ case PRIMARY_KEY_INDEX:
+ // Do nothing, already created
+ break;
+ case PRIMARY_KEY_ORDERED_INDEX:
+ error= create_ordered_index(*key_name, key_info);
+ break;
+ case UNIQUE_ORDERED_INDEX:
+ if (!(error= create_ordered_index(*key_name, key_info)))
+ error= create_unique_index(get_unique_index_name(i), key_info);
+ break;
+ case UNIQUE_INDEX:
+ error= create_unique_index(get_unique_index_name(i), key_info);
+ break;
+ case ORDERED_INDEX:
+ error= create_ordered_index(*key_name, key_info);
break;
default:
+ DBUG_ASSERT(false);
+ break;
+ }
+
+ if (error)
+ {
DBUG_PRINT("error", ("Failed to create index %u", i));
drop_table();
- my_errno= res;
- goto err_end;
+ my_errno= error;
+ break;
}
}
-err_end:
DBUG_RETURN(my_errno);
}
+int ha_ndbcluster::create_ordered_index(const char *name,
+ KEY *key_info)
+{
+ DBUG_ENTER("create_ordered_index");
+ DBUG_RETURN(create_index(name, key_info, false));
+}
+
+int ha_ndbcluster::create_unique_index(const char *name,
+ KEY *key_info)
+{
+
+ DBUG_ENTER("create_unique_index");
+ DBUG_RETURN(create_index(name, key_info, true));
+}
+
+
/*
Create an index in NDB Cluster
*/
int ha_ndbcluster::create_index(const char *name,
- KEY *key_info){
+ KEY *key_info,
+ bool unique)
+{
NdbDictionary::Dictionary *dict= m_ndb->getDictionary();
KEY_PART_INFO *key_part= key_info->key_part;
KEY_PART_INFO *end= key_part + key_info->key_parts;
DBUG_ENTER("create_index");
DBUG_PRINT("enter", ("name: %s ", name));
-
- // Check that an index with the same name do not already exist
- if (dict->getIndex(name, m_tabname))
- ERR_RETURN(dict->getNdbError());
-
+
NdbDictionary::Index ndb_index(name);
- if (key_info->flags & HA_NOSAME)
+ if (unique)
ndb_index.setType(NdbDictionary::Index::UniqueHashIndex);
else
{
@@ -2321,10 +2599,10 @@ int ndbcluster_drop_database(const char *path)
longlong ha_ndbcluster::get_auto_increment()
-{
- // NOTE If number of values to be inserted is known
- // the autoincrement cache could be used here
- Uint64 auto_value= m_ndb->getAutoIncrementValue(m_tabname);
+{
+ int cache_size = rows_to_insert ? rows_to_insert : 32;
+ Uint64 auto_value=
+ m_ndb->getAutoIncrementValue(m_tabname, cache_size);
return (longlong)auto_value;
}
@@ -2340,16 +2618,18 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
m_ndb(NULL),
m_table(NULL),
m_table_flags(HA_REC_NOT_IN_SEQ |
- HA_KEYPOS_TO_RNDPOS |
HA_NOT_EXACT_COUNT |
- HA_NO_WRITE_DELAYED |
HA_NO_PREFIX_CHAR_KEYS |
- HA_NO_BLOBS |
- HA_DROP_BEFORE_CREATE |
- HA_NOT_READ_AFTER_KEY),
- m_use_write(false)
+ HA_NO_BLOBS),
+ m_use_write(false),
+ retrieve_all_fields(FALSE),
+ rows_to_insert(0),
+ rows_inserted(0),
+ bulk_insert_rows(1024),
+ ops_pending(0)
{
-
+ int i;
+
DBUG_ENTER("ha_ndbcluster");
m_tabname[0]= '\0';
@@ -2360,6 +2640,12 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
records= 100;
block_size= 1024;
+ for (i= 0; i < MAX_KEY; i++)
+ {
+ m_indextype[i]= UNDEFINED_INDEX;
+ m_unique_index_name[i]= NULL;
+ }
+
DBUG_VOID_RETURN;
}
@@ -2445,7 +2731,7 @@ Ndb* ha_ndbcluster::seize_ndb()
#else
ndb= new Ndb("");
#endif
- if (ndb->init(NDB_MAX_TRANSACTIONS) != 0)
+ if (ndb->init(max_transactions) != 0)
{
ERR_PRINT(ndb->getNdbError());
/*
@@ -2500,11 +2786,6 @@ int ha_ndbcluster::check_ndb_connection()
}
m_ndb= (Ndb*)thd->transaction.ndb;
m_ndb->setDatabaseName(m_dbname);
- if (m_ndb->waitUntilReady() != 0)
- {
- DBUG_PRINT("error", ("Ndb was not ready"));
- DBUG_RETURN(3);
- }
DBUG_RETURN(0);
}
@@ -2561,7 +2842,6 @@ int ndbcluster_discover(const char *dbname, const char *name,
DBUG_RETURN(0);
}
-static Ndb* g_ndb= NULL;
#ifdef USE_DISCOVER_ON_STARTUP
/*
@@ -2653,6 +2933,14 @@ bool ndbcluster_end()
DBUG_RETURN(0);
}
+void ndbcluster_print_error(int error)
+{
+ DBUG_ENTER("ndbcluster_print_error");
+ TABLE tab;
+ tab.table_name = NULL;
+ ha_ndbcluster error_handler(&tab);
+ error_handler.print_error(error, MYF(0));
+}
/*
Set m_tabname from full pathname to table file
@@ -2751,32 +3039,27 @@ ha_rows
ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
key_range *max_key)
{
- ha_rows records= 10; /* Good guess when you don't know anything */
KEY *key_info= table->key_info + inx;
uint key_length= key_info->key_length;
+ NDB_INDEX_TYPE idx_type= get_index_type(inx);
DBUG_ENTER("records_in_range");
DBUG_PRINT("enter", ("inx: %u", inx));
- DBUG_DUMP("start_key", min_key->key, min_key->length);
- DBUG_DUMP("end_key", max_key->key, max_key->length);
- DBUG_PRINT("enter", ("start_search_flag: %u end_search_flag: %u",
- min_key->flag, max_key->flag));
- /*
- Check that start_key_len is equal to
- the length of the used index and
- prevent partial scan/read of hash indexes by returning HA_POS_ERROR
- */
- NDB_INDEX_TYPE idx_type= get_index_type(inx);
- if ((idx_type == UNIQUE_INDEX || idx_type == PRIMARY_KEY_INDEX) &&
- min_key->length < key_length)
- {
- DBUG_PRINT("warning", ("Tried to use index which required"
- "full key length: %d, HA_POS_ERROR",
- key_length));
- records= HA_POS_ERROR;
- }
- DBUG_RETURN(records);
+ // Prevent partial read of hash indexes by returning HA_POS_ERROR
+ if ((idx_type == UNIQUE_INDEX || idx_type == PRIMARY_KEY_INDEX) &&
+ ((min_key && min_key->length < key_length) ||
+ (max_key && max_key->length < key_length)))
+ DBUG_RETURN(HA_POS_ERROR);
+
+ // Read from hash index with full key
+ // This is a "const" table which returns only one record!
+ if ((idx_type != ORDERED_INDEX) &&
+ ((min_key && min_key->length == key_length) ||
+ (max_key && max_key->length == key_length)))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(10); /* Good guess when you don't know anything */
}
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 029ebc11e46..39c1779a27a 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -37,8 +37,10 @@ class NdbResultSet; // Forward declaration
typedef enum ndb_index_type {
UNDEFINED_INDEX = 0,
PRIMARY_KEY_INDEX = 1,
- UNIQUE_INDEX = 2,
- ORDERED_INDEX = 3
+ PRIMARY_KEY_ORDERED_INDEX = 2,
+ UNIQUE_INDEX = 3,
+ UNIQUE_ORDERED_INDEX = 4,
+ ORDERED_INDEX = 5
} NDB_INDEX_TYPE;
@@ -71,12 +73,17 @@ class ha_ndbcluster: public handler
int index_prev(byte *buf);
int index_first(byte *buf);
int index_last(byte *buf);
- int rnd_init(bool scan=1);
+ int rnd_init(bool scan);
int rnd_end();
int rnd_next(byte *buf);
int rnd_pos(byte *buf, byte *pos);
void position(const byte *record);
+ int read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted);
+ int read_range_next();
+ bool get_error_message(int error, String *buf);
void info(uint);
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
@@ -86,11 +93,12 @@ class ha_ndbcluster: public handler
const char * table_type() const { return("ndbcluster");}
const char ** bas_ext() const;
ulong table_flags(void) const { return m_table_flags; }
- ulong index_flags(uint idx) const;
- uint max_record_length() const { return NDB_MAX_TUPLE_SIZE; };
- uint max_keys() const { return MAX_KEY; }
- uint max_key_parts() const { return NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; };
- uint max_key_length() const { return NDB_MAX_KEY_SIZE;};
+ ulong index_flags(uint idx, uint part) const;
+ uint max_supported_record_length() const { return NDB_MAX_TUPLE_SIZE; };
+ uint max_supported_keys() const { return MAX_KEY; }
+ uint max_supported_key_parts() const
+ { return NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; };
+ uint max_supported_key_length() const { return NDB_MAX_KEY_SIZE;};
int rename_table(const char *from, const char *to);
int delete_table(const char *name);
@@ -112,6 +120,8 @@ class ha_ndbcluster: public handler
const char* index_type(uint key_number) {
switch (get_index_type(key_number)) {
case ORDERED_INDEX:
+ case UNIQUE_ORDERED_INDEX:
+ case PRIMARY_KEY_ORDERED_INDEX:
return "BTREE";
case UNIQUE_INDEX:
case PRIMARY_KEY_INDEX:
@@ -122,6 +132,8 @@ class ha_ndbcluster: public handler
double scan_time();
ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
+ void start_bulk_insert(ha_rows rows);
+ int end_bulk_insert();
static Ndb* seize_ndb();
static void release_ndb(Ndb* ndb);
@@ -130,11 +142,15 @@ class ha_ndbcluster: public handler
private:
int alter_table_name(const char *from, const char *to);
int drop_table();
- int create_index(const char *name, KEY *key_info);
+ int create_index(const char *name, KEY *key_info, bool unique);
+ int create_ordered_index(const char *name, KEY *key_info);
+ int create_unique_index(const char *name, KEY *key_info);
int initialize_autoincrement(const void* table);
+ int build_index_list();
int get_metadata(const char* path);
void release_metadata();
const char* get_index_name(uint idx_no) const;
+ const char* get_unique_index_name(uint idx_no) const;
NDB_INDEX_TYPE get_index_type(uint idx_no) const;
NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const;
@@ -142,17 +158,16 @@ class ha_ndbcluster: public handler
byte *buf);
int unique_index_read(const byte *key, uint key_len,
byte *buf);
- int ordered_index_scan(const byte *key, uint key_len,
- byte *buf,
- enum ha_rkey_function find_flag);
+ int ordered_index_scan(const key_range *start_key,
+ const key_range *end_key,
+ bool sorted, byte* buf);
int full_table_scan(byte * buf);
int next_result(byte *buf);
-#if 0
+ int define_read_attrs(byte* buf, NdbOperation* op);
int filtered_scan(const byte *key, uint key_len,
byte *buf,
enum ha_rkey_function find_flag);
-#endif
-
+ int close_scan();
void unpack_record(byte *buf);
void set_dbname(const char *pathname);
@@ -167,6 +182,9 @@ class ha_ndbcluster: public handler
int get_ndb_value(NdbOperation*, uint fieldnr, byte *field_ptr);
int set_primary_key(NdbOperation *op, const byte *key);
int set_primary_key(NdbOperation *op);
+ int set_primary_key_from_old_data(NdbOperation *op, const byte *old_data);
+ int set_bounds(NdbOperation *ndb_op, const key_range *key,
+ int bound);
int key_cmp(uint keynr, const byte * old_row, const byte * new_row);
void print_results();
@@ -188,8 +206,14 @@ class ha_ndbcluster: public handler
THR_LOCK_DATA m_lock;
NDB_SHARE *m_share;
NDB_INDEX_TYPE m_indextype[MAX_KEY];
+ const char* m_unique_index_name[MAX_KEY];
NdbRecAttr *m_value[NDB_MAX_ATTRIBUTES_IN_TABLE];
bool m_use_write;
+ bool retrieve_all_fields;
+ ha_rows rows_to_insert;
+ ha_rows rows_inserted;
+ ha_rows bulk_insert_rows;
+ ha_rows ops_pending;
};
bool ndbcluster_init(void);
@@ -204,6 +228,7 @@ int ndbcluster_discover(const char* dbname, const char* name,
const void** frmblob, uint* frmlen);
int ndbcluster_drop_database(const char* path);
+void ndbcluster_print_error(int error);
diff --git a/sql/handler.cc b/sql/handler.cc
index 079ff5ba687..017b9d9d4c8 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -35,10 +35,11 @@
#ifdef HAVE_EXAMPLE_DB
#include "examples/ha_example.h"
#endif
+#ifdef HAVE_ARCHIVE_DB
+#include "examples/ha_archive.h"
+#endif
#ifdef HAVE_INNOBASE_DB
#include "ha_innodb.h"
-#else
-#define innobase_query_caching_of_table_permitted(X,Y,Z) 1
#endif
#ifdef HAVE_NDBCLUSTER_DB
#include "ha_ndbcluster.h"
@@ -88,6 +89,8 @@ struct show_table_type_st sys_table_types[]=
"Alias for NDBCLUSTER", DB_TYPE_NDBCLUSTER},
{"EXAMPLE",&have_example_db,
"Example storage engine", DB_TYPE_EXAMPLE_DB},
+ {"ARCHIVE",&have_archive_db,
+ "Archive storage engine", DB_TYPE_ARCHIVE_DB},
{NullS, NULL, NullS, DB_TYPE_UNKNOWN}
};
@@ -189,6 +192,10 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
case DB_TYPE_EXAMPLE_DB:
return new ha_example(table);
#endif
+#ifdef HAVE_ARCHIVE_DB
+ case DB_TYPE_ARCHIVE_DB:
+ return new ha_archive(table);
+#endif
#ifdef HAVE_NDBCLUSTER_DB
case DB_TYPE_NDBCLUSTER:
return new ha_ndbcluster(table);
@@ -210,6 +217,16 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
}
}
+bool ha_caching_allowed(THD* thd, char* table_key,
+ uint key_length, uint8 cache_type)
+{
+#ifdef HAVE_INNOBASE_DB
+ if (cache_type == HA_CACHE_TBL_ASKTRANSACT)
+ return innobase_query_caching_of_table_permitted(thd, table_key, key_length);
+#endif
+ return 1;
+}
+
int ha_init()
{
int error= 0;
@@ -366,17 +383,25 @@ int ha_report_binlog_offset_and_commit(THD *thd,
#ifdef HAVE_INNOBASE_DB
THD_TRANS *trans;
trans = &thd->transaction.all;
- if (trans->innobase_tid)
+ if (trans->innodb_active_trans)
{
+ /*
+ If we updated some InnoDB tables (innodb_active_trans is true), the
+ binlog coords will be reported into InnoDB during the InnoDB commit
+ (innobase_report_binlog_offset_and_commit). But if we updated only
+ non-InnoDB tables, we need an explicit call to report it.
+ */
if ((error=innobase_report_binlog_offset_and_commit(thd,
- trans->innobase_tid,
- log_file_name,
- end_offset)))
+ trans->innobase_tid,
+ log_file_name,
+ end_offset)))
{
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
error=1;
}
}
+ else if (opt_innodb_safe_binlog) // Don't report if not useful
+ innobase_store_binlog_offset_and_flush_log(log_file_name, end_offset);
#endif
return error;
}
@@ -469,7 +494,10 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
{
if ((error=ndbcluster_commit(thd,trans->ndb_tid)))
{
- my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
+ if (error == -1)
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
+ else
+ ndbcluster_print_error(error);
error=1;
}
if (trans == &thd->transaction.all)
@@ -535,7 +563,10 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
{
if ((error=ndbcluster_rollback(thd, trans->ndb_tid)))
{
- my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
+ if (error == -1)
+ my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
+ else
+ ndbcluster_print_error(error);
error=1;
}
trans->ndb_tid = 0;
@@ -569,10 +600,11 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
if ((trans == &thd->transaction.all) && mysql_bin_log.is_open())
{
/*
- Update the binary log with a BEGIN/ROLLBACK block if we have cached some
- queries and we updated some non-transactional table. Such cases should
- be rare (updating a non-transactional table inside a transaction...).
- Count disk writes to trans_log in any case.
+ Update the binary log with a BEGIN/ROLLBACK block if we have
+ cached some queries and we updated some non-transactional
+ table. Such cases should be rare (updating a
+ non-transactional table inside a transaction...). Count disk
+ writes to trans_log in any case.
*/
if (my_b_tell(&thd->transaction.trans_log))
{
@@ -593,13 +625,12 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
reinit_io_cache(&thd->transaction.trans_log,
WRITE_CACHE, (my_off_t) 0, 0, 1);
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
+ if (operation_done)
+ thd->transaction.cleanup();
}
thd->variables.tx_isolation=thd->session_tx_isolation;
if (operation_done)
- {
statistic_increment(ha_rollback_count,&LOCK_status);
- thd->transaction.cleanup();
- }
}
#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
@@ -617,12 +648,12 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
simply truncate the binlog cache, we lose the part of the binlog cache where
the update is. If we want to not lose it, we need to write the SAVEPOINT
command and the ROLLBACK TO SAVEPOINT command to the binlog cache. The latter
- is easy: it's just write at the end of the binlog cache, but the former should
- be *inserted* to the place where the user called SAVEPOINT. The solution is
- that when the user calls SAVEPOINT, we write it to the binlog cache (so no
- need to later insert it). As transactions are never intermixed in the binary log
- (i.e. they are serialized), we won't have conflicts with savepoint names when
- using mysqlbinlog or in the slave SQL thread.
+ is easy: it's just write at the end of the binlog cache, but the former
+ should be *inserted* to the place where the user called SAVEPOINT. The
+ solution is that when the user calls SAVEPOINT, we write it to the binlog
+ cache (so no need to later insert it). As transactions are never intermixed
+ in the binary log (i.e. they are serialized), we won't have conflicts with
+ savepoint names when using mysqlbinlog or in the slave SQL thread.
Then when ROLLBACK TO SAVEPOINT is called, if we updated some
non-transactional table, we don't truncate the binlog cache but instead write
ROLLBACK TO SAVEPOINT to it; otherwise we truncate the binlog cache (which
@@ -856,46 +887,6 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
DBUG_RETURN(error);
}
-int handler::check(THD* thd, HA_CHECK_OPT* check_opt)
-{
- return HA_ADMIN_NOT_IMPLEMENTED;
-}
-
-int handler::backup(THD* thd, HA_CHECK_OPT* check_opt)
-{
- return HA_ADMIN_NOT_IMPLEMENTED;
-}
-
-int handler::restore(THD* thd, HA_CHECK_OPT* check_opt)
-{
- return HA_ADMIN_NOT_IMPLEMENTED;
-}
-
-int handler::repair(THD* thd, HA_CHECK_OPT* check_opt)
-{
- return HA_ADMIN_NOT_IMPLEMENTED;
-}
-
-int handler::optimize(THD* thd, HA_CHECK_OPT* check_opt)
-{
- return HA_ADMIN_NOT_IMPLEMENTED;
-}
-
-int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt)
-{
- return HA_ADMIN_NOT_IMPLEMENTED;
-}
-
-int handler::assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt)
-{
- return HA_ADMIN_NOT_IMPLEMENTED;
-}
-
-int handler::preload_keys(THD* thd, HA_CHECK_OPT* check_opt)
-{
- return HA_ADMIN_NOT_IMPLEMENTED;
-}
-
/*
Read first row (only) from a table
This is never called for InnoDB or BDB tables, as these table types
@@ -913,35 +904,23 @@ int handler::read_first_row(byte * buf, uint primary_key)
If there is very few deleted rows in the table, find the first row by
scanning the table.
*/
- if (deleted < 10 || primary_key >= MAX_KEY ||
- !(index_flags(primary_key) & HA_READ_ORDER))
+ if (deleted < 10 || primary_key >= MAX_KEY)
{
- (void) rnd_init();
+ (void) ha_rnd_init(1);
while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
- (void) rnd_end();
+ (void) ha_rnd_end();
}
else
{
/* Find the first row through the primary key */
- (void) index_init(primary_key);
+ (void) ha_index_init(primary_key);
error=index_first(buf);
- (void) index_end();
+ (void) ha_index_end();
}
DBUG_RETURN(error);
}
-/*
- The following function is only needed for tables that may be temporary tables
- during joins
-*/
-
-int handler::restart_rnd_next(byte *buf, byte *pos)
-{
- return HA_ERR_WRONG_COMMAND;
-}
-
-
/* Set a timestamp in record */
void handler::update_timestamp(byte *record)
@@ -1121,7 +1100,21 @@ void handler::print_error(int error, myf errflag)
break;
default:
{
- my_error(ER_GET_ERRNO,errflag,error);
+ /* The error was "unknown" to this function.
+ Ask handler if it has got a message for this error */
+ bool temporary= FALSE;
+ String str;
+ temporary= get_error_message(error, &str);
+ if (!str.is_empty())
+ {
+ const char* engine= table_type();
+ if (temporary)
+ my_error(ER_GET_TEMPORARY_ERRMSG,MYF(0),error,str.ptr(),engine);
+ else
+ my_error(ER_GET_ERRMSG,MYF(0),error,str.ptr(),engine);
+ }
+ else
+ my_error(ER_GET_ERRNO,errflag,error);
DBUG_VOID_RETURN;
}
}
@@ -1130,6 +1123,22 @@ void handler::print_error(int error, myf errflag)
}
+/*
+ Return an error message specific to this handler
+
+ SYNOPSIS
+ error error code previously returned by handler
+ buf Pointer to String where to add error message
+
+ Returns true if this is a temporary error
+ */
+
+bool handler::get_error_message(int error, String* buf)
+{
+ return FALSE;
+}
+
+
/* Return key if error because of duplicated keys */
uint handler::get_dup_key(int error)
@@ -1195,30 +1204,6 @@ int handler::index_next_same(byte *buf, const byte *key, uint keylen)
}
-/*
- This is called to delete all rows in a table
- If the handler don't support this, then this function will
- return HA_ERR_WRONG_COMMAND and MySQL will delete the rows one
- by one.
-*/
-
-int handler::delete_all_rows()
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-bool handler::caching_allowed(THD* thd, char* table_key,
- uint key_length, uint8 cache_type)
-{
-#ifdef HAVE_INNOBASE_DB
- if (cache_type == HA_CACHE_TBL_ASKTRANSACT)
- return innobase_query_caching_of_table_permitted(thd, table_key,
- key_length);
- else
-#endif
- return 1;
-}
-
/****************************************************************************
** Some general functions that isn't in the handler class
****************************************************************************/
@@ -1241,8 +1226,6 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
if (update_create_info)
{
update_create_info_from_table(create_info, &table);
- if (table.file->table_flags() & HA_DROP_BEFORE_CREATE)
- table.file->delete_table(name);
}
if (lower_case_table_names == 2 &&
!(table.file->table_flags() & HA_FILE_BASED))
@@ -1499,3 +1482,15 @@ int handler::compare_key(key_range *range)
cmp= key_compare_result_on_equal;
return cmp;
}
+
+int handler::index_read_idx(byte * buf, uint index, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag)
+{
+ int error= ha_index_init(index);
+ if (!error)
+ error= index_read(buf, key, key_len, find_flag);
+ if (!error)
+ error= ha_index_end();
+ return error;
+}
+
diff --git a/sql/handler.h b/sql/handler.h
index 8cc5921eacb..13874fa6bb0 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -43,53 +43,45 @@
#define HA_ADMIN_INTERNAL_ERROR -4
#define HA_ADMIN_INVALID -5
#define HA_ADMIN_REJECT -6
+#define HA_ADMIN_TRY_ALTER -7
/* Bits in table_flags() to show what database can do */
-#define HA_READ_RND_SAME 1 /* Read RND-record to KEY-record
- (To update with RND-read) */
-#define HA_KEYPOS_TO_RNDPOS 2 /* ha_info gives pos to record */
-#define HA_TABLE_SCAN_ON_INDEX 4 /* No separate data/index file */
-#define HA_REC_NOT_IN_SEQ 8 /* ha_info don't return recnumber;
+#define HA_READ_RND_SAME (1 << 0) /* can switch index during the scan
+ with ::rnd_same() - not used yet.
+ see mi_rsame/heap_rsame/myrg_rsame */
+#define HA_TABLE_SCAN_ON_INDEX (1 << 2) /* No separate data/index file */
+#define HA_REC_NOT_IN_SEQ (1 << 3) /* ha_info don't return recnumber;
It returns a position to ha_r_rnd */
-#define HA_HAS_GEOMETRY (1 << 4)
+#define HA_CAN_GEOMETRY (1 << 4)
#define HA_FAST_KEY_READ (1 << 5) /* no need for a record cache in filesort */
-#define HA_KEY_READ_WRONG_STR (1 << 6) /* keyread returns converted strings */
-#define HA_NULL_KEY (1 << 7) /* One can have keys with NULL */
-#define HA_DUPP_POS (1 << 8) /* ha_position() gives dupp row */
+#define HA_NULL_IN_KEY (1 << 7) /* One can have keys with NULL */
+#define HA_DUPP_POS (1 << 8) /* ha_position() gives dup row */
#define HA_NO_BLOBS (1 << 9) /* Doesn't support blobs */
-#define HA_BLOB_KEY (1 << 10) /* key on blob */
-#define HA_AUTO_PART_KEY (1 << 11)
-#define HA_REQUIRE_PRIMARY_KEY (1 << 12)
+#define HA_CAN_INDEX_BLOBS (1 << 10)
+#define HA_AUTO_PART_KEY (1 << 11) /* auto-increment in multi-part key */
+#define HA_REQUIRE_PRIMARY_KEY (1 << 12) /* .. and can't create a hidden one */
#define HA_NOT_EXACT_COUNT (1 << 13)
-#define HA_NO_WRITE_DELAYED (1 << 14)
+#define HA_CAN_INSERT_DELAYED (1 << 14) /* only handlers with table-level locks
+ need no special code to support
+ INSERT DELAYED */
#define HA_PRIMARY_KEY_IN_READ_INDEX (1 << 15)
-#define HA_DROP_BEFORE_CREATE (1 << 16)
-#define HA_NOT_READ_AFTER_KEY (1 << 17)
#define HA_NOT_DELETE_WITH_CACHE (1 << 18)
-#define HA_NO_TEMP_TABLES (1 << 19)
#define HA_NO_PREFIX_CHAR_KEYS (1 << 20)
#define HA_CAN_FULLTEXT (1 << 21)
#define HA_CAN_SQL_HANDLER (1 << 22)
#define HA_NO_AUTO_INCREMENT (1 << 23)
#define HA_HAS_CHECKSUM (1 << 24)
-/*
- Next record gives next record according last record read (even
- if database is updated after read). Not used at this point.
-*/
-#define HA_LASTKEY_ORDER (1 << 25)
-/* Table data are stored in separate files */
+/* Table data are stored in separate files (for lower_case_table_names) */
#define HA_FILE_BASED (1 << 26)
/* bits in index_flags(index_number) for what you can do with index */
-#define HA_WRONG_ASCII_ORDER 1 /* Can't use sorting through key */
-#define HA_READ_NEXT 2 /* Read next record with same key */
-#define HA_READ_PREV 4 /* Read prev. record with same key */
-#define HA_READ_ORDER 8 /* Read through record-keys in order */
+#define HA_READ_NEXT 1 /* TODO really use this flag */
+#define HA_READ_PREV 2 /* supports ::index_prev */
+#define HA_READ_ORDER 4 /* index_next/prev follow sort order */
+#define HA_READ_RANGE 8 /* can find all records in a range */
#define HA_ONLY_WHOLE_INDEX 16 /* Can't use part key searches */
-#define HA_NOT_READ_PREFIX_LAST 32 /* No support for index_read_last() */
-#define HA_KEY_READ_ONLY 64 /* Support HA_EXTRA_KEYREAD */
-
+#define HA_KEYREAD_ONLY 64 /* Support HA_EXTRA_KEYREAD */
/* operations for disable/enable indexes */
#define HA_KEY_SWITCH_NONUNIQ 0
@@ -108,9 +100,6 @@
#define HA_DDL_WITH_LOCK 2 /* Can create/drop with locked table */
#define HA_DDL_ONLINE 4 /* Can create/drop without lock */
-/* Return value for ddl methods */
-#define HA_DDL_NOT_IMPLEMENTED -1
-
/*
Parameters for open() (in register form->filestat)
HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED
@@ -158,7 +147,7 @@ enum db_type
DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM,
DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
- DB_TYPE_EXAMPLE_DB,
+ DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB,
DB_TYPE_DEFAULT // Must be last
};
@@ -239,6 +228,18 @@ class handler :public Sql_alloc
protected:
struct st_table *table; /* The table definition */
+ virtual int index_init(uint idx) { active_index=idx; return 0; }
+ virtual int index_end() { active_index=MAX_KEY; return 0; }
+ /*
+ rnd_init() can be called two times without rnd_end() in between
+ (it only makes sense if scan=1).
+ then the second call should prepare for the new table scan (e.g
+ if rnd_init allocates the cursor, second call should position it
+ to the start of the table, no need to deallocate and allocate it again
+ */
+ virtual int rnd_init(bool scan) =0;
+ virtual int rnd_end() { return 0; }
+
public:
byte *ref; /* Pointer to current row */
byte *dupp_ref; /* Pointer to dupp row */
@@ -270,6 +271,7 @@ public:
uint block_size; /* index block size */
uint raid_type,raid_chunks;
FT_INFO *ft_handler;
+ enum {NONE=0, INDEX, RND} inited;
bool auto_increment_column_changed;
bool implicit_emptied; /* Can be !=0 only if HEAP */
@@ -279,15 +281,16 @@ public:
delete_length(0), auto_increment_value(0),
records(0), deleted(0), mean_rec_length(0),
create_time(0), check_time(0), update_time(0),
- key_used_on_scan(MAX_KEY), active_index(MAX_REF_PARTS),
+ key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
ref_length(sizeof(my_off_t)), block_size(0),
- raid_type(0), ft_handler(0), implicit_emptied(0)
+ raid_type(0), ft_handler(0), inited(NONE), implicit_emptied(0)
{}
- virtual ~handler(void) {}
+ virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
int ha_open(const char *name, int mode, int test_if_locked);
void update_timestamp(byte *record);
void update_auto_increment();
virtual void print_error(int error, myf errflag);
+ virtual bool get_error_message(int error, String *buf);
uint get_dup_key(int error);
void change_table_ptr(TABLE *table_arg) { table=table_arg; }
virtual double scan_time()
@@ -298,88 +301,140 @@ public:
virtual bool has_transactions(){ return 0;}
virtual uint extra_rec_buf_length() { return 0; }
virtual ha_rows estimate_number_of_rows() { return records+EXTRA_RECORDS; }
- virtual const char *index_type(uint key_number) { return "";}
- virtual int index_init(uint idx) { active_index=idx; return 0;}
- virtual int index_end() {return 0; }
+ virtual const char *index_type(uint key_number) { DBUG_ASSERT(0); return "";}
+
+ int ha_index_init(uint idx)
+ {
+ DBUG_ASSERT(inited==NONE);
+ inited=INDEX;
+ return index_init(idx);
+ }
+ int ha_index_end()
+ {
+ DBUG_ASSERT(inited==INDEX);
+ inited=NONE;
+ return index_end();
+ }
+ int ha_rnd_init(bool scan)
+ {
+ DBUG_ASSERT(inited==NONE || (inited==RND && scan));
+ inited=RND;
+ return rnd_init(scan);
+ }
+ int ha_rnd_end()
+ {
+ DBUG_ASSERT(inited==RND);
+ inited=NONE;
+ return rnd_end();
+ }
+ /* this is neseccary in many places, e.g. in HANDLER command */
+ int ha_index_or_rnd_end()
+ {
+ return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
+ }
uint get_index(void) const { return active_index; }
virtual int open(const char *name, int mode, uint test_if_locked)=0;
- virtual void initialize(void) {}
virtual int close(void)=0;
- virtual int write_row(byte * buf)=0;
- virtual int update_row(const byte * old_data, byte * new_data)=0;
- virtual int delete_row(const byte * buf)=0;
+ virtual int write_row(byte * buf) { return HA_ERR_WRONG_COMMAND; }
+ virtual int update_row(const byte * old_data, byte * new_data)
+ { return HA_ERR_WRONG_COMMAND; }
+ virtual int delete_row(const byte * buf)
+ { return HA_ERR_WRONG_COMMAND; }
virtual int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)=0;
+ uint key_len, enum ha_rkey_function find_flag)
+ { return HA_ERR_WRONG_COMMAND; }
virtual int index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)=0;
- virtual int index_next(byte * buf)=0;
- virtual int index_prev(byte * buf)=0;
- virtual int index_first(byte * buf)=0;
- virtual int index_last(byte * buf)=0;
+ uint key_len, enum ha_rkey_function find_flag);
+ virtual int index_next(byte * buf)
+ { return HA_ERR_WRONG_COMMAND; }
+ virtual int index_prev(byte * buf)
+ { return HA_ERR_WRONG_COMMAND; }
+ virtual int index_first(byte * buf)
+ { return HA_ERR_WRONG_COMMAND; }
+ virtual int index_last(byte * buf)
+ { return HA_ERR_WRONG_COMMAND; }
virtual int index_next_same(byte *buf, const byte *key, uint keylen);
virtual int index_read_last(byte * buf, const byte * key, uint key_len)
- {
- return (my_errno=HA_ERR_WRONG_COMMAND);
- }
+ { return (my_errno=HA_ERR_WRONG_COMMAND); }
virtual int read_range_first(const key_range *start_key,
const key_range *end_key,
bool eq_range, bool sorted);
virtual int read_range_next();
int compare_key(key_range *range);
- virtual int ft_init()
- { return -1; }
+ virtual int ft_init() { return HA_ERR_WRONG_COMMAND; }
virtual FT_INFO *ft_init_ext(uint flags,uint inx,const byte *key,
uint keylen)
{ return NULL; }
- virtual int ft_read(byte *buf) { return -1; }
- virtual int rnd_init(bool scan=1)=0;
- virtual int rnd_end() { return 0; }
+ virtual int ft_read(byte *buf) { return HA_ERR_WRONG_COMMAND; }
virtual int rnd_next(byte *buf)=0;
virtual int rnd_pos(byte * buf, byte *pos)=0;
virtual int read_first_row(byte *buf, uint primary_key);
- virtual int restart_rnd_next(byte *buf, byte *pos);
+ /*
+ The following function is only needed for tables that may be temporary
+ tables during joins
+ */
+ virtual int restart_rnd_next(byte *buf, byte *pos)
+ { return HA_ERR_WRONG_COMMAND; }
+ virtual int rnd_same(byte *buf, uint inx)
+ { return HA_ERR_WRONG_COMMAND; }
virtual ha_rows records_in_range(uint inx, key_range *min_key,
key_range *max_key)
{ return (ha_rows) 10; }
virtual void position(const byte *record)=0;
- virtual my_off_t row_position() { return HA_OFFSET_ERROR; }
virtual void info(uint)=0;
- virtual int extra(enum ha_extra_function operation)=0;
+ virtual int extra(enum ha_extra_function operation)
+ { return 0; }
virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
- {
- return extra(operation);
- }
+ { return extra(operation); }
virtual int reset() { return extra(HA_EXTRA_RESET); }
virtual int external_lock(THD *thd, int lock_type)=0;
virtual void unlock_row() {}
virtual int start_stmt(THD *thd) {return 0;}
- virtual int delete_all_rows();
+ /*
+ This is called to delete all rows in a table
+ If the handler don't support this, then this function will
+ return HA_ERR_WRONG_COMMAND and MySQL will delete the rows one
+ by one.
+ */
+ virtual int delete_all_rows()
+ { return (my_errno=HA_ERR_WRONG_COMMAND); }
virtual longlong get_auto_increment();
virtual void update_create_info(HA_CREATE_INFO *create_info) {}
- virtual int check(THD* thd, HA_CHECK_OPT* check_opt );
- virtual int repair(THD* thd, HA_CHECK_OPT* check_opt);
- virtual bool check_and_repair(THD *thd) {return 1;}
- virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt);
- virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt);
- virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt);
- virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
- virtual int backup(THD* thd, HA_CHECK_OPT* check_opt);
+
+ /* admin commands - called from mysql_admin_table */
+ virtual int check(THD* thd, HA_CHECK_OPT* check_opt)
+ { return HA_ADMIN_NOT_IMPLEMENTED; }
+ virtual int backup(THD* thd, HA_CHECK_OPT* check_opt)
+ { return HA_ADMIN_NOT_IMPLEMENTED; }
/*
restore assumes .frm file must exist, and that generate_table() has been
called; It will just copy the data file and run repair.
*/
- virtual int restore(THD* thd, HA_CHECK_OPT* check_opt);
- virtual int dump(THD* thd, int fd = -1) { return ER_DUMP_NOT_IMPLEMENTED; }
+ virtual int restore(THD* thd, HA_CHECK_OPT* check_opt)
+ { return HA_ADMIN_NOT_IMPLEMENTED; }
+ virtual int repair(THD* thd, HA_CHECK_OPT* check_opt)
+ { return HA_ADMIN_NOT_IMPLEMENTED; }
+ virtual int optimize(THD* thd, HA_CHECK_OPT* check_opt)
+ { return HA_ADMIN_NOT_IMPLEMENTED; }
+ virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt)
+ { return HA_ADMIN_NOT_IMPLEMENTED; }
+ virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt)
+ { return HA_ADMIN_NOT_IMPLEMENTED; }
+ virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt)
+ { return HA_ADMIN_NOT_IMPLEMENTED; }
+ /* end of the list of admin commands */
+
+ virtual bool check_and_repair(THD *thd) { return HA_ERR_WRONG_COMMAND; }
+ virtual int dump(THD* thd, int fd = -1) { return HA_ERR_WRONG_COMMAND; }
virtual int disable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
virtual int enable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
virtual int indexes_are_disabled(void) {return 0;}
virtual void start_bulk_insert(ha_rows rows) {}
virtual int end_bulk_insert() {return 0; }
- virtual int discard_or_import_tablespace(my_bool discard) {return -1;}
- // not implemented by default
- virtual int net_read_dump(NET* net)
- { return ER_DUMP_NOT_IMPLEMENTED; }
+ virtual int discard_or_import_tablespace(my_bool discard)
+ {return HA_ERR_WRONG_COMMAND;}
+ virtual int net_read_dump(NET* net) { return HA_ERR_WRONG_COMMAND; }
virtual char *update_table_comment(const char * comment)
{ return (char*) comment;}
virtual void append_create_info(String *packet) {}
@@ -394,38 +449,47 @@ public:
virtual const char *table_type() const =0;
virtual const char **bas_ext() const =0;
virtual ulong table_flags(void) const =0;
- virtual ulong index_flags(uint idx) const
- {
- return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_KEY_READ_ONLY);
- }
+ virtual ulong index_flags(uint idx, uint part=~0) const =0;
virtual ulong index_ddl_flags(KEY *wanted_index) const
- {
- return (HA_DDL_SUPPORT);
- }
- virtual int add_index(TABLE *table, KEY *key_info, uint num_of_keys)
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "online add index");
- return (HA_DDL_NOT_IMPLEMENTED);
- }
- virtual int drop_index(TABLE *table, uint *key_num, uint num_of_keys)
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "online drop index");
- return (HA_DDL_NOT_IMPLEMENTED);
- }
- virtual uint max_record_length() const =0;
- virtual uint max_keys() const =0;
- virtual uint max_key_parts() const =0;
- virtual uint max_key_length()const =0;
- virtual uint max_key_part_length() { return 255; }
+ { return (HA_DDL_SUPPORT); }
+ virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
+ { return (HA_ERR_WRONG_COMMAND); }
+ virtual int drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys)
+ { return (HA_ERR_WRONG_COMMAND); }
+
+ uint max_record_length() const
+ { return min(HA_MAX_REC_LENGTH, max_supported_record_length()); }
+ uint max_keys() const
+ { return min(MAX_KEY, max_supported_keys()); }
+ uint max_key_parts() const
+ { return min(MAX_REF_PARTS, max_supported_key_parts()); }
+ uint max_key_length() const
+ { return min(MAX_KEY_LENGTH, max_supported_key_length()); }
+ uint max_key_part_length() const
+ { return min(MAX_KEY_LENGTH, max_supported_key_part_length()); }
+
+ virtual uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
+ virtual uint max_supported_keys() const { return 0; }
+ virtual uint max_supported_key_parts() const { return MAX_REF_PARTS; }
+ virtual uint max_supported_key_length() const { return MAX_KEY_LENGTH; }
+ virtual uint max_supported_key_part_length() const { return 255; }
virtual uint min_record_length(uint options) const { return 1; }
+
virtual bool low_byte_first() const { return 1; }
virtual uint checksum() const { return 0; }
virtual bool is_crashed() const { return 0; }
virtual bool auto_repair() const { return 0; }
+ /*
+ default rename_table() and delete_table() rename/delete files with a
+ given name and extensions from bas_ext()
+ */
virtual int rename_table(const char *from, const char *to);
virtual int delete_table(const char *name);
+
virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
+
+ /* lock_count() can be more than one if the table is a MERGE */
virtual uint lock_count(void) const { return 1; }
virtual THR_LOCK_DATA **store_lock(THD *thd,
THR_LOCK_DATA **to,
@@ -433,24 +497,18 @@ public:
/* Type of table for caching query */
virtual uint8 table_cache_type() { return HA_CACHE_TBL_NONTRANSACT; }
- /*
- Is query with this table cachable (have sense only for ASKTRANSACT
- tables)
- */
- static bool caching_allowed(THD* thd, char* table_key,
- uint key_length, uint8 cahe_type);
-
- /*
- RETURN
- true Primary key (if there is one) is clustered key covering all fields
- false otherwise
- */
- virtual bool primary_key_is_clustered() { return false; }
-
- virtual int cmp_ref(const byte *ref1, const byte *ref2)
- {
- return memcmp(ref1, ref2, ref_length);
- }
+
+ /*
+ RETURN
+ true Primary key (if there is one) is clustered key covering all fields
+ false otherwise
+ */
+ virtual bool primary_key_is_clustered() { return FALSE; }
+
+ virtual int cmp_ref(const byte *ref1, const byte *ref2)
+ {
+ return memcmp(ref1, ref2, ref_length);
+ }
};
/* Some extern variables used with handlers */
@@ -465,8 +523,11 @@ extern TYPELIB tx_isolation_typelib;
#define ha_commit(thd) (ha_commit_trans((thd), &((thd)->transaction.all)))
#define ha_rollback(thd) (ha_rollback_trans((thd), &((thd)->transaction.all)))
-#define ha_supports_generate(T) (T != DB_TYPE_INNODB)
+#define ha_supports_generate(T) (T != DB_TYPE_INNODB && \
+ T != DB_TYPE_BERKELEY_DB)
+bool ha_caching_allowed(THD* thd, char* table_key,
+ uint key_length, uint8 cache_type);
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);
diff --git a/sql/item.cc b/sql/item.cc
index 8dfe40abea8..8dfb8fb5587 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -230,8 +230,8 @@ bool Item::get_date(TIME *ltime,uint fuzzydate)
char buff[40];
String tmp(buff,sizeof(buff), &my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
- str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) <=
- TIMESTAMP_DATETIME_ERROR)
+ str_to_datetime_with_warn(res->ptr(), res->length(),
+ ltime, fuzzydate) <= MYSQL_TIMESTAMP_ERROR)
{
bzero((char*) ltime,sizeof(*ltime));
return 1;
@@ -249,7 +249,7 @@ bool Item::get_time(TIME *ltime)
char buff[40];
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
- str_to_time(res->ptr(),res->length(),ltime))
+ str_to_time_with_warn(res->ptr(), res->length(), ltime))
{
bzero((char*) ltime,sizeof(*ltime));
return 1;
@@ -257,7 +257,7 @@ bool Item::get_time(TIME *ltime)
return 0;
}
-CHARSET_INFO * Item::default_charset() const
+CHARSET_INFO *Item::default_charset()
{
return current_thd->variables.collation_connection;
}
@@ -658,7 +658,9 @@ default_set_param_func(Item_param *param,
Item_param::Item_param(unsigned pos_in_query_arg) :
state(NO_VALUE),
item_result_type(STRING_RESULT),
- item_type(STRING_ITEM),
+ /* Don't pretend to be a literal unless value for this item is set. */
+ item_type(PARAM_ITEM),
+ param_type(MYSQL_TYPE_STRING),
pos_in_query(pos_in_query_arg),
set_param_func(default_set_param_func)
{
@@ -766,6 +768,73 @@ bool Item_param::set_longdata(const char *str, ulong length)
/*
+ Set parameter value from user variable value.
+
+ SYNOPSIS
+ set_from_user_var
+ thd Current thread
+ entry User variable structure (NULL means use NULL value)
+
+ RETURN
+ 0 OK
+ 1 Out of memort
+*/
+
+bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
+{
+ DBUG_ENTER("Item_param::set_from_user_var");
+ if (entry && entry->value)
+ {
+ item_result_type= entry->type;
+ switch (entry->type) {
+ case REAL_RESULT:
+ set_double(*(double*)entry->value);
+ item_type= Item::REAL_ITEM;
+ item_result_type= REAL_RESULT;
+ break;
+ case INT_RESULT:
+ set_int(*(longlong*)entry->value, 21);
+ item_type= Item::INT_ITEM;
+ item_result_type= INT_RESULT;
+ break;
+ case STRING_RESULT:
+ {
+ CHARSET_INFO *fromcs= entry->collation.collation;
+ CHARSET_INFO *tocs= thd->variables.collation_connection;
+ uint32 dummy_offset;
+
+ value.cs_info.character_set_client= fromcs;
+ /*
+ Setup source and destination character sets so that they
+ are different only if conversion is necessary: this will
+ make later checks easier.
+ */
+ value.cs_info.final_character_set_of_str_value=
+ String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
+ tocs : fromcs;
+ /*
+ Exact value of max_length is not known unless data is converted to
+ charset of connection, so we have to set it later.
+ */
+ item_type= Item::STRING_ITEM;
+ item_result_type= STRING_RESULT;
+
+ if (set_str((const char *)entry->value, entry->length))
+ DBUG_RETURN(1);
+ break;
+ }
+ default:
+ DBUG_ASSERT(0);
+ set_null();
+ }
+ }
+ else
+ set_null();
+
+ DBUG_RETURN(0);
+}
+
+/*
Resets parameter after execution.
SYNOPSIS
@@ -783,21 +852,29 @@ void Item_param::reset()
str_value.free();
else
str_value.length(0);
+ str_value_ptr.length(0);
/*
- We must prevent all charset conversions unless data of str_value
- has been written to the binary log.
+ We must prevent all charset conversions untill data has been written
+ to the binary log.
*/
str_value.set_charset(&my_charset_bin);
state= NO_VALUE;
maybe_null= 1;
null_value= 0;
+ /*
+ Don't reset item_type to PARAM_ITEM: it's only needed to guard
+ us from item optimizations at prepare stage, when item doesn't yet
+ contain a literal of some kind.
+ In all other cases when this object is accessed its value is
+ set (this assumption is guarded by 'state' and
+ DBUG_ASSERTS(state != NO_VALUE) in all Item_param::get_*
+ methods).
+ */
}
int Item_param::save_in_field(Field *field, bool no_conversions)
{
- DBUG_ASSERT(current_thd->command == COM_EXECUTE);
-
field->set_notnull();
switch (state) {
@@ -837,6 +914,17 @@ bool Item_param::get_time(TIME *res)
}
+bool Item_param::get_date(TIME *res, uint fuzzydate)
+{
+ if (state == TIME_VALUE)
+ {
+ *res= value.time;
+ return 0;
+ }
+ return Item::get_date(res, fuzzydate);
+}
+
+
double Item_param::val()
{
switch (state) {
@@ -896,7 +984,7 @@ String *Item_param::val_str(String* str)
switch (state) {
case STRING_VALUE:
case LONG_DATA_VALUE:
- return &str_value;
+ return &str_value_ptr;
case REAL_VALUE:
str->set(value.real, NOT_FIXED_DEC, &my_charset_bin);
return str;
@@ -1010,6 +1098,12 @@ bool Item_param::convert_str_value(THD *thd)
}
max_length= str_value.length();
decimals= 0;
+ /*
+ str_value_ptr is returned from val_str(). It must be not alloced
+ to prevent it's modification by val_str() invoker.
+ */
+ str_value_ptr.set(str_value.ptr(), str_value.length(),
+ str_value.charset());
}
return rc;
}
@@ -2368,6 +2462,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
field_example= ((Item_field*) item)->field;
else
field_example= 0;
+ max_length= real_length(item);
collation.set(item->collation);
}
@@ -2387,6 +2482,7 @@ static Item_result type_convertor[4][4]=
bool Item_type_holder::join_types(THD *thd, Item *item)
{
+ uint32 new_length= real_length(item);
bool change_field= 0, skip_store_field= 0;
Item_result new_type= type_convertor[item_type][item->result_type()];
@@ -2412,7 +2508,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
// size/type should be changed
if (change_field ||
(new_type != item_type) ||
- (max_length < item->max_length) ||
+ (max_length < new_length) ||
((new_type == INT_RESULT) &&
(decimals < item->decimals)) ||
(!maybe_null && item->maybe_null) ||
@@ -2421,7 +2517,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
{
// new field has some parameters worse then current
skip_store_field|= (change_field &&
- (max_length > item->max_length) ||
+ (max_length > new_length) ||
((new_type == INT_RESULT) &&
(decimals > item->decimals)) ||
(maybe_null && !item->maybe_null) ||
@@ -2450,7 +2546,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
return 1;
}
- max_length= max(max_length, item->max_length);
+ max_length= max(max_length, new_length);
decimals= max(decimals, item->decimals);
maybe_null|= item->maybe_null;
item_type= new_type;
@@ -2459,6 +2555,26 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
return 0;
}
+uint32 Item_type_holder::real_length(Item *item)
+{
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ return ((Item_field *)item)->max_disp_length();
+ }
+ switch (item->result_type())
+ {
+ case STRING_RESULT:
+ return item->max_length;
+ case REAL_RESULT:
+ return 53;
+ case INT_RESULT:
+ return 20;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0); // we should never go there
+ return 0;
+ }
+}
double Item_type_holder::val()
{
diff --git a/sql/item.h b/sql/item.h
index 69a6718a5a9..a169fc32a0b 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -98,7 +98,8 @@ public:
COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM,
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM,
- SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER};
+ SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER,
+ PARAM_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
@@ -161,6 +162,31 @@ public:
/* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */
virtual double val()=0;
virtual longlong val_int()=0;
+ /*
+ Return string representation of this item object.
+
+ The argument to val_str() is an allocated buffer this or any
+ nested Item object can use to store return value of this method.
+ This buffer should only be used if the item itself doesn't have an
+ own String buffer. In case when the item maintains it's own string
+ buffer, it's preferrable to return it instead to minimize number of
+ mallocs/memcpys.
+ The caller of this method can modify returned string, but only in
+ case when it was allocated on heap, (is_alloced() is true). This
+ allows the caller to efficiently use a buffer allocated by a child
+ without having to allocate a buffer of it's own. The buffer, given
+ to val_str() as agrument, belongs to the caller and is later used
+ by the caller at it's own choosing.
+ A few implications from the above:
+ - unless you return a string object which only points to your buffer
+ but doesn't manages it you should be ready that it will be
+ modified.
+ - even for not allocated strings (is_alloced() == false) the caller
+ can change charset (see Item_func_{typecast/binary}. XXX: is this
+ a bug?
+ - still you should try to minimize data copying and return internal
+ object whenever possible.
+ */
virtual String *val_str(String*)=0;
virtual Field *get_tmp_table_field() { return 0; }
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
@@ -221,7 +247,7 @@ public:
virtual Item *real_item() { return this; }
virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
- CHARSET_INFO *default_charset() const;
+ static CHARSET_INFO *default_charset();
virtual CHARSET_INFO *compare_collation() { return NULL; }
virtual bool walk(Item_processor processor, byte *arg)
@@ -409,17 +435,11 @@ class Item_field :public Item_ident
void set_field(Field *field);
public:
Field *field,*result_field;
-#ifndef DBUG_OFF
- bool double_fix;
-#endif
Item_field(const char *db_par,const char *table_name_par,
const char *field_name_par)
:Item_ident(db_par,table_name_par,field_name_par),
field(0), result_field(0)
-#ifndef DBUG_OFF
- ,double_fix(0)
-#endif
{ collation.set(DERIVATION_IMPLICIT); }
// Constructor need to process subselect with temporary tables (see Item)
Item_field(THD *thd, Item_field *item);
@@ -459,6 +479,7 @@ public:
bool is_null() { return field->is_null(); }
Item *get_tmp_table_item(THD *thd);
void cleanup();
+ inline uint32 max_disp_length() { return field->max_length(); }
friend class Item_default_value;
friend class Item_insert_value;
friend class st_select_lex_unit;
@@ -492,19 +513,33 @@ public:
void print(String *str) { str->append("NULL", 4); }
};
+
+/* Item represents one placeholder ('?') of prepared statement */
+
class Item_param :public Item
{
-public:
+public:
enum enum_item_param_state
{
NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE,
STRING_VALUE, TIME_VALUE, LONG_DATA_VALUE
} state;
+ /*
+ A buffer for string and long data values. Historically all allocated
+ values returned from val_str() were treated as eligible to
+ modification. I. e. in some cases Item_func_concat can append it's
+ second argument to return value of the first one. Because of that we
+ can't return the original buffer holding string data from val_str(),
+ and have to have one buffer for data and another just pointing to
+ the data. This is the latter one and it's returned from val_str().
+ Can not be declared inside the union as it's not a POD type.
+ */
+ String str_value_ptr;
union
{
- longlong integer;
- double real;
+ longlong integer;
+ double real;
/*
Character sets conversion info for string values.
Character sets of client and connection defined at bind time are used
@@ -517,7 +552,7 @@ public:
/*
This points at character set of connection if conversion
to it is required (i. e. if placeholder typecode is not BLOB).
- Otherwise it's equal to character_set_client (to simplify
+ Otherwise it's equal to character_set_client (to simplify
check in convert_str_value()).
*/
CHARSET_INFO *final_character_set_of_str_value;
@@ -528,22 +563,33 @@ public:
/* Cached values for virtual methods to save us one switch. */
enum Item_result item_result_type;
enum Type item_type;
- /*
+
+ /*
+ Used when this item is used in a temporary table.
+ This is NOT placeholder metadata sent to client, as this value
+ is assigned after sending metadata (in setup_one_conversion_function).
+ For example in case of 'SELECT ?' you'll get MYSQL_TYPE_STRING both
+ in result set and placeholders metadata, no matter what type you will
+ supply for this placeholder in mysql_stmt_execute.
+ */
+ enum enum_field_types param_type;
+ /*
Offset of placeholder inside statement text. Used to create
no-placeholders version of this statement for the binary log.
- */
+ */
uint pos_in_query;
Item_param(uint pos_in_query_arg);
enum Item_result result_type () const { return item_result_type; }
enum Type type() const { return item_type; }
- enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ enum_field_types field_type() const { return param_type; }
double val();
longlong val_int();
String *val_str(String*);
bool get_time(TIME *tm);
+ bool get_date(TIME *tm, uint fuzzydate);
int save_in_field(Field *field, bool no_conversions);
void set_null();
@@ -552,6 +598,7 @@ public:
bool set_str(const char *str, ulong length);
bool set_longdata(const char *str, ulong length);
void set_time(TIME *tm, timestamp_type type, uint32 max_length_arg);
+ bool set_from_user_var(THD *thd, const user_var_entry *entry);
void reset();
/*
Assign placeholder value from bind data.
@@ -564,16 +611,18 @@ public:
const String *query_val_str(String *str) const;
bool convert_str_value(THD *thd);
-
+
Item *new_item() { return new Item_param(pos_in_query); }
- /*
- If value for parameter was not set we treat it as non-const
- so noone will use parameters value in fix_fields still
+ /*
+ If value for parameter was not set we treat it as non-const
+ so noone will use parameters value in fix_fields still
parameter is constant during execution.
*/
virtual table_map used_tables() const
{ return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; }
void print(String *str) { str->append('?'); }
+ /* parameter never equal to other parameter of other item */
+ bool eq(const Item *item, bool binary_cmp) const { return 0; }
};
class Item_int :public Item_num
@@ -871,7 +920,10 @@ public:
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(); }
- table_map used_tables() const { return (*ref)->used_tables(); }
+ table_map used_tables() const
+ {
+ return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables();
+ }
void set_result_field(Field *field) { result_field= field; }
bool is_result_field() { return 1; }
void save_in_result_field(bool no_conversions)
@@ -1250,6 +1302,7 @@ public:
String *val_str(String*);
bool join_types(THD *thd, Item *);
Field *example() { return field_example; }
+ static uint32 real_length(Item *item);
void cleanup()
{
DBUG_ENTER("Item_type_holder::cleanup");
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 446d72ac143..91257c31fb9 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -922,8 +922,8 @@ Item_func_if::fix_length_and_dec()
decimals=max(args[1]->decimals,args[2]->decimals);
enum Item_result arg1_type=args[1]->result_type();
enum Item_result arg2_type=args[2]->result_type();
- bool null1=args[1]->null_value;
- bool null2=args[2]->null_value;
+ bool null1=args[1]->const_item() && args[1]->null_value;
+ bool null2=args[2]->const_item() && args[2]->null_value;
if (null1)
{
@@ -2151,49 +2151,62 @@ Item_func::optimize_type Item_func_like::select_optimize() const
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
DBUG_ASSERT(fixed == 0);
- if (Item_bool_func2::fix_fields(thd, tlist, ref))
+ if (Item_bool_func2::fix_fields(thd, tlist, ref) ||
+ escape_item->fix_fields(thd, tlist, &escape_item))
return 1;
- /*
- We could also do boyer-more for non-const items, but as we would have to
- recompute the tables for each row it's not worth it.
- */
- if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
- !(specialflag & SPECIAL_NO_NEW_FUNC))
+ if (!escape_item->const_during_execution())
{
- String* res2 = args[1]->val_str(&tmp_value2);
- if (!res2)
- return 0; // Null argument
-
- const size_t len = res2->length();
- const char* first = res2->ptr();
- const char* last = first + len - 1;
+ my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
+ return 1;
+ }
+
+ if (escape_item->const_item())
+ {
+ /* If we are on execution stage */
+ String *escape_str= escape_item->val_str(&tmp_value1);
+ escape= escape_str ? *(escape_str->ptr()) : '\\';
+
/*
- len must be > 2 ('%pattern%')
- heuristic: only do TurboBM for pattern_len > 2
+ We could also do boyer-more for non-const items, but as we would have to
+ recompute the tables for each row it's not worth it.
*/
-
- if (len > MIN_TURBOBM_PATTERN_LEN + 2 &&
- *first == wild_many &&
- *last == wild_many)
- {
- const char* tmp = first + 1;
- for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
- canDoTurboBM = (tmp == last) && !use_mb(args[0]->collation.collation);
- }
-
- if (canDoTurboBM)
+ if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
+ !(specialflag & SPECIAL_NO_NEW_FUNC))
{
- pattern = first + 1;
- pattern_len = len - 2;
- DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
- int *suff = (int*) thd->alloc(sizeof(int)*((pattern_len + 1)*2+
- alphabet_size));
- bmGs = suff + pattern_len + 1;
- bmBc = bmGs + pattern_len + 1;
- turboBM_compute_good_suffix_shifts(suff);
- turboBM_compute_bad_character_shifts();
- DBUG_PRINT("info",("done"));
+ String* res2 = args[1]->val_str(&tmp_value2);
+ if (!res2)
+ return 0; // Null argument
+
+ const size_t len = res2->length();
+ const char* first = res2->ptr();
+ const char* last = first + len - 1;
+ /*
+ len must be > 2 ('%pattern%')
+ heuristic: only do TurboBM for pattern_len > 2
+ */
+
+ if (len > MIN_TURBOBM_PATTERN_LEN + 2 &&
+ *first == wild_many &&
+ *last == wild_many)
+ {
+ const char* tmp = first + 1;
+ for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
+ canDoTurboBM = (tmp == last) && !use_mb(args[0]->collation.collation);
+ }
+ if (canDoTurboBM)
+ {
+ pattern = first + 1;
+ pattern_len = len - 2;
+ DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
+ int *suff = (int*) thd->alloc(sizeof(int)*((pattern_len + 1)*2+
+ alphabet_size));
+ bmGs = suff + pattern_len + 1;
+ bmBc = bmGs + pattern_len + 1;
+ turboBM_compute_good_suffix_shifts(suff);
+ turboBM_compute_bad_character_shifts();
+ DBUG_PRINT("info",("done"));
+ }
}
}
return 0;
@@ -2298,15 +2311,19 @@ longlong Item_func_regex::val_int()
}
-Item_func_regex::~Item_func_regex()
+void Item_func_regex::cleanup()
{
+ DBUG_ENTER("Item_func_regex::cleanup");
+ Item_bool_func::cleanup();
if (regex_compiled)
{
regfree(&preg);
regex_compiled=0;
}
+ DBUG_VOID_RETURN;
}
+
#endif /* USE_REGEX */
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 2288a99c55f..23ac82e79e6 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -875,12 +875,14 @@ class Item_func_like :public Item_bool_func2
bool turboBM_matches(const char* text, int text_len) const;
enum { alphabet_size = 256 };
+ Item *escape_item;
+
public:
char escape;
- Item_func_like(Item *a,Item *b, char* escape_arg)
+ Item_func_like(Item *a,Item *b, Item *escape_arg)
:Item_bool_func2(a,b), canDoTurboBM(false), pattern(0), pattern_len(0),
- bmGs(0), bmBc(0), escape(*escape_arg) {}
+ bmGs(0), bmBc(0), escape_item(escape_arg) {}
longlong val_int();
enum Functype functype() const { return LIKE_FUNC; }
optimize_type select_optimize() const;
@@ -903,7 +905,7 @@ class Item_func_regex :public Item_bool_func
public:
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
regex_compiled(0),regex_is_const(0) {}
- ~Item_func_regex();
+ void cleanup();
longlong val_int();
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
const char *func_name() const { return "regexp"; }
diff --git a/sql/item_create.cc b/sql/item_create.cc
index e314bfc3e2c..e2c85af49bc 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -85,6 +85,11 @@ Item *create_func_conv(Item* a, Item *b, Item *c)
return new Item_func_conv(a,b,c);
}
+Item *create_func_convert_tz(Item* a, Item *b, Item *c)
+{
+ return new Item_func_convert_tz(a,b,c);
+}
+
Item *create_func_cos(Item* a)
{
return new Item_func_cos(a);
@@ -145,7 +150,7 @@ Item *create_func_found_rows(void)
{
THD *thd=current_thd;
thd->lex->safe_to_cache_query= 0;
- return new Item_int(NullS,(longlong) thd->found_rows(),21);
+ return new Item_func_found_rows();
}
Item *create_func_from_days(Item* a)
@@ -364,7 +369,7 @@ Item *create_func_space(Item *a)
CHARSET_INFO *cs= current_thd->variables.collation_connection;
Item *sp;
- if (cs->state & MY_CS_NONTEXT)
+ if (cs->mbminlen > 1)
{
sp= new Item_string("",0,cs);
if (sp)
diff --git a/sql/item_create.h b/sql/item_create.h
index d48aed5284a..18c5b3239f3 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -31,6 +31,7 @@ Item *create_func_char_length(Item* a);
Item *create_func_cast(Item *a, Cast_target cast_type, int len, CHARSET_INFO *cs);
Item *create_func_connection_id(void);
Item *create_func_conv(Item* a, Item *b, Item *c);
+Item *create_func_convert_tz(Item* a, Item *b, Item *c);
Item *create_func_cos(Item* a);
Item *create_func_cot(Item* a);
Item *create_func_crc32(Item* a);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ac7025a391a..c2c93586af8 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2593,27 +2593,39 @@ longlong Item_func_get_user_var::val_int()
/*
+ Get variable by name and, if necessary, put the record of variable
+ use into the binary log.
+
+ SYNOPSIS
+ get_var_with_binlog()
+ thd Current thread
+ name Variable name
+ out_entry [out] variable structure or NULL. The pointer is set
+ regardless of whether function succeeded or not.
+
When a user variable is invoked from an update query (INSERT, UPDATE etc),
stores this variable and its value in thd->user_var_events, so that it can be
written to the binlog (will be written just before the query is written, see
log.cc).
+
+ RETURN
+ 0 OK
+ 1 Failed to put appropiate record into binary log
+
*/
-void Item_func_get_user_var::fix_length_and_dec()
+int get_var_with_binlog(THD *thd, LEX_STRING &name,
+ user_var_entry **out_entry)
{
- THD *thd=current_thd;
BINLOG_USER_VAR_EVENT *user_var_event;
- maybe_null=1;
- decimals=NOT_FIXED_DEC;
- max_length=MAX_BLOB_WIDTH;
-
- if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
- null_value= 1;
- else
- collation.set(var_entry->collation);
+ user_var_entry *var_entry;
+ var_entry= get_variable(&thd->user_vars, name, 0);
if (!(opt_bin_log && is_update_query(thd->lex->sql_command)))
- return;
+ {
+ *out_entry= var_entry;
+ return 0;
+ }
if (!var_entry)
{
@@ -2640,13 +2652,16 @@ void Item_func_get_user_var::fix_length_and_dec()
if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
goto err;
}
- /*
- If this variable was already stored in user_var_events by this query
- (because it's used in more than one place in the query), don't store
- it.
- */
else if (var_entry->used_query_id == thd->query_id)
- return;
+ {
+ /*
+ If this variable was already stored in user_var_events by this query
+ (because it's used in more than one place in the query), don't store
+ it.
+ */
+ *out_entry= var_entry;
+ return 0;
+ }
uint size;
/*
@@ -2681,11 +2696,34 @@ void Item_func_get_user_var::fix_length_and_dec()
var_entry->used_query_id= thd->query_id;
if (insert_dynamic(&thd->user_var_events, (gptr) &user_var_event))
goto err;
-
- return;
+
+ *out_entry= var_entry;
+ return 0;
err:
- thd->fatal_error();
+ *out_entry= var_entry;
+ return 1;
+}
+
+
+void Item_func_get_user_var::fix_length_and_dec()
+{
+ THD *thd=current_thd;
+ int error;
+ maybe_null=1;
+ decimals=NOT_FIXED_DEC;
+ max_length=MAX_BLOB_WIDTH;
+
+ error= get_var_with_binlog(thd, name, &var_entry);
+
+ if (var_entry)
+ collation.set(var_entry->collation);
+ else
+ null_value= 1;
+
+ if (error)
+ thd->fatal_error();
+
return;
}
@@ -3168,7 +3206,6 @@ longlong Item_func_is_free_lock::val_int()
{
DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
- THD *thd=current_thd;
User_level_lock *ull;
null_value=0;
@@ -3191,7 +3228,6 @@ longlong Item_func_is_used_lock::val_int()
{
DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
- THD *thd=current_thd;
User_level_lock *ull;
null_value=1;
@@ -3339,3 +3375,12 @@ Item_func_sp::fix_length_and_dec()
}
DBUG_VOID_RETURN;
}
+
+
+longlong Item_func_found_rows::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ THD *thd= current_thd;
+
+ return thd->found_rows();
+}
diff --git a/sql/item_func.h b/sql/item_func.h
index 1d945af35b2..8636bcd6507 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1151,3 +1151,13 @@ public:
void fix_length_and_dec();
};
+
+
+class Item_func_found_rows :public Item_int_func
+{
+public:
+ Item_func_found_rows() :Item_int_func() {}
+ longlong val_int();
+ const char *func_name() const { return "found_rows"; }
+ void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 676d8c1386a..b0c685c1c46 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -950,17 +950,10 @@ String *Item_func_left::val_str(String *str)
return 0;
if (length <= 0)
return &my_empty_string;
- length= res->charpos(length);
- if (res->length() > (ulong) length)
- { // Safe even if const arg
- if (!res->alloced_length())
- { // Don't change const str
- str_value= *res; // Not malloced string
- res= &str_value;
- }
- res->length((uint) length);
- }
- return res;
+ if (res->length() <= (uint) length)
+ return res;
+ str_value.set(*res, 0, res->charpos(length));
+ return &str_value;
}
@@ -1461,6 +1454,7 @@ void Item_func_encode::fix_length_and_dec()
{
max_length=args[0]->max_length;
maybe_null=args[0]->maybe_null;
+ collation.set(&my_charset_bin);
}
String *Item_func_encode::val_str(String *str)
@@ -1476,6 +1470,7 @@ String *Item_func_encode::val_str(String *str)
res=copy_if_not_alloced(str,res,res->length());
sql_crypt.init();
sql_crypt.encode((char*) res->ptr(),res->length());
+ res->set_charset(&my_charset_bin);
return res;
}
@@ -2097,10 +2092,8 @@ String *Item_func_lpad::val_str(String *str)
count-= pad_char_length;
}
if (count > 0)
- {
- pad->length(pad->charpos(count));
- str->append(*pad);
- }
+ str->append(pad->ptr(), pad->charpos(count), collation.collation);
+
str->append(*res);
null_value= 0;
return str;
@@ -2285,8 +2278,8 @@ String *Item_func_hex::val_str(String *str)
from++, to+=2)
{
uint tmp=(uint) (uchar) *from;
- to[0]=_dig_vec[tmp >> 4];
- to[1]=_dig_vec[tmp & 15];
+ to[0]=_dig_vec_upper[tmp >> 4];
+ to[1]=_dig_vec_upper[tmp & 15];
}
return &tmp_value;
}
@@ -2746,9 +2739,6 @@ static uint nanoseq;
static ulonglong uuid_time=0;
static char clock_seq_and_node_str[]="-0000-000000000000";
-/* we cannot use _dig_vec[] as letters should be lowercase */
-static const char hex[] = "0123456789abcdef";
-
/* number of 100-nanosecond intervals between
1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00 */
#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * 1000 * 10 )
@@ -2761,7 +2751,7 @@ static void tohex(char *to, uint from, uint len)
to+= len;
while (len--)
{
- *--to= hex[from & 15];
+ *--to= _dig_vec_lower[from & 15];
from >>= 4;
}
}
@@ -2798,8 +2788,8 @@ String *Item_func_uuid::val_str(String *str)
s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1;
for (i=sizeof(mac)-1 ; i>=0 ; i--)
{
- *--s=hex[mac[i] & 15];
- *--s=hex[mac[i] >> 4];
+ *--s=_dig_vec_lower[mac[i] & 15];
+ *--s=_dig_vec_lower[mac[i] >> 4];
}
randominit(&uuid_rand, tmp + (ulong)start_time, tmp + bytes_sent);
set_clock_seq_str();
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 48d38c0d602..91a31502780 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -74,6 +74,11 @@ void Item_subselect::init(st_select_lex *select_lex,
else
engine= new subselect_single_select_engine(select_lex, result, this);
}
+ {
+ SELECT_LEX *upper= unit->outer_select();
+ if (upper->parsing_place == SELECT_LEX_NODE::IN_HAVING)
+ upper->subquery_in_having= 1;
+ }
DBUG_VOID_RETURN;
}
@@ -657,7 +662,6 @@ Item_in_subselect::single_value_transformer(JOIN *join,
!(select_lex->next_select()))
{
Item *item;
- subs_type type= substype();
if (func->l_op())
{
/*
@@ -1183,7 +1187,7 @@ int subselect_single_select_engine::exec()
join->thd->where= save_where;
executed= 1;
join->thd->lex->current_select= save_select;
- DBUG_RETURN(join->error?join->error:1);
+ DBUG_RETURN(join->error ? join->error : 1);
}
if (item->engine_changed)
{
@@ -1235,6 +1239,8 @@ int subselect_uniquesubquery_engine::exec()
}
else
{
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->ref.key);
error= table->file->index_read(table->record[0],
tab->ref.key_buff,
tab->ref.key_length,HA_READ_KEY_EXACT);
@@ -1256,7 +1262,7 @@ int subselect_uniquesubquery_engine::exec()
subselect_uniquesubquery_engine::~subselect_uniquesubquery_engine()
{
/* Tell handler we don't need the index anymore */
- tab->table->file->index_end();
+ tab->table->file->ha_index_end();
}
@@ -1283,6 +1289,8 @@ int subselect_indexsubquery_engine::exec()
}
else
{
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->ref.key);
error= table->file->index_read(table->record[0],
tab->ref.key_buff,
tab->ref.key_length,HA_READ_KEY_EXACT);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 3275440e522..50864132932 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -477,6 +477,16 @@ longlong Item_sum_count::val_int()
return (longlong) count;
}
+
+void Item_sum_count::cleanup()
+{
+ DBUG_ENTER("Item_sum_count::cleanup");
+ Item_sum_int::cleanup();
+ used_table_cache= ~(table_map) 0;
+ DBUG_VOID_RETURN;
+}
+
+
/*
Avgerage
*/
@@ -691,6 +701,15 @@ Item_sum_hybrid::val_str(String *str)
}
+void Item_sum_hybrid::cleanup()
+{
+ DBUG_ENTER("Item_sum_hybrid::cleanup");
+ Item_sum::cleanup();
+ used_table_cache= ~(table_map) 0;
+ DBUG_VOID_RETURN;
+}
+
+
Item *Item_sum_min::copy_or_same(THD* thd)
{
return new (&thd->mem_root) Item_sum_min(thd, this);
@@ -1777,6 +1796,9 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
String tmp((char *)&buff,sizeof(buff),default_charset_info), tmp2;
char *record= (char*) item->table->record[0];
+ if (item->result.length())
+ item->result.append(*item->separator);
+
tmp.length(0);
for (uint i= 0; i < item->arg_count_field; i++)
@@ -1806,14 +1828,6 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
item->result.append(*res);
}
}
- if (item->tree_mode) // Last item of tree
- {
- item->show_elements++;
- if (item->show_elements < item->tree->elements_in_tree)
- item->result.append(*item->separator);
- }
- else
- item->result.append(*item->separator);
/* stop if length of result more than group_concat_max_len */
if (item->result.length() > item->group_concat_max_len)
@@ -1844,7 +1858,7 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
tree_mode(0), distinct(is_distinct), warning_for_row(0),
separator(is_separator), tree(&tree_base), table(0),
order(0), tables_list(0),
- show_elements(0), arg_count_order(0), arg_count_field(0),
+ arg_count_order(0), arg_count_field(0),
count_cut_values(0)
{
Item *item_select;
@@ -1910,7 +1924,6 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
order(item->order),
tables_list(item->tables_list),
group_concat_max_len(item->group_concat_max_len),
- show_elements(item->show_elements),
arg_count_order(item->arg_count_order),
arg_count_field(item->arg_count_field),
field_list_offset(item->field_list_offset),
@@ -2218,15 +2231,9 @@ String* Item_func_group_concat::val_str(String* str)
return 0;
if (tree_mode)
{
- show_elements= 0;
tree_walk(tree, (tree_walk_action)&dump_leaf_key, (void*)this,
left_root_right);
}
- else
- {
- if (!warning_for_row)
- result.length(result.length()-separator->length());
- }
if (count_cut_values && !warning_available)
{
warning_available= TRUE;
diff --git a/sql/item_sum.h b/sql/item_sum.h
index ce46e92e6cf..2dde6f73425 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -207,6 +207,7 @@ class Item_sum_count :public Item_sum_int
void make_const(longlong count_arg) { count=count_arg; used_table_cache=0; }
longlong val_int();
void reset_field();
+ void cleanup();
void update_field();
const char *func_name() const { return "count"; }
Item *copy_or_same(THD* thd);
@@ -463,6 +464,7 @@ class Item_sum_hybrid :public Item_sum
void min_max_update_str_field();
void min_max_update_real_field();
void min_max_update_int_field();
+ void cleanup();
};
@@ -729,7 +731,6 @@ class Item_func_group_concat : public Item_sum
ORDER **order;
TABLE_LIST *tables_list;
ulong group_concat_max_len;
- uint show_elements;
uint arg_count_order;
uint arg_count_field;
uint field_list_offset;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 39f67ba24f8..3baf55abc0c 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -425,21 +425,21 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
str->append(month_names[l_time->month-1],3);
break;
case 'W':
- if (type == TIMESTAMP_TIME)
+ if (type == MYSQL_TIMESTAMP_TIME)
return 1;
weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
l_time->day),0);
str->append(day_names[weekday]);
break;
case 'a':
- if (type == TIMESTAMP_TIME)
+ if (type == MYSQL_TIMESTAMP_TIME)
return 1;
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
l_time->day),0);
str->append(day_names[weekday],3);
break;
case 'D':
- if (type == TIMESTAMP_TIME)
+ if (type == MYSQL_TIMESTAMP_TIME)
return 1;
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
str->append_with_prefill(intbuff, length, 1, '0');
@@ -507,7 +507,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'j':
- if (type == TIMESTAMP_TIME)
+ if (type == MYSQL_TIMESTAMP_TIME)
return 1;
length= int10_to_str(calc_daynr(l_time->year,l_time->month,
l_time->day) -
@@ -555,7 +555,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
case 'u':
{
uint year;
- if (type == TIMESTAMP_TIME)
+ if (type == MYSQL_TIMESTAMP_TIME)
return 1;
length= int10_to_str(calc_week(l_time,
(*ptr) == 'U' ?
@@ -569,7 +569,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
case 'V':
{
uint year;
- if (type == TIMESTAMP_TIME)
+ if (type == MYSQL_TIMESTAMP_TIME)
return 1;
length= int10_to_str(calc_week(l_time,
((*ptr) == 'V' ?
@@ -584,7 +584,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
case 'X':
{
uint year;
- if (type == TIMESTAMP_TIME)
+ if (type == MYSQL_TIMESTAMP_TIME)
return 1;
(void) calc_week(l_time,
((*ptr) == 'X' ?
@@ -596,7 +596,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
}
break;
case 'w':
- if (type == TIMESTAMP_TIME)
+ if (type == MYSQL_TIMESTAMP_TIME)
return 1;
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
l_time->day),1);
@@ -894,6 +894,9 @@ longlong Item_func_year::val_int()
longlong Item_func_unix_timestamp::val_int()
{
+ TIME ltime;
+ bool not_used;
+
DBUG_ASSERT(fixed == 1);
if (arg_count == 0)
return (longlong) current_thd->query_start();
@@ -903,12 +906,19 @@ longlong Item_func_unix_timestamp::val_int()
if (field->type() == FIELD_TYPE_TIMESTAMP)
return ((Field_timestamp*) field)->get_timestamp();
}
- String *str=args[0]->val_str(&value);
- if ((null_value=args[0]->null_value))
+
+ if (get_arg0_date(&ltime, 0))
{
- return 0; /* purecov: inspected */
+ /*
+ We have to set null_value again because get_arg0_date will also set it
+ to true if we have wrong datetime parameter (and we should return 0 in
+ this case).
+ */
+ null_value= args[0]->null_value;
+ return 0;
}
- return (longlong) str_to_timestamp(str->ptr(),str->length());
+
+ return (longlong) TIME_to_timestamp(current_thd, &ltime, &not_used);
}
@@ -1103,7 +1113,7 @@ int Item_date::save_in_field(Field *field, bool no_conversions)
if (get_date(&ltime, TIME_FUZZY_DATE))
return set_field_to_null(field);
field->set_notnull();
- field->store_time(&ltime, TIMESTAMP_DATE);
+ field->store_time(&ltime, MYSQL_TIMESTAMP_DATE);
return 0;
}
@@ -1125,31 +1135,22 @@ bool Item_func_from_days::get_date(TIME *ltime, uint fuzzy_date)
return 1;
bzero(ltime, sizeof(TIME));
get_date_from_daynr((long) value, &ltime->year, &ltime->month, &ltime->day);
- ltime->time_type= TIMESTAMP_DATE;
+ ltime->time_type= MYSQL_TIMESTAMP_DATE;
return 0;
}
void Item_func_curdate::fix_length_and_dec()
{
- struct tm start;
-
collation.set(&my_charset_bin);
decimals=0;
max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
- store_now_in_tm(current_thd->query_start(),&start);
+ store_now_in_TIME(&ltime);
- /* For getdate */
- ltime.year= start.tm_year+1900;
- ltime.month= start.tm_mon+1;
- ltime.day= start.tm_mday;
- ltime.hour= 0;
- ltime.minute= 0;
- ltime.second= 0;
- ltime.second_part=0;
- ltime.neg=0;
- ltime.time_type=TIMESTAMP_DATE;
+ /* We don't need to set second_part and neg because they already 0 */
+ ltime.hour= ltime.minute= ltime.second= 0;
+ ltime.time_type= MYSQL_TIMESTAMP_DATE;
value= (longlong) TIME_to_ulonglong_date(&ltime);
}
@@ -1165,31 +1166,39 @@ String *Item_func_curdate::val_str(String *str)
return str;
}
-bool Item_func_curdate::get_date(TIME *res,
- uint fuzzy_date __attribute__((unused)))
+/*
+ Converts current time in my_time_t to TIME represenatation for local
+ time zone. Defines time zone (local) used for whole CURDATE function.
+*/
+void Item_func_curdate_local::store_now_in_TIME(TIME *now_time)
{
- *res=ltime;
- return 0;
+ THD *thd= current_thd;
+ thd->variables.time_zone->gmt_sec_to_TIME(now_time,
+ (my_time_t)thd->query_start());
+ thd->time_zone_used= 1;
}
/*
- Converts time in time_t to struct tm represenatation for local timezone.
- Defines timezone (local) used for whole CURDATE function
+ Converts current time in my_time_t to TIME represenatation for UTC
+ time zone. Defines time zone (UTC) used for whole UTC_DATE function.
*/
-void Item_func_curdate_local::store_now_in_tm(time_t now, struct tm *now_tm)
+void Item_func_curdate_utc::store_now_in_TIME(TIME *now_time)
{
- localtime_r(&now,now_tm);
+ my_tz_UTC->gmt_sec_to_TIME(now_time,
+ (my_time_t)(current_thd->query_start()));
+ /*
+ We are not flagging this query as using time zone, since it uses fixed
+ UTC-SYSTEM time-zone.
+ */
}
-/*
- Converts time in time_t to struct tm represenatation for UTC
- Defines timezone (UTC) used for whole UTC_DATE function
-*/
-void Item_func_curdate_utc::store_now_in_tm(time_t now, struct tm *now_tm)
+bool Item_func_curdate::get_date(TIME *res,
+ uint fuzzy_date __attribute__((unused)))
{
- gmtime_r(&now,now_tm);
+ *res=ltime;
+ return 0;
}
@@ -1203,17 +1212,12 @@ String *Item_func_curtime::val_str(String *str)
void Item_func_curtime::fix_length_and_dec()
{
- struct tm start;
- String tmp((char*) buff,sizeof(buff), &my_charset_bin);
TIME ltime;
+ String tmp((char*) buff,sizeof(buff), &my_charset_bin);
- decimals=0;
- store_now_in_tm(current_thd->query_start(),&start);
- ltime.hour= start.tm_hour;
- ltime.minute= start.tm_min;
- ltime.second= start.tm_sec;
- ltime.second_part= 0;
- ltime.neg= 0;
+ decimals=0;
+ collation.set(&my_charset_bin);
+ store_now_in_TIME(&ltime);
value= TIME_to_ulonglong_time(&ltime);
make_time((DATE_TIME_FORMAT *) 0, &ltime, &tmp);
max_length= buff_length= tmp.length();
@@ -1221,22 +1225,30 @@ void Item_func_curtime::fix_length_and_dec()
/*
- Converts time in time_t to struct tm represenatation for local timezone.
- Defines timezone (local) used for whole CURTIME function
+ Converts current time in my_time_t to TIME represenatation for local
+ time zone. Defines time zone (local) used for whole CURTIME function.
*/
-void Item_func_curtime_local::store_now_in_tm(time_t now, struct tm *now_tm)
+void Item_func_curtime_local::store_now_in_TIME(TIME *now_time)
{
- localtime_r(&now,now_tm);
+ THD *thd= current_thd;
+ thd->variables.time_zone->gmt_sec_to_TIME(now_time,
+ (my_time_t)thd->query_start());
+ thd->time_zone_used= 1;
}
/*
- Converts time in time_t to struct tm represenatation for UTC.
- Defines timezone (UTC) used for whole UTC_TIME function
+ Converts current time in my_time_t to TIME represenatation for UTC
+ time zone. Defines time zone (UTC) used for whole UTC_TIME function.
*/
-void Item_func_curtime_utc::store_now_in_tm(time_t now, struct tm *now_tm)
+void Item_func_curtime_utc::store_now_in_TIME(TIME *now_time)
{
- gmtime_r(&now,now_tm);
+ my_tz_UTC->gmt_sec_to_TIME(now_time,
+ (my_time_t)(current_thd->query_start()));
+ /*
+ We are not flagging this query as using time zone, since it uses fixed
+ UTC-SYSTEM time-zone.
+ */
}
@@ -1250,18 +1262,12 @@ String *Item_func_now::val_str(String *str)
void Item_func_now::fix_length_and_dec()
{
- struct tm start;
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
decimals=0;
collation.set(&my_charset_bin);
- store_now_in_tm(current_thd->query_start(),&start);
-
- /* For getdate */
- localtime_to_TIME(&ltime, &start);
- ltime.time_type= TIMESTAMP_DATETIME;
-
+ store_now_in_TIME(&ltime);
value= (longlong) TIME_to_ulonglong_datetime(&ltime);
make_datetime((DATE_TIME_FORMAT *) 0, &ltime, &tmp);
@@ -1269,39 +1275,47 @@ void Item_func_now::fix_length_and_dec()
}
-bool Item_func_now::get_date(TIME *res,
- uint fuzzy_date __attribute__((unused)))
+/*
+ Converts current time in my_time_t to TIME represenatation for local
+ time zone. Defines time zone (local) used for whole NOW function.
+*/
+void Item_func_now_local::store_now_in_TIME(TIME *now_time)
{
- *res=ltime;
- return 0;
+ THD *thd= current_thd;
+ thd->variables.time_zone->gmt_sec_to_TIME(now_time,
+ (my_time_t)thd->query_start());
+ thd->time_zone_used= 1;
}
-int Item_func_now::save_in_field(Field *to, bool no_conversions)
+/*
+ Converts current time in my_time_t to TIME represenatation for UTC
+ time zone. Defines time zone (UTC) used for whole UTC_TIMESTAMP function.
+*/
+void Item_func_now_utc::store_now_in_TIME(TIME *now_time)
{
- to->set_notnull();
- to->store_time(&ltime,TIMESTAMP_DATETIME);
- return 0;
+ my_tz_UTC->gmt_sec_to_TIME(now_time,
+ (my_time_t)(current_thd->query_start()));
+ /*
+ We are not flagging this query as using time zone, since it uses fixed
+ UTC-SYSTEM time-zone.
+ */
}
-/*
- Converts time in time_t to struct tm represenatation for local timezone.
- Defines timezone (local) used for whole CURRENT_TIMESTAMP function
-*/
-void Item_func_now_local::store_now_in_tm(time_t now, struct tm *now_tm)
+bool Item_func_now::get_date(TIME *res,
+ uint fuzzy_date __attribute__((unused)))
{
- localtime_r(&now,now_tm);
+ *res=ltime;
+ return 0;
}
-/*
- Converts time in time_t to struct tm represenatation for UTC.
- Defines timezone (UTC) used for whole UTC_TIMESTAMP function
-*/
-void Item_func_now_utc::store_now_in_tm(time_t now, struct tm *now_tm)
+int Item_func_now::save_in_field(Field *to, bool no_conversions)
{
- gmtime_r(&now,now_tm);
+ to->set_notnull();
+ to->store_time(&ltime, MYSQL_TIMESTAMP_DATETIME);
+ return 0;
}
@@ -1461,7 +1475,7 @@ String *Item_func_date_format::val_str(String *str)
{
String *res;
if (!(res=args[0]->val_str(str)) ||
- (str_to_time(res->ptr(),res->length(),&l_time)))
+ (str_to_time_with_warn(res->ptr(), res->length(), &l_time)))
goto null_date;
l_time.year=l_time.month=l_time.day=0;
@@ -1486,7 +1500,9 @@ String *Item_func_date_format::val_str(String *str)
/* Create the result string */
if (!make_date_time(&date_time_format, &l_time,
- is_time_format ? TIMESTAMP_TIME : TIMESTAMP_DATE, str))
+ is_time_format ? MYSQL_TIMESTAMP_TIME :
+ MYSQL_TIMESTAMP_DATE,
+ str))
return str;
null_date:
@@ -1495,24 +1511,31 @@ null_date:
}
+void Item_func_from_unixtime::fix_length_and_dec()
+{
+ thd= current_thd;
+ collation.set(&my_charset_bin);
+ decimals=0;
+ max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
+ thd->time_zone_used= 1;
+}
+
+
String *Item_func_from_unixtime::val_str(String *str)
{
- struct tm tm_tmp;
- time_t tmp;
- TIME ltime;
+ TIME time_tmp;
+ my_time_t tmp;
DBUG_ASSERT(fixed == 1);
tmp= (time_t) args[0]->val_int();
if ((null_value=args[0]->null_value))
goto null_date;
-
- localtime_r(&tmp,&tm_tmp);
-
- localtime_to_TIME(&ltime, &tm_tmp);
-
+
+ thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, tmp);
+
if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN))
goto null_date;
- make_datetime((DATE_TIME_FORMAT *) 0, &ltime, str);
+ make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
return str;
null_date:
@@ -1523,28 +1546,109 @@ null_date:
longlong Item_func_from_unixtime::val_int()
{
- TIME ltime;
- struct tm tm_tmp;
- time_t tmp;
+ TIME time_tmp;
+ my_time_t tmp;
+
DBUG_ASSERT(fixed == 1);
tmp= (time_t) (ulong) args[0]->val_int();
if ((null_value=args[0]->null_value))
return 0;
- localtime_r(&tmp,&tm_tmp);
- localtime_to_TIME(&ltime, &tm_tmp);
- return (longlong) TIME_to_ulonglong_datetime(&ltime);
+
+ current_thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, tmp);
+
+ return (longlong) TIME_to_ulonglong_datetime(&time_tmp);
}
bool Item_func_from_unixtime::get_date(TIME *ltime,
uint fuzzy_date __attribute__((unused)))
{
- time_t tmp=(time_t) (ulong) args[0]->val_int();
+ my_time_t tmp=(my_time_t) args[0]->val_int();
if ((null_value=args[0]->null_value))
return 1;
- struct tm tm_tmp;
- localtime_r(&tmp,&tm_tmp);
- localtime_to_TIME(ltime, &tm_tmp);
+
+ current_thd->variables.time_zone->gmt_sec_to_TIME(ltime, tmp);
+
+ return 0;
+}
+
+
+void Item_func_convert_tz::fix_length_and_dec()
+{
+ String str;
+
+ thd= current_thd;
+ collation.set(&my_charset_bin);
+ decimals= 0;
+ max_length= MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
+
+ if (args[1]->const_item())
+ from_tz= my_tz_find(thd, args[1]->val_str(&str));
+
+ if (args[2]->const_item())
+ to_tz= my_tz_find(thd, args[2]->val_str(&str));
+}
+
+
+String *Item_func_convert_tz::val_str(String *str)
+{
+ TIME time_tmp;
+
+ if (get_date(&time_tmp, 0))
+ return 0;
+
+ if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN))
+ {
+ null_value= 1;
+ return 0;
+ }
+
+ make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
+ return str;
+}
+
+
+longlong Item_func_convert_tz::val_int()
+{
+ TIME time_tmp;
+
+ if (get_date(&time_tmp, 0))
+ return 0;
+
+ return (longlong)TIME_to_ulonglong_datetime(&time_tmp);
+}
+
+
+bool Item_func_convert_tz::get_date(TIME *ltime,
+ uint fuzzy_date __attribute__((unused)))
+{
+ my_time_t my_time_tmp;
+ bool not_used;
+ String str;
+
+ if (!args[1]->const_item())
+ from_tz= my_tz_find(thd, args[1]->val_str(&str));
+
+ if (!args[2]->const_item())
+ to_tz= my_tz_find(thd, args[2]->val_str(&str));
+
+ if (from_tz==0 || to_tz==0 || get_arg0_date(ltime, 0))
+ {
+ null_value= 1;
+ return 1;
+ }
+
+ /* Check if we in range where we treat datetime values as non-UTC */
+ if (ltime->year < TIMESTAMP_MAX_YEAR && ltime->year > TIMESTAMP_MIN_YEAR ||
+ ltime->year==TIMESTAMP_MAX_YEAR && ltime->month==1 && ltime->day==1 ||
+ ltime->year==TIMESTAMP_MIN_YEAR && ltime->month==12 && ltime->day==31)
+ {
+ my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, &not_used);
+ if (my_time_tmp >= TIMESTAMP_MIN_VALUE && my_time_tmp <= TIMESTAMP_MAX_VALUE)
+ to_tz->gmt_sec_to_TIME(ltime, my_time_tmp);
+ }
+
+ null_value= 0;
return 0;
}
@@ -1617,7 +1721,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
case INTERVAL_DAY_HOUR:
{
longlong sec, days, daynr, microseconds, extra_sec;
- ltime->time_type=TIMESTAMP_DATETIME; // Return full date
+ ltime->time_type= MYSQL_TIMESTAMP_DATETIME; // Return full date
microseconds= ltime->second_part + sign*interval.second_part;
extra_sec= microseconds/1000000L;
microseconds= microseconds%1000000L;
@@ -1704,7 +1808,7 @@ String *Item_date_add_interval::val_str(String *str)
if (Item_date_add_interval::get_date(&ltime,0))
return 0;
- if (ltime.time_type == TIMESTAMP_DATE)
+ if (ltime.time_type == MYSQL_TIMESTAMP_DATE)
format= DATE_ONLY;
else if (ltime.second_part)
format= DATE_TIME_MICROSECOND;
@@ -1727,7 +1831,7 @@ longlong Item_date_add_interval::val_int()
if (Item_date_add_interval::get_date(&ltime,0))
return (longlong) 0;
date = (ltime.year*100L + ltime.month)*100L + ltime.day;
- return ltime.time_type == TIMESTAMP_DATE ? date :
+ return ltime.time_type == MYSQL_TIMESTAMP_DATE ? date :
((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second;
}
@@ -1808,7 +1912,7 @@ longlong Item_extract::val_int()
else
{
String *res= args[0]->val_str(&value);
- if (!res || str_to_time(res->ptr(),res->length(),&ltime))
+ if (!res || str_to_time_with_warn(res->ptr(), res->length(), &ltime))
{
null_value=1;
return 0;
@@ -1986,7 +2090,7 @@ String *Item_datetime_typecast::val_str(String *str)
bool Item_time_typecast::get_time(TIME *ltime)
{
bool res= get_arg0_time(ltime);
- ltime->time_type= TIMESTAMP_TIME;
+ ltime->time_type= MYSQL_TIMESTAMP_TIME;
return res;
}
@@ -2009,7 +2113,7 @@ String *Item_time_typecast::val_str(String *str)
bool Item_date_typecast::get_date(TIME *ltime, uint fuzzy_date)
{
bool res= get_arg0_date(ltime,1);
- ltime->time_type= TIMESTAMP_DATE;
+ ltime->time_type= MYSQL_TIMESTAMP_DATE;
return res;
}
@@ -2115,17 +2219,17 @@ String *Item_func_add_time::val_str(String *str)
{
if (get_arg0_date(&l_time1,1) ||
args[1]->get_time(&l_time2) ||
- l_time1.time_type == TIMESTAMP_TIME ||
- l_time2.time_type != TIMESTAMP_TIME)
+ l_time1.time_type == MYSQL_TIMESTAMP_TIME ||
+ l_time2.time_type != MYSQL_TIMESTAMP_TIME)
goto null_date;
}
else // ADDTIME function
{
if (args[0]->get_time(&l_time1) ||
args[1]->get_time(&l_time2) ||
- l_time2.time_type == TIMESTAMP_DATETIME)
+ l_time2.time_type == MYSQL_TIMESTAMP_DATETIME)
goto null_date;
- is_time= (l_time1.time_type == TIMESTAMP_TIME);
+ is_time= (l_time1.time_type == MYSQL_TIMESTAMP_TIME);
if (is_time && (l_time2.neg == l_time1.neg && l_time1.neg))
l_time3.neg= 1;
}
@@ -2248,11 +2352,11 @@ bool calc_time_diff(TIME *l_time1,TIME *l_time2, int l_sign,
long microseconds= *microseconds_out;
/*
- We suppose that if first argument is TIMESTAMP_TIME
+ We suppose that if first argument is MYSQL_TIMESTAMP_TIME
the second argument should be TIMESTAMP_TIME also.
We should check it before calc_time_diff call.
*/
- if (l_time1->time_type == TIMESTAMP_TIME) // Time value
+ if (l_time1->time_type == MYSQL_TIMESTAMP_TIME) // Time value
days= l_time1->day - l_sign*l_time2->day;
else // DateTime value
days= (calc_daynr((uint) l_time1->year,
@@ -2317,7 +2421,7 @@ String *Item_func_timediff::val_str(String *str)
&seconds, &microseconds);
/*
- For TIMESTAMP_TIME only:
+ For MYSQL_TIMESTAMP_TIME only:
If both argumets are negative values and diff between them
is negative we need to swap sign as result should be positive.
*/
@@ -2591,13 +2695,13 @@ void Item_func_get_format::print(String *str)
str->append('(');
switch (type) {
- case TIMESTAMP_DATE:
+ case MYSQL_TIMESTAMP_DATE:
str->append("DATE, ");
break;
- case TIMESTAMP_DATETIME:
+ case MYSQL_TIMESTAMP_DATETIME:
str->append("DATETIME, ");
break;
- case TIMESTAMP_TIME:
+ case MYSQL_TIMESTAMP_TIME:
str->append("TIME, ");
break;
default:
@@ -2680,25 +2784,25 @@ void Item_func_str_to_date::fix_length_and_dec()
decimals=0;
cached_field_type= MYSQL_TYPE_STRING;
max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
- cached_timestamp_type= TIMESTAMP_NONE;
+ cached_timestamp_type= MYSQL_TIMESTAMP_NONE;
if ((const_item= args[1]->const_item()))
{
format= args[1]->val_str(&format_str);
cached_format_type= check_result_type(format->ptr(), format->length());
switch (cached_format_type) {
case DATE_ONLY:
- cached_timestamp_type= TIMESTAMP_DATE;
+ cached_timestamp_type= MYSQL_TIMESTAMP_DATE;
cached_field_type= MYSQL_TYPE_DATE;
max_length= MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
break;
case TIME_ONLY:
case TIME_MICROSECOND:
- cached_timestamp_type= TIMESTAMP_TIME;
+ cached_timestamp_type= MYSQL_TIMESTAMP_TIME;
cached_field_type= MYSQL_TYPE_TIME;
max_length= MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
break;
default:
- cached_timestamp_type= TIMESTAMP_DATETIME;
+ cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME;
cached_field_type= MYSQL_TYPE_DATETIME;
break;
}
@@ -2724,7 +2828,7 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
ltime, cached_timestamp_type))
goto null_date;
- if (cached_timestamp_type == TIMESTAMP_TIME && ltime->day)
+ if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day)
{
/*
Day part for time type can be nonzero value and so
@@ -2765,6 +2869,6 @@ bool Item_func_last_day::get_date(TIME *ltime, uint fuzzy_date)
ltime->day= days_in_month[month_idx];
if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366)
ltime->day= 29;
- ltime->time_type= TIMESTAMP_DATE;
+ ltime->time_type= MYSQL_TIMESTAMP_DATE;
return 0;
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 263969cd26b..fe72ac6193b 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -348,6 +348,7 @@ public:
Item_date_func() :Item_str_func() {}
Item_date_func(Item *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
+ Item_date_func(Item *a,Item *b, Item *c) :Item_str_func(a,b,c) {}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field(TABLE *t_arg)
{
@@ -356,7 +357,7 @@ public:
};
-/* Abstract CURTIME function. Children should define what timezone is used */
+/* Abstract CURTIME function. Children should define what time zone is used */
class Item_func_curtime :public Item_func
{
@@ -378,10 +379,10 @@ public:
}
/*
Abstract method that defines which time zone is used for conversion.
- Converts time from time_t representation to broken down representation
- in struct tm using gmtime_r or localtime_r functions.
+ Converts time current time in my_time_t representation to broken-down
+ TIME representation using UTC-SYSTEM or per-thread time zone.
*/
- virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
+ virtual void store_now_in_TIME(TIME *now_time)=0;
};
@@ -391,7 +392,7 @@ public:
Item_func_curtime_local() :Item_func_curtime() {}
Item_func_curtime_local(Item *a) :Item_func_curtime(a) {}
const char *func_name() const { return "curtime"; }
- void store_now_in_tm(time_t now, struct tm *now_tm);
+ virtual void store_now_in_TIME(TIME *now_time);
};
@@ -401,7 +402,7 @@ public:
Item_func_curtime_utc() :Item_func_curtime() {}
Item_func_curtime_utc(Item *a) :Item_func_curtime(a) {}
const char *func_name() const { return "utc_time"; }
- void store_now_in_tm(time_t now, struct tm *now_tm);
+ virtual void store_now_in_TIME(TIME *now_time);
};
@@ -413,12 +414,11 @@ class Item_func_curdate :public Item_date
TIME ltime;
public:
Item_func_curdate() :Item_date() {}
- void set_result_from_tm(struct tm *now);
longlong val_int() { DBUG_ASSERT(fixed == 1); return (value) ; }
String *val_str(String *str);
void fix_length_and_dec();
bool get_date(TIME *res, uint fuzzy_date);
- virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
+ virtual void store_now_in_TIME(TIME *now_time)=0;
};
@@ -427,7 +427,7 @@ class Item_func_curdate_local :public Item_func_curdate
public:
Item_func_curdate_local() :Item_func_curdate() {}
const char *func_name() const { return "curdate"; }
- void store_now_in_tm(time_t now, struct tm *now_tm);
+ void store_now_in_TIME(TIME *now_time);
};
@@ -436,7 +436,7 @@ class Item_func_curdate_utc :public Item_func_curdate
public:
Item_func_curdate_utc() :Item_func_curdate() {}
const char *func_name() const { return "utc_date"; }
- void store_now_in_tm(time_t now, struct tm *now_tm);
+ void store_now_in_TIME(TIME *now_time);
};
@@ -458,7 +458,7 @@ public:
String *val_str(String *str);
void fix_length_and_dec();
bool get_date(TIME *res, uint fuzzy_date);
- virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
+ virtual void store_now_in_TIME(TIME *now_time)=0;
};
@@ -468,7 +468,7 @@ public:
Item_func_now_local() :Item_func_now() {}
Item_func_now_local(Item *a) :Item_func_now(a) {}
const char *func_name() const { return "now"; }
- void store_now_in_tm(time_t now, struct tm *now_tm);
+ virtual void store_now_in_TIME(TIME *now_time);
virtual enum Functype functype() const { return NOW_FUNC; }
};
@@ -479,7 +479,7 @@ public:
Item_func_now_utc() :Item_func_now() {}
Item_func_now_utc(Item *a) :Item_func_now(a) {}
const char *func_name() const { return "utc_timestamp"; }
- void store_now_in_tm(time_t now, struct tm *now_tm);
+ virtual void store_now_in_TIME(TIME *now_time);
};
@@ -509,6 +509,7 @@ public:
class Item_func_from_unixtime :public Item_date_func
{
+ THD *thd;
public:
Item_func_from_unixtime(Item *a) :Item_date_func(a) {}
double val()
@@ -519,12 +520,29 @@ class Item_func_from_unixtime :public Item_date_func
longlong val_int();
String *val_str(String *str);
const char *func_name() const { return "from_unixtime"; }
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- decimals=0;
- max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
- }
+ void fix_length_and_dec();
+ bool get_date(TIME *res, uint fuzzy_date);
+};
+
+
+/*
+ We need Time_zone class declaration for storing pointers in
+ Item_func_convert_tz.
+*/
+class Time_zone;
+
+class Item_func_convert_tz :public Item_date_func
+{
+ THD *thd;
+ Time_zone *from_tz, *to_tz;
+ public:
+ Item_func_convert_tz(Item *a, Item *b, Item *c):
+ Item_date_func(a, b, c) {}
+ longlong val_int();
+ double val() { return (double) val_int(); }
+ String *val_str(String *str);
+ const char *func_name() const { return "convert_tz"; }
+ void fix_length_and_dec();
bool get_date(TIME *res, uint fuzzy_date);
};
diff --git a/sql/lex.h b/sql/lex.h
index b72ba53ec7e..24a6431adf5 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -139,6 +139,7 @@ static SYMBOL symbols[] = {
{ "DAY_MICROSECOND", SYM(DAY_MICROSECOND_SYM)},
{ "DAY_MINUTE", SYM(DAY_MINUTE_SYM)},
{ "DAY_SECOND", SYM(DAY_SECOND_SYM)},
+ { "DEALLOCATE", SYM(DEALLOCATE_SYM)},
{ "DEC", SYM(DECIMAL_SYM)},
{ "DECIMAL", SYM(DECIMAL_SYM)},
{ "DECLARE", SYM(DECLARE_SYM)},
@@ -224,7 +225,7 @@ static SYMBOL symbols[] = {
{ "IGNORE", SYM(IGNORE_SYM)},
{ "IMPORT", SYM(IMPORT)},
{ "IN", SYM(IN_SYM)},
- { "INDEX", SYM(INDEX)},
+ { "INDEX", SYM(INDEX_SYM)},
{ "INDEXES", SYM(INDEXES)},
{ "INFILE", SYM(INFILE)},
{ "INNER", SYM(INNER_SYM)},
@@ -332,6 +333,7 @@ static SYMBOL symbols[] = {
{ "OFFSET", SYM(OFFSET_SYM)},
{ "OLD_PASSWORD", SYM(OLD_PASSWORD)},
{ "ON", SYM(ON)},
+ { "ONE_SHOT", SYM(ONE_SHOT_SYM)},
{ "OPEN", SYM(OPEN_SYM)},
{ "OPTIMIZE", SYM(OPTIMIZE)},
{ "OPTION", SYM(OPTION)},
@@ -347,6 +349,7 @@ static SYMBOL symbols[] = {
{ "POINT", SYM(POINT_SYM)},
{ "POLYGON", SYM(POLYGON)},
{ "PRECISION", SYM(PRECISION)},
+ { "PREPARE", SYM(PREPARE_SYM)},
{ "PREV", SYM(PREV_SYM)},
{ "PRIMARY", SYM(PRIMARY_SYM)},
{ "PRIVILEGES", SYM(PRIVILEGES)},
@@ -543,6 +546,7 @@ static SYMBOL sql_functions[] = {
{ "CONNECTION_ID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)},
{ "CONTAINS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_contains)},
{ "CONV", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)},
+ { "CONVERT_TZ", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_convert_tz)},
{ "COUNT", SYM(COUNT_SYM)},
{ "COS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)},
{ "COT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)},
diff --git a/sql/log.cc b/sql/log.cc
index a673e72e26c..225aaae0549 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -25,12 +25,14 @@
#include "mysql_priv.h"
#include "sql_acl.h"
#include "sql_repl.h"
+#include "ha_innodb.h" // necessary to cut the binlog when crash recovery
#include <my_dir.h>
#include <stdarg.h>
#include <m_ctype.h> // For test_if_number
MYSQL_LOG mysql_log, mysql_slow_log, mysql_bin_log;
+ulong sync_binlog_counter= 0;
static bool test_if_number(const char *str,
long *res, bool allow_wildcards);
@@ -299,6 +301,7 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
if ((index_file_nr= my_open(index_file_name,
O_RDWR | O_CREAT | O_BINARY ,
MYF(MY_WME))) < 0 ||
+ my_sync(index_file_nr, MYF(MY_WME)) ||
init_io_cache(&index_file, index_file_nr,
IO_SIZE, WRITE_CACHE,
my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)),
@@ -359,16 +362,21 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
goto err;
bytes_written+= description_event_for_queue->get_event_len();
}
- if (flush_io_cache(&log_file))
+ if (flush_io_cache(&log_file) ||
+ my_sync(log_file.file, MYF(MY_WME)))
goto err;
if (write_file_name_to_index_file)
{
- /* As this is a new log file, we write the file name to the index file */
+ /*
+ As this is a new log file, we write the file name to the index
+ file. As every time we write to the index file, we sync it.
+ */
if (my_b_write(&index_file, (byte*) log_file_name,
strlen(log_file_name)) ||
my_b_write(&index_file, (byte*) "\n", 1) ||
- flush_io_cache(&index_file))
+ flush_io_cache(&index_file) ||
+ my_sync(index_file.file, MYF(MY_WME)))
goto err;
}
break;
@@ -449,7 +457,8 @@ static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset)
goto err;
}
/* The following will either truncate the file or fill the end with \n' */
- if (my_chsize(file, offset - init_offset, '\n', MYF(MY_WME)))
+ if (my_chsize(file, offset - init_offset, '\n', MYF(MY_WME)) ||
+ my_sync(file, MYF(MY_WME)))
goto err;
/* Reset data in old index cache */
@@ -1048,6 +1057,8 @@ void MYSQL_LOG::new_file(bool need_lock)
open(old_name, save_log_type, new_name_ptr, index_file_name, io_cache_type,
no_auto_events, max_size, 1);
+ if (this == &mysql_bin_log)
+ report_pos_in_innodb();
my_free(old_name,MYF(0));
end:
@@ -1218,6 +1229,17 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
}
+inline bool sync_binlog(IO_CACHE *cache)
+{
+ if (sync_binlog_period == ++sync_binlog_counter && sync_binlog_period)
+ {
+ sync_binlog_counter= 0;
+ return my_sync(cache->file, MYF(MY_WME));
+ }
+ return 0;
+}
+
+
/*
Write an event to the binary log
*/
@@ -1285,6 +1307,54 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (thd)
{
+#if MYSQL_VERSION_ID < 50000
+ /*
+ To make replication of charsets working in 4.1 we are writing values
+ of charset related variables before every statement in the binlog,
+ if values of those variables differ from global server-wide defaults.
+ We are using SET ONE_SHOT command so that the charset vars get reset
+ to default after the first non-SET statement.
+ In the next 5.0 this won't be needed as we will use the new binlog
+ format to store charset info.
+ */
+ if ((thd->variables.character_set_client->number !=
+ global_system_variables.collation_server->number) ||
+ (thd->variables.character_set_client->number !=
+ thd->variables.collation_connection->number) ||
+ (thd->variables.collation_server->number !=
+ thd->variables.collation_connection->number))
+ {
+ char buf[200];
+ int written= my_snprintf(buf, sizeof(buf)-1,
+ "SET ONE_SHOT CHARACTER_SET_CLIENT=%u,\
+COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
+ (uint) thd->variables.character_set_client->number,
+ (uint) thd->variables.collation_connection->number,
+ (uint) thd->variables.collation_database->number,
+ (uint) thd->variables.collation_server->number);
+ Query_log_event e(thd, buf, written, 0);
+ e.set_log_pos(this);
+ if (e.write(file))
+ goto err;
+ }
+ /*
+ We use the same ONE_SHOT trick for making replication of time zones
+ working in 4.1. Again in 5.0 we have better means for doing this.
+ */
+ if (thd->time_zone_used &&
+ thd->variables.time_zone != global_system_variables.time_zone)
+ {
+ char buf[MAX_TIME_ZONE_NAME_LENGTH + 26];
+ char *buf_end= strxmov(buf, "SET ONE_SHOT TIME_ZONE='",
+ thd->variables.time_zone->get_name()->ptr(),
+ "'", NullS);
+ Query_log_event e(thd, buf, buf_end - buf, 0);
+ e.set_log_pos(this);
+ if (e.write(file))
+ goto err;
+ }
+#endif
+
if (thd->last_insert_id_used)
{
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
@@ -1398,9 +1468,9 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (file == &log_file) // we are writing to the real log (disk)
{
- if (flush_io_cache(file))
+ if (flush_io_cache(file) || sync_binlog(file))
goto err;
-
+
if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log))
{
/*
@@ -1413,6 +1483,30 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (event_info->get_type_code() == QUERY_EVENT ||
event_info->get_type_code() == EXEC_LOAD_EVENT)
{
+#ifndef DBUG_OFF
+ if (unlikely(opt_crash_binlog_innodb))
+ {
+ /*
+ This option is for use in rpl_crash_binlog_innodb.test.
+ 1st we want to verify that Binlog_dump thread cannot send the
+ event now (because of LOCK_log): we here tell the Binlog_dump
+ thread to wake up, sleep for the slave to have time to possibly
+ receive data from the master (it should not), and then crash.
+ 2nd we want to verify that at crash recovery the rolled back
+ event is cut from the binlog.
+ */
+ if (!(--opt_crash_binlog_innodb))
+ {
+ signal_update();
+ sleep(2);
+ fprintf(stderr,"This is a normal crash because of"
+ " --crash-binlog-innodb\n");
+ assert(0);
+ }
+ DBUG_PRINT("info",("opt_crash_binlog_innodb: %d",
+ opt_crash_binlog_innodb));
+ }
+#endif
error = ha_report_binlog_offset_and_commit(thd, log_file_name,
file->pos_in_file);
called_handler_commit=1;
@@ -1558,7 +1652,8 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
commit_or_rollback ? 6 : 8,
TRUE);
qinfo.set_log_pos(this);
- if (qinfo.write(&log_file) || flush_io_cache(&log_file))
+ if (qinfo.write(&log_file) || flush_io_cache(&log_file) ||
+ sync_binlog(&log_file))
goto err;
}
if (cache->error) // Error on read
@@ -1567,6 +1662,22 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
write_error=1; // Don't give more errors
goto err;
}
+#ifndef DBUG_OFF
+ if (unlikely(opt_crash_binlog_innodb))
+ {
+ /* see the previous MYSQL_LOG::write() method for a comment */
+ if (!(--opt_crash_binlog_innodb))
+ {
+ signal_update();
+ sleep(2);
+ fprintf(stderr, "This is a normal crash because of"
+ " --crash-binlog-innodb\n");
+ assert(0);
+ }
+ DBUG_PRINT("info",("opt_crash_binlog_innodb: %d",
+ opt_crash_binlog_innodb));
+ }
+#endif
if ((ha_report_binlog_offset_and_commit(thd, log_file_name,
log_file.pos_in_file)))
goto err;
@@ -1979,4 +2090,138 @@ bool flush_error_log()
}
+/*
+ If the server has InnoDB on, and InnoDB has published the position of the
+ last committed transaction (which happens only if a crash recovery occured at
+ this startup) then truncate the previous binary log at the position given by
+ InnoDB. If binlog is shorter than the position, print a message to the error
+ log.
+
+ SYNOPSIS
+ cut_spurious_tail()
+
+ RETURN VALUES
+ 1 Error
+ 0 Ok
+*/
+
+bool MYSQL_LOG::cut_spurious_tail()
+{
+ int error= 0;
+ char llbuf1[22], llbuf2[22];
+ ulonglong actual_size;
+
+ DBUG_ENTER("cut_spurious_tail");
+#ifdef HAVE_INNOBASE_DB
+ if (have_innodb != SHOW_OPTION_YES)
+ DBUG_RETURN(0);
+ /*
+ This is the place where we use information from InnoDB to cut the
+ binlog.
+ */
+ char *name= ha_innobase::get_mysql_bin_log_name();
+ ulonglong pos= ha_innobase::get_mysql_bin_log_pos();
+ if (name[0] == 0 || pos == ULONGLONG_MAX)
+ {
+ DBUG_PRINT("info", ("InnoDB has not set binlog info"));
+ DBUG_RETURN(0);
+ }
+ /* The binlog given by InnoDB normally is never an active binlog */
+ if (is_open() && is_active(name))
+ {
+ sql_print_error("Warning: after InnoDB crash recovery, InnoDB says that "
+ "the binary log of the previous run has the same name "
+ "'%s' as the current one; this is likely to be abnormal.",
+ name);
+ DBUG_RETURN(1);
+ }
+ sql_print_error("After InnoDB crash recovery, checking if the binary log "
+ "'%s' contains rolled back transactions which must be "
+ "removed from it...", name);
+ /* If we have a too long binlog, cut. If too short, print error */
+ int fd= my_open(name, O_EXCL | O_APPEND | O_BINARY | O_WRONLY, MYF(MY_WME));
+ if (fd < 0)
+ {
+ int save_errno= my_errno;
+ sql_print_error("Could not open the binary log '%s' for truncation.",
+ name);
+ if (save_errno != ENOENT)
+ sql_print_error("The binary log '%s' should not be used for "
+ "replication.", name);
+ DBUG_RETURN(1);
+ }
+
+ if (pos > (actual_size= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME))))
+ {
+ /*
+ Note that when we have MyISAM rollback this error message should be
+ reconsidered.
+ */
+ sql_print_error("The binary log '%s' is shorter than its expected size "
+ "(actual: %s, expected: %s) so it misses at least one "
+ "committed transaction; so it should not be used for "
+ "replication or point-in-time recovery. You would need "
+ "to restart slaves from a fresh master's data "
+ "snapshot ",
+ name, llstr(actual_size, llbuf1),
+ llstr(pos, llbuf2));
+ error= 1;
+ goto err;
+ }
+ if (pos < actual_size)
+ {
+ sql_print_error("The binary log '%s' is bigger than its expected size "
+ "(actual: %s, expected: %s) so it contains a rolled back "
+ "transaction; now truncating that.", name,
+ llstr(actual_size, llbuf1), llstr(pos, llbuf2));
+ /*
+ As on some OS, my_chsize() can only pad with 0s instead of really
+ truncating. Then mysqlbinlog (and Binlog_dump thread) will error on
+ these zeroes. This is annoying, but not more (you just need to manually
+ switch replication to the next binlog). Fortunately, in my_chsize.c, it
+ says that all modern machines support real ftruncate().
+
+ */
+ if ((error= my_chsize(fd, pos, 0, MYF(MY_WME))))
+ goto err;
+ }
+err:
+ if (my_close(fd, MYF(MY_WME)))
+ error= 1;
+#endif
+ DBUG_RETURN(error);
+}
+
+
+/*
+ If the server has InnoDB on, store the binlog name and position into
+ InnoDB. This function is used every time we create a new binlog.
+ SYNOPSIS
+ report_pos_in_innodb()
+
+ NOTES
+ This cannot simply be done in MYSQL_LOG::open(), because when we create
+ the first binlog at startup, we have not called ha_init() yet so we cannot
+ write into InnoDB yet.
+
+ RETURN VALUES
+ 1 Error
+ 0 Ok
+*/
+
+void MYSQL_LOG::report_pos_in_innodb()
+{
+ DBUG_ENTER("report_pos_in_innodb");
+#ifdef HAVE_INNOBASE_DB
+ if (is_open() && have_innodb == SHOW_OPTION_YES)
+ {
+ DBUG_PRINT("info", ("Reporting binlog info into InnoDB - "
+ "name: '%s' position: %d",
+ log_file_name, my_b_tell(&log_file)));
+ innobase_store_binlog_offset_and_flush_log(log_file_name,
+ my_b_tell(&log_file));
+ }
+#endif
+ DBUG_VOID_RETURN;
+}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index b8d80883451..3b69e1c3176 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -203,6 +203,29 @@ static inline int read_str(char * &buf, char *buf_end, char * &str,
}
/*
+ Transforms a string into "" or its expression in 0x... form.
+*/
+static char *str_to_hex(char *to, char *from, uint len)
+{
+ char *p= to;
+ if (len)
+ {
+ p= strmov(p, "0x");
+ for (uint i= 0; i < len; i++, p+= 2)
+ {
+ /* val[i] is char. Casting to uchar helps greatly if val[i] < 0 */
+ uint tmp= (uint) (uchar) from[i];
+ p[0]= _dig_vec_upper[tmp >> 4];
+ p[1]= _dig_vec_upper[tmp & 15];
+ }
+ *p= 0;
+ }
+ else
+ p= strmov(p, "\"\"");
+ return p; // pointer to end 0 of 'to'
+}
+
+/*
Prints a "session_var=value" string. Used by mysqlbinlog to print some SET
commands just before it prints a query.
*/
@@ -607,6 +630,7 @@ end:
#else
#define UNLOCK_MUTEX
#define LOCK_MUTEX
+#define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet)
#endif
/*
@@ -2910,7 +2934,7 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
void User_var_log_event::pack_info(Protocol* protocol)
{
char *buf= 0;
- uint val_offset= 2 + name_len;
+ uint val_offset= 4 + name_len;
uint event_len= val_offset;
if (is_null)
@@ -2934,16 +2958,21 @@ void User_var_log_event::pack_info(Protocol* protocol)
event_len= longlong10_to_str(uint8korr(val), buf + val_offset,-10)-buf;
break;
case STRING_RESULT:
- /*
- This is correct as pack_info is used for SHOW BINLOG command
- only. But be carefull this is may be incorrect in other cases as
- string may contain \ and '.
- */
- event_len= val_offset + 2 + val_len;
- buf= my_malloc(event_len, MYF(MY_WME));
- buf[val_offset]= '\'';
- memcpy(buf + val_offset + 1, val, val_len);
- buf[val_offset + val_len + 1]= '\'';
+ /* 15 is for 'COLLATE' and other chars */
+ buf= my_malloc(event_len+val_len*2+1+2*MY_CS_NAME_SIZE+15, MYF(MY_WME));
+ CHARSET_INFO *cs;
+ if (!(cs= get_charset(charset_number, MYF(0))))
+ {
+ strmov(buf+val_offset, "???");
+ event_len+= 3;
+ }
+ else
+ {
+ char *p= strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
+ p= str_to_hex(p, val, val_len);
+ p= strxmov(p, " COLLATE ", cs->name, NullS);
+ event_len= p-buf;
+ }
break;
case ROW_RESULT:
default:
@@ -2952,8 +2981,10 @@ void User_var_log_event::pack_info(Protocol* protocol)
}
}
buf[0]= '@';
- buf[1+name_len]= '=';
- memcpy(buf+1, name, name_len);
+ buf[1]= '`';
+ buf[2+name_len]= '`';
+ buf[3+name_len]= '=';
+ memcpy(buf+2, name, name_len);
protocol->store(buf, event_len, &my_charset_bin);
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
}
@@ -3046,8 +3077,9 @@ void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* las
fprintf(file, "\tUser_var\n");
}
- fprintf(file, "SET @");
+ fprintf(file, "SET @`");
my_fwrite(file, (byte*) name, (uint) (name_len), MYF(MY_NABP | MY_WME));
+ fprintf(file, "`");
if (is_null)
{
@@ -3067,7 +3099,42 @@ void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* las
fprintf(file, ":=%s;\n", int_buf);
break;
case STRING_RESULT:
- fprintf(file, ":='%s';\n", val);
+ {
+ /*
+ Let's express the string in hex. That's the most robust way. If we
+ print it in character form instead, we need to escape it with
+ character_set_client which we don't know (we will know it in 5.0, but
+ in 4.1 we don't know it easily when we are printing
+ User_var_log_event). Explanation why we would need to bother with
+ character_set_client (quoting Bar):
+ > Note, the parser doesn't switch to another unescaping mode after
+ > it has met a character set introducer.
+ > For example, if an SJIS client says something like:
+ > SET @a= _ucs2 \0a\0b'
+ > the string constant is still unescaped according to SJIS, not
+ > according to UCS2.
+ */
+ char *p, *q;
+ if (!(p= (char *)my_alloca(2*val_len+1+2))) // 2 hex digits per byte
+ break; // no error, as we are 'void'
+ str_to_hex(p, val, val_len);
+ /*
+ For proper behaviour when mysqlbinlog|mysql, we need to explicitely
+ specify the variable's collation. It will however cause problems when
+ people want to mysqlbinlog|mysql into another server not supporting the
+ character set. But there's not much to do about this and it's unlikely.
+ */
+ CHARSET_INFO *cs;
+ if (!(cs= get_charset(charset_number, MYF(0))))
+ /*
+ Generate an unusable command (=> syntax error) is probably the best
+ thing we can do here.
+ */
+ fprintf(file, ":=???;\n");
+ else
+ fprintf(file, ":=_%s %s COLLATE %s;\n", cs->csname, p, cs->name);
+ my_afree(p);
+ }
break;
case ROW_RESULT:
default:
@@ -3088,7 +3155,9 @@ void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* las
int User_var_log_event::exec_event(struct st_relay_log_info* rli)
{
Item *it= 0;
- CHARSET_INFO *charset= get_charset(charset_number, MYF(0));
+ CHARSET_INFO *charset;
+ if (!(charset= get_charset(charset_number, MYF(MY_WME))))
+ return 1;
LEX_STRING user_var_name;
user_var_name.str= name;
user_var_name.length= name_len;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index c8b57d9fb55..792b1a1189f 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -24,10 +24,10 @@
#ifndef MYSQL_CLIENT
#include <my_global.h>
-#include <assert.h>
#include <mysql_version.h>
#include <mysql_embed.h>
#include <my_sys.h>
+#include <my_time.h>
#include <m_string.h>
#include <hash.h>
#include <signal.h>
@@ -388,7 +388,9 @@ inline THD *_current_thd(void)
#include "field.h" /* Field definitions */
#include "protocol.h"
#include "sql_udf.h"
+class user_var_entry;
#include "item.h"
+#include "tztime.h"
typedef Comp_creator* (*chooser_compare_func_creator)(bool invert);
/* sql_parse.cc */
void free_items(Item *item);
@@ -418,6 +420,7 @@ struct Query_cache_query_flags
uint character_set_results_num;
uint collation_connection_num;
ha_rows limit;
+ Time_zone *time_zone;
};
#define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
#include "sql_cache.h"
@@ -570,7 +573,8 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List<Key> &keys,
uint order_num, ORDER *order,
enum enum_duplicates handle_duplicates,
- ALTER_INFO *alter_info);
+ ALTER_INFO *alter_info, bool do_send_ok=1);
+int mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
int mysql_create_like_table(THD *thd, TABLE_LIST *table,
HA_CREATE_INFO *create_info,
Table_ident *src_table);
@@ -679,8 +683,10 @@ int mysqld_show_column_types(THD *thd);
int mysqld_help (THD *thd, const char *text);
/* sql_prepare.cc */
-void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
+int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
+ LEX_STRING *name=NULL);
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_free(THD *thd, char *packet);
void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
@@ -698,8 +704,9 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
/* sql_handler.cc */
int mysql_ha_open(THD *thd, TABLE_LIST *tables);
-int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok=0);
-int mysql_ha_closeall(THD *thd, TABLE_LIST *tables);
+int mysql_ha_close(THD *thd, TABLE_LIST *tables,
+ bool dont_send_ok=0, bool dont_lock=0, bool no_alias=0);
+int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed=0);
int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
@@ -862,7 +869,7 @@ extern Le_creator le_creator;
extern uchar *days_in_month;
extern char language[LIBLEN],reg_ext[FN_EXTLEN];
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
-extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file;
+extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
extern char log_error_file[FN_REFLEN];
extern double last_query_cost;
extern double log_10[32];
@@ -899,8 +906,8 @@ extern ulong max_binlog_size, max_relay_log_size;
extern ulong rpl_recovery_rank, thread_cache_size;
extern ulong com_stat[(uint) SQLCOM_END], com_other, back_log;
extern ulong specialflag, current_pid;
-extern ulong expire_logs_days;
-extern my_bool relay_log_purge;
+extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter;
+extern my_bool relay_log_purge, opt_innodb_safe_binlog;
extern uint test_flags,select_errors,ha_open_options;
extern uint protocol_version, mysqld_port, dropping_tables;
extern uint delay_key_write_options, lower_case_table_names;
@@ -918,8 +925,10 @@ 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;
extern my_bool opt_secure_auth;
+extern uint opt_crash_binlog_innodb;
extern char *shared_memory_base_name, *mysqld_unix_port;
extern bool opt_enable_shared_memory;
+extern char *default_tz_name;
extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
extern FILE *bootstrap_file;
@@ -960,9 +969,11 @@ extern struct my_option my_long_options[];
/* optional things, have_* variables */
-extern SHOW_COMP_OPTION have_isam, have_innodb, have_berkeley_db, have_example_db;
+extern SHOW_COMP_OPTION have_isam, have_innodb, have_berkeley_db;
+extern SHOW_COMP_OPTION have_example_db, have_archive_db;
extern SHOW_COMP_OPTION have_raid, have_openssl, have_symlink;
extern SHOW_COMP_OPTION have_query_cache, have_berkeley_db, have_innodb;
+extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;
extern SHOW_COMP_OPTION have_crypt;
extern SHOW_COMP_OPTION have_compress;
@@ -1028,12 +1039,13 @@ uint calc_days_in_year(uint year);
void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day);
void init_time(void);
-long my_gmt_sec(TIME *, long *current_timezone);
-time_t str_to_timestamp(const char *str,uint length);
-bool str_to_time(const char *str,uint length,TIME *l_time);
-longlong str_to_datetime(const char *str,uint length, uint fuzzy_date);
-timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
- uint flags);
+my_time_t my_system_gmt_sec(const TIME *, long *current_timezone, bool *not_exist);
+my_time_t TIME_to_timestamp(THD *thd, const TIME *t, bool *not_exist);
+bool str_to_time_with_warn(const char *str,uint length,TIME *l_time);
+timestamp_type str_to_datetime_with_warn(const char *str, uint length,
+ TIME *l_time, uint flags);
+longlong number_to_TIME(longlong nr, TIME *time_res, bool fuzzy_date,
+ int *was_cut);
void localtime_to_TIME(TIME *to, struct tm *from);
void calc_time_from_sec(TIME *to, long seconds, long microseconds);
@@ -1112,6 +1124,9 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
LEX_STRING component);
Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
uint length, const char *item_name);
+/* item_func.cc */
+int get_var_with_binlog(THD *thd, LEX_STRING &name,
+ user_var_entry **out_entry);
/* log.cc */
bool flush_error_log(void);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index e4302a4a9ad..564a8090b23 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -50,10 +50,6 @@
#define ONE_THREAD
#endif
-#define SHUTDOWN_THD
-#define MAIN_THD
-#define SIGNAL_THD
-
#ifdef HAVE_purify
#define IF_PURIFY(A,B) (A)
#else
@@ -276,11 +272,13 @@ my_bool opt_secure_auth= 0;
my_bool opt_short_log_format= 0;
my_bool opt_log_queries_not_using_indexes= 0;
my_bool lower_case_file_system= 0;
+my_bool opt_innodb_safe_binlog= 0;
volatile bool mqh_used = 0;
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
uint delay_key_write_options, protocol_version;
uint lower_case_table_names;
+uint opt_crash_binlog_innodb;
uint volatile thread_count, thread_running, kill_cached_threads, wake_thread;
ulong back_log, connect_timeout, concurrency;
@@ -309,7 +307,7 @@ ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
ulong max_connections,max_used_connections,
max_connect_errors, max_user_connections = 0;
ulong thread_id=1L,current_pid;
-ulong slow_launch_threads = 0;
+ulong slow_launch_threads = 0, sync_binlog_period;
ulong expire_logs_days = 0;
ulong rpl_recovery_rank=0;
ulong my_bind_addr; /* the address we bind to */
@@ -317,23 +315,15 @@ volatile ulong cached_thread_count= 0;
double last_query_cost= -1; /* -1 denotes that no query was compiled yet */
double log_10[32]; /* 10 potences */
-ulonglong log_10_int[20]=
-{
- 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL,
- ULL(100000000), ULL(1000000000), ULL(10000000000), ULL(100000000000),
- ULL(1000000000000), ULL(10000000000000), ULL(100000000000000),
- ULL(1000000000000000), ULL(10000000000000000), ULL(100000000000000000),
- ULL(1000000000000000000), ULL(10000000000000000000)
-};
-
time_t start_time;
-char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], time_zone[30];
+char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
+char *default_tz_name;
char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN];
char* log_error_file_ptr= log_error_file;
char mysql_real_data_home[FN_REFLEN],
language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
- max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file,
+ *mysqld_user,*mysqld_chroot, *opt_init_file,
*opt_init_connect, *opt_init_slave,
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
@@ -379,9 +369,10 @@ KEY_CACHE *sql_key_cache;
CHARSET_INFO *system_charset_info, *files_charset_info ;
CHARSET_INFO *national_charset_info, *table_alias_charset;
-SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam,
- have_ndbcluster, have_example_db;
+SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam, have_ndbcluster,
+ have_example_db, have_archive_db;
SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache;
+SHOW_COMP_OPTION have_geometry, have_rtree_keys;
SHOW_COMP_OPTION have_crypt, have_compress;
/* Thread specific variables */
@@ -665,7 +656,7 @@ static void close_connections(void)
break;
}
#ifndef __bsdi__ // Bug in BSDI kernel
- if (tmp->net.vio)
+ if (tmp->vio_ok())
{
sql_print_error(ER(ER_FORCING_CLOSE),my_progname,
tmp->thread_id,tmp->user ? tmp->user : "");
@@ -831,7 +822,6 @@ static void __cdecl kill_server(int sig_ptr)
#if defined(USE_ONE_SIGNAL_HAND) || (defined(__NETWARE__) && defined(SIGNALS_DONT_BREAK_READ))
extern "C" pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
{
- SHUTDOWN_THD;
my_thread_init(); // Initialize new thread
kill_server(0);
my_thread_end(); // Normally never reached
@@ -914,6 +904,7 @@ void clean_up(bool print_message)
if (use_slave_mask)
bitmap_free(&slave_error_mask);
#endif
+ my_tz_free();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
acl_free(1);
grant_free();
@@ -1259,6 +1250,12 @@ static void server_init(void)
{
DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
+ if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
+ {
+ sql_print_error("The socket file path is too long (> %d): %s",
+ sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
+ unireg_abort(1);
+ }
if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
@@ -1507,7 +1504,7 @@ void mysql_cb_init()
}
-/ *To get the name of the NetWare volume having MySQL data folder */
+/* To get the name of the NetWare volume having MySQL data folder */
static void getvolumename()
{
@@ -1578,6 +1575,7 @@ static void registerwithneb()
/*
Callback for NSS Volume Deactivation event
*/
+
ulong neb_event_callback(struct EventBlock *eblock)
{
EventChangeVolStateEnter_s *voldata;
@@ -1606,7 +1604,7 @@ ulong neb_event_callback(struct EventBlock *eblock)
#define ADMIN_VOL_PATH "_ADMIN:/Volumes/"
-staticvoid getvolumeID(BYTE *volumeName)
+static void getvolumeID(BYTE *volumeName)
{
char path[zMAX_FULL_NAME];
Key_t rootKey= 0, fileKey= 0;
@@ -1614,7 +1612,7 @@ staticvoid getvolumeID(BYTE *volumeName)
zInfo_s info;
STATUS status;
- /* Get the root key */
+ /* Get the root key */
if ((status= zRootKey(0, &rootKey)) != zOK)
{
consoleprintf("\nGetNSSVolumeProperties - Failed to get root key, status: %d\n.", (int) status);
@@ -1718,7 +1716,6 @@ static void init_signals(void)
signal(SIGALRM, SIG_IGN);
signal(SIGBREAK,SIG_IGN);
signal_thread = pthread_self();
- SIGNAL_THD;
}
static void start_signal_handler(void)
@@ -2122,7 +2119,6 @@ int uname(struct utsname *a)
extern "C" pthread_handler_decl(handle_shutdown,arg)
{
MSG msg;
- SHUTDOWN_THD;
my_thread_init();
/* this call should create the message queue for this thread */
@@ -2151,7 +2147,6 @@ int STDCALL handle_kill(ulong ctrl_type)
#ifdef OS2
extern "C" pthread_handler_decl(handle_shutdown,arg)
{
- SHUTDOWN_THD;
my_thread_init();
// wait semaphore
@@ -2276,9 +2271,17 @@ static int init_common_variables(const char *conf_file_name, int argc,
{
struct tm tm_tmp;
localtime_r(&start_time,&tm_tmp);
- strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
+ strmov(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
}
#endif
+ /*
+ We set SYSTEM time zone as reasonable default and
+ also for failure of my_tz_init() and bootstrap mode.
+ If user explicitly set time zone with --default-time-zone
+ option we will change this value in my_tz_init().
+ */
+ global_system_variables.time_zone= my_tz_SYSTEM;
+
/*
Init mutexes for the global MYSQL_LOG objects.
@@ -2584,6 +2587,41 @@ server.");
}
}
+ if (opt_innodb_safe_binlog)
+ {
+ if (have_innodb != SHOW_OPTION_YES)
+ sql_print_error("Warning: --innodb-safe-binlog is meaningful only if "
+ "the InnoDB storage engine is enabled in the server.");
+#ifdef HAVE_INNOBASE_DB
+ if (innobase_flush_log_at_trx_commit != 1)
+ {
+ sql_print_error("Warning: --innodb-safe-binlog is meaningful only if "
+ "innodb_flush_log_at_trx_commit is 1; now setting it "
+ "to 1.");
+ innobase_flush_log_at_trx_commit= 1;
+ }
+ if (innobase_unix_file_flush_method)
+ {
+ /*
+ This option has so many values that it's hard to know which value is
+ good (especially "littlesync", and on Windows... see
+ srv/srv0start.c).
+ */
+ sql_print_error("Warning: --innodb-safe-binlog requires that "
+ "the innodb_flush_method actually synchronizes the "
+ "InnoDB log to disk; it is your responsibility "
+ "to verify that the method you chose does it.");
+ }
+ if (sync_binlog_period != 1)
+ {
+ sql_print_error("Warning: --innodb-safe-binlog is meaningful only if "
+ "the global sync_binlog variable is 1; now setting it "
+ "to 1.");
+ sync_binlog_period= 1;
+ }
+#endif
+ }
+
if (ha_init())
{
sql_print_error("Can't init databases");
@@ -2592,6 +2630,18 @@ server.");
if (opt_myisam_log)
(void) mi_log(1);
+ /*
+ Now that InnoDB is initialized, we can know the last good binlog position
+ and cut the binlog if needed. This function does nothing if there was no
+ crash recovery by InnoDB.
+ */
+ if (opt_innodb_safe_binlog)
+ {
+ /* not fatal if fails (but print errors) */
+ mysql_bin_log.cut_spurious_tail();
+ }
+ mysql_bin_log.report_pos_in_innodb();
+
/* call ha_init_key_cache() on all key caches to init them */
process_key_caches(&ha_init_key_cache);
/* We must set dflt_key_cache in case we are using ISAM tables */
@@ -2862,7 +2912,8 @@ we force server id to 2, but this MySQL server will not act as a slave.");
*/
error_handler_hook = my_message_sql;
start_signal_handler(); // Creates pidfile
- if (acl_init((THD *)0, opt_noacl))
+ if (acl_init((THD *)0, opt_noacl) ||
+ my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
{
abort_loop=1;
select_thread_in_use=0;
@@ -3069,7 +3120,7 @@ int main(int argc, char **argv)
need to have an unique named hEventShudown through the
application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
*/
- int2str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
+ int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
"MySQLShutdown"), 10);
/* Must be initialized early for comparison of service name */
@@ -3713,7 +3764,7 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
HANDLE event_server_read= 0;
THD *thd= 0;
- p= int2str(connect_number, connect_number_char, 10);
+ p= int10_to_str(connect_number, connect_number_char, 10);
/*
The name of event and file-mapping events create agree next rule:
shared_memory_base_name+unique_part+number_of_connection
@@ -3890,8 +3941,8 @@ enum options_mysqld
OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
OPT_INNODB_FLUSH_METHOD,
OPT_INNODB_FAST_SHUTDOWN,
- OPT_INNODB_FILE_PER_TABLE,
- OPT_SAFE_SHOW_DB,
+ OPT_INNODB_FILE_PER_TABLE, OPT_CRASH_BINLOG_INNODB,
+ OPT_SAFE_SHOW_DB, OPT_INNODB_SAFE_BINLOG,
OPT_INNODB, OPT_ISAM, OPT_NDBCLUSTER, OPT_SKIP_SAFEMALLOC,
OPT_TEMP_POOL, OPT_TX_ISOLATION,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
@@ -3961,7 +4012,7 @@ enum options_mysqld
OPT_RANGE_ALLOC_BLOCK_SIZE,
OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
- OPT_SYNC_FRM, OPT_BDB_NOSYNC,
+ OPT_SYNC_FRM, OPT_SYNC_BINLOG, OPT_BDB_NOSYNC,
OPT_ENABLE_SHARED_MEMORY,
OPT_SHARED_MEMORY_BASE_NAME,
OPT_OLD_PASSWORDS,
@@ -3975,6 +4026,7 @@ enum options_mysqld
OPT_TIME_FORMAT,
OPT_DATETIME_FORMAT,
OPT_LOG_QUERIES_NOT_USING_INDEXES,
+ OPT_DEFAULT_TIME_ZONE,
OPT_OPTIMIZER_SEARCH_DEPTH,
OPT_OPTIMIZER_PRUNE_LEVEL
};
@@ -4038,6 +4090,12 @@ Disable with --skip-bdb (will save memory).",
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"character_set_server", 'C', "Set the default character set.",
+ (gptr*) &default_character_set_name, (gptr*) &default_character_set_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ {"collation_server", OPT_DEFAULT_COLLATION, "Set the default collation.",
+ (gptr*) &default_collation_name, (gptr*) &default_collation_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.",
(gptr*) &opt_console, (gptr*) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
@@ -4071,10 +4129,10 @@ Disable with --skip-bdb (will save memory).",
(gptr*) &des_key_file, (gptr*) &des_key_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
#endif /* HAVE_OPENSSL */
- {"default-character-set", 'C', "Set the default character set.",
+ {"default-character-set", 'C', "Set the default character set (Deprecated option, use character_set_server instead).",
(gptr*) &default_character_set_name, (gptr*) &default_character_set_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
- {"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation.",
+ {"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation (Deprecated option, use character_set_server instead).",
(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,
@@ -4083,6 +4141,9 @@ Disable with --skip-bdb (will save memory).",
{"default-table-type", OPT_STORAGE_ENGINE,
"(deprecated) Use default-storage-engine.", 0, 0,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.",
+ (gptr*) &default_tz_name, (gptr*) &default_tz_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE.",
0,0,0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"delay-key-write-for-all-tables", OPT_DELAY_KEY_WRITE_ALL,
@@ -4529,11 +4590,11 @@ log and this option does nothing anymore.",
NO_ARG, 0, 0, 0, 0, 0, 0},
{"log-warnings", 'W', "Log some not critical warnings to the log file.",
(gptr*) &global_system_variables.log_warnings,
- (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 1, 0, 0,
+ (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0,
0, 0, 0},
{"warnings", 'W', "Deprecated ; Use --log-warnings instead.",
(gptr*) &global_system_variables.log_warnings,
- (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 1, 0, 0,
+ (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0,
0, 0, 0},
{ "back_log", OPT_BACK_LOG,
"The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.",
@@ -4565,6 +4626,12 @@ log and this option does nothing anymore.",
"The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'.",
(gptr*) &connect_timeout, (gptr*) &connect_timeout,
0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 },
+#ifdef HAVE_REPLICATION
+ {"crash_binlog_innodb", OPT_CRASH_BINLOG_INNODB,
+ "Used only for testing, to crash when writing Nth event to binlog.",
+ (gptr*) &opt_crash_binlog_innodb, (gptr*) &opt_crash_binlog_innodb,
+ 0, GET_UINT, REQUIRED_ARG, 0, 0, ~(uint)0, 0, 1, 0},
+#endif
{"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT,
"How long a INSERT DELAYED thread should wait for INSERT statements before terminating.",
(gptr*) &delayed_insert_timeout, (gptr*) &delayed_insert_timeout, 0,
@@ -4644,6 +4711,26 @@ log and this option does nothing anymore.",
"Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.",
(gptr*) &innobase_lock_wait_timeout, (gptr*) &innobase_lock_wait_timeout,
0, GET_LONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
+#ifdef HAVE_REPLICATION
+ /*
+ Disabled for the 4.1.3 release. Disabling just this paragraph of code is
+ enough, as then user can't set it to 1 so it will always be ignored in the
+ rest of code.
+ */
+#if MYSQL_VERSION_ID >= 40103
+ /*
+ innodb_safe_binlog is not a variable, just an option. Does not make
+ sense to make it a variable, as it is only used at startup (and so the
+ value would be lost at next startup, so setting it on the fly would have no
+ effect).
+ */
+ {"innodb_safe_binlog", OPT_INNODB_SAFE_BINLOG,
+ "After a crash recovery by InnoDB, truncate the binary log after the last "
+ "not-rolled-back statement/transaction.",
+ (gptr*) &opt_innodb_safe_binlog, (gptr*) &opt_innodb_safe_binlog,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
+#endif
+#endif
{"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY,
"Helps in performance tuning in heavily concurrent environments.",
(gptr*) &innobase_thread_concurrency, (gptr*) &innobase_thread_concurrency,
@@ -4950,6 +5037,12 @@ The minimum value for this variable is 4096.",
(gptr*) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG,
MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD,
1, 0},
+ {"sync-binlog", OPT_SYNC_BINLOG,
+ "Sync the binlog to disk after every #th event. \
+#=0 (the default) does no sync. Syncing slows MySQL down",
+ (gptr*) &sync_binlog_period,
+ (gptr*) &sync_binlog_period, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1,
+ 0},
{"table_cache", OPT_TABLE_CACHE,
"The number of open tables for all threads.", (gptr*) &table_cache_size,
(gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L,
@@ -4999,18 +5092,18 @@ The minimum value for this variable is 4096.",
0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0},
{ "date-format", OPT_DATE_FORMAT,
"The DATE format (For future).",
- (gptr*) &opt_date_time_formats[TIMESTAMP_DATE],
- (gptr*) &opt_date_time_formats[TIMESTAMP_DATE],
+ (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE],
+ (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE],
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ "datetime-format", OPT_DATETIME_FORMAT,
"The DATETIME/TIMESTAMP format (for future).",
- (gptr*) &opt_date_time_formats[TIMESTAMP_DATETIME],
- (gptr*) &opt_date_time_formats[TIMESTAMP_DATETIME],
+ (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME],
+ (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME],
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ "time-format", OPT_TIME_FORMAT,
"The TIME format (for future).",
- (gptr*) &opt_date_time_formats[TIMESTAMP_TIME],
- (gptr*) &opt_date_time_formats[TIMESTAMP_TIME],
+ (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME],
+ (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME],
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -5107,6 +5200,12 @@ struct show_var_st status_vars[]= {
{"Com_unlock_tables", (char*) (com_stat+(uint) SQLCOM_UNLOCK_TABLES),SHOW_LONG},
{"Com_update", (char*) (com_stat+(uint) SQLCOM_UPDATE),SHOW_LONG},
{"Com_update_multi", (char*) (com_stat+(uint) SQLCOM_UPDATE_MULTI),SHOW_LONG},
+ {"Com_prepare_sql", (char*) (com_stat+(uint) SQLCOM_PREPARE),
+ SHOW_LONG},
+ {"Com_execute_sql", (char*) (com_stat+(uint) SQLCOM_EXECUTE),
+ SHOW_LONG},
+ {"Com_dealloc_sql", (char*) (com_stat+(uint)
+ SQLCOM_DEALLOCATE_PREPARE), SHOW_LONG},
{"Connections", (char*) &thread_id, SHOW_LONG_CONST},
{"Created_tmp_disk_tables", (char*) &created_tmp_disk_tables,SHOW_LONG},
{"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG},
@@ -5322,7 +5421,6 @@ static void mysql_init_variables(void)
specialflag= opened_tables= created_tmp_tables= created_tmp_disk_tables= 0;
binlog_cache_use= binlog_cache_disk_use= 0;
max_used_connections= slow_launch_threads = 0;
- max_sort_char= 0;
mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
errmesg= 0;
mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
@@ -5429,6 +5527,11 @@ static void mysql_init_variables(void)
#else
have_example_db= SHOW_OPTION_NO;
#endif
+#ifdef HAVE_ARCHIVE_DB
+ have_archive_db= SHOW_OPTION_YES;
+#else
+ have_archive_db= SHOW_OPTION_NO;
+#endif
#ifdef HAVE_NDBCLUSTER_DB
have_ndbcluster=SHOW_OPTION_DISABLED;
#else
@@ -5454,6 +5557,16 @@ static void mysql_init_variables(void)
#else
have_query_cache=SHOW_OPTION_NO;
#endif
+#ifdef HAVE_SPATIAL
+ have_geometry=SHOW_OPTION_YES;
+#else
+ have_geometry=SHOW_OPTION_NO;
+#endif
+#ifdef HAVE_RTREE_KEYS
+ have_rtree_keys=SHOW_OPTION_YES;
+#else
+ have_rtree_keys=SHOW_OPTION_NO;
+#endif
#ifdef HAVE_CRYPT
have_crypt=SHOW_OPTION_YES;
#else
@@ -5525,7 +5638,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
mysql_data_home= mysql_real_data_home;
break;
case 'u':
- if (!mysqld_user)
+ if (!mysqld_user || !strcmp(mysqld_user, argument))
mysqld_user= argument;
else
fprintf(stderr, "Warning: Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
@@ -5555,6 +5668,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'V':
print_version();
exit(0);
+ case 'W':
+ if (!argument)
+ global_system_variables.log_warnings++;
+ else if (argument == disabled_my_option)
+ global_system_variables.log_warnings= 0L;
+ else
+ global_system_variables.log_warnings= atoi(argument);
+ break;
case 'T':
test_flags= argument ? (uint) atoi(argument) : 0;
test_flags&= ~TEST_NO_THREADS;
@@ -6089,11 +6210,11 @@ static void get_options(int argc,char **argv)
if (opt_log_queries_not_using_indexes)
opt_specialflag|= SPECIAL_LOG_QUERIES_NOT_USING_INDEXES;
- if (init_global_datetime_format(TIMESTAMP_DATE,
+ if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
&global_system_variables.date_format) ||
- init_global_datetime_format(TIMESTAMP_TIME,
+ init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
&global_system_variables.time_format) ||
- init_global_datetime_format(TIMESTAMP_DATETIME,
+ init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
&global_system_variables.datetime_format))
exit(1);
}
@@ -6316,7 +6437,7 @@ static void create_pid_file()
O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
{
char buff[21], *end;
- end= int2str((long) getpid(), buff, 10);
+ end= int10_to_str((long) getpid(), buff, 10);
*end++= '\n';
(void) my_write(file, (byte*) buff, (uint) (end-buff),MYF(MY_WME));
(void) my_close(file, MYF(0));
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 5e5d4b14c89..36a10370508 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -285,7 +285,9 @@ my_net_write(NET *net,const char *packet,ulong len)
buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE))
return 1;
+#ifndef DEBUG_DATA_PACKETS
DBUG_DUMP("packet_header",(char*) buff,NET_HEADER_SIZE);
+#endif
return test(net_write_buff(net,packet,len));
}
@@ -395,6 +397,9 @@ net_write_buff(NET *net,const char *packet,ulong len)
else
left_length= (ulong) (net->buff_end - net->write_pos);
+#ifdef DEBUG_DATA_PACKETS
+ DBUG_DUMP("data", packet, len);
+#endif
if (len > left_length)
{
if (net->write_pos != net->buff)
@@ -777,6 +782,8 @@ my_real_read(NET *net, ulong *complen)
if (i == 0)
{ /* First parts is packet length */
ulong helping;
+ DBUG_DUMP("packet_header",(char*) net->buff+net->where_b,
+ NET_HEADER_SIZE);
if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr)
{
if (net->buff[net->where_b] != (uchar) 255)
@@ -785,7 +792,6 @@ my_real_read(NET *net, ulong *complen)
("Packets out of order (Found: %d, expected %u)",
(int) net->buff[net->where_b + 3],
net->pkt_nr));
- DBUG_DUMP("packet_header",(char*) net->buff+net->where_b, 4);
#ifdef EXTRA_DEBUG
fprintf(stderr,"Packets out of order (Found: %d, expected %d)\n",
(int) net->buff[net->where_b + 3],
@@ -842,6 +848,10 @@ end:
vio_blocking(net->vio, net_blocking, &old_mode);
}
net->reading_or_writing=0;
+#ifdef DEBUG_DATA_PACKETS
+ if (len != packet_error)
+ DBUG_DUMP("data",(char*) net->buff+net->where_b, len);
+#endif
return(len);
}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index f14f331008d..08eae68c855 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -729,7 +729,7 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
int QUICK_RANGE_SELECT::init()
{
DBUG_ENTER("QUICK_RANGE_SELECT::init");
- DBUG_RETURN(error= file->index_init(index));
+ DBUG_RETURN(error= file->ha_index_init(index));
}
QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
@@ -737,7 +737,8 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
DBUG_ENTER("QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT");
if (!dont_free)
{
- file->index_end();
+ if (file->inited)
+ file->ha_index_end();
file->extra(HA_EXTRA_NO_KEYREAD);
delete_dynamic(&ranges); /* ranges are allocated in alloc */
if (free_file)
@@ -1514,7 +1515,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
table_map prev_tables,
ha_rows limit, bool force_quick_range)
{
- uint basflag;
uint idx;
double scan_time;
DBUG_ENTER("test_quick_select");
@@ -1529,14 +1529,13 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (!cond || (specialflag & SPECIAL_SAFE_MODE) && ! force_quick_range ||
!limit)
DBUG_RETURN(0); /* purecov: inspected */
- if (!((basflag= head->file->table_flags()) & HA_KEYPOS_TO_RNDPOS) &&
- keys_to_use.is_set_all() || keys_to_use.is_clear_all())
- DBUG_RETURN(0); /* Not smart database */
+ if (keys_to_use.is_clear_all())
+ DBUG_RETURN(0);
records=head->file->records;
if (!records)
records++; /* purecov: inspected */
scan_time=(double) records / TIME_FOR_COMPARE+1;
- read_time=(double) head->file->scan_time()+ scan_time + 1.0;
+ read_time=(double) head->file->scan_time()+ scan_time + 1.1;
if (head->force_index)
scan_time= read_time= DBL_MAX;
if (limit < records)
@@ -1557,7 +1556,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
/* set up parameter that is passed to all functions */
param.thd= thd;
- param.baseflag=basflag;
+ param.baseflag=head->file->table_flags();
param.prev_tables=prev_tables | const_tables;
param.read_tables=read_tables;
param.current_table= head->map;
@@ -2971,7 +2970,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
}
if (found_records != HA_POS_ERROR && found_records > 2 &&
read_index_only &&
- (param->table->file->index_flags(keynr) & HA_KEY_READ_ONLY) &&
+ (param->table->file->index_flags(keynr) & HA_KEYREAD_ONLY) &&
!(pk_is_clustered && keynr == param->table->primary_key))
{
/* We can resolve this by only reading through this key. */
@@ -2988,6 +2987,8 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
found_records)+
(double) found_records / TIME_FOR_COMPARE);
}
+ DBUG_PRINT("info",("read_time: %g found_read_time: %g",
+ read_time, found_read_time));
if (read_time > found_read_time && found_records != HA_POS_ERROR
/*|| read_time == DBL_MAX*/ )
{
@@ -3991,7 +3992,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
{
swap_variables(SEL_ARG *,key1,key2);
}
- else if (!(key1=key1->clone_tree()))
+ if (key1->use_count > 0 || !(key1=key1->clone_tree()))
return 0; // OOM
}
@@ -4060,10 +4061,10 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
SEL_ARG *next=key2->next; // Keys are not overlapping
if (key2_shared)
{
- SEL_ARG *tmp= new SEL_ARG(*key2); // Must make copy
- if (!tmp)
+ SEL_ARG *cpy= new SEL_ARG(*key2); // Must make copy
+ if (!cpy)
return 0; // OOM
- key1=key1->insert(tmp);
+ key1=key1->insert(cpy);
key2->increment_use_count(key1->use_count+1);
}
else
@@ -4299,8 +4300,17 @@ SEL_ARG::find_range(SEL_ARG *key)
/*
-** Remove a element from the tree
-** This also frees all sub trees that is used by the element
+ Remove a element from the tree
+
+ SYNOPSIS
+ tree_delete()
+ key Key that is to be deleted from tree (this)
+
+ NOTE
+ This also frees all sub trees that is used by the element
+
+ RETURN
+ root of new tree (with key deleted)
*/
SEL_ARG *
@@ -4308,7 +4318,10 @@ SEL_ARG::tree_delete(SEL_ARG *key)
{
enum leaf_color remove_color;
SEL_ARG *root,*nod,**par,*fix_par;
- root=this; this->parent= 0;
+ DBUG_ENTER("tree_delete");
+
+ root=this;
+ this->parent= 0;
/* Unlink from list */
if (key->prev)
@@ -4355,7 +4368,7 @@ SEL_ARG::tree_delete(SEL_ARG *key)
}
if (root == &null_element)
- return 0; // Maybe root later
+ DBUG_RETURN(0); // Maybe root later
if (remove_color == BLACK)
root=rb_delete_fixup(root,nod,fix_par);
test_rb_tree(root,root->parent);
@@ -4363,7 +4376,7 @@ SEL_ARG::tree_delete(SEL_ARG *key)
root->use_count=this->use_count; // Fix root counters
root->elements=this->elements-1;
root->maybe_flag=this->maybe_flag;
- return root;
+ DBUG_RETURN(root);
}
@@ -5223,7 +5236,6 @@ bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List<Item> *fields)
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
TABLE_REF *ref)
{
- table->file->index_end(); // Remove old cursor
QUICK_RANGE_SELECT *quick=new QUICK_RANGE_SELECT(thd, table, ref->key, 1);
KEY *key_info = &table->key_info[ref->key];
KEY_PART *key_part;
@@ -5719,22 +5731,13 @@ QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q,
uint used_key_parts)
: QUICK_RANGE_SELECT(*q), rev_it(rev_ranges)
{
- bool not_read_after_key = file->table_flags() & HA_NOT_READ_AFTER_KEY;
QUICK_RANGE *r;
QUICK_RANGE **pr= (QUICK_RANGE**)ranges.buffer;
QUICK_RANGE **last_range= pr + ranges.elements;
- for (; pr!=last_range; ++pr)
- {
- r= *pr;
- rev_ranges.push_front(r);
- if (not_read_after_key && range_reads_after_key(r))
- {
- error = HA_ERR_UNSUPPORTED;
- dont_free=1; // Don't free memory from 'q'
- return;
- }
- }
+ for (; pr!=last_range; pr++)
+ rev_ranges.push_front(*pr);
+
/* Remove EQ_RANGE flag for keys that are not using the full key */
for (r = rev_it++; r; r = rev_it++)
{
@@ -5803,29 +5806,10 @@ int QUICK_SELECT_DESC::get_next()
else
{
DBUG_ASSERT(range->flag & NEAR_MAX || range_reads_after_key(range));
-#ifndef NOT_IMPLEMENTED_YET
result=file->index_read(record, (byte*) range->max_key,
range->max_length,
((range->flag & NEAR_MAX) ?
HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV));
-#else
- /*
- Heikki changed Sept 11, 2002: since InnoDB does not store the cursor
- position if READ_KEY_EXACT is used to a primary key with all
- key columns specified, we must use below HA_READ_KEY_OR_NEXT,
- so that InnoDB stores the cursor position and is able to move
- the cursor one step backward after the search.
- */
- /*
- Note: even if max_key is only a prefix, HA_READ_AFTER_KEY will
- do the right thing - go past all keys which match the prefix
- */
- result=file->index_read(record, (byte*) range->max_key,
- range->max_length,
- ((range->flag & NEAR_MAX) ?
- HA_READ_KEY_OR_NEXT : HA_READ_AFTER_KEY));
- result = file->index_prev(record);
-#endif
}
if (result)
{
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 8c1cd9ce1cb..75b00b97ce7 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -46,9 +46,9 @@
#include "mysql_priv.h"
#include "sql_select.h"
-static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
- Field* field, COND *cond,
- uint *range_fl, uint *key_prefix_length);
+static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, Field* field,
+ COND *cond, uint *range_fl,
+ uint *key_prefix_length);
static int reckey_in_range(bool max_fl, TABLE_REF *ref, Field* field,
COND *cond, uint range_fl, uint prefix_len);
static int maxmin_in_range(bool max_fl, Field* field, COND *cond);
@@ -166,11 +166,6 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
Item_field *item_field= ((Item_field*) expr);
TABLE *table= item_field->field->table;
- if ((table->file->table_flags() & HA_NOT_READ_AFTER_KEY))
- {
- const_result=0;
- break;
- }
/*
Look for a partial key that can be used for optimization.
If we succeed, ref.key_length will contain the length of
@@ -186,7 +181,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
- error= table->file->index_init((uint) ref.key);
+ error= table->file->ha_index_init((uint) ref.key);
if (!ref.key_length)
error= table->file->index_first(table->record[0]);
@@ -206,7 +201,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
table->key_read= 0;
table->file->extra(HA_EXTRA_NO_KEYREAD);
}
- table->file->index_end();
+ table->file->ha_index_end();
if (error)
{
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
@@ -260,12 +255,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
- if ((table->file->table_flags() & HA_NOT_READ_AFTER_KEY))
- {
- const_result= 0;
- break;
- }
- error= table->file->index_init((uint) ref.key);
+ error= table->file->ha_index_init((uint) ref.key);
if (!ref.key_length)
error= table->file->index_last(table->record[0]);
@@ -285,7 +275,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
table->key_read=0;
table->file->extra(HA_EXTRA_NO_KEYREAD);
}
- table->file->index_end();
+ table->file->ha_index_end();
if (error)
{
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
@@ -648,7 +638,7 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
keyinfo != keyinfo_end;
keyinfo++,idx++)
{
- if (table->file->index_flags(idx) & HA_WRONG_ASCII_ORDER)
+ if (!(table->file->index_flags(idx) & HA_READ_ORDER))
break;
KEY_PART_INFO *part,*part_end;
diff --git a/sql/password.c b/sql/password.c
index 9f4910d8c60..0ac91346a55 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -218,6 +218,8 @@ check_scramble_323(const char *scrambled, const char *message,
to=buff;
for (pos=scrambled ; *pos ; pos++)
*to++=(char) (floor(my_rnd(&rand_st)*31)+64);
+ if (pos-scrambled != SCRAMBLE_LENGTH_323)
+ return 1;
extra=(char) (floor(my_rnd(&rand_st)*31));
to=buff;
while (*scrambled)
@@ -321,8 +323,8 @@ octet2hex(char *to, const uint8 *str, uint len)
const uint8 *str_end= str + len;
for (; str != str_end; ++str)
{
- *to++= _dig_vec[(*str & 0xF0) >> 4];
- *to++= _dig_vec[*str & 0x0F];
+ *to++= _dig_vec_upper[(*str & 0xF0) >> 4];
+ *to++= _dig_vec_upper[*str & 0x0F];
}
*to= '\0';
}
diff --git a/sql/protocol.cc b/sql/protocol.cc
index b2334b0f356..065fcd3d4af 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -27,6 +27,8 @@
#include "sp_rcontext.h"
#include <stdarg.h>
+static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
+
#ifndef EMBEDDED_LIBRARY
bool Protocol::net_store_data(const char *from, uint length)
#else
@@ -700,7 +702,7 @@ bool Protocol_simple::store_null()
#endif
char buff[1];
buff[0]= (char)251;
- return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
+ return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
}
#endif
@@ -1003,7 +1005,7 @@ bool Protocol_prep::store_tiny(longlong from)
char buff[1];
field_pos++;
buff[0]= (uchar) from;
- return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
+ return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
}
@@ -1015,7 +1017,7 @@ bool Protocol_prep::store_short(longlong from)
field_types[field_pos] == MYSQL_TYPE_YEAR);
#endif
field_pos++;
- char *to= packet->prep_append(2, PACKET_BUFFET_EXTRA_ALLOC);
+ char *to= packet->prep_append(2, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
return 1;
int2store(to, (int) from);
@@ -1031,7 +1033,7 @@ bool Protocol_prep::store_long(longlong from)
field_types[field_pos] == MYSQL_TYPE_LONG);
#endif
field_pos++;
- char *to= packet->prep_append(4, PACKET_BUFFET_EXTRA_ALLOC);
+ char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
return 1;
int4store(to, from);
@@ -1046,7 +1048,7 @@ bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
field_types[field_pos] == MYSQL_TYPE_LONGLONG);
#endif
field_pos++;
- char *to= packet->prep_append(8, PACKET_BUFFET_EXTRA_ALLOC);
+ char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
return 1;
int8store(to, from);
@@ -1061,7 +1063,7 @@ bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
field_types[field_pos] == MYSQL_TYPE_FLOAT);
#endif
field_pos++;
- char *to= packet->prep_append(4, PACKET_BUFFET_EXTRA_ALLOC);
+ char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
return 1;
float4store(to, from);
@@ -1076,7 +1078,7 @@ bool Protocol_prep::store(double from, uint32 decimals, String *buffer)
field_types[field_pos] == MYSQL_TYPE_DOUBLE);
#endif
field_pos++;
- char *to= packet->prep_append(8, PACKET_BUFFET_EXTRA_ALLOC);
+ char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
return 1;
float8store(to, from);
@@ -1125,7 +1127,7 @@ bool Protocol_prep::store(TIME *tm)
else
length=0;
buff[0]=(char) length; // Length is stored first
- return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
+ return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
}
bool Protocol_prep::store_date(TIME *tm)
@@ -1142,7 +1144,7 @@ bool Protocol_prep::store_time(TIME *tm)
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_TIME);
#endif
- char buff[15],*pos;
+ char buff[13], *pos;
uint length;
field_pos++;
pos= buff+1;
@@ -1153,11 +1155,11 @@ bool Protocol_prep::store_time(TIME *tm)
pos[7]= (uchar) tm->second;
int4store(pos+8, tm->second_part);
if (tm->second_part)
- length=11;
+ length=12;
else if (tm->hour || tm->minute || tm->second || tm->day)
length=8;
else
length=0;
buff[0]=(char) length; // Length is stored first
- return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
+ return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
}
diff --git a/sql/protocol.h b/sql/protocol.h
index 25efecab712..079c06ae155 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -18,7 +18,6 @@
#pragma interface /* gcc class implementation */
#endif
-#define PACKET_BUFFET_EXTRA_ALLOC 1024
class i_string;
class THD;
@@ -36,8 +35,10 @@ protected:
enum enum_field_types *field_types;
#endif
uint field_count;
+#ifndef EMBEDDED_LIBRARY
bool net_store_data(const char *from, uint length);
-#ifdef EMBEDDED_LIBRARY
+#else
+ virtual bool net_store_data(const char *from, uint length);
char **next_field;
MYSQL_FIELD *next_mysql_field;
MEM_ROOT *alloc;
diff --git a/sql/records.cc b/sql/records.cc
index 264f7fe1241..37fbc7570ed 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -70,7 +70,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
info->io_cache=tempfile;
reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
info->ref_pos=table->file->ref;
- table->file->rnd_init(0);
+ if (!table->file->inited)
+ table->file->ha_rnd_init(0);
/*
table->sort.addon_field is checked because if we use addon fields,
@@ -105,7 +106,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
else if (table->sort.record_pointers)
{
DBUG_PRINT("info",("using record_pointers"));
- table->file->rnd_init(0);
+ table->file->ha_rnd_init(0);
info->cache_pos=table->sort.record_pointers;
info->cache_end=info->cache_pos+
table->sort.found_records*info->ref_length;
@@ -116,7 +117,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
{
DBUG_PRINT("info",("using rr_sequential"));
info->read_record=rr_sequential;
- table->file->rnd_init();
+ table->file->ha_rnd_init(1);
/* We can use record cache if we don't update dynamic length tables */
if (!table->no_cache &&
(use_record_cache > 0 ||
@@ -142,7 +143,8 @@ void end_read_record(READ_RECORD *info)
{
filesort_free_buffers(info->table);
(void) info->file->extra(HA_EXTRA_NO_CACHE);
- (void) info->file->rnd_end();
+ if (info->read_record != rr_quick) // otherwise quick_range does it
+ (void) info->file->ha_index_or_rnd_end();
info->table=0;
}
}
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 2a5381ae478..4feb24f06b2 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -63,6 +63,11 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
static int init_failsafe_rpl_thread(THD* thd)
{
DBUG_ENTER("init_failsafe_rpl_thread");
+ /*
+ thd->bootstrap is to report errors barely to stderr; if this code is
+ enable again one day, one should check if bootstrap is still needed (maybe
+ this thread has no other error reporting method).
+ */
thd->system_thread = thd->bootstrap = 1;
thd->host_or_ip= "";
thd->client_capabilities = 0;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 811c700d527..614d615e37b 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -183,7 +183,7 @@ sys_var_key_cache_long sys_key_cache_age_threshold("key_cache_age_threshold",
param_age_threshold));
sys_var_bool_ptr sys_local_infile("local_infile",
&opt_local_infile);
-sys_var_thd_bool sys_log_warnings("log_warnings", &SV::log_warnings);
+sys_var_thd_ulong sys_log_warnings("log_warnings", &SV::log_warnings);
sys_var_thd_ulong sys_long_query_time("long_query_time",
&SV::long_query_time);
sys_var_thd_bool sys_low_priority_updates("low_priority_updates",
@@ -330,6 +330,10 @@ sys_var_thd_table_type sys_table_type("table_type",
&SV::table_type);
sys_var_thd_storage_engine sys_storage_engine("storage_engine",
&SV::table_type);
+#ifdef HAVE_REPLICATION
+sys_var_sync_binlog_period sys_sync_binlog_period("sync_binlog", &sync_binlog_period);
+#endif
+sys_var_bool_ptr sys_sync_frm("sync_frm", &opt_sync_frm);
sys_var_long_ptr sys_table_cache_size("table_cache",
&table_cache_size);
sys_var_long_ptr sys_thread_cache_size("thread_cache_size",
@@ -352,13 +356,13 @@ sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_p
sys_var_thd_date_time_format sys_time_format("time_format",
&SV::time_format,
- TIMESTAMP_TIME);
+ MYSQL_TIMESTAMP_TIME);
sys_var_thd_date_time_format sys_date_format("date_format",
&SV::date_format,
- TIMESTAMP_DATE);
+ MYSQL_TIMESTAMP_DATE);
sys_var_thd_date_time_format sys_datetime_format("datetime_format",
&SV::datetime_format,
- TIMESTAMP_DATETIME);
+ MYSQL_TIMESTAMP_DATETIME);
/* Variables that are bits in THD */
@@ -442,6 +446,7 @@ static sys_var_thd_ulong sys_default_week_format("default_week_format",
sys_var_thd_ulong sys_group_concat_max_len("group_concat_max_len",
&SV::group_concat_max_len);
+sys_var_thd_time_zone sys_time_zone("time_zone");
/* Read only variables */
@@ -580,11 +585,16 @@ sys_var *sys_variables[]=
&sys_sql_mode,
&sys_sql_warnings,
&sys_storage_engine,
+#ifdef HAVE_REPLICATION
+ &sys_sync_binlog_period,
+#endif
+ &sys_sync_frm,
&sys_table_cache_size,
&sys_table_type,
&sys_thread_cache_size,
&sys_time_format,
&sys_timestamp,
+ &sys_time_zone,
&sys_tmp_table_size,
&sys_trans_alloc_block_size,
&sys_trans_prealloc_size,
@@ -645,15 +655,18 @@ struct show_var_st init_vars[]= {
{"ft_query_expansion_limit",(char*) &ft_query_expansion_limit, SHOW_LONG},
{"ft_stopword_file", (char*) &ft_stopword_file, SHOW_CHAR_PTR},
{sys_group_concat_max_len.name, (char*) &sys_group_concat_max_len, SHOW_SYS},
+ {"have_archive", (char*) &have_archive_db, SHOW_HAVE},
{"have_bdb", (char*) &have_berkeley_db, SHOW_HAVE},
{"have_compress", (char*) &have_compress, SHOW_HAVE},
{"have_crypt", (char*) &have_crypt, SHOW_HAVE},
{"have_innodb", (char*) &have_innodb, SHOW_HAVE},
{"have_isam", (char*) &have_isam, SHOW_HAVE},
+ {"have_geometry", (char*) &have_geometry, SHOW_HAVE},
{"have_ndbcluster", (char*) &have_ndbcluster, SHOW_HAVE},
{"have_openssl", (char*) &have_openssl, SHOW_HAVE},
{"have_query_cache", (char*) &have_query_cache, SHOW_HAVE},
{"have_raid", (char*) &have_raid, SHOW_HAVE},
+ {"have_rtree_keys", (char*) &have_rtree_keys, SHOW_HAVE},
{"have_symlink", (char*) &have_symlink, SHOW_HAVE},
{"init_connect", (char*) &sys_init_connect, SHOW_SYS},
{"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR},
@@ -796,6 +809,10 @@ struct show_var_st init_vars[]= {
{sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS},
{sys_sql_mode.name, (char*) &sys_sql_mode, SHOW_SYS},
{sys_storage_engine.name, (char*) &sys_storage_engine, SHOW_SYS},
+#ifdef HAVE_REPLICATION
+ {sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period, SHOW_SYS},
+#endif
+ {sys_sync_frm.name, (char*) &sys_sync_frm, SHOW_SYS},
{"table_cache", (char*) &table_cache_size, SHOW_LONG},
{sys_table_type.name, (char*) &sys_table_type, SHOW_SYS},
{sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS},
@@ -805,8 +822,9 @@ struct show_var_st init_vars[]= {
{"thread_stack", (char*) &thread_stack, SHOW_LONG},
{sys_time_format.name, (char*) &sys_time_format, SHOW_SYS},
#ifdef HAVE_TZNAME
- {"timezone", time_zone, SHOW_CHAR},
+ {"system_time_zone", system_time_zone, SHOW_CHAR},
#endif
+ {"time_zone", (char*) &sys_time_zone, SHOW_SYS},
{sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS},
{"tmpdir", (char*) &opt_mysql_tmpdir, SHOW_CHAR_PTR},
{sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size,
@@ -1719,19 +1737,31 @@ CHARSET_INFO *get_old_charset_by_name(const char *name)
bool sys_var_collation::check(THD *thd, set_var *var)
{
CHARSET_INFO *tmp;
- char buff[80];
- String str(buff,sizeof(buff), system_charset_info), *res;
- if (!(res=var->value->val_str(&str)))
+ if (var->value->result_type() == STRING_RESULT)
{
- my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
- return 1;
+ char buff[80];
+ String str(buff,sizeof(buff), system_charset_info), *res;
+ if (!(res=var->value->val_str(&str)))
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
+ return 1;
+ }
+ if (!(tmp=get_charset_by_name(res->c_ptr(),MYF(0))))
+ {
+ my_error(ER_UNKNOWN_COLLATION, MYF(0), res->c_ptr());
+ return 1;
+ }
}
-
- if (!(tmp=get_charset_by_name(res->c_ptr(),MYF(0))))
+ else // INT_RESULT
{
- my_error(ER_UNKNOWN_COLLATION, MYF(0), res->c_ptr());
- return 1;
+ if (!(tmp=get_charset(var->value->val_int(),MYF(0))))
+ {
+ char buf[20];
+ int10_to_str(var->value->val_int(), buf, -10);
+ my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
+ return 1;
+ }
}
var->save_result.charset= tmp; // Save for update
return 0;
@@ -1741,23 +1771,36 @@ bool sys_var_collation::check(THD *thd, set_var *var)
bool sys_var_character_set::check(THD *thd, set_var *var)
{
CHARSET_INFO *tmp;
- char buff[80];
- String str(buff,sizeof(buff), system_charset_info), *res;
- if (!(res=var->value->val_str(&str)))
- {
- if (!nullable)
+ if (var->value->result_type() == STRING_RESULT)
+ {
+ char buff[80];
+ String str(buff,sizeof(buff), system_charset_info), *res;
+ if (!(res=var->value->val_str(&str)))
{
- my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
+ if (!nullable)
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
+ return 1;
+ }
+ tmp= NULL;
+ }
+ else if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) &&
+ !(tmp=get_old_charset_by_name(res->c_ptr())))
+ {
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr());
return 1;
}
- tmp= NULL;
}
- else if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) &&
- !(tmp=get_old_charset_by_name(res->c_ptr())))
+ else // INT_RESULT
{
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr());
- return 1;
+ if (!(tmp=get_charset(var->value->val_int(),MYF(0))))
+ {
+ char buf[20];
+ int10_to_str(var->value->val_int(), buf, -10);
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), buf);
+ return 1;
+ }
}
var->save_result.charset= tmp; // Save for update
return 0;
@@ -1870,6 +1913,20 @@ void sys_var_character_set_server::set_default(THD *thd, enum_var_type type)
}
}
+#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50000)
+bool sys_var_character_set_server::check(THD *thd, set_var *var)
+{
+ if ((var->type == OPT_GLOBAL) &&
+ (mysql_bin_log.is_open() ||
+ active_mi->slave_running || active_mi->rli.slave_running))
+ {
+ my_printf_error(0, "Binary logging and replication forbid changing \
+the global server character set or collation", MYF(0));
+ return 1;
+ }
+ return sys_var_character_set::check(thd,var);
+}
+#endif
CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd,
enum_var_type type)
@@ -1963,6 +2020,20 @@ void sys_var_collation_database::set_default(THD *thd, enum_var_type type)
}
}
+#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50000)
+bool sys_var_collation_server::check(THD *thd, set_var *var)
+{
+ if ((var->type == OPT_GLOBAL) &&
+ (mysql_bin_log.is_open() ||
+ active_mi->slave_running || active_mi->rli.slave_running))
+ {
+ my_printf_error(0, "Binary logging and replication forbid changing \
+the global server character set or collation", MYF(0));
+ return 1;
+ }
+ return sys_var_collation::check(thd,var);
+}
+#endif
bool sys_var_collation_server::update(THD *thd, set_var *var)
{
@@ -2264,6 +2335,22 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
pthread_mutex_unlock(&LOCK_active_mi);
return 0;
}
+
+
+bool sys_var_sync_binlog_period::update(THD *thd, set_var *var)
+{
+ pthread_mutex_t *lock_log= mysql_bin_log.get_log_lock();
+ sync_binlog_period= var->save_result.ulong_value;
+ /*
+ Must reset the counter otherwise it may already be beyond the new period
+ and so the new period will not be taken into account. Need mutex otherwise
+ might be cancelled by a simultanate ++ in MYSQL_LOG::write().
+ */
+ pthread_mutex_lock(lock_log);
+ sync_binlog_counter= 0;
+ pthread_mutex_unlock(lock_log);
+ return 0;
+}
#endif /* HAVE_REPLICATION */
bool sys_var_rand_seed1::update(THD *thd, set_var *var)
@@ -2279,6 +2366,77 @@ bool sys_var_rand_seed2::update(THD *thd, set_var *var)
}
+bool sys_var_thd_time_zone::check(THD *thd, set_var *var)
+{
+ char buff[MAX_TIME_ZONE_NAME_LENGTH];
+ String str(buff, sizeof(buff), &my_charset_latin1);
+ String *res= var->value->val_str(&str);
+
+#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50000)
+ if ((var->type == OPT_GLOBAL) &&
+ (mysql_bin_log.is_open() ||
+ active_mi->slave_running || active_mi->rli.slave_running))
+ {
+ my_printf_error(0, "Binary logging and replication forbid changing "
+ "of the global server time zone", MYF(0));
+ return 1;
+ }
+#endif
+
+ if (!(var->save_result.time_zone= my_tz_find(thd, res)))
+ {
+ my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), res ? res->c_ptr() : "NULL");
+ return 1;
+ }
+ return 0;
+}
+
+
+bool sys_var_thd_time_zone::update(THD *thd, set_var *var)
+{
+ /* We are using Time_zone object found during check() phase */
+ *get_tz_ptr(thd,var->type)= var->save_result.time_zone;
+ return 0;
+}
+
+
+byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ /*
+ We can use ptr() instead of c_ptr() here because String contaning
+ time zone name is guaranteed to be zero ended.
+ */
+ return (byte *)((*get_tz_ptr(thd,type))->get_name()->ptr());
+}
+
+
+Time_zone** sys_var_thd_time_zone::get_tz_ptr(THD *thd,
+ enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return &global_system_variables.time_zone;
+ else
+ return &thd->variables.time_zone;
+}
+
+
+void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ {
+ if (default_tz_name)
+ {
+ String str(default_tz_name, &my_charset_latin1);
+ global_system_variables.time_zone= my_tz_find(thd, &str);
+ }
+ else
+ global_system_variables.time_zone= my_tz_SYSTEM;
+ }
+ else
+ thd->variables.time_zone= global_system_variables.time_zone;
+}
+
/*
Functions to update thd->options bits
*/
@@ -2559,6 +2717,36 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list)
}
+/*
+ Say if all variables set by a SET support the ONE_SHOT keyword (currently,
+ only character set and collation do; later timezones will).
+
+ SYNOPSIS
+
+ not_all_support_one_shot
+ set_var List of variables to update
+
+ NOTES
+ It has a "not_" because it makes faster tests (no need to "!")
+
+ RETURN VALUE
+ 0 all variables of the list support ONE_SHOT
+ 1 at least one does not support ONE_SHOT
+*/
+
+bool not_all_support_one_shot(List<set_var_base> *var_list)
+{
+ List_iterator_fast<set_var_base> it(*var_list);
+ set_var_base *var;
+ while ((var= it++))
+ {
+ if (var->no_support_one_shot())
+ return 1;
+ }
+ return 0;
+}
+
+
/*****************************************************************************
Functions to handle SET mysql_internal_variable=const_expr
*****************************************************************************/
diff --git a/sql/set_var.h b/sql/set_var.h
index 699f320bbd9..a51e44285d6 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -49,10 +49,20 @@ public:
const char *name;
sys_after_update_func after_update;
- sys_var(const char *name_arg) :name(name_arg),after_update(0)
- {}
+#if MYSQL_VERSION_ID < 50000
+ bool no_support_one_shot;
+#endif
+ sys_var(const char *name_arg)
+ :name(name_arg), after_update(0)
+#if MYSQL_VERSION_ID < 50000
+ , no_support_one_shot(1)
+#endif
+ {}
sys_var(const char *name_arg,sys_after_update_func func)
- :name(name_arg),after_update(func)
+ :name(name_arg), after_update(func)
+#if MYSQL_VERSION_ID < 50000
+ , no_support_one_shot(1)
+#endif
{}
virtual ~sys_var() {}
virtual bool check(THD *thd, set_var *var);
@@ -452,7 +462,7 @@ public:
};
-#ifndef EMBEDDED_LIBRARY
+#ifdef HAVE_REPLICATION
class sys_var_slave_skip_counter :public sys_var
{
public:
@@ -465,6 +475,14 @@ public:
type() or value_ptr()
*/
};
+
+class sys_var_sync_binlog_period :public sys_var_long_ptr
+{
+public:
+ sys_var_sync_binlog_period(const char *name_arg, ulong *value_ptr)
+ :sys_var_long_ptr(name_arg,value_ptr) {}
+ bool update(THD *thd, set_var *var);
+};
#endif
class sys_var_rand_seed1 :public sys_var
@@ -487,12 +505,17 @@ public:
class sys_var_collation :public sys_var_thd
{
public:
- sys_var_collation(const char *name_arg) :sys_var_thd(name_arg) {}
+ sys_var_collation(const char *name_arg) :sys_var_thd(name_arg)
+ {
+#if MYSQL_VERSION_ID < 50000
+ no_support_one_shot= 0;
+#endif
+ }
bool check(THD *thd, set_var *var);
SHOW_TYPE type() { return SHOW_CHAR; }
bool check_update_type(Item_result type)
{
- return type != STRING_RESULT; /* Only accept strings */
+ return ((type != STRING_RESULT) && (type != INT_RESULT));
}
bool check_default(enum_var_type type) { return 0; }
virtual void set_default(THD *thd, enum_var_type type)= 0;
@@ -502,13 +525,23 @@ class sys_var_character_set :public sys_var_thd
{
public:
bool nullable;
- sys_var_character_set(const char *name_arg) :sys_var_thd(name_arg)
- { nullable= 0; }
+ sys_var_character_set(const char *name_arg) :
+ sys_var_thd(name_arg)
+ {
+ nullable= 0;
+#if MYSQL_VERSION_ID < 50000
+ /*
+ In fact only almost all variables derived from sys_var_character_set
+ support ONE_SHOT; character_set_results doesn't. But that's good enough.
+ */
+ no_support_one_shot= 0;
+#endif
+ }
bool check(THD *thd, set_var *var);
SHOW_TYPE type() { return SHOW_CHAR; }
bool check_update_type(Item_result type)
{
- return type != STRING_RESULT; /* Only accept strings */
+ return ((type != STRING_RESULT) && (type != INT_RESULT));
}
bool check_default(enum_var_type type) { return 0; }
bool update(THD *thd, set_var *var);
@@ -541,6 +574,9 @@ class sys_var_character_set_server :public sys_var_character_set
public:
sys_var_character_set_server(const char *name_arg) :
sys_var_character_set(name_arg) {}
+#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50000)
+ bool check(THD *thd, set_var *var);
+#endif
void set_default(THD *thd, enum_var_type type);
CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type);
};
@@ -576,6 +612,9 @@ class sys_var_collation_server :public sys_var_collation
{
public:
sys_var_collation_server(const char *name_arg) :sys_var_collation(name_arg) {}
+#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50000)
+ bool check(THD *thd, set_var *var);
+#endif
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
@@ -630,7 +669,7 @@ public:
class sys_var_thd_date_time_format :public sys_var_thd
{
DATE_TIME_FORMAT *SV::*offset;
- enum timestamp_type date_time_type;
+ timestamp_type date_time_type;
public:
sys_var_thd_date_time_format(const char *name_arg,
DATE_TIME_FORMAT *SV::*offset_arg,
@@ -677,6 +716,29 @@ public:
SHOW_TYPE type() { return show_type; }
};
+class sys_var_thd_time_zone :public sys_var_thd
+{
+public:
+ sys_var_thd_time_zone(const char *name_arg):
+ sys_var_thd(name_arg)
+ {
+#if MYSQL_VERSION_ID < 50000
+ no_support_one_shot= 0;
+#endif
+ }
+ bool check(THD *thd, set_var *var);
+ SHOW_TYPE type() { return SHOW_CHAR; }
+ bool check_update_type(Item_result type)
+ {
+ return type != STRING_RESULT; /* Only accept strings */
+ }
+ bool check_default(enum_var_type type) { return 0; }
+ bool update(THD *thd, set_var *var);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+ virtual void set_default(THD *thd, enum_var_type type);
+ Time_zone **get_tz_ptr(THD *thd, enum_var_type type);
+};
+
/****************************************************************************
Classes for parsing of the SET command
****************************************************************************/
@@ -689,7 +751,10 @@ public:
virtual int check(THD *thd)=0; /* To check privileges etc. */
virtual int update(THD *thd)=0; /* To set the value */
/* light check for PS */
- virtual int light_check(THD *thd) { return check(thd); }
+ virtual int light_check(THD *thd) { return check(thd); }
+#if MYSQL_VERSION_ID < 50000
+ virtual bool no_support_one_shot() { return 1; }
+#endif
};
@@ -707,6 +772,7 @@ public:
ulong ulong_value;
ulonglong ulonglong_value;
DATE_TIME_FORMAT *date_time_format;
+ Time_zone *time_zone;
} save_result;
LEX_STRING base; /* for structs */
@@ -731,6 +797,9 @@ public:
int check(THD *thd);
int update(THD *thd);
int light_check(THD *thd);
+#if MYSQL_VERSION_ID < 50000
+ bool no_support_one_shot() { return var->no_support_one_shot; }
+#endif
};
@@ -833,6 +902,7 @@ void set_var_init();
void set_var_free();
sys_var *find_sys_var(const char *str, uint length=0);
int sql_set_variables(THD *thd, List<set_var_base> *var_list);
+bool not_all_support_one_shot(List<set_var_base> *var_list);
void fix_delay_key_write(THD *thd, enum_var_type type);
ulong fix_sql_mode(ulong sql_mode);
extern sys_var_str sys_charset_system;
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index f35eb975b7a..75cbf12f60c 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -174,7 +174,7 @@ character-set=latin2
"Zji-B¹tìn timeout pøi ètení komunikaèního packetu",
"Zji-B¹tìna chyba pøi zápisu komunikaèního packetu",
"Zji-B¹tìn timeout pøi zápisu komunikaèního packetu",
-"V-Býsledný øetìzec je del¹í ne¾ max_allowed_packet",
+"V-Býsledný øetìzec je del¹í ne¾ 'max_allowed_packet'",
"Typ pou-B¾ité tabulky nepodporuje BLOB/TEXT sloupce",
"Typ pou-B¾ité tabulky nepodporuje AUTO_INCREMENT sloupce",
"INSERT DELAYED nen-Bí mo¾no s tabulkou '%-.64s' pou¾ít, proto¾e je zamèená pomocí LOCK TABLES",
@@ -209,74 +209,74 @@ character-set=latin2
"Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a mìla by být opravena",
"Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a poslední (automatická?) oprava se nezdaøila",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
-"Cannot add a child row: a foreign key constraint fails",
-"Cannot delete a parent row: a foreign key constraint fails",
+"Cannot add or update a child row: a foreign key constraint fails",
+"Cannot delete or update a parent row: a foreign key constraint fails",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -284,30 +284,34 @@ character-set=latin2
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you will get problems if you get an unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
-"Query cache failed to set size %lu, new query cache size is %lu",
+"Query cache failed to set size %lu; new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",
-"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
+"MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work",
"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
+"'%s' is deprecated; use '%s' instead",
"The target table %-.100s of the %s is not updatable",
-"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
+"The '%s' feature is disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
-"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Truncated incorrect %-.32s value: '%-.128s'"
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 105c138c440..b4b42b41969 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -126,7 +126,7 @@ character-set=latin1
"For mange felter",
"For store poster. Max post størrelse, uden BLOB's, er %d. Du må lave nogle felter til BLOB's",
"Thread stack brugt: Brugt: %ld af en %ld stak. Brug 'mysqld -O thread_stack=#' for at allokere en større stak om nødvendigt",
-"Krydsreferencer fundet i OUTER JOIN. Check dine ON conditions",
+"Krydsreferencer fundet i OUTER JOIN; check dine ON conditions",
"Kolonne '%-.32s' bruges som UNIQUE eller INDEX men er ikke defineret som NOT NULL",
"Kan ikke læse funktionen '%-.64s'",
"Kan ikke starte funktionen '%-.64s'; %-.80s",
@@ -168,7 +168,7 @@ character-set=latin1
"Timeout-fejl ved læsning af kommunukations-pakker (communication packets)",
"Fik fejlmeddelelse ved skrivning af kommunukations-pakker (communication packets)",
"Timeout-fejl ved skrivning af kommunukations-pakker (communication packets)",
-"Strengen med resultater er større end max_allowed_packet",
+"Strengen med resultater er større end 'max_allowed_packet'",
"Denne tabeltype understøtter ikke brug af BLOB og TEXT kolonner",
"Denne tabeltype understøtter ikke brug af AUTO_INCREMENT kolonner",
"INSERT DELAYED kan ikke bruges med tabellen '%-.64s', fordi tabellen er låst med LOCK TABLES",
@@ -208,7 +208,7 @@ character-set=latin1
"Denne handling kræver en kørende slave. Konfigurer en slave og brug kommandoen START SLAVE",
"Denne server er ikke konfigureret som slave. Ret in config-filen eller brug kommandoen CHANGE MASTER TO",
"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Kunne ikke danne en slave-tråd. Check systemressourcerne",
+"Kunne ikke danne en slave-tråd; check systemressourcerne",
"Brugeren %-.64s har allerede mere end 'max_user_connections' aktive forbindelser",
"Du må kun bruge konstantudtryk med SET",
"Lock wait timeout overskredet",
@@ -216,10 +216,10 @@ character-set=latin1
"Update lås kan ikke opnås under en READ UNCOMMITTED transaktion",
"DROP DATABASE er ikke tilladt mens en tråd holder på globalt read lock",
"CREATE DATABASE er ikke tilladt mens en tråd holder på globalt read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -227,26 +227,26 @@ character-set=latin1
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
-+ "Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Variable '%-.64s' is a %s variable",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
@@ -254,23 +254,23 @@ character-set=latin1
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -278,13 +278,13 @@ character-set=latin1
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support, they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -299,9 +299,13 @@ character-set=latin1
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Modtog fejl %d '%-.100s' fra %s",
+"Modtog temporary fejl %d '%-.100s' fra %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 93dbeab1a5c..af0c3a1bc0b 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -176,7 +176,7 @@ character-set=latin1
"Timeout bij het lezen van communicatiepakketten",
"Fout bij het schrijven van communicatiepakketten",
"Timeout bij het schrijven van communicatiepakketten",
-"Resultaat string is langer dan max_allowed_packet",
+"Resultaat string is langer dan 'max_allowed_packet'",
"Het gebruikte tabel type ondersteunt geen BLOB/TEXT kolommen",
"Het gebruikte tabel type ondersteunt geen AUTO_INCREMENT kolommen",
"INSERT DELAYED kan niet worden gebruikt bij table '%-.64s', vanwege een 'lock met LOCK TABLES",
@@ -253,32 +253,32 @@ character-set=latin1
"Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -286,13 +286,13 @@ character-set=latin1
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -307,9 +307,13 @@ character-set=latin1
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 3f8e5483fef..7706257a55d 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -24,8 +24,8 @@ character-set=latin1
"Can't read dir of '%-.64s' (errno: %d)",
"Can't change dir to '%-.64s' (errno: %d)",
"Record has changed since last read in table '%-.64s'",
-"Disk full (%s). Waiting for someone to free some space...",
-"Can't write, duplicate key in table '%-.64s'",
+"Disk full (%s); waiting for someone to free some space...",
+"Can't write; duplicate key in table '%-.64s'",
"Error on close of '%-.64s' (errno: %d)",
"Error reading file '%-.64s' (errno: %d)",
"Error on rename of '%-.64s' to '%-.64s' (errno: %d)",
@@ -37,25 +37,25 @@ character-set=latin1
"Table storage engine for '%-.64s' doesn't have this option",
"Can't find record in '%-.64s'",
"Incorrect information in file: '%-.64s'",
-"Incorrect key file for table: '%-.64s'; try to repair it",
+"Incorrect key file for table '%-.64s'; try to repair it",
"Old key file for table '%-.64s'; repair it!",
"Table '%-.64s' is read only",
-"Out of memory. Restart daemon and try again (needed %d bytes)",
-"Out of sort memory. Increase daemon sort buffer size",
-"Unexpected eof found when reading file '%-.64s' (errno: %d)",
+"Out of memory; restart server and try again (needed %d bytes)",
+"Out of sort memory; increase server sort buffer size",
+"Unexpected EOF found when reading file '%-.64s' (errno: %d)",
"Too many connections",
-"Out of memory; Check if mysqld or some other process uses all available memory. If not you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space",
+"Out of memory; check if mysqld or some other process uses all available memory; if not, you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space",
"Can't get hostname for your address",
"Bad handshake",
-"Access denied for user: '%-.32s'@'%-.64s' to database '%-.64s'",
-"Access denied for user: '%-.32s'@'%-.64s' (Using password: %s)",
-"No Database Selected",
+"Access denied for user '%-.32s'@'%-.64s' to database '%-.64s'",
+"Access denied for user '%-.32s'@'%-.64s' (using password: %s)",
+"No database selected",
"Unknown command",
"Column '%-.64s' cannot be null",
"Unknown database '%-.64s'",
"Table '%-.64s' already exists",
"Unknown table '%-.64s'",
-"Column: '%-.64s' in %-.64s is ambiguous",
+"Column '%-.64s' in %-.64s is ambiguous",
"Server shutdown in progress",
"Unknown column '%-.64s' in '%-.64s'",
"'%-.64s' isn't in GROUP BY",
@@ -73,28 +73,28 @@ character-set=latin1
"Invalid default value for '%-.64s'",
"Multiple primary key defined",
"Too many keys specified; max %d keys allowed",
-"Too many key parts specified. Max %d parts allowed",
+"Too many key parts specified; max %d parts allowed",
"Specified key was too long; max key length is %d bytes",
"Key column '%-.64s' doesn't exist in table",
"BLOB column '%-.64s' can't be used in key specification with the used table type",
-"Too big column length for column '%-.64s' (max = %d). Use BLOB instead",
-"Incorrect table definition; There can only be one auto column and it must be defined as a key",
+"Column length too big for column '%-.64s' (max = %d); use BLOB instead",
+"Incorrect table definition; there can be only one auto column and it must be defined as a key",
"%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d\n",
"%s: Normal shutdown\n",
"%s: Got signal %d. Aborting!\n",
-"%s: Shutdown Complete\n",
+"%s: Shutdown complete\n",
"%s: Forcing close of thread %ld user: '%-.32s'\n",
"Can't create IP socket",
-"Table '%-.64s' has no index like the one used in CREATE INDEX. Recreate the table",
-"Field separator argument is not what is expected. Check the manual",
-"You can't use fixed rowlength with BLOBs. Please use 'fields terminated by'",
+"Table '%-.64s' has no index like the one used in CREATE INDEX; recreate the table",
+"Field separator argument is not what is expected; check the manual",
+"You can't use fixed rowlength with BLOBs; please use 'fields terminated by'",
"The file '%-.64s' must be in the database directory or be readable by all",
"File '%-.80s' already exists",
"Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld",
"Records: %ld Duplicates: %ld",
-"Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the storage engine doesn't support unique sub keys",
-"You can't delete all columns with ALTER TABLE. Use DROP TABLE instead",
-"Can't DROP '%-.64s'. Check that column/key exists",
+"Incorrect sub part key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique sub keys",
+"You can't delete all columns with ALTER TABLE; use DROP TABLE instead",
+"Can't DROP '%-.64s'; check that column/key exists",
"Records: %ld Duplicates: %ld Warnings: %ld",
"You can't specify target table '%-.64s' for update in FROM clause",
"Unknown thread id: %lu",
@@ -107,7 +107,7 @@ character-set=latin1
"BLOB/TEXT column '%-.64s' can't have a default value",
"Incorrect database name '%-.100s'",
"Incorrect table name '%-.100s'",
-"The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok",
+"The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay",
"Unknown error",
"Unknown procedure '%-.64s'",
"Incorrect parameter count to procedure '%-.64s'",
@@ -119,44 +119,44 @@ character-set=latin1
"A table must have at least 1 column",
"The table '%-.64s' is full",
"Unknown character set: '%-.64s'",
-"Too many tables. MySQL can only use %d tables in a join",
+"Too many tables; MySQL can only use %d tables in a join",
"Too many columns",
-"Too big row size. The maximum row size for the used table type, not counting BLOBs, is %ld. You have to change some fields to TEXT or BLOBs",
+"Row size too large. The maximum row size for the used table type, not counting BLOBs, is %ld. You have to change some columns to TEXT or BLOBs",
"Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed",
-"Cross dependency found in OUTER JOIN. Examine your ON conditions",
+"Cross dependency found in OUTER JOIN; examine your ON conditions",
"Column '%-.64s' is used with UNIQUE or INDEX but is not defined as NOT NULL",
"Can't load function '%-.64s'",
"Can't initialize function '%-.64s'; %-.80s",
"No paths allowed for shared library",
-"Function '%-.64s' already exist",
+"Function '%-.64s' already exists",
"Can't open shared library '%-.64s' (errno: %d %-.64s)",
"Can't find function '%-.64s' in library'",
"Function '%-.64s' is not defined",
-"Host '%-.64s' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'",
+"Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'",
"Host '%-.64s' is not allowed to connect to this MySQL server",
-"You are using MySQL as an anonymous users and anonymous users are not allowed to change passwords",
+"You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords",
"You must have privileges to update tables in the mysql database to be able to change passwords for others",
"Can't find any matching row in the user table",
"Rows matched: %ld Changed: %ld Warnings: %ld",
-"Can't create a new thread (errno %d). If you are not out of available memory, you can consult the manual for a possible OS-dependent bug",
+"Can't create a new thread (errno %d); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug",
"Column count doesn't match value count at row %ld",
"Can't reopen table: '%-.64s'",
"Invalid use of NULL value",
"Got error '%-.64s' from regexp",
-"Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause",
+"Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause",
"There is no such grant defined for user '%-.32s' on host '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for table '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
-"Illegal GRANT/REVOKE command. Please consult the manual which privileges can be used",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for table '%-.64s'",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
+"Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used",
"The host or user argument to GRANT is too long",
"Table '%-.64s.%-.64s' doesn't exist",
"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
"The used command is not allowed with this MySQL version",
-"You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use",
+"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use",
"Delayed insert thread couldn't get requested lock for table %-.64s",
"Too many delayed threads in use",
"Aborted connection %ld to db: '%-.64s' user: '%-.32s' (%-.64s)",
-"Got a packet bigger than 'max_allowed_packet'",
+"Got a packet bigger than 'max_allowed_packet' bytes",
"Got a read error from the connection pipe",
"Got an error from fcntl()",
"Got packets out of order",
@@ -165,7 +165,7 @@ character-set=latin1
"Got timeout reading communication packets",
"Got an error writing communication packets",
"Got timeout writing communication packets",
-"Result string is longer than max_allowed_packet",
+"Result string is longer than 'max_allowed_packet' bytes",
"The used table type doesn't support BLOB/TEXT columns",
"The used table type doesn't support AUTO_INCREMENT columns",
"INSERT DELAYED can't be used with table '%-.64s' because it is locked with LOCK TABLES",
@@ -174,7 +174,7 @@ character-set=latin1
"All tables in the MERGE table are not identically defined",
"Can't write, because of unique constraint, to table '%-.64s'",
"BLOB/TEXT column '%-.64s' used in key specification without a key length",
-"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
+"All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead",
"Result consisted of more than one row",
"This table type requires a primary key",
"This version of MySQL is not compiled with RAID support",
@@ -200,23 +200,23 @@ character-set=latin1
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded; Try restarting transaction",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add or update a child row: a foreign key constraint fails",
@@ -224,50 +224,50 @@ character-set=latin1
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
"ZLIB: Not enough memory",
"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
"ZLIB: Input data corrupted",
-"%d line(s) was(were) cut by group_concat()",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -275,30 +275,34 @@ character-set=latin1
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL. Otherwise you will get problems if you get an unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you will get problems if you get an unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
-"Query cache failed to set size %lu, new query cache size is %lu",
+"Query cache failed to set size %lu; new query cache size is %lu",
"Column '%-.64s' cannot be part of FULLTEXT index",
"Unknown key cache '%-.100s'",
-"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
+"MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work",
"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
+"'%s' is deprecated; use '%s' instead",
"The target table %-.100s of the %s is not updatable",
-"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
+"The '%s' feature is disabled; you need MySQL built with '%s' to have it working",
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
-"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Truncated incorrect %-.32s value: '%-.128s'"
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 706ea858121..ace966b693a 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -206,11 +206,11 @@ character-set=latin7
"Tabel '%-.64s' on märgitud vigaseks ja viimane (automaatne?) parandus ebaõnnestus",
"Hoiatus: mõnesid transaktsioone mittetoetavaid tabeleid ei suudetud tagasi kerida",
"Mitme lausendiga transaktsioon nõudis rohkem ruumi kui lubatud 'max_binlog_cache_size' muutujaga. Suurenda muutuja väärtust ja proovi uuesti",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"Kasutajal %-.64s on juba rohkem ühendusi kui lubatud 'max_user_connections' muutujaga",
"Ainult konstantsed suurused on lubatud SET klauslis",
"Kontrollaeg ületatud luku järel ootamisel; Proovi transaktsiooni otsast alata",
@@ -235,44 +235,44 @@ character-set=latin7
"Transaktsioone toetavate ning mittetoetavate tabelite kooskasutamine ei ole lubatud",
"Määrangut '%s' on lauses kasutatud topelt",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -280,13 +280,13 @@ character-set=latin7
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -301,9 +301,13 @@ character-set=latin7
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 7a7c4bbcbe0..63568b9ebd7 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -165,7 +165,7 @@ character-set=latin1
"Timeout en lecture des paquets reçus",
"Erreur d'écriture des paquets envoyés",
"Timeout d'écriture des paquets envoyés",
-"La chaîne résultat est plus grande que max_allowed_packet",
+"La chaîne résultat est plus grande que 'max_allowed_packet'",
"Ce type de table ne supporte pas les colonnes BLOB/TEXT",
"Ce type de table ne supporte pas les colonnes AUTO_INCREMENT",
"INSERT DELAYED ne peut être utilisé avec la table '%-.64s', car elle est verrouée avec LOCK TABLES",
@@ -224,50 +224,50 @@ character-set=latin1
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -275,13 +275,13 @@ character-set=latin1
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -296,9 +296,13 @@ character-set=latin1
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index dee216f3bfd..d2588b10092 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -177,7 +177,7 @@ character-set=latin1
"Zeitüberschreitung beim Lesen eines Kommunikationspakets",
"Fehler beim Schreiben eines Kommunikationspakets",
"Zeitüberschreitung beim Schreiben eines Kommunikationspakets",
-"Ergebnis ist länger als max_allowed_packet",
+"Ergebnis ist länger als 'max_allowed_packet'",
"Der verwendete Tabellentyp unterstützt keine BLOB- und TEXT-Spalten",
"Der verwendete Tabellentyp unterstützt keine AUTO_INCREMENT-Spalten",
"INSERT DELAYED kann nicht auf Tabelle '%-.64s' angewendet werden, da diese mit LOCK TABLES gesperrt ist",
@@ -258,7 +258,7 @@ character-set=latin1
"Schlüssel- und Tabellenverweis passen nicht zusammen",
"Operand solle %d Spalte(n) enthalten",
"Unterabfrage lieferte mehr als einen Datensatz zurück",
-"Unbekannter Prepared-Statement-Handler (%ld) für %s angegeben",
+"Unbekannter Prepared-Statement-Handler (%.*s) für %s angegeben",
"Die Hilfe-Datenbank ist beschädigt oder existiert nicht",
"Zyklischer Verweis in Unterabfragen",
"Spalte '%s' wird von %s nach %s umgewandelt",
@@ -272,10 +272,10 @@ character-set=latin1
"Slave läuft bereits",
"Slave wurde bereits angehalten",
"Unkomprimierte Daten sind zu groß. Die maximale Größe beträgt %d",
-"Z_MEM_ERROR: Für zlib steht nicht genug Speicher zur Verfügung",
-"Z_BUF_ERROR: Im Ausgabepuffer ist nicht genug Platz für zlib vorhanden (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)",
-"Z_DATA_ERROR: Eingabedaten für zlib beschädigt",
-"%d Zeile(n) durch group_concat() abgeschnitten",
+"ZLIB: Steht nicht genug Speicher zur Verfügung",
+"ZLIB: Im Ausgabepuffer ist nicht genug Platz vorhanden (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)",
+"ZLIB: Eingabedaten beschädigt",
+"%d Zeile(n) durch GROUP_CONCAT() abgeschnitten",
"Anzahl der Datensätze in Zeile %ld geringer als Anzahl der Spalten",
"Anzahl der Datensätze in Zeile %ld größer als Anzahl der Spalten",
"Daten abgeschnitten, NULL für NOT NULL-Spalte '%s' in Zeile %ld angegeben",
@@ -308,9 +308,13 @@ character-set=latin1
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index d5ba8d93cd1..2d099e149f6 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -138,16 +138,16 @@ character-set=greek
"ÐñÝðåé íá Ý÷åôå äéêáßùìá äéüñèùóçò ðéíÜêùí (update) óôç âÜóç äåäïìÝíùí mysql ãéá íá ìðïñåßôå íá áëëÜîåôå ôá passwords Üëëùí ÷ñçóôþí",
"Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò áíôßóôïé÷çò åããñáöÞò óôïí ðßíáêá ôùí ÷ñçóôþí",
"Rows matched: %ld Changed: %ld Warnings: %ld",
-"Can't create a new thread (errno %d). If you are not out of available memory, you can consult the manual for a possible OS-dependent bug",
+"Can't create a new thread (errno %d); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug",
"Column count doesn't match value count at row %ld",
"Can't reopen table: '%-.64s'",
"Invalid use of NULL value",
"Got error '%-.64s' from regexp",
-"Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause",
+"Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause",
"There is no such grant defined for user '%-.32s' on host '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for table '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
-"Illegal GRANT/REVOKE command. Please consult the manual which privileges can be used.",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for table '%-.64s'",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
+"Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used.",
"The host or user argument to GRANT is too long",
"Table '%-.64s.%-.64s' doesn't exist",
"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
@@ -156,7 +156,7 @@ character-set=greek
"Delayed insert thread couldn't get requested lock for table %-.64s",
"Too many delayed threads in use",
"Aborted connection %ld to db: '%-.64s' user: '%-32s' (%-.64s)",
-"Got a packet bigger than 'max_allowed_packet'",
+"Got a packet bigger than 'max_allowed_packet' bytes",
"Got a read error from the connection pipe",
"Got an error from fcntl()",
"Got packets out of order",
@@ -165,7 +165,7 @@ character-set=greek
"Got timeout reading communication packets",
"Got an error writing communication packets",
"Got timeout writing communication packets",
-"Result string is longer than max_allowed_packet",
+"Result string is longer than 'max_allowed_packet' bytes",
"The used table type doesn't support BLOB/TEXT columns",
"The used table type doesn't support AUTO_INCREMENT columns",
"INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
@@ -174,7 +174,7 @@ character-set=greek
"All tables in the MERGE table are not identically defined",
"Can't write, because of unique constraint, to table '%-.64s'",
"BLOB column '%-.64s' used in key specification without a key length",
-"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
+"All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead",
"Result consisted of more than one row",
"This table type requires a primary key",
"This version of MySQL is not compiled with RAID support",
@@ -200,23 +200,23 @@ character-set=greek
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -224,50 +224,50 @@ character-set=greek
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -275,13 +275,13 @@ character-set=greek
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -296,9 +296,13 @@ character-set=greek
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 235d09e760c..ac9539b35cf 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -109,7 +109,7 @@ character-set=latin2
"A(z) '%-.64s' blob objektumnak nem lehet alapertelmezett erteke",
"Hibas adatbazisnev: '%-.100s'",
"Hibas tablanev: '%-.100s'",
-"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET SQL_BIG_SELECTS=1 beallitast, ha a SELECT ok",
+"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET SQL_BIG_SELECTS=1 beallitast, ha a SELECT okay",
"Ismeretlen hiba",
"Ismeretlen eljaras: '%-.64s'",
"Rossz parameter a(z) '%-.64s'eljaras szamitasanal",
@@ -167,7 +167,7 @@ character-set=latin2
"Idotullepes a kommunikacios adatcsomagok olvasasa soran",
"Hiba a kommunikacios csomagok irasa soran",
"Idotullepes a kommunikacios csomagok irasa soran",
-"Ez eredmeny sztring nagyobb, mint a lehetseges maximum: max_allowed_packet",
+"Ez eredmeny sztring nagyobb, mint a lehetseges maximum: 'max_allowed_packet'",
"A hasznalt tabla tipus nem tamogatja a BLOB/TEXT mezoket",
"A hasznalt tabla tipus nem tamogatja az AUTO_INCREMENT tipusu mezoket",
"Az INSERT DELAYED nem hasznalhato a '%-.64s' tablahoz, mert a tabla zarolt (LOCK TABLES)",
@@ -202,23 +202,23 @@ character-set=latin2
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -226,50 +226,50 @@ character-set=latin2
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -277,13 +277,13 @@ character-set=latin2
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -298,9 +298,13 @@ character-set=latin2
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index b5eaabe9824..33ea2cb2a9d 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -165,7 +165,7 @@ character-set=latin1
"Rilevato un timeout ricevendo i pacchetti di comunicazione",
"Rilevato un errore inviando i pacchetti di comunicazione",
"Rilevato un timeout inviando i pacchetti di comunicazione",
-"La stringa di risposta e` piu` lunga di max_allowed_packet",
+"La stringa di risposta e` piu` lunga di 'max_allowed_packet'",
"Il tipo di tabella usata non supporta colonne di tipo BLOB/TEXT",
"Il tipo di tabella usata non supporta colonne di tipo AUTO_INCREMENT",
"L'inserimento ritardato (INSERT DELAYED) non puo` essere usato con la tabella '%-.64s', perche` soggetta a lock da 'LOCK TABLES'",
@@ -242,32 +242,32 @@ character-set=latin1
"Errore fatale %d: '%-.128s' dal master leggendo i dati dal log binario",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -275,13 +275,13 @@ character-set=latin1
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -296,9 +296,13 @@ character-set=latin1
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index a4cb4cd513d..6bb82cc9749 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -50,7 +50,7 @@ character-set=ujis
"¤½¤Î address ¤Î hostname ¤¬°ú¤±¤Þ¤»¤ó.",
"Bad handshake",
"¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ¤Î '%-.64s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥¢¥¯¥»¥¹¤òµñÈݤ·¤Þ¤¹",
-"¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ¤òµñÈݤ·¤Þ¤¹.(Using password: %s)",
+"¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ¤òµñÈݤ·¤Þ¤¹.uUsing password: %s)",
"¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤Þ¤»¤ó.",
"¤½¤Î¥³¥Þ¥ó¥É¤Ï²¿¡©",
"Column '%-.64s' ¤Ï null ¤Ë¤Ï¤Ç¤­¤Ê¤¤¤Î¤Ç¤¹",
@@ -75,12 +75,12 @@ character-set=ujis
"Invalid default value for '%-.64s'",
"Ê£¿ô¤Î primary key ¤¬ÄêµÁ¤µ¤ì¤Þ¤·¤¿",
"key ¤Î»ØÄ꤬¿¤¹¤®¤Þ¤¹. key ¤ÏºÇÂç %d ¤Þ¤Ç¤Ç¤¹",
-"Too many key parts specified. Max %d parts allowed",
+"Too many key parts specified; max %d parts allowed",
"key ¤¬Ä¹¤¹¤®¤Þ¤¹. key ¤ÎŤµ¤ÏºÇÂç %d ¤Ç¤¹",
"Key column '%-.64s' ¤¬¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ê¤Þ¤»¤ó.",
"BLOB column '%-.64s' can't be used in key specification with the used table type",
"column '%-.64s' ¤Ï,³ÎÊݤ¹¤ë column ¤ÎÂ礭¤µ¤¬Â¿¤¹¤®¤Þ¤¹. (ºÇÂç %d ¤Þ¤Ç). BLOB ¤ò¤«¤ï¤ê¤Ë»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤.",
-"¥Æ¡¼¥Ö¥ë¤ÎÄêµÁ¤¬°ã¤¤¤Þ¤¹; There can only be one auto column and it must be defined as a key",
+"¥Æ¡¼¥Ö¥ë¤ÎÄêµÁ¤¬°ã¤¤¤Þ¤¹; there can be only one auto column and it must be defined as a key",
"%s: ½àÈ÷´°Î»\n",
"%s: Normal shutdown\n",
"%s: Got signal %d. ̾̂!\n",
@@ -88,15 +88,15 @@ character-set=ujis
"%s: ¥¹¥ì¥Ã¥É %ld ¶¯À©½ªÎ» user: '%-.64s'\n",
"IP socket ¤¬ºî¤ì¤Þ¤»¤ó",
"Table '%-.64s' ¤Ï¤½¤Î¤è¤¦¤Ê index ¤ò»ý¤Ã¤Æ¤¤¤Þ¤»¤ó(CREATE INDEX ¼Â¹Ô»þ¤Ë»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó). ¥Æ¡¼¥Ö¥ë¤òºî¤êľ¤·¤Æ¤¯¤À¤µ¤¤",
-"Field separator argument is not what is expected. Check the manual",
-"You can't use fixed rowlength with BLOBs. Please use 'fields terminated by'.",
+"Field separator argument is not what is expected; check the manual",
+"You can't use fixed rowlength with BLOBs; please use 'fields terminated by'.",
"¥Õ¥¡¥¤¥ë '%-.64s' ¤Ï databse ¤Î directory ¤Ë¤¢¤ë¤«Á´¤Æ¤Î¥æ¡¼¥¶¡¼¤¬Æɤá¤ë¤è¤¦¤Ëµö²Ä¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó.",
"File '%-.64s' ¤Ï´û¤Ë¸ºß¤·¤Þ¤¹",
"¥ì¥³¡¼¥É¿ô: %ld ºï½ü: %ld Skipped: %ld Warnings: %ld",
"¥ì¥³¡¼¥É¿ô: %ld ½ÅÊ£: %ld",
-"Incorrect sub part key. The used key part isn't a string or the used length is longer than the key part",
+"Incorrect sub part key; the used key part isn't a string or the used length is longer than the key part",
"ALTER TABLE ¤ÇÁ´¤Æ¤Î column ¤Ïºï½ü¤Ç¤­¤Þ¤»¤ó. DROP TABLE ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤",
-"'%-.64s' ¤òÇË´þ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿. Check that column/key exists",
+"'%-.64s' ¤òÇË´þ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿; check that column/key exists",
"¥ì¥³¡¼¥É¿ô: %ld ½ÅÊ£¿ô: %ld Warnings: %ld",
"You can't specify target table '%-.64s' for update in FROM clause",
"thread id: %lu ¤Ï¤¢¤ê¤Þ¤»¤ó",
@@ -109,7 +109,7 @@ character-set=ujis
"BLOB column '%-.64s' can't have a default value",
"»ØÄꤷ¤¿ database ̾ '%-.100s' ¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹",
"»ØÄꤷ¤¿ table ̾ '%-.100s' ¤Ï¤Þ¤Á¤¬¤Ã¤Æ¤¤¤Þ¤¹",
-"The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok",
+"The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay",
"Unknown error",
"Unknown procedure '%-.64s'",
"Incorrect parameter count to procedure '%-.64s'",
@@ -121,11 +121,11 @@ character-set=ujis
"¥Æ¡¼¥Ö¥ë¤ÏºÇÄã 1 ¸Ä¤Î column ¤¬É¬ÍפǤ¹",
"table '%-.64s' ¤Ï¤¤¤Ã¤Ñ¤¤¤Ç¤¹",
"character set '%-.64s' ¤Ï¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤»¤ó",
-"¥Æ¡¼¥Ö¥ë¤¬Â¿¤¹¤®¤Þ¤¹. MySQL can only use %d tables in a join",
+"¥Æ¡¼¥Ö¥ë¤¬Â¿¤¹¤®¤Þ¤¹; MySQL can only use %d tables in a join",
"column ¤¬Â¿¤¹¤®¤Þ¤¹",
"row size ¤¬Â礭¤¹¤®¤Þ¤¹. BLOB ¤ò´Þ¤Þ¤Ê¤¤¾ì¹ç¤Î row size ¤ÎºÇÂç¤Ï %d ¤Ç¤¹. ¤¤¤¯¤Ä¤«¤Î field ¤ò BLOB ¤ËÊѤ¨¤Æ¤¯¤À¤µ¤¤.",
"Thread stack overrun: Used: %ld of a %ld stack. ¥¹¥¿¥Ã¥¯Îΰè¤ò¿¤¯¤È¤ê¤¿¤¤¾ì¹ç¡¢'mysqld -O thread_stack=#' ¤È»ØÄꤷ¤Æ¤¯¤À¤µ¤¤",
-"Cross dependency found in OUTER JOIN. Examine your ON conditions",
+"Cross dependency found in OUTER JOIN; examine your ON conditions",
"Column '%-.64s' ¤¬ UNIQUE ¤« INDEX ¤Ç»ÈÍѤµ¤ì¤Þ¤·¤¿. ¤³¤Î¥«¥é¥à¤Ï NOT NULL ¤ÈÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó.",
"function '%-.64s' ¤ò ¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó",
"function '%-.64s' ¤ò½é´ü²½¤Ç¤­¤Þ¤»¤ó; %-.80s",
@@ -145,11 +145,11 @@ character-set=ujis
"Can't reopen table: '%-.64s'",
"NULL ÃͤλÈÍÑÊýË¡¤¬ÉÔŬÀڤǤ¹",
"Got error '%-.64s' from regexp",
-"Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause",
+"Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause",
"¥æ¡¼¥¶¡¼ '%-.32s' (¥Û¥¹¥È '%-.64s' ¤Î¥æ¡¼¥¶¡¼) ¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó",
"¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ,¥Æ¡¼¥Ö¥ë '%-.64s' ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó",
"¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s'\n ¥«¥é¥à '%-.64s' ¥Æ¡¼¥Ö¥ë '%-.64s' ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó",
-"Illegal GRANT/REVOKE command. Please consult the manual which privleges can be used.",
+"Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used.",
"The host or user argument to GRANT is too long",
"Table '%-.64s.%s' doesn't exist",
"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
@@ -158,7 +158,7 @@ character-set=ujis
"Delayed insert thread couldn't get requested lock for table %-.64s",
"Too many delayed threads in use",
"Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)",
-"Got a packet bigger than 'max_allowed_packet'",
+"Got a packet bigger than 'max_allowed_packet' bytes",
"Got a read error from the connection pipe",
"Got an error from fcntl()",
"Got packets out of order",
@@ -167,7 +167,7 @@ character-set=ujis
"Got timeout reading communication packets",
"Got an error writing communication packets",
"Got timeout writing communication packets",
-"Result string is longer than max_allowed_packet",
+"Result string is longer than 'max_allowed_packet' bytes",
"The used table type doesn't support BLOB/TEXT columns",
"The used table type doesn't support AUTO_INCREMENT columns",
"INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
@@ -176,7 +176,7 @@ character-set=ujis
"All tables in the MERGE table are not defined identically",
"Can't write, because of unique constraint, to table '%-.64s'",
"BLOB column '%-.64s' used in key specification without a key length",
-"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
+"All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead",
"Result consisted of more than one row",
"This table type requires a primary key",
"This version of MySQL is not compiled with RAID support",
@@ -202,23 +202,23 @@ character-set=ujis
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -226,50 +226,50 @@ character-set=ujis
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -277,13 +277,13 @@ character-set=ujis
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -299,8 +299,12 @@ character-set=ujis
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got NDB error %d '%-.100s'",
+"Got temporary NDB error %d '%-.100s'",
+"Unknown or incorrect time zone: '%-.64s'",
++ "Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 091e19e8b71..884ce735815 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -48,7 +48,7 @@ character-set=euckr
"´ç½ÅÀÇ ÄÄÇ»ÅÍÀÇ È£½ºÆ®À̸§À» ¾òÀ» ¼ö ¾øÀ¾´Ï´Ù.",
"Bad handshake",
"'%-.32s'@'%-.64s' »ç¿ëÀÚ´Â '%-.64s' µ¥ÀÌŸº£À̽º¿¡ Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù.",
-"'%-.32s'@'%-.64s' »ç¿ëÀÚ´Â Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù. (Using password: %s)",
+"'%-.32s'@'%-.64s' »ç¿ëÀÚ´Â Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù. (using password: %s)",
"¼±ÅÃµÈ µ¥ÀÌŸº£À̽º°¡ ¾ø½À´Ï´Ù.",
"¸í·É¾î°¡ ¹ºÁö ¸ð¸£°Ú¾î¿ä...",
"Ä®·³ '%-.64s'´Â ³Î(Null)ÀÌ µÇ¸é ¾ÈµË´Ï´Ù. ",
@@ -123,7 +123,7 @@ character-set=euckr
"Ä®·³ÀÌ ³Ê¹« ¸¹½À´Ï´Ù.",
"³Ê¹« Å« row »çÀÌÁîÀÔ´Ï´Ù. BLOB¸¦ °è»êÇÏÁö ¾Ê°í ÃÖ´ë row »çÀÌÁî´Â %dÀÔ´Ï´Ù. ¾ó¸¶°£ÀÇ ÇʵåµéÀ» BLOB·Î ¹Ù²Ù¼Å¾ß °Ú±º¿ä..",
"¾²·¹µå ½ºÅÃÀÌ ³ÑÃƽÀ´Ï´Ù. »ç¿ë: %ld°³ ½ºÅÃ: %ld°³. ¸¸¾à ÇÊ¿ä½Ã ´õÅ« ½ºÅÃÀ» ¿øÇÒ¶§¿¡´Â 'mysqld -O thread_stack=#' ¸¦ Á¤ÀÇÇϼ¼¿ä",
-"Cross dependency found in OUTER JOIN. Examine your ON conditions",
+"Cross dependency found in OUTER JOIN; examine your ON conditions",
"'%-.64s' Ä®·³ÀÌ UNIQUE³ª INDEX¸¦ »ç¿ëÇÏ¿´Áö¸¸ NOT NULLÀÌ Á¤ÀǵÇÁö ¾Ê¾Ò±º¿ä...",
"'%-.64s' ÇÔ¼ö¸¦ ·ÎµåÇÏÁö ¸øÇß½À´Ï´Ù.",
"'%-.64s' ÇÔ¼ö¸¦ ÃʱâÈ­ ÇÏÁö ¸øÇß½À´Ï´Ù.; %-.80s",
@@ -143,7 +143,7 @@ character-set=euckr
"Å×À̺íÀ» ´Ù½Ã ¿­¼ö ¾ø±º¿ä: '%-.64s",
"NULL °ªÀ» À߸ø »ç¿ëÇϼ̱º¿ä...",
"regexp¿¡¼­ '%-.64s'°¡ ³µ½À´Ï´Ù.",
-"Mixing of GROUP Ä®·³s (MIN(),MAX(),COUNT()...) with no GROUP Ä®·³s is illegal if there is no GROUP BY clause",
+"Mixing of GROUP Ä®·³s (MIN(),MAX(),COUNT(),...) with no GROUP Ä®·³s is illegal if there is no GROUP BY clause",
"»ç¿ëÀÚ '%-.32s' (È£½ºÆ® '%-.64s')¸¦ À§ÇÏ¿© Á¤ÀÇµÈ ±×·± ½ÂÀÎÀº ¾ø½À´Ï´Ù.",
"'%-.16s' ¸í·ÉÀº ´ÙÀ½ »ç¿ëÀÚ¿¡°Ô °ÅºÎµÇ¾ú½À´Ï´Ù. : '%-.32s'@'%-.64s' for Å×À̺í '%-.64s'",
"'%-.16s' ¸í·ÉÀº ´ÙÀ½ »ç¿ëÀÚ¿¡°Ô °ÅºÎµÇ¾ú½À´Ï´Ù. : '%-.32s'@'%-.64s' for Ä®·³ '%-.64s' in Å×À̺í '%-.64s'",
@@ -165,7 +165,7 @@ character-set=euckr
"Åë½Å ÆÐŶÀ» Àд Áß timeoutÀÌ ¹ß»ýÇÏ¿´½À´Ï´Ù.",
"Åë½Å ÆÐŶÀ» ±â·ÏÇÏ´Â Áß ¿À·ù°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù.",
"Åë½Å ÆÐÆÂÀ» ±â·ÏÇÏ´Â Áß timeoutÀÌ ¹ß»ýÇÏ¿´½À´Ï´Ù.",
-"Result string is longer than max_allowed_packet",
+"Result string is longer than 'max_allowed_packet' bytes",
"The used table type doesn't support BLOB/TEXT columns",
"The used table type doesn't support AUTO_INCREMENT columns",
"INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
@@ -174,7 +174,7 @@ character-set=euckr
"All tables in the MERGE table are not defined identically",
"Can't write, because of unique constraint, to table '%-.64s'",
"BLOB column '%-.64s' used in key specification without a key length",
-"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
+"All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead",
"Result consisted of more than one row",
"This table type requires a primary key",
"This version of MySQL is not compiled with RAID support",
@@ -200,23 +200,23 @@ character-set=euckr
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -224,50 +224,50 @@ character-set=euckr
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -275,13 +275,13 @@ character-set=euckr
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -296,9 +296,13 @@ character-set=euckr
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index f42eeb93a94..27ebe984c7e 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -121,35 +121,35 @@ character-set=latin1
"A table must have at least 1 column",
"The table '%-.64s' is full",
"Unknown character set: '%-.64s'",
-"Too many tables. MySQL can only use %d tables in a join",
-"Too many fields",
-"Too big row size. The maximum row size, not counting blobs, is %d. You have to change some fields to blobs",
+"Too many tables; MySQL can only use %d tables in a join",
+"Too many columns",
+"Row size too large. The maximum row size for the used table type, not counting BLOBs, is %ld. You have to change some columns to TEXT or BLOBs",
"Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed",
-"Cross dependency found in OUTER JOIN. Examine your ON conditions",
+"Cross dependency found in OUTER JOIN; examine your ON conditions",
"Column '%-.32s' is used with UNIQUE or INDEX but is not defined as NOT NULL",
"Can't load function '%-.64s'",
"Can't initialize function '%-.64s'; %-.80s",
"No paths allowed for shared library",
-"Function '%-.64s' already exist",
+"Function '%-.64s' already exists",
"Can't open shared library '%-.64s' (errno: %d %s)",
"Can't find function '%-.64s' in library'",
"Function '%-.64s' is not defined",
-"Host '%-.64s' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'",
+"Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'",
"Host '%-.64s' is not allowed to connect to this MySQL server",
-"You are using MySQL as an anonymous users and anonymous users are not allowed to change passwords",
+"You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords",
"You must have privileges to update tables in the mysql database to be able to change passwords for others",
"Can't find any matching row in the user table",
"Rows matched: %ld Changed: %ld Warnings: %ld",
-"Can't create a new thread (errno %d). If you are not out of available memory you can consult the manual for any possible OS dependent bug",
+"Can't create a new thread (errno %d); if you are not out of available memory you can consult the manual for any possible OS dependent bug",
"Column count doesn't match value count at row %ld",
"Can't reopen table: '%-.64s",
"Invalid use of NULL value",
"Got error '%-.64s' from regexp",
-"Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause",
+"Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause",
"There is no such grant defined for user '%-.32s' on host '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for table '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
-"Illegal GRANT/REVOKE command. Please consult the manual which privleges can be used.",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for table '%-.64s'",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
+"Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used.",
"The host or user argument to GRANT is too long",
"Table '%-.64s.%s' doesn't exist",
"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
@@ -158,7 +158,7 @@ character-set=latin1
"Delayed insert thread couldn't get requested lock for table %-.64s",
"Too many delayed threads in use",
"Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)",
-"Got a packet bigger than 'max_allowed_packet'",
+"Got a packet bigger than 'max_allowed_packet' bytes",
"Got a read error from the connection pipe",
"Got an error from fcntl()",
"Got packets out of order",
@@ -167,7 +167,7 @@ character-set=latin1
"Got timeout reading communication packets",
"Got an error writing communication packets",
"Got timeout writing communication packets",
-"Result string is longer than max_allowed_packet",
+"Result string is longer than 'max_allowed_packet' bytes",
"The used table type doesn't support BLOB/TEXT columns",
"The used table type doesn't support AUTO_INCREMENT columns",
"INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
@@ -176,7 +176,7 @@ character-set=latin1
"All tables in the MERGE table are not defined identically",
"Can't write, because of unique constraint, to table '%-.64s'",
"BLOB column '%-.64s' used in key specification without a key length",
-"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
+"All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead",
"Result consisted of more than one row",
"This table type requires a primary key",
"This version of MySQL is not compiled with RAID support",
@@ -202,23 +202,23 @@ character-set=latin1
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -226,50 +226,50 @@ character-set=latin1
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -277,13 +277,13 @@ character-set=latin1
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -298,9 +298,13 @@ character-set=latin1
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Mottok feil %d '%-.100s' fra %s",
+"Mottok temporary feil %d '%-.100s' fra %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 71e14b3df5b..764032da9da 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -121,35 +121,35 @@ character-set=latin1
"A table must have at least 1 column",
"The table '%-.64s' is full",
"Unknown character set: '%-.64s'",
-"Too many tables. MySQL can only use %d tables in a join",
-"Too many fields",
-"Too big row size. The maximum row size, not counting blobs, is %d. You have to change some fields to blobs",
+"Too many tables; MySQL can only use %d tables in a join",
+"Too many columns",
+"Row size too large. The maximum row size for the used table type, not counting BLOBs, is %ld. You have to change some columns to TEXT or BLOBs",
"Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed",
-"Cross dependency found in OUTER JOIN. Examine your ON conditions",
+"Cross dependency found in OUTER JOIN; examine your ON conditions",
"Column '%-.32s' is used with UNIQUE or INDEX but is not defined as NOT NULL",
"Can't load function '%-.64s'",
"Can't initialize function '%-.64s'; %-.80s",
"No paths allowed for shared library",
-"Function '%-.64s' already exist",
+"Function '%-.64s' already exists",
"Can't open shared library '%-.64s' (errno: %d %s)",
"Can't find function '%-.64s' in library'",
"Function '%-.64s' is not defined",
-"Host '%-.64s' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'",
+"Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'",
"Host '%-.64s' is not allowed to connect to this MySQL server",
-"You are using MySQL as an anonymous users and anonymous users are not allowed to change passwords",
+"You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords",
"You must have privileges to update tables in the mysql database to be able to change passwords for others",
"Can't find any matching row in the user table",
"Rows matched: %ld Changed: %ld Warnings: %ld",
-"Can't create a new thread (errno %d). If you are not out of available memory you can consult the manual for any possible OS dependent bug",
+"Can't create a new thread (errno %d); if you are not out of available memory you can consult the manual for any possible OS dependent bug",
"Column count doesn't match value count at row %ld",
"Can't reopen table: '%-.64s",
"Invalid use of NULL value",
"Got error '%-.64s' from regexp",
-"Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause",
+"Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause",
"There is no such grant defined for user '%-.32s' on host '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for table '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
-"Illegal GRANT/REVOKE command. Please consult the manual which privleges can be used.",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for table '%-.64s'",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
+"Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used.",
"The host or user argument to GRANT is too long",
"Table '%-.64s.%s' doesn't exist",
"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
@@ -158,7 +158,7 @@ character-set=latin1
"Delayed insert thread couldn't get requested lock for table %-.64s",
"Too many delayed threads in use",
"Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)",
-"Got a packet bigger than 'max_allowed_packet'",
+"Got a packet bigger than 'max_allowed_packet' bytes",
"Got a read error from the connection pipe",
"Got an error from fcntl()",
"Got packets out of order",
@@ -167,7 +167,7 @@ character-set=latin1
"Got timeout reading communication packets",
"Got an error writing communication packets",
"Got timeout writing communication packets",
-"Result string is longer than max_allowed_packet",
+"Result string is longer than 'max_allowed_packet' bytes",
"The used table type doesn't support BLOB/TEXT columns",
"The used table type doesn't support AUTO_INCREMENT columns",
"INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
@@ -176,7 +176,7 @@ character-set=latin1
"All tables in the MERGE table are not defined identically",
"Can't write, because of unique constraint, to table '%-.64s'",
"BLOB column '%-.64s' used in key specification without a key length",
-"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
+"All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead",
"Result consisted of more than one row",
"This table type requires a primary key",
"This version of MySQL is not compiled with RAID support",
@@ -202,23 +202,23 @@ character-set=latin1
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -226,50 +226,50 @@ character-set=latin1
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -277,13 +277,13 @@ character-set=latin1
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -298,9 +298,13 @@ character-set=latin1
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Mottok feil %d '%-.100s' fa %s",
+"Mottok temporary feil %d '%-.100s' fra %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 51e23c18dfd..68464d0b8f1 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -51,8 +51,8 @@ character-set=latin2
"Zbyt ma³o miejsca/pamiêci dla w?tku",
"Nie mo¿na otrzymaæ nazwy hosta dla twojego adresu",
"Z³y uchwyt(handshake)",
-"Access denied for user: '%-.32s'@'%-.64s' to database '%-.64s'",
-"Access denied for user: '%-.32s'@'%-.64s' (Using password: %s)",
+"Access denied for user '%-.32s'@'%-.64s' to database '%-.64s'",
+"Access denied for user '%-.32s'@'%-.64s' (using password: %s)",
"Nie wybrano ¿adnej bazy danych",
"Nieznana komenda",
"Kolumna '%-.64s' nie mo¿e byæ null",
@@ -114,8 +114,8 @@ character-set=latin2
"Operacja SELECT bêdzie dotyczy³a zbyt wielu rekordów i prawdopodobnie zajmie bardzo du¿o czasu. Sprawd¥ warunek WHERE i u¿yj SQL_OPTION BIG_SELECTS=1 je?li operacja SELECT jest poprawna",
"Unknown error",
"Unkown procedure %s",
-"Wrong parameter count to procedure %s",
-"Wrong parameters to procedure %s",
+"Incorrect parameter count to procedure %s",
+"Incorrect parameters to procedure %s",
"Unknown table '%-.64s' in %s",
"Field '%-.64s' specified twice",
"Invalid use of group function",
@@ -123,35 +123,35 @@ character-set=latin2
"A table must have at least 1 column",
"The table '%-.64s' is full",
"Unknown character set: '%-.64s'",
-"Too many tables. MySQL can only use %d tables in a join",
-"Too many fields",
-"Too big row size. The maximum row size, not counting blobs, is %d. You have to change some fields to blobs",
+"Too many tables; MySQL can only use %d tables in a join",
+"Too many columns",
+"Row size too large. The maximum row size for the used table type, not counting BLOBs, is %ld. You have to change some columns to TEXT or BLOBs",
"Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed",
-"Cross dependency found in OUTER JOIN. Examine your ON conditions",
+"Cross dependency found in OUTER JOIN; examine your ON conditions",
"Column '%-.32s' is used with UNIQUE or INDEX but is not defined as NOT NULL",
"Can't load function '%-.64s'",
"Can't initialize function '%-.64s'; %-.80s",
"No paths allowed for shared library",
-"Function '%-.64s' already exist",
+"Function '%-.64s' already exists",
"Can't open shared library '%-.64s' (errno: %d %s)",
"Can't find function '%-.64s' in library'",
"Function '%-.64s' is not defined",
-"Host '%-.64s' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'",
+"Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'",
"Host '%-.64s' is not allowed to connect to this MySQL server",
-"You are using MySQL as an anonymous users and anonymous users are not allowed to change passwords",
+"You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords",
"You must have privileges to update tables in the mysql database to be able to change passwords for others",
"Can't find any matching row in the user table",
"Rows matched: %ld Changed: %ld Warnings: %ld",
-"Can't create a new thread (errno %d). If you are not out of available memory you can consult the manual for any possible OS dependent bug",
+"Can't create a new thread (errno %d); if you are not out of available memory you can consult the manual for any possible OS dependent bug",
"Column count doesn't match value count at row %ld",
"Can't reopen table: '%-.64s",
"Invalid use of NULL value",
"Got error '%-.64s' from regexp",
-"Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause",
+"Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause",
"There is no such grant defined for user '%-.32s' on host '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for table '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
-"Illegal GRANT/REVOKE command. Please consult the manual which privleges can be used.",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for table '%-.64s'",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
+"Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used.",
"The host or user argument to GRANT is too long",
"Table '%-.64s.%s' doesn't exist",
"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
@@ -160,7 +160,7 @@ character-set=latin2
"Delayed insert thread couldn't get requested lock for table %-.64s",
"Too many delayed threads in use",
"Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)",
-"Got a packet bigger than 'max_allowed_packet'",
+"Got a packet bigger than 'max_allowed_packet' bytes",
"Got a read error from the connection pipe",
"Got an error from fcntl()",
"Got packets out of order",
@@ -169,7 +169,7 @@ character-set=latin2
"Got timeout reading communication packets",
"Got an error writing communication packets",
"Got timeout writing communication packets",
-"Result string is longer than max_allowed_packet",
+"Result string is longer than 'max_allowed_packet' bytes",
"The used table type doesn't support BLOB/TEXT columns",
"The used table type doesn't support AUTO_INCREMENT columns",
"INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
@@ -178,7 +178,7 @@ character-set=latin2
"All tables in the MERGE table are not defined identically",
"Can't write, because of unique constraint, to table '%-.64s'",
"BLOB column '%-.64s' used in key specification without a key length",
-"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
+"All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead",
"Result consisted of more than one row",
"This table type requires a primary key",
"This version of MySQL is not compiled with RAID support",
@@ -204,23 +204,23 @@ character-set=latin2
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -228,50 +228,50 @@ character-set=latin2
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -279,13 +279,13 @@ character-set=latin2
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -300,9 +300,13 @@ character-set=latin2
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 7a969a6541b..7561f12cb7c 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -78,7 +78,7 @@ character-set=latin1
"Chave especificada longa demais. O comprimento de chave máximo permitido é %d",
"Coluna chave '%-.64s' não existe na tabela",
"Coluna BLOB '%-.64s' não pode ser utilizada na especificação de chave para o tipo de tabela usado",
-"Comprimento da coluna '%-.64s' grande demais (max = %d). Use BLOB em seu lugar",
+"Comprimento da coluna '%-.64s' grande demais (max = %d); use BLOB em seu lugar",
"Definição incorreta de tabela. Somente é permitido um único campo auto-incrementado e ele tem que ser definido como chave",
"%s: Pronto para conexões\n",
"%s: 'Shutdown' normal\n",
@@ -94,7 +94,7 @@ character-set=latin1
"Registros: %ld - Deletados: %ld - Ignorados: %ld - Avisos: %ld",
"Registros: %ld - Duplicados: %ld",
"Sub parte da chave incorreta. A parte da chave usada não é uma 'string' ou o comprimento usado é maior que parte da chave ou o manipulador de tabelas não suporta sub chaves únicas",
-"Você não pode deletar todas as colunas com ALTER TABLE. Use DROP TABLE em seu lugar",
+"Você não pode deletar todas as colunas com ALTER TABLE; use DROP TABLE em seu lugar",
"Não se pode fazer DROP '%-.64s'. Confira se esta coluna/chave existe",
"Registros: %ld - Duplicados: %ld - Avisos: %ld",
"You can't specify target table '%-.64s' for update in FROM clause",
@@ -123,8 +123,8 @@ character-set=latin1
"Tabelas demais. O MySQL pode usar somente %d tabelas em uma junção (JOIN)",
"Colunas demais",
"Tamanho de linha grande demais. O máximo tamanho de linha, não contando BLOBs, é %d. Você tem que mudar alguns campos para BLOBs",
-"Estouro da pilha do 'thread'. Usados %ld de uma pilha de %ld . Use 'mysqld -O thread_stack=#' para especificar uma pilha maior, se necessário",
-"Dependência cruzada encontrada em junção externa (OUTER JOIN). Examine as condições utilizadas nas cláusulas 'ON'",
+"Estouro da pilha do 'thread'. Usados %ld de uma pilha de %ld. Use 'mysqld -O thread_stack=#' para especificar uma pilha maior, se necessário",
+"Dependência cruzada encontrada em junção externa (OUTER JOIN); examine as condições utilizadas nas cláusulas 'ON'",
"Coluna '%-.64s' é usada com única (UNIQUE) ou índice (INDEX), mas não está definida como não-nula (NOT NULL)",
"Não pode carregar a função '%-.64s'",
"Não pode inicializar a função '%-.64s' - '%-.80s'",
@@ -247,24 +247,24 @@ character-set=latin1
"Referência da chave e referência da tabela não coincidem",
"Operand should contain %d column(s)",
"Subconsulta retorna mais que 1 registro",
-"Desconhecido manipulador de declaração preparado (%ld) determinado para %s",
+"Desconhecido manipulador de declaração preparado (%.*s) determinado para %s",
"Banco de dado de ajuda corrupto ou não existente",
"Referência cíclica em subconsultas",
"Convertendo coluna '%s' de %s para %s",
"Referência '%-.64s' não suportada (%s)",
"Cada tabela derivada deve ter seu próprio alias",
"Select %u foi reduzido durante otimização",
-"Tabela '%-.64s' de um dos SELECT's não pode ser usada em %-.32s",
+"Tabela '%-.64s' de um dos SELECTs não pode ser usada em %-.32s",
"Cliente não suporta o protocolo de autenticação exigido pelo servidor; considere a atualização do cliente MySQL",
"Todas as partes de uma SPATIAL KEY devem ser NOT NULL",
"COLLATION '%s' não é válida para CHARACTER SET '%s'",
"O slave já está rodando",
"O slave já está parado",
"Tamanho muito grande dos dados des comprimidos. O máximo tamanho é %d. (provavelmente, o comprimento dos dados descomprimidos está corrupto)",
-"Z_MEM_ERROR: Não suficiente memória disponível para zlib",
-"Z_BUF_ERROR: Não suficiente espaço no buffer emissor para zlib (provavelmente, o comprimento dos dados descomprimidos está corrupto)",
-"Z_DATA_ERROR: Dados de entrada está corrupto para zlib",
-"%d linha(s) foi(foram) cortada(s) por group_concat()",
+"ZLIB: Não suficiente memória disponível",
+"ZLIB: Não suficiente espaço no buffer emissor (provavelmente, o comprimento dos dados descomprimidos está corrupto)",
+"ZLIB: Dados de entrada está corrupto",
+"%d linha(s) foram cortada(s) por GROUP_CONCAT()",
"Conta de registro é menor que a conta de coluna na linha %ld",
"Conta de registro é maior que a conta de coluna na linha %ld",
"Dado truncado, NULL fornecido para NOT NULL coluna '%s' na linha %ld",
@@ -300,6 +300,10 @@ character-set=latin1
"Incorreta definição de tabela; Pode ter somente uma coluna TIMESTAMP com CURRENT_TIMESTAMP em DEFAULT ou ON UPDATE cláusula"
"Inválida cláusula ON UPDATE para campo '%-.64s'",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index c53c9b11d0d..03dd45fb6c2 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -111,7 +111,7 @@ character-set=latin2
"Coloana BLOB '%-.64s' nu poate avea o valoare default",
"Numele bazei de date este incorect '%-.100s'",
"Numele tabelei este incorect '%-.100s'",
-"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp. Verifica clauza WHERE si foloseste SET SQL_BIG_SELECTS=1 daca SELECT-ul e ok",
+"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp; verifica clauza WHERE si foloseste SET SQL_BIG_SELECTS=1 daca SELECT-ul e okay",
"Eroare unknown",
"Procedura unknown '%-.64s'",
"Procedura '%-.64s' are un numar incorect de parametri",
@@ -169,7 +169,7 @@ character-set=latin2
"Timeout obtinut citind pachetele de comunicatie (communication packets)",
"Eroare in scrierea pachetelor de comunicatie (communication packets)",
"Timeout obtinut scriind pachetele de comunicatie (communication packets)",
-"Sirul rezultat este mai lung decit max_allowed_packet",
+"Sirul rezultat este mai lung decit 'max_allowed_packet'",
"Tipul de tabela folosit nu suporta coloane de tip BLOB/TEXT",
"Tipul de tabela folosit nu suporta coloane de tip AUTO_INCREMENT",
"INSERT DELAYED nu poate fi folosit cu tabela '%-.64s', deoarece este locked folosing LOCK TABLES",
@@ -192,7 +192,7 @@ character-set=latin2
"Got error %d during FLUSH_LOGS",
"Got error %d during CHECKPOINT",
"Aborted connection %ld to db: '%-.64s' user: '%-.32s' host: `%-.64s' (%-.64s)",
-"The handler for the table does not support binary table dump","Binlog closed while trying to FLUSH MASTER",
+"The handler for the table does not support binary table dump",
"Binlog closed while trying to FLUSH MASTER",
"Failed rebuilding the index of dumped table '%-.64s'",
"Error from master: '%-.64s'",
@@ -204,23 +204,23 @@ character-set=latin2
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
-"This operation cannot be performed with a running slave, run STOP SLAVE first",
-"This operation requires a running slave, configure slave and do START SLAVE",
-"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Could not create slave thread, check system resources",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
+"This operation cannot be performed with a running slave; run STOP SLAVE first",
+"This operation requires a running slave; configure slave and do START SLAVE",
+"The server is not configured as slave; fix in config file or with CHANGE MASTER TO",
+"Could not initialize master info structure; more error messages can be found in the MySQL error log",
+"Could not create slave thread; check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -228,50 +228,50 @@ character-set=latin2
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -279,13 +279,13 @@ character-set=latin2
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -300,9 +300,13 @@ character-set=latin2
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 30a024ef86a..3b0286ea3f8 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -244,32 +244,32 @@ character-set=koi8r
"ðÏÌÕÞÅÎÁ ÎÅÉÓÐÒÁ×ÉÍÁÑ ÏÛÉÂËÁ %d: '%-.128s' ÏÔ ÇÏÌÏ×ÎÏÇÏ ÓÅÒ×ÅÒÁ × ÐÒÏÃÅÓÓÅ ×ÙÂÏÒËÉ ÄÁÎÎÙÈ ÉÚ Ä×ÏÉÞÎÏÇÏ ÖÕÒÎÁÌÁ",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"ïÐÅÒÁÎÄ ÄÏÌÖÅÎ ÓÏÄÅÒÖÁÔØ %d ËÏÌÏÎÏË",
"ðÏÄÚÁÐÒÏÓ ×ÏÚ×ÒÁÝÁÅÔ ÂÏÌÅÅ ÏÄÎÏÊ ÚÁÐÉÓÉ",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"ãÉËÌÉÞÅÓËÁÑ ÓÓÙÌËÁ ÎÁ ÐÏÄÚÁÐÒÏÓ",
"ðÒÅÏÂÒÁÚÏ×ÁÎÉÅ ÐÏÌÑ '%s' ÉÚ %s × %s",
"óÓÙÌËÁ '%-.64s' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ (%s)",
-"Every derived table must have it's own alias",
+"Every derived table must have its own alias",
"Select %u ÂÙÌ ÕÐÒÁÚÄÎÅÎ × ÐÒÏÃÅÓÓÅ ÏÐÔÉÍÉÚÁÃÉÉ",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -277,13 +277,13 @@ character-set=koi8r
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"óÅÒ×ÅÒ ÚÁÐÕÝÅÎ × ÒÅÖÉÍÅ --secure-auth (ÂÅÚÏÐÁÓÎÏÊ Á×ÔÏÒÉÚÁÃÉÉ), ÎÏ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%s'@'%s' ÐÁÒÏÌØ ÓÏÈÒÁÎ£Î × ÓÔÁÒÏÍ ÆÏÒÍÁÔÅ; ÎÅÏÂÈÏÄÉÍÏ ÏÂÎÏ×ÉÔØ ÆÏÒÍÁÔ ÐÁÒÏÌÑ",
"ðÏÌÅ ÉÌÉ ÓÓÙÌËÁ '%-.64s%s%-.64s%s%-.64s' ÉÚ SELECTÁ #%d ÂÙÌÁ ÎÁÊÄÅÎÁ × SELECTÅ #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -298,9 +298,13 @@ character-set=koi8r
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index 18633e0b7be..a64d9056701 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -236,8 +236,20 @@ character-set=cp1250
"Mešanje tabela koje podržavaju transakcije i onih koje ne podržavaju transakcije je iskljuèeno",
"Opcija '%s' je upotrebljena dva puta u istom iskazu",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Access denied; you need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Incorrect usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Slave SQL thread ignored the query because of replicate-*-table rules",
+"Variable '%-.64s' is a %s variable",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
@@ -245,23 +257,23 @@ character-set=cp1250
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
"Row %ld was truncated; it contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -269,13 +281,13 @@ character-set=cp1250
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -290,9 +302,13 @@ character-set=cp1250
"The MySQL server is running with the %s option so it cannot execute this statement"
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 5cd9b4f0e26..ebd64f34f88 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -100,8 +100,8 @@ character-set=latin2
"Súbor '%-.64s' u¾ existuje",
"Záznamov: %ld Zmazaných: %ld Preskoèených: %ld Varovania: %ld",
"Záznamov: %ld Opakovaných: %ld",
-"Wrong sub part key. The used key part isn't a string or the used length is longer than the key part",
-"One nemô¾em zmaza» all fields with ALTER TABLE. Use DROP TABLE instead",
+"Incorrect sub part key; the used key part isn't a string or the used length is longer than the key part",
+"One nemô¾em zmaza» all fields with ALTER TABLE; use DROP TABLE instead",
"Nemô¾em zru¹i» (DROP) '%-.64s'. Skontrolujte, èi neexistujú záznamy/kµúèe",
"Záznamov: %ld Opakovaných: %ld Varovania: %ld",
"You can't specify target table '%-.64s' for update in FROM clause",
@@ -140,22 +140,22 @@ character-set=latin2
"Nemô¾em otvori» zdieµanú kni¾nicu '%-.64s' (chybový kód: %d %s)",
"Nemô¾em nájs» funkciu '%-.64s' v kni¾nici'",
"Funkcia '%-.64s' nie je definovaná",
-"Host '%-.64s' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'",
+"Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'",
"Host '%-.64s' is not allowed to connect to this MySQL server",
-"You are using MySQL as an anonymous users and anonymous users are not allowed to change passwords",
+"You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords",
"You must have privileges to update tables in the mysql database to be able to change passwords for others",
"Can't find any matching row in the user table",
"Rows matched: %ld Changed: %ld Warnings: %ld",
-"Can't create a new thread (errno %d). If you are not out of available memory, you can consult the manual for a possible OS-dependent bug",
+"Can't create a new thread (errno %d); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug",
"Column count doesn't match value count at row %ld",
"Can't reopen table: '%-.64s",
"Invalid use of NULL value",
"Got error '%-.64s' from regexp",
-"Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause",
+"Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause",
"There is no such grant defined for user '%-.32s' on host '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for table '%-.64s'",
-"%-.16s command denied to user: '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
-"Illegal GRANT/REVOKE command. Please consult the manual which privleges can be used.",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for table '%-.64s'",
+"%-.16s command denied to user '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'",
+"Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used.",
"The host or user argument to GRANT is too long",
"Table '%-.64s.%s' doesn't exist",
"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
@@ -164,7 +164,7 @@ character-set=latin2
"Delayed insert thread couldn't get requested lock for table %-.64s",
"Too many delayed threads in use",
"Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)",
-"Got a packet bigger than 'max_allowed_packet'",
+"Got a packet bigger than 'max_allowed_packet' bytes",
"Got a read error from the connection pipe",
"Got an error from fcntl()",
"Got packets out of order",
@@ -173,7 +173,7 @@ character-set=latin2
"Got timeout reading communication packets",
"Got an error writing communication packets",
"Got timeout writing communication packets",
-"Result string is longer than max_allowed_packet",
+"Result string is longer than 'max_allowed_packet' bytes",
"The used table type doesn't support BLOB/TEXT columns",
"The used table type doesn't support AUTO_INCREMENT columns",
"INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
@@ -182,7 +182,7 @@ character-set=latin2
"All tables in the MERGE table are not defined identically",
"Can't write, because of unique constraint, to table '%-.64s'",
"BLOB column '%-.64s' used in key specification without a key length",
-"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
+"All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead",
"Result consisted of more than one row",
"This table type requires a primary key",
"This version of MySQL is not compiled with RAID support",
@@ -208,7 +208,7 @@ character-set=latin2
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again",
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again",
"This operation cannot be performed with a running slave, run STOP SLAVE first",
"This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
@@ -216,15 +216,15 @@ character-set=latin2
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
+"Lock wait timeout exceeded; try restarting transaction",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
+"Incorrect arguments to %s",
"'%-.32s'@'%-.64s' is not allowed to create new users",
"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
+"Deadlock found when trying to get lock; try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
@@ -232,50 +232,50 @@ character-set=latin2
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
+"Incorrect usage of %s and %s",
"The used SELECT statements have a different number of columns",
"Can't execute the query because you have a conflicting read lock",
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
+"Access denied; you need the %-.128s privilege for this operation",
"Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL",
"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
"Variable '%-.64s' doesn't have a default value",
"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
+"Incorrect argument type to variable '%-.64s'",
"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
+"Incorrect usage/placement of '%s'",
"This version of MySQL doesn't yet support '%s'",
"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Slave SQL thread ignored the query because of replicate-*-table rules",
"Variable '%-.64s' is a %s variable",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
+"Incorrect foreign key definition for '%-.64s': %s",
+"Key reference and table reference don't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
-"Unknown prepared statement handler (%ld) given to %s",
+"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias",
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Every derived table must have its own alias",
+"Select %u was reduced during optimization",
+"Table '%-.64s' from one of the SELECTs cannot be used in %-.32s",
"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
-"All parts of a SPATIAL KEY must be NOT NULL",
+"All parts of a SPATIAL index must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"Slave is already running",
"Slave has already been stopped",
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
-"Z_MEM_ERROR: Not enough memory available for zlib",
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
-"Z_DATA_ERROR: Input data was corrupted for zlib",
-"%d line(s) was(were) cut by group_concat()",
+"Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory",
+"ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data corrupted",
+"%d line(s) were cut by GROUP_CONCAT()",
"Row %ld doesn't contain data for all columns",
-"Row %ld was truncated; It contained more data than there were input columns",
-"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
-"Data truncated, out of range for column '%s' at row %ld",
+"Row %ld was truncated; it contained more data than there were input columns",
+"Data truncated; NULL supplied to NOT NULL column '%s' at row %ld",
+"Data truncated; out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
@@ -283,13 +283,13 @@ character-set=latin2
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
-"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
+"Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later when MySQL slave with SSL will be started",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started",
"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL",
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"Incorrect parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you are not safe in case of unexpected slave's mysqld restart",
"SQL thread is not to be started so UNTIL options are ignored",
"Incorrect index name '%-.100s'",
"Incorrect catalog name '%-.100s'",
@@ -304,9 +304,13 @@ character-set=latin2
"The MySQL server is running with the %s option so it cannot execute this statement",
"Column '%-.100s' has duplicated value '%-.64s' in %s"
"Truncated wrong %-.32s value: '%-.128s'"
-"Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
-"Invalid ON UPDATE clause for '%-.64s' field",
+"Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+"Invalid ON UPDATE clause for '%-.64s' column",
"This command is not supported in the prepared statement protocol yet",
+"Got error %d '%-.100s' from %s",
+"Got temporary error %d '%-.100s' from %s",
+"Unknown or incorrect time zone: '%-.64s'",
+"Invalid TIMESTAMP value in column '%s' at row %ld",
"Can't create a %s from within another stored routine"
"%s %s already exists"
"%s %s does not exist"
diff --git a/sql/slave.cc b/sql/slave.cc
index d652ad0e664..5bc2599211e 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -72,6 +72,7 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
static int request_table_dump(MYSQL* mysql, const char* db, const char* table);
static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
const char* table_name, bool overwrite);
+static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi);
/*
Find out which replications threads are running
@@ -1374,31 +1375,90 @@ static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi)
return 1;
}
- MYSQL_RES *master_clock_res;
- MYSQL_ROW master_clock_row;
- time_t slave_clock;
+ /*
+ Compare the master and slave's clock. Do not die if master's clock is
+ unavailable (very old master not supporting UNIX_TIMESTAMP()?).
+ */
+ MYSQL_RES *master_res= 0;
+ MYSQL_ROW master_row;
+
+ if (!mysql_real_query(mysql, "SELECT UNIX_TIMESTAMP()", 23) &&
+ (master_res= mysql_store_result(mysql)) &&
+ (master_row= mysql_fetch_row(master_res)))
+ {
+ mi->clock_diff_with_master=
+ (long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10));
+ }
+ else
+ {
+ mi->clock_diff_with_master= 0; /* The "most sensible" value */
+ sql_print_error("Warning: \"SELECT UNIX_TIMESTAMP()\" failed on master, \
+do not trust column Seconds_Behind_Master of SHOW SLAVE STATUS");
+ }
+ if (master_res)
+ mysql_free_result(master_res);
+
+ /*
+ Check that the master's server id and ours are different. Because if they
+ are equal (which can result from a simple copy of master's datadir to slave,
+ thus copying some my.cnf), replication will work but all events will be
+ skipped.
+ Do not die if SHOW VARIABLES LIKE 'SERVER_ID' fails on master (very old
+ master?).
+ Note: we could have put a @@SERVER_ID in the previous SELECT
+ UNIX_TIMESTAMP() instead, but this would not have worked on 3.23 masters.
+ */
+ if (!mysql_real_query(mysql, "SHOW VARIABLES LIKE 'SERVER_ID'", 31) &&
+ (master_res= mysql_store_result(mysql)))
+ {
+ if ((master_row= mysql_fetch_row(master_res)) &&
+ (::server_id == strtoul(master_row[1], 0, 10)) &&
+ !replicate_same_server_id)
+ errmsg= "The slave I/O thread stops because master and slave have equal \
+MySQL server ids; these ids must be different for replication to work (or \
+the --replicate-same-server-id option must be used on slave but this does \
+not always make sense; please check the manual before using it).";
+ mysql_free_result(master_res);
+ }
- if (mysql_real_query(mysql, "SELECT UNIX_TIMESTAMP()", 23))
- errmsg= "\"SELECT UNIX_TIMESTAMP()\" failed on master";
- else if (!(master_clock_res= mysql_store_result(mysql)))
+ /*
+ Check that the master's global character_set_server and ours are the same.
+ Not fatal if query fails (old master?).
+ */
+ if (!mysql_real_query(mysql, "SELECT @@GLOBAL.COLLATION_SERVER", 32) &&
+ (master_res= mysql_store_result(mysql)))
{
- errmsg= "Could not read the result of \"SELECT UNIX_TIMESTAMP()\" on \
-master";
+ if ((master_row= mysql_fetch_row(master_res)) &&
+ strcmp(master_row[0], global_system_variables.collation_server->name))
+ errmsg= "The slave I/O thread stops because master and slave have \
+different values for the COLLATION_SERVER global variable. The values must \
+be equal for replication to work";
+ mysql_free_result(master_res);
}
- else
+
+ /*
+ Perform analogous check for time zone. Theoretically we also should
+ perform check here to verify that SYSTEM time zones are the same on
+ slave and master, but we can't rely on value of @@system_time_zone
+ variable (it is time zone abbreviation) since it determined at start
+ time and so could differ for slave and master even if they are really
+ in the same system time zone. So we are omiting this check and just
+ relying on documentation. Also according to Monty there are many users
+ who are using replication between servers in various time zones. Hence
+ such check will broke everything for them. (And now everything will
+ work for them because by default both their master and slave will have
+ 'SYSTEM' time zone).
+ */
+ if (!mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) &&
+ (master_res= mysql_store_result(mysql)))
{
- if (!(master_clock_row= mysql_fetch_row(master_clock_res)))
- errmsg= "Could not read a row from the result of \"SELECT \
-UNIX_TIMESTAMP()\" on master";
- else
- {
- slave_clock= time((time_t*) 0);
- mi->clock_diff_with_master= (long) (slave_clock -
- strtoul(master_clock_row[0], 0, 10));
- DBUG_PRINT("info",("slave_clock=%lu, master_clock=%s",
- slave_clock, master_clock_row[0]));
- }
- mysql_free_result(master_clock_res);
+ if ((master_row= mysql_fetch_row(master_res)) &&
+ strcmp(master_row[0],
+ global_system_variables.time_zone->get_name()->ptr()))
+ errmsg= "The slave I/O thread stops because master and slave have \
+different values for the TIME_ZONE global variable. The values must \
+be equal for replication to work";
+ mysql_free_result(master_res);
}
if (errmsg)
@@ -1406,6 +1466,7 @@ UNIX_TIMESTAMP()\" on master";
sql_print_error(errmsg);
return 1;
}
+
return 0;
}
@@ -1573,7 +1634,7 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
thd->net.no_send_ok = 0; // Clear up garbage after create_table_from_dump
if (!called_connected)
mysql_close(mysql);
- if (errmsg && thd->net.vio)
+ if (errmsg && thd->vio_ok())
send_error(thd, error, errmsg);
DBUG_RETURN(test(error)); // Return 1 on error
}
@@ -2681,7 +2742,6 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
DBUG_ENTER("init_slave_thread");
thd->system_thread = (thd_type == SLAVE_THD_SQL) ?
SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO;
- thd->bootstrap= 1;
thd->host_or_ip= "";
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
@@ -3781,7 +3841,6 @@ err:
static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
{
- int return_val= 1;
DBUG_ENTER("process_io_rotate");
safe_mutex_assert_owner(&mi->data_lock);
diff --git a/sql/spatial.cc b/sql/spatial.cc
index ab415d9af10..0668dd2faab 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -15,6 +15,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
+
+#ifdef HAVE_SPATIAL
+
#define MAX_DIGITS_IN_DOUBLE 16
/***************************** Gis_class_info *******************************/
@@ -395,7 +398,7 @@ bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
if (trs->skip_char(',')) // Didn't find ','
break;
}
- if (n_points < 2)
+ if (n_points < 1)
{
trs->set_error_msg("Too few points in LINESTRING");
return 1;
@@ -484,6 +487,11 @@ int Gis_line_string::is_closed(int *closed) const
if (no_data(data, 4))
return 1;
n_points= uint4korr(data);
+ if (n_points == 1)
+ {
+ *closed=1;
+ return 0;
+ }
data+= 4;
if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1;
@@ -1652,3 +1660,4 @@ const Geometry::Class_info *Gis_geometry_collection::get_class_info() const
return &geometrycollection_class;
}
+#endif /*HAVE_SPATIAL*/
diff --git a/sql/spatial.h b/sql/spatial.h
index cc1cc70f1bc..45db1ca8d00 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -17,6 +17,8 @@
#ifndef _spatial_h
#define _spatial_h
+#ifdef HAVE_SPATIAL
+
const uint SRID_SIZE= 4;
const uint SIZEOF_STORED_DOUBLE= 8;
const uint POINT_DATA_SIZE= SIZEOF_STORED_DOUBLE*2;
@@ -459,4 +461,5 @@ struct Geometry_buffer
void *arr[(geometry_buffer_size - 1)/sizeof(void *) + 1];
};
+#endif /*HAVE_SPATAIAL*/
#endif
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index c1740a80fa5..36926d4526d 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -629,10 +629,10 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
if (passwd_len == acl_user_tmp->salt_len)
{
if (acl_user_tmp->salt_len == 0 ||
- acl_user_tmp->salt_len == SCRAMBLE_LENGTH &&
- check_scramble(passwd, thd->scramble, acl_user_tmp->salt) == 0 ||
+ (acl_user_tmp->salt_len == SCRAMBLE_LENGTH ?
+ check_scramble(passwd, thd->scramble, acl_user_tmp->salt) :
check_scramble_323(passwd, thd->scramble,
- (ulong *) acl_user_tmp->salt) == 0)
+ (ulong *) acl_user_tmp->salt)) == 0)
{
acl_user= acl_user_tmp;
res= 0;
@@ -1021,7 +1021,7 @@ static void acl_insert_db(const char *user, const char *host, const char *db,
*/
ulong acl_get(const char *host, const char *ip,
- const char *user, const char *db, my_bool db_is_pattern)
+ const char *user, const char *db, my_bool db_is_pattern)
{
ulong host_access,db_access;
uint i,key_length;
@@ -1507,8 +1507,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1);
- table->file->index_init(0);
- if (table->file->index_read(table->record[0],
+ if (table->file->index_read_idx(table->record[0], 0,
(byte*) table->field[0]->ptr,0,
HA_READ_KEY_EXACT))
{
@@ -1519,7 +1518,6 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
else
my_error(ER_NO_PERMISSION_TO_CREATE_USER, MYF(0),
thd->user, thd->host_or_ip);
- error= -1;
goto end;
}
old_row_exists = 0;
@@ -1656,7 +1654,6 @@ end:
&thd->lex->mqh,
rights);
}
- table->file->index_end();
DBUG_RETURN(error);
}
@@ -1692,8 +1689,7 @@ static int replace_db_table(TABLE *table, const char *db,
table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
- table->file->index_init(0);
- if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr,0,
+ if (table->file->index_read_idx(table->record[0],0,(byte*) table->field[0]->ptr,0,
HA_READ_KEY_EXACT))
{
if (what == 'N')
@@ -1747,13 +1743,11 @@ static int replace_db_table(TABLE *table, const char *db,
acl_update_db(combo.user.str,combo.host.str,db,rights);
else
acl_insert_db(combo.user.str,combo.host.str,db,rights);
- table->file->index_end();
DBUG_RETURN(0);
/* This could only happen if the grant tables got corrupted */
table_error:
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
- table->file->index_end();
abort:
DBUG_RETURN(-1);
@@ -1875,8 +1869,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
col_privs->field[3]->pack_length());
key_copy(key,col_privs,0,key_len);
col_privs->field[4]->store("",0, &my_charset_latin1);
- col_privs->file->index_init(0);
- if (col_privs->file->index_read(col_privs->record[0],
+ if (col_privs->file->index_read_idx(col_privs->record[0],0,
(byte*) col_privs->field[0]->ptr,
key_len, HA_READ_KEY_EXACT))
{
@@ -1991,7 +1984,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
List_iterator <LEX_COLUMN> iter(columns);
class LEX_COLUMN *xx;
- table->file->index_init(0);
+ table->file->ha_index_init(0);
while ((xx=iter++))
{
ulong privileges = xx->rights;
@@ -2061,7 +2054,6 @@ static int replace_column_table(GRANT_TABLE *g_t,
my_hash_insert(&g_t->hash_columns,(byte*) grant_column);
}
}
- table->file->index_end();
/*
If revoke of privileges on the table level, remove all such privileges
@@ -2070,7 +2062,6 @@ static int replace_column_table(GRANT_TABLE *g_t,
if (revoke_grant)
{
- table->file->index_init(0);
if (table->file->index_read(table->record[0], (byte*) table->field[0]->ptr,
key_length, HA_READ_KEY_EXACT))
goto end;
@@ -2126,7 +2117,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
}
end:
- table->file->index_end();
+ table->file->ha_index_end();
DBUG_RETURN(result);
}
@@ -2639,15 +2630,13 @@ my_bool grant_init(THD *org_thd)
goto end;
t_table = tables[0].table; c_table = tables[1].table;
- t_table->file->index_init(0);
+ t_table->file->ha_index_init(0);
if (t_table->file->index_first(t_table->record[0]))
{
- t_table->file->index_end();
return_val= 0;
goto end_unlock;
}
grant_option= TRUE;
- t_table->file->index_end();
/* Will be restored by org_thd->store_globals() */
my_pthread_setspecific_ptr(THR_MALLOC,&memex);
@@ -2667,7 +2656,7 @@ my_bool grant_init(THD *org_thd)
{
sql_print_error("Warning: 'tables_priv' entry '%s %s@%s' "
"ignored in --skip-name-resolve mode.",
- mem_check->tname, mem_check->user,
+ mem_check->tname, mem_check->user,
mem_check->host, mem_check->host);
continue;
}
@@ -2684,6 +2673,7 @@ my_bool grant_init(THD *org_thd)
return_val=0; // Return ok
end_unlock:
+ t_table->file->ha_index_end();
mysql_unlock_tables(thd, lock);
thd->version--; // Force close to free memory
@@ -2909,7 +2899,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
if (table->grant.version != grant_version)
{
table->grant.grant_table=
- table_hash_search(thd->host,thd->ip,thd->db,
+ table_hash_search(thd->host, thd->ip, table->table_cache_key,
thd->priv_user,
table->real_name,0); /* purecov: inspected */
table->grant.version=grant_version; /* purecov: inspected */
@@ -3022,7 +3012,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
if (table->grant.version != grant_version)
{
table->grant.grant_table=
- table_hash_search(thd->host,thd->ip,thd->db,
+ table_hash_search(thd->host, thd->ip, table->db,
thd->priv_user,
table->real_name,0); /* purecov: inspected */
table->grant.version=grant_version; /* purecov: inspected */
@@ -3627,12 +3617,10 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list)
record[0])))
{
tables[0].table->file->print_error(error, MYF(0));
- tables[0].table->file->index_end();
DBUG_RETURN(-1);
}
delete_dynamic_element(&acl_users, acl_userd);
}
- tables[0].table->file->index_end();
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6af822e3ec2..22f93bb05ba 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -300,6 +300,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
thd->proc_info="Flushing tables";
close_old_data_files(thd,thd->open_tables,1,1);
+ mysql_ha_close_list(thd, tables);
bool found=1;
/* Wait until all threads has closed all the tables we had locked */
DBUG_PRINT("info",
@@ -850,6 +851,9 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
DBUG_RETURN(0);
}
+ /* close handler tables which are marked for flush */
+ mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
+
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
table && table->in_use ;
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
@@ -1220,6 +1224,7 @@ bool wait_for_tables(THD *thd)
{
thd->some_tables_deleted=0;
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0);
+ mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
if (!table_is_used(thd->open_tables,1))
break;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
@@ -1760,6 +1765,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
}
tmp_table->reginfo.lock_type=TL_WRITE; // Simulate locked
+ tmp_table->in_use= thd;
tmp_table->tmp_table = (tmp_table->file->has_transactions() ?
TRANSACTIONAL_TMP_TABLE : TMP_TABLE);
tmp_table->table_cache_key=(char*) (tmp_table+1);
@@ -2184,8 +2190,19 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
!((Item_field*) item)->field)
{
uint elem= fields.elements;
- if (insert_fields(thd,tables,((Item_field*) item)->db_name,
- ((Item_field*) item)->table_name, &it))
+ Item_subselect *subsel= thd->lex->current_select->master_unit()->item;
+ if (subsel &&
+ subsel->substype() == Item_subselect::EXISTS_SUBS)
+ {
+ /*
+ It is EXISTS(SELECT * ...) and we can replace * by any constant.
+
+ Item_int do not need fix_fields() because it is basic constant.
+ */
+ it.replace(new Item_int("Not_used", (longlong) 1, 21));
+ }
+ else if (insert_fields(thd,tables,((Item_field*) item)->db_name,
+ ((Item_field*) item)->table_name, &it))
{
if (arena)
thd->restore_backup_item_arena(arena, &backup);
diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h
index 0274cd700da..5c51f3ecb67 100644
--- a/sql/sql_bitmap.h
+++ b/sql/sql_bitmap.h
@@ -64,15 +64,15 @@ public:
char *s=buf; int i;
for (i=sizeof(buffer)-1; i>=0 ; i--)
{
- if ((*s=_dig_vec[buffer[i] >> 4]) != '0')
+ if ((*s=_dig_vec_upper[buffer[i] >> 4]) != '0')
break;
- if ((*s=_dig_vec[buffer[i] & 15]) != '0')
+ if ((*s=_dig_vec_upper[buffer[i] & 15]) != '0')
break;
}
for (s++, i-- ; i>=0 ; i--)
{
- *s++=_dig_vec[buffer[i] >> 4];
- *s++=_dig_vec[buffer[i] & 15];
+ *s++=_dig_vec_upper[buffer[i] >> 4];
+ *s++=_dig_vec_upper[buffer[i] & 15];
}
*s=0;
return buf;
@@ -91,7 +91,16 @@ template <> class Bitmap<64>
ulonglong map;
public:
Bitmap<64>() { }
+#if defined(__NETWARE__)
+ /*
+ Metwork compiler gives error on Bitmap<64>
+ Changed to Bitmap, since in this case also it will proper construct
+ this class
+ */
+ explicit Bitmap(uint prefix_to_set) { set_prefix(prefix_to_set); }
+#else
explicit Bitmap<64>(uint prefix_to_set) { set_prefix(prefix_to_set); }
+#endif
void init() { }
void init(uint prefix_to_set) { set_prefix(prefix_to_set); }
uint length() const { return 64; }
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 50bcca4b57e..68b4bc601fe 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -786,6 +786,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
flags.collation_connection_num=
thd->variables.collation_connection->number;
flags.limit= thd->variables.select_limit;
+ flags.time_zone= thd->variables.time_zone;
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size == 0)
@@ -977,6 +978,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
UINT_MAX);
flags.collation_connection_num= thd->variables.collation_connection->number;
flags.limit= thd->variables.select_limit;
+ flags.time_zone= thd->variables.time_zone;
memcpy((void *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
&flags, QUERY_CACHE_FLAGS_SIZE);
query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql,
@@ -1047,9 +1049,9 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
goto err_unlock; // Parse query
}
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
- if (check_tables && !handler::caching_allowed(thd, table->db(),
- table->key_length(),
- table->type()))
+ if (check_tables && !ha_caching_allowed(thd, table->db(),
+ table->key_length(),
+ table->type()))
{
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
table_list.db, table_list.alias));
@@ -2690,9 +2692,9 @@ my_bool Query_cache::ask_handler_allowance(THD *thd,
for (; tables_used; tables_used= tables_used->next)
{
TABLE *table= tables_used->table;
- if (!handler::caching_allowed(thd, table->table_cache_key,
- table->key_length,
- table->file->table_cache_type()))
+ if (!ha_caching_allowed(thd, table->table_cache_key,
+ table->key_length,
+ table->file->table_cache_type()))
{
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
tables_used->db, tables_used->alias));
@@ -3236,9 +3238,10 @@ void Query_cache::queries_dump()
Query_cache_query_flags flags;
memcpy(&flags, str+len, QUERY_CACHE_FLAGS_SIZE);
str[len]= 0; // make zero ending DB name
- DBUG_PRINT("qcache", ("F:%u C:%u L:%lu (%u) '%s' '%s'",
+ DBUG_PRINT("qcache", ("F:%u C:%u L:%lu T:'%s' (%u) '%s' '%s'",
flags.client_long_flag,
- flags.character_set_client_num, (ulong)flags.limit,
+ flags.character_set_client_num,
+ (ulong)flags.limit, flags.time_zone->get_name(),
len, str, strend(str)+1));
DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block,
(ulong) block->next, (ulong) block->prev,
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 7a4f3dff845..07c894dc8c1 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -81,7 +81,6 @@ extern "C" void free_user_var(user_var_entry *entry)
my_free((char*) entry,MYF(0));
}
-
bool key_part_spec::operator==(const key_part_spec& other) const
{
return length == other.length && !strcmp(field_name, other.field_name);
@@ -161,8 +160,9 @@ bool foreign_key_prefix(Key *a, Key *b)
THD::THD():user_time(0), current_arena(0), is_fatal_error(0),
last_insert_id_used(0),
- insert_id_used(0), rand_used(0), in_lock_tables(0),
- global_read_lock(0), bootstrap(0), spcont(NULL)
+ insert_id_used(0), rand_used(0), time_zone_used(0),
+ in_lock_tables(0), global_read_lock(0), bootstrap(0),
+ spcont(NULL)
{
host= user= priv_user= db= ip= 0;
catalog= (char*)"std"; // the only catalog we have for now
@@ -186,6 +186,7 @@ THD::THD():user_time(0), current_arena(0), is_fatal_error(0),
current_linfo = 0;
slave_thread = 0;
variables.pseudo_thread_id= 0;
+ one_shot_set= 0;
file_id = 0;
warn_id= 0;
db_charset= global_system_variables.collation_database;
@@ -762,7 +763,7 @@ bool select_send::send_data(List<Item> &items)
}
}
thd->sent_row_count++;
- if (!thd->net.vio)
+ if (!thd->vio_ok())
DBUG_RETURN(0);
if (!thd->net.report_error)
DBUG_RETURN(protocol->write());
@@ -1352,7 +1353,9 @@ Statement::Statement(THD *thd)
lex(&main_lex),
query(0),
query_length(0)
-{}
+{
+ name.str= NULL;
+}
/*
This constructor is called when statement is a subobject of THD:
@@ -1431,17 +1434,52 @@ static void delete_statement_as_hash_key(void *key)
delete (Statement *) key;
}
+static byte *get_stmt_name_hash_key(Statement *entry, uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length=(uint) entry->name.length;
+ return (byte*) entry->name.str;
+}
+
C_MODE_END
Statement_map::Statement_map() :
last_found_statement(0)
{
- enum { START_HASH_SIZE = 16 };
- hash_init(&st_hash, default_charset_info, START_HASH_SIZE, 0, 0,
+ enum
+ {
+ START_STMT_HASH_SIZE = 16,
+ START_NAME_HASH_SIZE = 16
+ };
+ hash_init(&st_hash, default_charset_info, START_STMT_HASH_SIZE, 0, 0,
get_statement_id_as_hash_key,
delete_statement_as_hash_key, MYF(0));
+ hash_init(&names_hash, &my_charset_bin, START_NAME_HASH_SIZE, 0, 0,
+ (hash_get_key) get_stmt_name_hash_key,
+ NULL,MYF(0));
}
+int Statement_map::insert(Statement *statement)
+{
+ int rc= my_hash_insert(&st_hash, (byte *) statement);
+ if (rc == 0)
+ last_found_statement= statement;
+ if (statement->name.str)
+ {
+ /*
+ If there is a statement with the same name, remove it. It is ok to
+ remove old and fail to insert new one at the same time.
+ */
+ Statement *old_stmt;
+ if ((old_stmt= find_by_name(&statement->name)))
+ erase(old_stmt);
+ if ((rc= my_hash_insert(&names_hash, (byte*)statement)))
+ hash_delete(&st_hash, (byte*)statement);
+ }
+ return rc;
+}
+
+
bool select_dumpvar::send_data(List<Item> &items)
{
List_iterator_fast<Item_func_set_user_var> li(vars);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 1e9b1d04351..08f73309a85 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -192,6 +192,8 @@ public:
int purge_first_log(struct st_relay_log_info* rli, bool included);
bool reset_logs(THD* thd);
void close(uint exiting);
+ bool cut_spurious_tail();
+ void report_pos_in_innodb();
// iterating through the log index file
int find_log_pos(LOG_INFO* linfo, const char* log_name,
@@ -408,6 +410,7 @@ struct system_variables
ulong query_prealloc_size;
ulong trans_alloc_block_size;
ulong trans_prealloc_size;
+ ulong log_warnings;
ulong group_concat_max_len;
/*
In slave thread we need to know in behalf of which
@@ -415,7 +418,6 @@ struct system_variables
*/
ulong pseudo_thread_id;
- my_bool log_warnings;
my_bool low_priority_updates;
my_bool new_mode;
my_bool query_cache_wlock_invalidate;
@@ -430,6 +432,8 @@ struct system_variables
CHARSET_INFO *collation_database;
CHARSET_INFO *collation_connection;
+ Time_zone *time_zone;
+
/* DATE, DATETIME and TIME formats */
DATE_TIME_FORMAT *date_format;
DATE_TIME_FORMAT *datetime_format;
@@ -528,6 +532,7 @@ public:
*/
bool allow_sum_func;
+ LEX_STRING name; /* name for named prepared statements */
LEX *lex; // parse tree descriptor
/*
Points to the query associated with this statement. It's const, but
@@ -563,8 +568,14 @@ public:
/*
- Used to seek all existing statements in the connection
- Deletes all statements in destructor.
+ Container for all statements created/used in a connection.
+ Statements in Statement_map have unique Statement::id (guaranteed by id
+ assignment in Statement::Statement)
+ Non-empty statement names are unique too: attempt to insert a new statement
+ with duplicate name causes older statement to be deleted
+
+ Statements are auto-deleted when they are removed from the map and when the
+ map is deleted.
*/
class Statement_map
@@ -572,34 +583,47 @@ class Statement_map
public:
Statement_map();
- int insert(Statement *statement)
+ int insert(Statement *statement);
+
+ Statement *find_by_name(LEX_STRING *name)
{
- int rc= my_hash_insert(&st_hash, (byte *) statement);
- if (rc == 0)
- last_found_statement= statement;
- return rc;
+ Statement *stmt;
+ stmt= (Statement*)hash_search(&names_hash, (byte*)name->str,
+ name->length);
+ return stmt;
}
Statement *find(ulong id)
{
if (last_found_statement == 0 || id != last_found_statement->id)
- last_found_statement= (Statement *) hash_search(&st_hash, (byte *) &id,
- sizeof(id));
+ {
+ Statement *stmt;
+ stmt= (Statement *) hash_search(&st_hash, (byte *) &id, sizeof(id));
+ if (stmt && stmt->name.str)
+ return NULL;
+ last_found_statement= stmt;
+ }
return last_found_statement;
}
void erase(Statement *statement)
{
if (statement == last_found_statement)
last_found_statement= 0;
+ if (statement->name.str)
+ {
+ hash_delete(&names_hash, (byte *) statement);
+ }
hash_delete(&st_hash, (byte *) statement);
}
~Statement_map()
{
hash_free(&st_hash);
+ hash_free(&names_hash);
}
private:
HASH st_hash;
+ HASH names_hash;
Statement *last_found_statement;
};
@@ -845,11 +869,12 @@ public:
/* scramble - random string sent to client on handshake */
char scramble[SCRAMBLE_LENGTH+1];
- bool slave_thread;
+ bool slave_thread, one_shot_set;
bool locked, some_tables_deleted;
bool last_cuted_field;
bool no_errors, password, is_fatal_error;
bool query_start_used,last_insert_id_used,insert_id_used,rand_used;
+ bool time_zone_used;
bool in_lock_tables,global_read_lock;
bool query_error, bootstrap, cleanup_done;
@@ -992,8 +1017,10 @@ public:
net.last_errno= 0;
net.report_error= 0;
}
+ inline bool vio_ok() const { return net.vio != 0; }
#else
void clear_error();
+ inline bool vio_ok() const { return true; }
#endif
inline void fatal_error()
{
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index e2c337e5064..fcb6134ce41 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -357,15 +357,25 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
{
error= -1;
my_error(ER_DB_DROP_EXISTS,MYF(0),db);
+ goto exit;
}
else
- {
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
- if (!silent)
- send_ok(thd,0);
+ }
+ else
+ {
+ pthread_mutex_lock(&LOCK_open);
+ remove_db_from_cache(db);
+ pthread_mutex_unlock(&LOCK_open);
+
+ error= -1;
+ if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0)) >= 0)
+ {
+ ha_drop_database(path);
+ query_cache_invalidate1(db);
+ error = 0;
}
- goto exit;
}
if (lower_case_table_names)
{
@@ -374,41 +384,30 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
my_casedn_str(files_charset_info, tmp_db);
db= tmp_db;
}
-
- pthread_mutex_lock(&LOCK_open);
- remove_db_from_cache(db);
- pthread_mutex_unlock(&LOCK_open);
-
- error = -1;
- if ((deleted=mysql_rm_known_files(thd, dirp, db, path,0)) >= 0 && thd)
+ if (!silent && deleted>=0 && thd)
{
- ha_drop_database(path);
- query_cache_invalidate1(db);
- if (!silent)
+ const char *query;
+ ulong query_length;
+ if (!thd->query)
{
- const char *query;
- ulong query_length;
- if (!thd->query)
- {
- /* The client used the old obsolete mysql_drop_db() call */
- query= path;
- query_length = (uint) (strxmov(path,"drop database `", db, "`",
- NullS)- path);
- }
- else
- {
- query=thd->query;
- query_length=thd->query_length;
- }
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, query, query_length, 0);
- thd->clear_error();
- mysql_bin_log.write(&qinfo);
- }
- send_ok(thd,(ulong) deleted);
+ /* The client used the old obsolete mysql_drop_db() call */
+ query= path;
+ query_length= (uint) (strxmov(path, "drop database `", db, "`",
+ NullS) - path);
+ }
+ else
+ {
+ query =thd->query;
+ query_length= thd->query_length;
+ }
+ mysql_update_log.write(thd, query, query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, query, query_length, 0);
+ thd->clear_error();
+ mysql_bin_log.write(&qinfo);
}
- error = 0;
+ send_ok(thd, (ulong) deleted);
}
exit:
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 440d404056b..9e425f86579 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -205,15 +205,24 @@ cleanup:
query_cache_invalidate3(thd, table_list, 1);
}
+ delete select;
transactional_table= table->file->has_transactions();
log_delayed= (transactional_table || table->tmp_table);
- if (deleted && (error <= 0 || !transactional_table))
+ /*
+ We write to the binary log even if we deleted no row, because maybe the
+ user is using this command to ensure that a table is clean on master *and
+ on slave*. Think of the case of a user having played separately with the
+ master's table and slave's table and wanting to take a fresh identical
+ start now.
+ error < 0 means "really no error". error <= 0 means "maybe some error".
+ */
+ if ((deleted || (error < 0)) && (error <= 0 || !transactional_table))
{
if (mysql_bin_log.is_open())
{
if (error <= 0)
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length,
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
@@ -232,7 +241,6 @@ cleanup:
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
- delete select;
free_underlaid_joins(thd, &thd->lex->select_lex);
if (error >= 0 || thd->net.report_error)
send_error(thd,thd->killed_errno());
@@ -560,6 +568,8 @@ bool multi_delete::send_eof()
rows and we succeeded, or also in an error case when there
was a non-transaction-safe table involved, since
modifications in it cannot be rolled back.
+ Note that if we deleted nothing we don't write to the binlog (TODO:
+ fix this).
*/
if (deleted && (error <= 0 || normal_tables))
{
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 46794f45f3c..48bc6f4c5a2 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -117,7 +117,6 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
select_union *derived_result;
bool is_union= first_select->next_select() &&
first_select->next_select()->linkage == UNION_TYPE;
- bool is_subsel= first_select->first_inner_unit() ? 1: 0;
SELECT_LEX *save_current_select= lex->current_select;
DBUG_ENTER("mysql_derived");
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index fcc56cbf9c9..56c1b0a1b51 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -43,7 +43,9 @@
thd->handler_tables=tmp; }
static TABLE **find_table_ptr_by_name(THD *thd,const char *db,
- const char *table_name, bool is_alias);
+ const char *table_name,
+ bool is_alias, bool dont_lock,
+ bool *was_flushed);
int mysql_ha_open(THD *thd, TABLE_LIST *tables)
{
@@ -66,24 +68,61 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables)
return 0;
}
-int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
+
+/*
+ Close a HANDLER table.
+
+ SYNOPSIS
+ mysql_ha_close()
+ thd Thread identifier.
+ tables A list of tables with the first entry to close.
+ dont_send_ok Suppresses the commands' ok message and
+ error message and error return.
+ dont_lock Suppresses the normal locking of LOCK_open.
+
+ DESCRIPTION
+ Though this function takes a list of tables, only the first list entry
+ will be closed. Broadcasts a COND_refresh condition.
+ If mysql_ha_close() is not called from the parser, 'dont_send_ok'
+ must be set.
+ If the caller did already lock LOCK_open, it must set 'dont_lock'.
+
+ IMPLEMENTATION
+ find_table_ptr_by_name() closes the table, if a FLUSH TABLE is outstanding.
+ It returns a NULL pointer in this case, but flags the situation in
+ 'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages
+ is suppressed.
+
+ RETURN
+ 0 ok
+ -1 error
+*/
+
+int mysql_ha_close(THD *thd, TABLE_LIST *tables,
+ bool dont_send_ok, bool dont_lock, bool no_alias)
{
- TABLE **ptr=find_table_ptr_by_name(thd, tables->db, tables->alias, 1);
+ TABLE **table_ptr;
+ bool was_flushed;
- if (*ptr)
+ table_ptr= find_table_ptr_by_name(thd, tables->db, tables->alias,
+ !no_alias, dont_lock, &was_flushed);
+ if (*table_ptr)
{
- VOID(pthread_mutex_lock(&LOCK_open));
- if (close_thread_table(thd, ptr))
+ (*table_ptr)->file->ha_index_or_rnd_end();
+ if (!dont_lock)
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (close_thread_table(thd, table_ptr))
{
/* Tell threads waiting for refresh that something has happened */
VOID(pthread_cond_broadcast(&COND_refresh));
}
- VOID(pthread_mutex_unlock(&LOCK_open));
+ if (!dont_lock)
+ VOID(pthread_mutex_unlock(&LOCK_open));
}
- else
+ else if (!was_flushed && !dont_send_ok)
{
- my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),
- tables->alias, "HANDLER");
+ my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
+ tables->alias, "HANDLER");
return -1;
}
if (!dont_send_ok)
@@ -91,13 +130,65 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
return 0;
}
-int mysql_ha_closeall(THD *thd, TABLE_LIST *tables)
+
+/*
+ Close a list of HANDLER tables.
+
+ SYNOPSIS
+ mysql_ha_close_list()
+ thd Thread identifier.
+ tables The list of tables to close. If NULL,
+ close all HANDLER tables.
+ flushed Close only tables which are marked flushed.
+ Used only if tables is NULL.
+
+ DESCRIPTION
+ The list of HANDLER tables may be NULL, in which case all HANDLER
+ tables are closed. Broadcasts a COND_refresh condition, for
+ every table closed. If 'tables' is NULL and 'flushed' is set,
+ all HANDLER tables marked for flush are closed.
+ The caller must lock LOCK_open.
+
+ IMPLEMENTATION
+ find_table_ptr_by_name() closes the table, if it is marked for flush.
+ It returns a NULL pointer in this case, but flags the situation in
+ 'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages
+ is suppressed.
+
+ RETURN
+ 0 ok
+*/
+
+int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed)
{
- TABLE **ptr=find_table_ptr_by_name(thd, tables->db, tables->real_name, 0);
- if (*ptr && close_thread_table(thd, ptr))
+ TABLE_LIST *tl_item;
+ TABLE **table_ptr;
+
+ if (tables)
{
- /* Tell threads waiting for refresh that something has happened */
- VOID(pthread_cond_broadcast(&COND_refresh));
+ for (tl_item= tables ; tl_item; tl_item= tl_item->next)
+ {
+ mysql_ha_close(thd, tl_item, /*dont_send_ok*/ 1,
+ /*dont_lock*/ 1, /*no_alias*/ 1);
+ }
+ }
+ else
+ {
+ table_ptr= &(thd->handler_tables);
+ while (*table_ptr)
+ {
+ if (! flushed || ((*table_ptr)->version != refresh_version))
+ {
+ (*table_ptr)->file->ha_index_or_rnd_end();
+ if (close_thread_table(thd, table_ptr))
+ {
+ /* Tell threads waiting for refresh that something has happened */
+ VOID(pthread_cond_broadcast(&COND_refresh));
+ }
+ continue;
+ }
+ table_ptr= &((*table_ptr)->next);
+ }
}
return 0;
}
@@ -112,7 +203,10 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
ha_rows select_limit,ha_rows offset_limit)
{
int err, keyno=-1;
- TABLE *table=*find_table_ptr_by_name(thd, tables->db, tables->alias, 1);
+ bool was_flushed;
+ TABLE *table= *find_table_ptr_by_name(thd, tables->db, tables->alias,
+ /*is_alias*/ 1, /*dont_lock*/ 0,
+ &was_flushed);
if (!table)
{
my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),
@@ -136,7 +230,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
keyname,tables->alias);
return -1;
}
- table->file->index_init(keyno);
+ table->file->ha_index_or_rnd_end();
+ table->file->ha_index_init(keyno);
}
List<Item> list;
@@ -148,8 +243,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
uint num_rows;
byte *key;
uint key_len;
- LINT_INIT(key);
- LINT_INIT(key_len);
+ LINT_INIT(key);
+ LINT_INIT(key_len);
it++; // Skip first NULL field
@@ -180,7 +275,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
err=table->file->index_first(table->record[0]);
else
{
- if (!(err=table->file->rnd_init(1)))
+ table->file->ha_index_or_rnd_end();
+ if (!(err=table->file->ha_rnd_init(1)))
err=table->file->rnd_next(table->record[0]);
}
mode=RNEXT;
@@ -291,17 +387,51 @@ err0:
}
+/*
+ Find a HANDLER table by name.
+
+ SYNOPSIS
+ find_table_ptr_by_name()
+ thd Thread identifier.
+ db Database (schema) name.
+ table_name Table name ;-).
+ is_alias Table name may be an alias name.
+ dont_lock Suppresses the normal locking of LOCK_open.
+
+ DESCRIPTION
+ Find the table 'db'.'table_name' in the list of HANDLER tables of the
+ thread 'thd'. If the table has been marked by FLUSH TABLE(S), close it,
+ flag this situation in '*was_flushed' and broadcast a COND_refresh
+ condition.
+ An empty database (schema) name matches all database (schema) names.
+ If the caller did already lock LOCK_open, it must set 'dont_lock'.
+
+ IMPLEMENTATION
+ Just in case that the table is twice in 'thd->handler_tables' (!?!),
+ the loop does not break when the table was flushed. If another table
+ by that name was found and not flushed, '*was_flushed' is cleared again,
+ since a pointer to an open HANDLER table is returned.
+
+ RETURN
+ *was_flushed Table has been closed due to FLUSH TABLE.
+ NULL A HANDLER Table by that name does not exist (any more).
+ != NULL Pointer to the TABLE structure.
+*/
+
static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
- const char *table_name, bool is_alias)
+ const char *table_name,
+ bool is_alias, bool dont_lock,
+ bool *was_flushed)
{
int dblen;
- TABLE **ptr;
+ TABLE **table_ptr;
DBUG_ASSERT(db);
dblen= strlen(db);
- ptr= &(thd->handler_tables);
+ table_ptr= &(thd->handler_tables);
+ *was_flushed= FALSE;
- for (TABLE *table= *ptr; table ; table= *ptr)
+ for (TABLE *table= *table_ptr; table ; table= *table_ptr)
{
if ((db == any_db || !memcmp(table->table_cache_key, db, dblen)) &&
!my_strcasecmp(system_charset_info,
@@ -310,18 +440,22 @@ static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
{
if (table->version != refresh_version)
{
- VOID(pthread_mutex_lock(&LOCK_open));
- if (close_thread_table(thd, ptr))
+ if (!dont_lock)
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (close_thread_table(thd, table_ptr))
{
/* Tell threads waiting for refresh that something has happened */
VOID(pthread_cond_broadcast(&COND_refresh));
}
- VOID(pthread_mutex_unlock(&LOCK_open));
+ if (!dont_lock)
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ *was_flushed= TRUE;
continue;
}
+ *was_flushed= FALSE;
break;
}
- ptr= &(table->next);
+ table_ptr= &(table->next);
}
- return ptr;
+ return table_ptr;
}
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 44293b8214f..eabe66d33bf 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -22,8 +22,6 @@ struct st_find_field
Field *field;
};
-static void free_select(SQL_SELECT *sel);
-
/* Used fields */
static struct st_find_field init_used_fields[]=
@@ -48,9 +46,9 @@ static struct st_find_field init_used_fields[]=
enum enum_used_fields
{
help_topic_help_topic_id= 0,
- help_topic_name,
+ help_topic_name,
help_topic_help_category_id,
- help_topic_description,
+ help_topic_description,
help_topic_example,
help_category_help_category_id,
@@ -60,13 +58,13 @@ enum enum_used_fields
help_keyword_help_keyword_id,
help_keyword_name,
- help_relation_help_topic_id,
+ help_relation_help_topic_id,
help_relation_help_keyword_id
};
/*
- Fill st_find_field structure with pointers to fields
+ Fill st_find_field structure with pointers to fields
SYNOPSIS
init_fields()
@@ -90,7 +88,7 @@ static bool init_fields(THD *thd, TABLE_LIST *tables,
/* We have to use 'new' here as field will be re_linked on free */
Item_field *field= new Item_field("mysql", find_fields->table_name,
find_fields->field_name);
- if (!(find_fields->field= find_field_in_tables(thd, field, tables,
+ if (!(find_fields->field= find_field_in_tables(thd, field, tables,
&not_used, TRUE)))
DBUG_RETURN(1);
}
@@ -119,12 +117,12 @@ static bool init_fields(THD *thd, TABLE_LIST *tables,
NOTE
Field 'names' is set only if more than one topic is found.
- Fields 'name', 'description', 'example' are set only if
+ Fields 'name', 'description', 'example' are set only if
found exactly one topic.
*/
void memorize_variant_topic(THD *thd, TABLE *topics, int count,
- struct st_find_field *find_fields,
+ struct st_find_field *find_fields,
List<String> *names,
String *name, String *description, String *example)
{
@@ -136,7 +134,7 @@ void memorize_variant_topic(THD *thd, TABLE *topics, int count,
get_field(mem_root,find_fields[help_topic_description].field, description);
get_field(mem_root,find_fields[help_topic_example].field, example);
}
- else
+ else
{
if (count == 1)
names->push_back(name);
@@ -168,7 +166,7 @@ void memorize_variant_topic(THD *thd, TABLE *topics, int count,
NOTE
Field 'names' is set only if more than one topic was found.
- Fields 'name', 'description', 'example' are set only if
+ Fields 'name', 'description', 'example' are set only if
exactly one topic was found.
*/
@@ -179,12 +177,12 @@ int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_fields,
{
DBUG_ENTER("search_topics");
int count= 0;
-
+
READ_RECORD read_record_info;
init_read_record(&read_record_info, thd, topics, select,1,0);
while (!read_record_info.read_record(&read_record_info))
{
- if (!select->cond->val_int()) // Dosn't match like
+ if (!select->cond->val_int()) // Doesn't match like
continue;
memorize_variant_topic(thd,topics,count,find_fields,
names,name,description,example);
@@ -219,7 +217,7 @@ int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields,
{
DBUG_ENTER("search_keyword");
int count= 0;
-
+
READ_RECORD read_record_info;
init_read_record(&read_record_info, thd, keywords, select,1,0);
while (!read_record_info.read_record(&read_record_info) && count<2)
@@ -256,13 +254,13 @@ int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields,
description description of found topic (out)
example example for found topic (out)
- NOTE
+ NOTE
Field 'names' is set only if more than one topic was found.
- Fields 'name', 'description', 'example' are set only if
+ Fields 'name', 'description', 'example' are set only if
exactly one topic was found.
*/
-int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
+int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
struct st_find_field *find_fields, int16 key_id,
List<String> *names,
String *name, String *description, String *example)
@@ -273,7 +271,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
Field *rtopic_id, *rkey_id;
DBUG_ENTER("get_topics_for_keyword");
-
+
if ((iindex_topic= find_type((char*) primary_key_name,
&topics->keynames, 1+2)-1)<0 ||
(iindex_relations= find_type((char*) primary_key_name,
@@ -284,18 +282,18 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
}
rtopic_id= find_fields[help_relation_help_topic_id].field;
rkey_id= find_fields[help_relation_help_keyword_id].field;
-
- topics->file->index_init(iindex_topic);
- relations->file->index_init(iindex_relations);
-
+
+ topics->file->ha_index_init(iindex_topic);
+ relations->file->ha_index_init(iindex_relations);
+
rkey_id->store((longlong) key_id);
rkey_id->get_key_image(buff, rkey_id->pack_length(), rkey_id->charset(),
Field::itRAW);
int key_res= relations->file->index_read(relations->record[0],
(byte *)buff, rkey_id->pack_length(),
HA_READ_KEY_EXACT);
-
- for ( ;
+
+ for ( ;
!key_res && key_id == (int16) rkey_id->val_int() ;
key_res= relations->file->index_next(relations->record[0]))
{
@@ -305,7 +303,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
field->store((longlong) topic_id);
field->get_key_image(topic_id_buff, field->pack_length(), field->charset(),
Field::itRAW);
-
+
if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff,
field->pack_length(), HA_READ_KEY_EXACT))
{
@@ -314,50 +312,12 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
count++;
}
}
+ topics->file->ha_index_end();
+ relations->file->ha_index_end();
DBUG_RETURN(count);
}
/*
- Look for topics with keyword by mask
-
- SYNOPSIS
- search_topics_by_keyword()
- thd Thread handler
- keywords Table of keywords
- topics Table of topics
- relations Table of m:m relation "topic/keyword"
- find_fields Filled array of info for fields
- select Function to test for if matching help keyword.
- Normally 'help_keyword.name like 'bit%'
-
- RETURN VALUES
- # number of topics found
-
- names array of name of found topics (out)
-
- name name of found topic (out)
- description description of found topic (out)
- example example for found topic (out)
-
- NOTE
- Field 'names' is set only if more than one topic was found.
- Fields 'name', 'description', 'example' are set only if
- exactly one topic was found.
-*/
-
-int search_topics_by_keyword(THD *thd,
- TABLE *keywords, TABLE *topics, TABLE *relations,
- struct st_find_field *find_fields,
- SQL_SELECT *select, List<String> *names,
- String *name, String *description, String *example)
-{
- int key_id;
- return search_keyword(thd,keywords,find_fields,select,&key_id)!=1
- ? 0 : get_topics_for_keyword(thd,topics,relations,find_fields,key_id,
- names,name,description,example);
-}
-
-/*
Look for categories by mask
SYNOPSIS
@@ -382,10 +342,10 @@ int search_categories(THD *thd, TABLE *categories,
Field *pfname= find_fields[help_category_name].field;
Field *pcat_id= find_fields[help_category_help_category_id].field;
int count= 0;
- READ_RECORD read_record_info;
+ READ_RECORD read_record_info;
DBUG_ENTER("search_categories");
-
+
init_read_record(&read_record_info, thd, categories, select,1,0);
while (!read_record_info.read_record(&read_record_info))
{
@@ -398,7 +358,7 @@ int search_categories(THD *thd, TABLE *categories,
names->push_back(lname);
}
end_read_record(&read_record_info);
-
+
DBUG_RETURN(count);
}
@@ -423,7 +383,7 @@ void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname,
init_read_record(&read_record_info, thd, items, select,1,0);
while (!read_record_info.read_record(&read_record_info))
{
- if (!select->cond->val_int())
+ if (!select->cond->val_int())
continue;
String *name= new (&thd->mem_root) String();
get_field(&thd->mem_root,pfname,name);
@@ -436,7 +396,7 @@ void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname,
/*
Send to client answer for help request
-
+
SYNOPSIS
send_answer_1()
protocol - protocol for sending
@@ -466,10 +426,10 @@ int send_answer_1(Protocol *protocol, String *s1, String *s2, String *s3)
field_list.push_back(new Item_empty_string("name",64));
field_list.push_back(new Item_empty_string("description",1000));
field_list.push_back(new Item_empty_string("example",1000));
-
+
if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
-
+
protocol->prepare_for_resend();
protocol->store(s1);
protocol->store(s2);
@@ -539,7 +499,7 @@ extern "C" int string_ptr_cmp(const void* ptr1, const void* ptr2)
SYNOPSIS
send_variant_2_list()
protocol Protocol for sending
- names List of names
+ names List of names
cat Value of the column <is_it_category>
source_name name of category for all items..
@@ -548,8 +508,8 @@ extern "C" int string_ptr_cmp(const void* ptr1, const void* ptr2)
0 Data was successefully send
*/
-int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
- List<String> *names,
+int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
+ List<String> *names,
const char *cat, String *source_name)
{
DBUG_ENTER("send_variant_2_list");
@@ -589,17 +549,22 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
table goal table
error code of error (out)
-
+
RETURN VALUES
- # created SQL_SELECT
+ # created SQL_SELECT
*/
-SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables,
+SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables,
TABLE *table, int *error)
{
cond->fix_fields(thd, tables, &cond); // can never fail
SQL_SELECT *res= make_select(table,0,0,cond,error);
- return (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR))) ? 0 : res;
+ if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)))
+ {
+ delete res;
+ res=0;
+ }
+ return res;
}
/*
@@ -615,9 +580,9 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables,
pfname field "name" in table
error code of error (out)
-
+
RETURN VALUES
- # created SQL_SELECT
+ # created SQL_SELECT
*/
SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
@@ -626,7 +591,7 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
{
Item *cond= new Item_func_like(new Item_field(pfname),
new Item_string(mask,mlen,pfname->charset()),
- (char*) "\\");
+ new Item_string("\\",1,&my_charset_latin1));
if (thd->is_fatal_error)
return 0; // OOM
return prepare_simple_select(thd,cond,tables,table,error);
@@ -649,12 +614,10 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
int mysqld_help(THD *thd, const char *mask)
{
Protocol *protocol= thd->protocol;
- SQL_SELECT *select_topics_by_name= 0, *select_keyword_by_name= 0,
- *select_cat_by_name= 0, *select_topics_by_cat= 0, *select_cat_by_cat= 0,
- *select_root_cats= 0;
+ SQL_SELECT *select;
st_find_field used_fields[array_elements(init_used_fields)];
DBUG_ENTER("mysqld_help");
-
+
TABLE_LIST tables[4];
bzero((gptr)tables,sizeof(tables));
tables[0].alias= tables[0].real_name= (char*) "help_topic";
@@ -670,13 +633,13 @@ int mysqld_help(THD *thd, const char *mask)
tables[3].lock_type= TL_READ;
tables[3].next= 0;
tables[0].db= tables[1].db= tables[2].db= tables[3].db= (char*) "mysql";
-
+
List<String> topics_list, categories_list, subcategories_list;
String name, description, example;
int res, count_topics, count_categories, error;
uint mlen= strlen(mask);
MEM_ROOT *mem_root= &thd->mem_root;
-
+
if (open_and_lock_tables(thd, tables))
{
res= -1;
@@ -684,7 +647,7 @@ int mysqld_help(THD *thd, const char *mask)
}
/* Init tables and fields to be usable from items */
setup_tables(tables);
- memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
+ memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
{
res= -1;
@@ -693,39 +656,55 @@ int mysqld_help(THD *thd, const char *mask)
size_t i;
for (i=0; i<sizeof(tables)/sizeof(TABLE_LIST); i++)
tables[i].table->file->init_table_handle_for_HANDLER();
-
- if (!(select_topics_by_name=
+
+ if (!(select=
prepare_select_for_name(thd,mask,mlen,tables,tables[0].table,
- used_fields[help_topic_name].field,&error)) ||
- !(select_cat_by_name=
- prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
- used_fields[help_category_name].field,&error))||
- !(select_keyword_by_name=
- prepare_select_for_name(thd,mask,mlen,tables,tables[3].table,
- used_fields[help_keyword_name].field,&error)))
+ used_fields[help_topic_name].field,&error)))
{
res= -1;
goto end;
}
res= 1;
- count_topics= search_topics(thd,tables[0].table,used_fields,
- select_topics_by_name,&topics_list,
+ count_topics= search_topics(thd,tables[0].table,used_fields,
+ select,&topics_list,
&name, &description, &example);
+ delete select;
if (count_topics == 0)
- count_topics= search_topics_by_keyword(thd,tables[3].table,tables[0].table,
- tables[2].table,used_fields,
- select_keyword_by_name,&topics_list,
- &name,&description,&example);
-
+ {
+ int key_id;
+ if (!(select=
+ prepare_select_for_name(thd,mask,mlen,tables,tables[3].table,
+ used_fields[help_keyword_name].field,&error)))
+ {
+ res= -1;
+ goto end;
+ }
+ count_topics=search_keyword(thd,tables[3].table,used_fields,select,&key_id);
+ delete select;
+ count_topics= (count_topics != 1) ? 0 :
+ get_topics_for_keyword(thd,tables[0].table,tables[2].table,
+ used_fields,key_id,&topics_list,&name,
+ &description,&example);
+ }
+
if (count_topics == 0)
{
int16 category_id;
Field *cat_cat_id= used_fields[help_category_parent_category_id].field;
+ if (!(select=
+ prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
+ used_fields[help_category_name].field,&error)))
+ {
+ res= -1;
+ goto end;
+ }
+
count_categories= search_categories(thd, tables[1].table, used_fields,
- select_cat_by_name,
+ select,
&categories_list,&category_id);
+ delete select;
if (!count_categories)
{
if (send_header_2(protocol,FALSE))
@@ -746,22 +725,26 @@ int mysqld_help(THD *thd, const char *mask)
Item *cond_cat_by_cat=
new Item_func_equal(new Item_field(cat_cat_id),
new Item_int((int32)category_id));
- if (!(select_topics_by_cat= prepare_simple_select(thd,cond_topic_by_cat,
- tables,tables[0].table,
- &error)) ||
- !(select_cat_by_cat=
- prepare_simple_select(thd,cond_cat_by_cat,tables,
- tables[1].table,&error)))
+ if (!(select= prepare_simple_select(thd,cond_topic_by_cat,
+ tables,tables[0].table,&error)))
{
res= -1;
goto end;
}
get_all_items_for_category(thd,tables[0].table,
used_fields[help_topic_name].field,
- select_topics_by_cat,&topics_list);
+ select,&topics_list);
+ delete select;
+ if (!(select= prepare_simple_select(thd,cond_cat_by_cat,tables,
+ tables[1].table,&error)))
+ {
+ res= -1;
+ goto end;
+ }
get_all_items_for_category(thd,tables[1].table,
used_fields[help_category_name].field,
- select_cat_by_cat,&subcategories_list);
+ select,&subcategories_list);
+ delete select;
String *cat= categories_list.head();
if (send_header_2(protocol, true) ||
send_variant_2_list(mem_root,protocol,&topics_list, "N",cat) ||
@@ -780,30 +763,25 @@ int mysqld_help(THD *thd, const char *mask)
if (send_header_2(protocol, FALSE) ||
send_variant_2_list(mem_root,protocol, &topics_list, "N", 0))
goto end;
- search_categories(thd, tables[1].table, used_fields,
- select_cat_by_name,&categories_list, 0);
+ if (!(select=
+ prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
+ used_fields[help_category_name].field,&error)))
+ {
+ res= -1;
+ goto end;
+ }
+ search_categories(thd, tables[1].table, used_fields,
+ select,&categories_list, 0);
+ delete select;
/* Then send categories */
if (send_variant_2_list(mem_root,protocol, &categories_list, "Y", 0))
goto end;
}
res= 0;
-
+
send_eof(thd);
end:
- free_select(select_topics_by_name);
- free_select(select_keyword_by_name);
- free_select(select_cat_by_name);
- free_select(select_topics_by_cat);
- free_select(select_cat_by_cat);
- free_select(select_root_cats);
-
DBUG_RETURN(res);
}
-
-static void free_select(SQL_SELECT *sel)
-{
- if (sel)
- delete sel->quick;
-}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 19fb439c5cb..3acebf5cadc 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -183,7 +183,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
else
#endif /* EMBEDDED_LIBRARY */
res= open_and_lock_tables(thd, table_list);
- if (res)
+ if (res || thd->is_fatal_error)
DBUG_RETURN(-1);
table= table_list->table;
@@ -943,6 +943,10 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
/* _rowid is not used with delayed insert */
copy->rowid_field=0;
+
+ /* Adjust in_use for pointing to client thread */
+ copy->in_use= client_thd;
+
return copy;
/* Got fatal error */
@@ -1109,7 +1113,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
thd->fatal_error(); // Abort waiting inserts
goto end;
}
- if (di->table->file->has_transactions())
+ if (!(di->table->file->table_flags() & HA_CAN_INSERT_DELAYED))
{
thd->fatal_error();
my_error(ER_ILLEGAL_HA, MYF(0), di->table_list.real_name);
@@ -1215,8 +1219,10 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
di->status=0;
if (!di->stacked_inserts && !di->tables_in_use && thd->lock)
{
- /* No one is doing a insert delayed;
- Unlock it so that other threads can use it */
+ /*
+ No one is doing a insert delayed
+ Unlock table so that other threads can use it
+ */
MYSQL_LOCK *lock=thd->lock;
thd->lock=0;
pthread_mutex_unlock(&di->mutex);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 2c970e4c7ca..1ffe3d12139 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -44,13 +44,6 @@ pthread_key(LEX*,THR_LEX);
#define TOCK_NAME_LENGTH 24
/*
- Map to default keyword characters. This is used to test if an identifer
- is 'simple', in which case we don't have to do any character set conversions
- on it
-*/
-uchar *bin_ident_map= my_charset_bin.ident_map;
-
-/*
The following data is based on the latin1 character set, and is only
used when comparing keywords
*/
@@ -556,13 +549,9 @@ int yylex(void *arg, void *yythd)
else
#endif
{
- result_state= bin_ident_map[c] ? IDENT : IDENT_QUOTED;
- while (ident_map[c=yyGet()])
- {
- /* If not simple character, mark that we must convert it */
- if (!bin_ident_map[c])
- result_state= IDENT_QUOTED;
- }
+ for (result_state= c; ident_map[c= yyGet()]; result_state|= c);
+ /* If there were non-ASCII characters, mark that we must convert */
+ result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
}
length= (uint) (lex->ptr - lex->tok_start)-1;
if (lex->ignore_space)
@@ -664,12 +653,11 @@ int yylex(void *arg, void *yythd)
}
else
#endif
- while (ident_map[c = yyGet()])
- {
- /* If not simple character, mark that we must convert it */
- if (!bin_ident_map[c])
- result_state= IDENT_QUOTED;
- }
+ {
+ for (result_state=0; ident_map[c= yyGet()]; result_state|= c);
+ /* If there were non-ASCII characters, mark that we must convert */
+ result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
+ }
if (c == '.' && ident_map[yyPeek()])
lex->next_state=MY_LEX_IDENT_SEP;// Next is '.'
@@ -943,13 +931,11 @@ int yylex(void *arg, void *yythd)
We should now be able to handle:
[(global | local | session) .]variable_name
*/
- result_state= IDENT;
- while (ident_map[c=yyGet()])
- {
- /* If not simple character, mark that we must convert it */
- if (!bin_ident_map[c])
- result_state= IDENT_QUOTED;
- }
+
+ for (result_state= 0; ident_map[c= yyGet()]; result_state|= c);
+ /* If there were non-ASCII characters, mark that we must convert */
+ result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
+
if (c == '.')
lex->next_state=MY_LEX_IDENT_SEP;
length= (uint) (lex->ptr - lex->tok_start)-1;
@@ -1017,7 +1003,7 @@ void st_select_lex::init_query()
ref_pointer_array= 0;
select_n_having_items= 0;
prep_where= 0;
- explicit_limit= 0;
+ subquery_in_having= explicit_limit= 0;
first_execution= 1;
first_cond_optimization= 1;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 02b3da55921..387685194f3 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -84,6 +84,7 @@ enum enum_sql_command {
SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC,
SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_STATUS_FUNC,
+ SQLCOM_PREPARE, SQLCOM_EXECUTE, SQLCOM_DEALLOCATE_PREPARE,
/* This should be the last !!! */
SQLCOM_END
};
@@ -186,8 +187,8 @@ enum tablespace_op_type
e||+-------------------------+ ||
V| neighbor | V|
unit1.1<+==================>unit1.2 unit2.1
- fake1.1 fake2.1
- select1.1.1 select 1.1.2 select1.2.1 select2.1.1 select2.1.2
+ fake1.1
+ select1.1.1 select 1.1.2 select1.2.1 select2.1.1
|^
||
V|
@@ -453,6 +454,11 @@ public:
bool having_fix_field;
/* explicit LIMIT clause was used */
bool explicit_limit;
+ /*
+ there are subquery in HAVING clause => we can't close tables before
+ query processing end even if we use temporary table
+ */
+ bool subquery_in_having;
bool first_execution; /* first execution in SP or PS */
bool first_cond_optimization;
@@ -648,11 +654,22 @@ typedef struct st_lex
uint fk_delete_opt, fk_update_opt, fk_match_option;
uint slave_thd_opt;
uint8 describe;
- bool drop_if_exists, drop_temporary, local_file;
+ bool drop_if_exists, drop_temporary, local_file, one_shot_set;
bool in_comment, ignore_space, verbose, no_write_to_binlog;
bool derived_tables;
bool safe_to_cache_query;
ALTER_INFO alter_info;
+ /* Prepared statements SQL syntax:*/
+ LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
+ /*
+ Prepared statement query text or name of variable that holds the
+ prepared statement (in PREPARE ... queries)
+ */
+ LEX_STRING prepared_stmt_code;
+ /* If true, prepared_stmt_code is a name of variable that holds the query */
+ bool prepared_stmt_code_is_varref;
+ /* Names of user variables holding parameters (in EXECUTE) */
+ List<LEX_STRING> prepared_stmt_params;
sp_head *sphead;
sp_name *spname;
bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 3313ff913dc..c7a64ea8699 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -527,7 +527,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
((Field_timestamp*) field)->set_time();
else if (field != table->next_number_field)
field->set_warning((uint) MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_NULL_TO_NOTNULL);
+ ER_WARN_NULL_TO_NOTNULL, 1);
}
continue;
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 52cbe95d24d..6870721a085 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -295,9 +295,10 @@ int check_user(THD *thd, enum enum_server_command command,
thd->user, thd->host_or_ip);
DBUG_RETURN(-1);
}
+ /* We have to read very specific packet size */
if (send_old_password_request(thd) ||
- my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very
- { // specific packet size
+ my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
+ {
inc_host_errors(&thd->remote.sin_addr);
DBUG_RETURN(ER_HANDSHAKE_ERROR);
}
@@ -626,8 +627,9 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
uc->conn_per_hour=0;
}
}
- else // for FLUSH PRIVILEGES and FLUSH USER_RESOURCES
+ else
{
+ /* for FLUSH PRIVILEGES and FLUSH USER_RESOURCES */
for (uint idx=0;idx < hash_user_connections.records; idx++)
{
USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections,
@@ -951,7 +953,7 @@ pthread_handler_decl(handle_one_connection,arg)
pthread_detach_this_thread();
#if !defined( __WIN__) && !defined(OS2) // Win32 calls this in pthread_create
- // The following calls needs to be done before we call DBUG_ macros
+ /* The following calls needs to be done before we call DBUG_ macros */
if (!(test_flags & TEST_NO_THREADS) & my_thread_init())
{
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
@@ -970,7 +972,7 @@ pthread_handler_decl(handle_one_connection,arg)
*/
DBUG_PRINT("info", ("handle_one_connection called by thread %d\n",
thd->thread_id));
- // now that we've called my_thread_init(), it is safe to call DBUG_*
+ /* now that we've called my_thread_init(), it is safe to call DBUG_* */
#if defined(__WIN__)
init_signals(); // IRENA; testing ?
@@ -1032,7 +1034,7 @@ pthread_handler_decl(handle_one_connection,arg)
decrease_user_connections(thd->user_connect);
if (net->error && net->vio != 0 && net->report_error)
{
- if (!thd->killed && thd->variables.log_warnings)
+ if (!thd->killed && thd->variables.log_warnings > 1)
sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
thd->thread_id,(thd->db ? thd->db : "unconnected"),
thd->user ? thd->user : "unauthenticated",
@@ -1206,7 +1208,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
}
net_flush(&thd->net);
if ((error= table->file->dump(thd,fd)))
- my_error(ER_GET_ERRNO, MYF(0));
+ my_error(ER_GET_ERRNO, MYF(0), error);
err:
close_thread_tables(thd);
@@ -1244,7 +1246,7 @@ bool do_command(THD *thd)
packet=0;
old_timeout=net->read_timeout;
- // Wait max for 8 hours
+ /* Wait max for 8 hours */
net->read_timeout=(uint) thd->variables.net_wait_timeout;
thd->clear_error(); // Clear error message
@@ -1326,6 +1328,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (command != COM_STATISTICS && command != COM_PING)
query_id++;
thread_running++;
+ /* TODO: set thd->lex->sql_command to SQLCOM_END here */
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->server_status&=
@@ -1442,7 +1445,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_EXECUTE:
{
- thd->free_list= NULL;
mysql_stmt_execute(thd, packet, packet_length);
break;
}
@@ -1497,6 +1499,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->query_length= length;
thd->query= packet;
thd->query_id= query_id++;
+ /* TODO: set thd->lex->sql_command to SQLCOM_END here */
VOID(pthread_mutex_unlock(&LOCK_thread_count));
#ifndef EMBEDDED_LIBRARY
mysql_parse(thd, packet, length);
@@ -1544,7 +1547,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
packet, (uint) (pend-packet), thd->charset());
table_list.alias= table_list.real_name= conv_name.str;
packet= pend+1;
- // command not cachable => no gap for data base name
+ /* command not cachable => no gap for data base name */
if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1)))
break;
mysql_log.write(thd,command,"%s %s",table_list.real_name,fields);
@@ -1591,7 +1594,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
char *db=thd->strdup(packet), *alias;
- // null test to handle EOM
+ /* null test to handle EOM */
if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
{
net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
@@ -1605,7 +1608,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
mysql_log.write(thd,command,db);
- mysql_rm_db(thd,alias,0,0);
+ mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : db), 0, 0);
break;
}
#ifndef EMBEDDED_LIBRARY
@@ -1629,7 +1632,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->server_id = slave_server_id;
mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
unregister_slave(thd,1,1);
- // fake COM_QUIT -- if we get here, the thread needs to terminate
+ /* fake COM_QUIT -- if we get here, the thread needs to terminate */
error = TRUE;
net->error = 0;
break;
@@ -1650,10 +1653,28 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
#ifndef EMBEDDED_LIBRARY
case COM_SHUTDOWN:
+ {
statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd,SHUTDOWN_ACL))
break; /* purecov: inspected */
- DBUG_PRINT("quit",("Got shutdown command"));
+ /*
+ If the client is < 4.1.3, it is going to send us no argument; then
+ packet_length is 1, packet[0] is the end 0 of the packet. Note that
+ SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in
+ packet[0].
+ */
+ enum enum_shutdown_level level=
+ (enum enum_shutdown_level) (uchar) packet[0];
+ DBUG_PRINT("quit",("Got shutdown command for level %u", level));
+ if (level == SHUTDOWN_DEFAULT)
+ level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable
+ else if (level != SHUTDOWN_WAIT_ALL_BUFFERS)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "this shutdown level");
+ send_error(thd);
+ break;
+ }
+ DBUG_PRINT("quit",("Got shutdown command for level %u", level));
mysql_log.write(thd,command,NullS);
send_eof(thd);
#ifdef __WIN__
@@ -1667,6 +1688,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
kill_mysql();
error=TRUE;
break;
+ }
#endif
case COM_STATISTICS:
{
@@ -1988,7 +2010,98 @@ mysql_execute_command(THD *thd)
}
break;
}
-
+ case SQLCOM_PREPARE:
+ {
+ char *query_str;
+ uint query_len;
+ if (lex->prepared_stmt_code_is_varref)
+ {
+ /* This is PREPARE stmt FROM @var. */
+ String str;
+ CHARSET_INFO *to_cs= thd->variables.collation_connection;
+ bool need_conversion;
+ user_var_entry *entry;
+ uint32 unused;
+ /*
+ Convert @var contents to string in connection character set. Although
+ it is known that int/real/NULL value cannot be a valid query we still
+ convert it for error messages to uniform.
+ */
+ if ((entry=
+ (user_var_entry*)hash_search(&thd->user_vars,
+ (byte*)lex->prepared_stmt_code.str,
+ lex->prepared_stmt_code.length))
+ && entry->value)
+ {
+ String *pstr;
+ my_bool is_var_null;
+ pstr= entry->val_str(&is_var_null, &str, NOT_FIXED_DEC);
+ DBUG_ASSERT(!is_var_null);
+ if (!pstr)
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ DBUG_ASSERT(pstr == &str);
+ }
+ else
+ str.set("NULL", 4, &my_charset_latin1);
+ need_conversion=
+ String::needs_conversion(str.length(), str.charset(), to_cs, &unused);
+
+ query_len= need_conversion? (str.length() * to_cs->mbmaxlen) :
+ str.length();
+ if (!(query_str= alloc_root(&thd->mem_root, query_len+1)))
+ send_error(thd, ER_OUT_OF_RESOURCES);
+
+ if (need_conversion)
+ query_len= copy_and_convert(query_str, query_len, to_cs, str.ptr(),
+ str.length(), str.charset());
+ else
+ memcpy(query_str, str.ptr(), str.length());
+ query_str[query_len]= 0;
+ }
+ else
+ {
+ query_str= lex->prepared_stmt_code.str;
+ query_len= lex->prepared_stmt_code.length;
+ DBUG_PRINT("info", ("PREPARE: %.*s FROM '%.*s' \n",
+ lex->prepared_stmt_name.length,
+ lex->prepared_stmt_name.str,
+ query_len, query_str));
+ }
+ thd->command= COM_PREPARE;
+ if (!mysql_stmt_prepare(thd, query_str, query_len + 1,
+ &lex->prepared_stmt_name))
+ send_ok(thd, 0L, 0L, "Statement prepared");
+ break;
+ }
+ case SQLCOM_EXECUTE:
+ {
+ DBUG_PRINT("info", ("EXECUTE: %.*s\n",
+ lex->prepared_stmt_name.length,
+ lex->prepared_stmt_name.str));
+ mysql_sql_stmt_execute(thd, &lex->prepared_stmt_name);
+ lex->prepared_stmt_params.empty();
+ break;
+ }
+ case SQLCOM_DEALLOCATE_PREPARE:
+ {
+ Statement* stmt;
+ DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n",
+ lex->prepared_stmt_name.length,
+ lex->prepared_stmt_name.str));
+ if ((stmt= thd->stmt_map.find_by_name(&lex->prepared_stmt_name)))
+ {
+ thd->stmt_map.erase(stmt);
+ send_ok(thd);
+ }
+ else
+ {
+ res= -1;
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
+ lex->prepared_stmt_name.length, lex->prepared_stmt_name.str,
+ "DEALLOCATE PREPARE");
+ }
+ break;
+ }
case SQLCOM_DO:
if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
(res= open_and_lock_tables(thd,tables))))
@@ -2012,7 +2125,7 @@ mysql_execute_command(THD *thd)
{
if (check_global_access(thd, SUPER_ACL))
goto error;
- // PURGE MASTER LOGS TO 'file'
+ /* PURGE MASTER LOGS TO 'file' */
res = purge_master_logs(thd, lex->to_log);
break;
}
@@ -2020,7 +2133,7 @@ mysql_execute_command(THD *thd)
{
if (check_global_access(thd, SUPER_ACL))
goto error;
- // PURGE MASTER LOGS BEFORE 'data'
+ /* PURGE MASTER LOGS BEFORE 'data' */
res = purge_master_logs_before_date(thd, lex->purge_time);
break;
}
@@ -2251,14 +2364,23 @@ mysql_execute_command(THD *thd)
lex->create_list,
lex->key_list,
select_lex->item_list,lex->duplicates)))
+ {
+ /*
+ CREATE from SELECT give its SELECT_LEX for SELECT,
+ and item_list belong to SELECT
+ */
+ select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
res=handle_select(thd, lex, result);
- //reset for PS
+ select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
+ }
+ /* reset for PS */
lex->create_list.empty();
lex->key_list.empty();
}
}
- else // regular create
+ else
{
+ /* regular create */
if (lex->name)
res= mysql_create_like_table(thd, create_table, &lex->create_info,
(Table_ident *)lex->name);
@@ -2273,15 +2395,15 @@ mysql_execute_command(THD *thd)
send_ok(thd);
}
- // put tables back for PS rexecuting
+ /* put tables back for PS rexecuting */
tables= lex->link_first_table_back(tables, create_table,
create_table_local);
break;
create_error:
- res= 1; //error reported
+ res= 1; //error reported
unsent_create_error:
- // put tables back for PS rexecuting
+ /* put tables back for PS rexecuting */
tables= lex->link_first_table_back(tables, create_table,
create_table_local);
break;
@@ -2508,29 +2630,13 @@ unsent_create_error:
case SQLCOM_OPTIMIZE:
{
- HA_CREATE_INFO create_info;
if (check_db_used(thd,tables) ||
check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
- if (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC))
- {
- /* Use ALTER TABLE */
- lex->create_list.empty();
- lex->key_list.empty();
- lex->col_list.empty();
- lex->alter_info.reset();
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.row_type=ROW_TYPE_DEFAULT;
- create_info.default_table_charset=default_charset_info;
- res= mysql_alter_table(thd, NullS, NullS, &create_info,
- tables, lex->create_list,
- lex->key_list, 0, (ORDER *) 0,
- DUP_ERROR, &lex->alter_info);
- }
- else
- res = mysql_optimize_table(thd, tables, &lex->check_opt);
+ res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
+ mysql_recreate_table(thd, tables, 1) :
+ mysql_optimize_table(thd, tables, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
@@ -2611,7 +2717,11 @@ unsent_create_error:
lex->duplicates)))
/* Skip first table, which is the table we are inserting in */
lex->select_lex.table_list.first= (byte*) first_local_table->next;
- lex->select_lex.resolve_mode= SELECT_LEX::NOMATTER_MODE;
+ /*
+ insert/replace from SELECT give its SELECT_LEX for SELECT,
+ and item_list belong to SELECT
+ */
+ lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
res=handle_select(thd,lex,result);
/* revert changes for SP */
lex->select_lex.table_list.first= (byte*) first_local_table;
@@ -2813,7 +2923,7 @@ unsent_create_error:
char *db=select_lex->db ? select_lex->db : thd->db;
if (!db)
{
- send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
+ send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
goto error; /* purecov: inspected */
}
remove_escape(db); // Fix escaped '_'
@@ -2833,7 +2943,7 @@ unsent_create_error:
goto error;
}
/* grant is checked in mysqld_show_tables */
- if (select_lex->options & SELECT_DESCRIBE)
+ if (lex->describe)
res= mysqld_extend_show_tables(thd,db,
(lex->wild ? lex->wild->ptr() : NullS));
else
@@ -2920,14 +3030,31 @@ unsent_create_error:
}
case SQLCOM_SET_OPTION:
+ {
+ List<set_var_base> *lex_var_list= &lex->var_list;
if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
(res= open_and_lock_tables(thd,tables))))
break;
- if (!(res= sql_set_variables(thd, &lex->var_list)))
+ if (lex->one_shot_set && not_all_support_one_shot(lex_var_list))
+ {
+ my_printf_error(0, "The SET ONE_SHOT syntax is reserved for \
+purposes internal to the MySQL server", MYF(0));
+ res= -1;
+ break;
+ }
+ if (!(res= sql_set_variables(thd, lex_var_list)))
+ {
+ /*
+ If the previous command was a SET ONE_SHOT, we don't want to forget
+ about the ONE_SHOT property of that SET. So we use a |= instead of = .
+ */
+ thd->one_shot_set|= lex->one_shot_set;
send_ok(thd);
+ }
if (thd->net.report_error)
res= -1;
break;
+ }
case SQLCOM_UNLOCK_TABLES:
unlock_locked_tables(thd);
@@ -3023,7 +3150,8 @@ unsent_create_error:
send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
goto error;
}
- res=mysql_rm_db(thd,alias,lex->drop_if_exists,0);
+ res=mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : lex->name),
+ lex->drop_if_exists, 0);
break;
}
case SQLCOM_ALTER_DB:
@@ -3076,7 +3204,7 @@ unsent_create_error:
res=mysqld_show_create_db(thd,lex->name,&lex->create_info);
break;
}
- case SQLCOM_CREATE_FUNCTION: // UDF function
+ case SQLCOM_CREATE_FUNCTION: // UDF function
{
sp_head *sph;
if (check_access(thd,INSERT_ACL,"mysql",0,1,0))
@@ -3153,7 +3281,7 @@ unsent_create_error:
{
if (check_access(thd, UPDATE_ACL, "mysql",0,1,0))
goto error;
- break; // We are allowed to do changes
+ break; // We are allowed to do changes
}
}
}
@@ -3370,7 +3498,7 @@ unsent_create_error:
{
if (!lex->sphead)
{
- res= -1; // Shouldn't happen
+ res= -1; // Shouldn't happen
break;
}
uint namelen;
@@ -3442,7 +3570,7 @@ unsent_create_error:
uint smrx;
LINT_INIT(smrx);
- // In case the arguments are subselects...
+ /* In case the arguments are subselects... */
if (tables && ((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
(res= open_and_lock_tables(thd, tables))))
{
@@ -3451,8 +3579,10 @@ unsent_create_error:
fix_tables_pointers(lex->all_selects_list);
#ifndef EMBEDDED_LIBRARY
- // When executing substatements, they're assumed to send_error when
- // it happens, but not to send_ok.
+ /*
+ When executing substatements, they're assumed to send_error when
+ it happens, but not to send_ok.
+ */
my_bool nsok= thd->net.no_send_ok;
thd->net.no_send_ok= TRUE;
#endif
@@ -3636,7 +3766,31 @@ unsent_create_error:
send_ok(thd);
break;
}
- thd->proc_info="query end"; // QQ
+ thd->proc_info="query end";
+ if (thd->one_shot_set)
+ {
+ /*
+ If this is a SET, do nothing. This is to allow mysqlbinlog to print
+ many SET commands (in this case we want the charset temp setting to
+ live until the real query). This is also needed so that SET
+ CHARACTER_SET_CLIENT... does not cancel itself immediately.
+ */
+ if (lex->sql_command != SQLCOM_SET_OPTION)
+ {
+ thd->variables.character_set_client=
+ global_system_variables.character_set_client;
+ thd->variables.collation_connection=
+ global_system_variables.collation_connection;
+ thd->variables.collation_database=
+ global_system_variables.collation_database;
+ thd->variables.collation_server=
+ global_system_variables.collation_server;
+ thd->update_charset();
+ thd->variables.time_zone=
+ global_system_variables.time_zone;
+ thd->one_shot_set= 0;
+ }
+ }
/*
The return value for ROW_COUNT() is "implementation dependent" if
@@ -3658,14 +3812,16 @@ unsent_create_error:
thd->row_count_func= -1;
}
- // We end up here if res == 0 and send_ok() has been done,
- // or res != 0 and no send_error() has yet been done.
+ /*
+ We end up here if res == 0 and send_ok() has been done,
+ or res != 0 and no send_error() has yet been done.
+ */
if (res < 0)
send_error(thd,thd->killed_errno());
DBUG_RETURN(res);
error:
- // We end up here if send_error() has already been done.
+ /* We end up here if send_error() has already been done. */
DBUG_RETURN(-1);
}
@@ -3686,7 +3842,6 @@ error:
*/
int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables)
-
{
if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0))
return 1;
@@ -3785,7 +3940,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
thd->priv_user, db, test(want_access & GRANT_ACL));
else
db_access=thd->db_access;
- // Remove SHOW attribute and access rights we already have
+ /* Remove SHOW attribute and access rights we already have */
want_access &= ~(thd->master_access | EXTRA_ACL);
db_access= ((*save_priv=(db_access | thd->master_access)) & want_access);
@@ -3953,10 +4108,10 @@ bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
#define MY_YACC_INIT 1000 // Start with big alloc
#define MY_YACC_MAX 32000 // Because of 'short'
-bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, int *yystacksize)
+bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
{
LEX *lex=current_lex;
- int old_info=0;
+ ulong old_info=0;
if ((uint) *yystacksize >= MY_YACC_MAX)
return 1;
if (!lex->yacc_yyvs)
@@ -4021,7 +4176,7 @@ mysql_init_query(THD *thd, bool lexonly)
thd->total_warn_count=0; // Warnings for this query
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
thd->sent_row_count= thd->examined_row_count= 0;
- thd->is_fatal_error= thd->rand_used= 0;
+ thd->is_fatal_error= thd->rand_used= thd->time_zone_used= 0;
thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
SERVER_QUERY_NO_INDEX_USED |
SERVER_QUERY_NO_GOOD_INDEX_USED);
@@ -4072,7 +4227,7 @@ mysql_new_select(LEX *lex, bool move_down)
unit->link_prev= 0;
unit->return_to= lex->current_select;
select_lex->include_down(unit);
- // TODO: assign resolve_mode for fake subquery after merging with new tree
+ /* TODO: assign resolve_mode for fake subquery after merging with new tree */
}
else
{
@@ -4379,7 +4534,12 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
break;
case FIELD_TYPE_DECIMAL:
if (!length)
- new_field->length= 10; // Default length for DECIMAL
+ {
+ if ((new_field->length= new_field->decimals))
+ new_field->length++;
+ else
+ new_field->length= 10; // Default length for DECIMAL
+ }
if (new_field->length < MAX_FIELD_WIDTH) // Skip wrong argument
{
new_field->length+=sign_len;
@@ -5066,7 +5226,7 @@ void add_join_on(TABLE_LIST *b,Item *expr)
b->on_expr=expr;
else
{
- // This only happens if you have both a right and left join
+ /* This only happens if you have both a right and left join */
b->on_expr=new Item_cond_and(b->on_expr,expr);
}
b->on_expr->top_level_item();
@@ -5168,7 +5328,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
if (options & REFRESH_QUERY_CACHE_FREE)
{
query_cache.pack(); // FLUSH QUERY CACHE
- options &= ~REFRESH_QUERY_CACHE; //don't flush all cache, just free memory
+ options &= ~REFRESH_QUERY_CACHE; // Don't flush cache, just free memory
}
if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE))
{
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index a8a2f5e8515..d4f69e5dd4f 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -92,16 +92,22 @@ public:
bool get_longdata_error;
#ifndef EMBEDDED_LIBRARY
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
- uchar *read_pos);
+ uchar *read_pos, String *expanded_query);
#else
- bool (*set_params_data)(Prepared_statement *st);
+ bool (*set_params_data)(Prepared_statement *st, String *expanded_query);
#endif
+ bool (*set_params_from_vars)(Prepared_statement *stmt,
+ List<LEX_STRING>& varnames,
+ String *expanded_query);
public:
Prepared_statement(THD *thd_arg);
virtual ~Prepared_statement();
+ void setup_set_params();
virtual Statement::Type type() const;
};
+static void execute_stmt(THD *thd, Prepared_statement *stmt,
+ String *expanded_query, bool set_context);
/******************************************************************************
Implementation
@@ -130,7 +136,8 @@ find_prepared_statement(THD *thd, ulong id, const char *where,
if (stmt == 0 || stmt->type() != Statement::PREPARED_STATEMENT)
{
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), id, where);
+ char llbuf[22];
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 22, llstr(id, llbuf), where);
if (se == SEND_ERROR)
send_error(thd);
return 0;
@@ -211,7 +218,13 @@ static ulong get_param_length(uchar **packet, ulong len)
if (len < 5)
return 0;
(*packet)+=9; // Must be 254 when here
- /* TODO: why uint4korr here? (should be uint8korr) */
+ /*
+ In our client-server protocol all numbers bigger than 2^24
+ stored as 8 bytes with uint8korr. Here we always know that
+ parameter length is less than 2^4 so don't look at the second
+ 4 bytes. But still we need to obey the protocol hence 9 in the
+ assignment above.
+ */
return (ulong) uint4korr(pos+1);
}
#else
@@ -327,20 +340,19 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len)
{
uchar *to= *pos;
TIME tm;
-
- /* TODO: why length is compared with 8 here? */
- tm.second_part= (length > 8 ) ? (ulong) sint4korr(to+7): 0;
+ tm.neg= (bool) to[0];
+ day= (uint) sint4korr(to+1);
/*
Note, that though ranges of hour, minute and second are not checked
here we rely on them being < 256: otherwise
we'll get buffer overflow in make_{date,time} functions,
which are called when time value is converted to string.
*/
- day= (uint) sint4korr(to+1);
tm.hour= (uint) to[5] + day * 24;
tm.minute= (uint) to[6];
tm.second= (uint) to[7];
+ tm.second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
if (tm.hour > 838)
{
/* TODO: add warning 'Data truncated' here */
@@ -349,9 +361,8 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len)
tm.second= 59;
}
tm.day= tm.year= tm.month= 0;
- tm.neg= (bool)to[0];
- param->set_time(&tm, TIMESTAMP_TIME,
+ param->set_time(&tm, MYSQL_TIMESTAMP_TIME,
MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
*pos+= length;
@@ -360,14 +371,16 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len)
static void set_param_datetime(Item_param *param, uchar **pos, ulong len)
{
uint length;
-
+
if ((length= get_param_length(pos, len)) >= 4)
{
uchar *to= *pos;
TIME tm;
-
- tm.second_part= (length > 7 ) ? (ulong) sint4korr(to+7): 0;
-
+
+ tm.neg= 0;
+ tm.year= (uint) sint2korr(to);
+ tm.month= (uint) to[2];
+ tm.day= (uint) to[3];
/*
Note, that though ranges of hour, minute and second are not checked
here we rely on them being < 256: otherwise
@@ -381,13 +394,10 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len)
}
else
tm.hour= tm.minute= tm.second= 0;
-
- tm.year= (uint) sint2korr(to);
- tm.month= (uint) to[2];
- tm.day= (uint) to[3];
- tm.neg= 0;
- param->set_time(&tm, TIMESTAMP_DATETIME,
+ tm.second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
+
+ param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME,
MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
*pos+= length;
@@ -414,7 +424,7 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len)
tm.second_part= 0;
tm.neg= 0;
- param->set_time(&tm, TIMESTAMP_DATE,
+ param->set_time(&tm, MYSQL_TIMESTAMP_DATE,
MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
*pos+= length;
@@ -423,58 +433,25 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len)
#else/*!EMBEDDED_LIBRARY*/
void set_param_time(Item_param *param, uchar **pos, ulong len)
{
- TIME tm;
MYSQL_TIME *to= (MYSQL_TIME*)*pos;
-
- tm.second_part= to->second_part;
-
- tm.day= to->day;
- tm.hour= to->hour;
- tm.minute= to->minute;
- tm.second= to->second;
-
- tm.year= tm.month= 0;
- tm.neg= to->neg;
- param->set_time(&tm, TIMESTAMP_TIME,
+ param->set_time(to, MYSQL_TIMESTAMP_TIME,
MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
void set_param_datetime(Item_param *param, uchar **pos, ulong len)
{
- TIME tm;
MYSQL_TIME *to= (MYSQL_TIME*)*pos;
- tm.second_part= to->second_part;
-
- tm.day= to->day;
- tm.hour= to->hour;
- tm.minute= to->minute;
- tm.second= to->second;
- tm.year= to->year;
- tm.month= to->month;
- tm.neg= 0;
-
- param->set_time(&tm, TIMESTAMP_DATETIME,
+ param->set_time(to, MYSQL_TIMESTAMP_DATETIME,
MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
void set_param_date(Item_param *param, uchar **pos, ulong len)
{
- TIME tm;
MYSQL_TIME *to= (MYSQL_TIME*)*pos;
-
- tm.second_part= to->second_part;
- tm.day= to->day;
- tm.year= to->year;
- tm.month= to->month;
- tm.neg= 0;
- tm.hour= tm.minute= tm.second= 0;
- tm.second_part= 0;
- tm.neg= 0;
-
- param->set_time(&tm, TIMESTAMP_DATE,
+ param->set_time(to, MYSQL_TIMESTAMP_DATE,
MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
#endif /*!EMBEDDED_LIBRARY*/
@@ -580,6 +557,7 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
param->item_result_type= STRING_RESULT;
}
}
+ param->param_type= (enum enum_field_types) param_type;
}
#ifndef EMBEDDED_LIBRARY
@@ -589,19 +567,20 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
*/
static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
- uchar *read_pos, uchar *data_end)
+ uchar *read_pos, uchar *data_end,
+ String *query)
{
THD *thd= stmt->thd;
Item_param **begin= stmt->param_array;
Item_param **end= begin + stmt->param_count;
uint32 length= 0;
- String str, query;
+ String str;
const String *res;
DBUG_ENTER("insert_params_withlog");
- if (query.copy(stmt->query, stmt->query_length, default_charset_info))
+ if (query->copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
for (Item_param **it= begin; it < end; ++it)
@@ -622,20 +601,18 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */
- if (query.replace(param->pos_in_query+length, 1, *res))
+ if (query->replace(param->pos_in_query+length, 1, *res))
DBUG_RETURN(1);
length+= res->length()-1;
}
- if (alloc_query(thd, (char *)query.ptr(), query.length()+1))
- DBUG_RETURN(1);
-
DBUG_RETURN(0);
}
static bool insert_params(Prepared_statement *stmt, uchar *null_array,
- uchar *read_pos, uchar *data_end)
+ uchar *read_pos, uchar *data_end,
+ String *expanded_query)
{
Item_param **begin= stmt->param_array;
Item_param **end= begin + stmt->param_count;
@@ -700,7 +677,7 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
#else
-static bool emb_insert_params(Prepared_statement *stmt)
+static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query)
{
THD *thd= stmt->thd;
Item_param **it= stmt->param_array;
@@ -733,20 +710,20 @@ static bool emb_insert_params(Prepared_statement *stmt)
}
-static bool emb_insert_params_withlog(Prepared_statement *stmt)
+static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query)
{
THD *thd= stmt->thd;
Item_param **it= stmt->param_array;
Item_param **end= it + stmt->param_count;
MYSQL_BIND *client_param= thd->client_params;
- String str, query;
+ String str;
const String *res;
uint32 length= 0;
DBUG_ENTER("emb_insert_params_withlog");
- if (query.copy(stmt->query, stmt->query_length, default_charset_info))
+ if (query->copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
for (; it < end; ++it, ++client_param)
@@ -765,18 +742,16 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt)
*client_param->length :
client_param->buffer_length);
}
- res= param->query_val_str(&str);
- if (param->convert_str_value(thd))
- DBUG_RETURN(1); /* out of memory */
}
- if (query.replace(param->pos_in_query+length, 1, *res))
+ res= param->query_val_str(&str);
+ if (param->convert_str_value(thd))
+ DBUG_RETURN(1); /* out of memory */
+
+ if (query->replace(param->pos_in_query+length, 1, *res))
DBUG_RETURN(1);
+
length+= res->length()-1;
}
-
- if (alloc_query(thd, (char *) query.ptr(), query.length()+1))
- DBUG_RETURN(1);
-
DBUG_RETURN(0);
}
@@ -784,6 +759,105 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt)
/*
+ Set prepared statement parameters from user variables.
+ SYNOPSIS
+ insert_params_from_vars()
+ stmt Statement
+ varnames List of variables. Caller must ensure that number of variables
+ in the list is equal to number of statement parameters
+ query Ignored
+*/
+
+static bool insert_params_from_vars(Prepared_statement *stmt,
+ List<LEX_STRING>& varnames,
+ String *query __attribute__((unused)))
+{
+ Item_param **begin= stmt->param_array;
+ Item_param **end= begin + stmt->param_count;
+ user_var_entry *entry;
+ LEX_STRING *varname;
+ List_iterator<LEX_STRING> var_it(varnames);
+ DBUG_ENTER("insert_params_from_vars");
+
+ for (Item_param **it= begin; it < end; ++it)
+ {
+ Item_param *param= *it;
+ varname= var_it++;
+ entry= (user_var_entry*)hash_search(&stmt->thd->user_vars,
+ (byte*) varname->str,
+ varname->length);
+ if (param->set_from_user_var(stmt->thd, entry) ||
+ param->convert_str_value(stmt->thd))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Do the same as insert_params_from_vars but also construct query text for
+ binary log.
+ SYNOPSIS
+ insert_params_from_vars()
+ stmt Statement
+ varnames List of variables. Caller must ensure that number of variables
+ in the list is equal to number of statement parameters
+ query The query with parameter markers replaced with their values
+*/
+
+static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
+ List<LEX_STRING>& varnames,
+ String *query)
+{
+ Item_param **begin= stmt->param_array;
+ Item_param **end= begin + stmt->param_count;
+ user_var_entry *entry;
+ LEX_STRING *varname;
+ DBUG_ENTER("insert_params_from_vars");
+
+ List_iterator<LEX_STRING> var_it(varnames);
+ String str;
+ uint32 length= 0;
+ if (query->copy(stmt->query, stmt->query_length, default_charset_info))
+ DBUG_RETURN(1);
+
+ for (Item_param **it= begin; it < end; ++it)
+ {
+ Item_param *param= *it;
+ varname= var_it++;
+ if (get_var_with_binlog(stmt->thd, *varname, &entry))
+ DBUG_RETURN(1);
+ DBUG_ASSERT(entry);
+
+ 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);
+
+ buf= str.c_ptr_quick();
+ ptr= buf;
+ *ptr++= '@';
+ *ptr++= '\'';
+ ptr+=
+ escape_string_for_mysql(&my_charset_utf8_general_ci,
+ ptr, entry->name.str, entry->name.length);
+ *ptr++= '\'';
+ str.length(ptr - buf);
+
+ if (param->convert_str_value(stmt->thd))
+ DBUG_RETURN(1); /* out of memory */
+
+ if (query->replace(param->pos_in_query+length, 1, str))
+ DBUG_RETURN(1);
+ length+= str.length()-1;
+ }
+ DBUG_RETURN(0);
+}
+
+/*
Validate INSERT statement:
SYNOPSIS
@@ -979,7 +1053,7 @@ static int mysql_test_delete(Prepared_statement *stmt,
*/
static int mysql_test_select(Prepared_statement *stmt,
- TABLE_LIST *tables)
+ TABLE_LIST *tables, bool text_protocol)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
@@ -1009,30 +1083,32 @@ static int mysql_test_select(Prepared_statement *stmt,
goto err;
}
+ thd->used_tables= 0; // Updated by setup_fields
+
+ // JOIN::prepare calls
+ if (unit->prepare(thd, 0, 0))
+ {
+ send_error(thd);
+ goto err_prep;
+ }
if (lex->describe)
{
- if (send_prep_stmt(stmt, 0))
- goto err;
+ if (!text_protocol && send_prep_stmt(stmt, 0))
+ goto err_prep;
+ unit->cleanup();
}
else
{
- thd->used_tables= 0; // Updated by setup_fields
-
- // JOIN::prepare calls
- if (unit->prepare(thd, 0, 0))
+ if (!text_protocol)
{
- send_error(thd);
- goto err_prep;
- }
-
- if (send_prep_stmt(stmt, lex->select_lex.item_list.elements) ||
+ if (send_prep_stmt(stmt, lex->select_lex.item_list.elements) ||
thd->protocol_simple.send_fields(&lex->select_lex.item_list, 0)
#ifndef EMBEDDED_LIBRARY
- || net_flush(&thd->net)
+ || net_flush(&thd->net)
#endif
- )
- goto err_prep;
-
+ )
+ goto err_prep;
+ }
unit->cleanup();
}
thd->free_temporary_memory_pool_for_ps_preparing();
@@ -1199,6 +1275,7 @@ static int mysql_test_create_table(Prepared_statement *stmt,
DBUG_ENTER("mysql_test_create_table");
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
+ SELECT_LEX *select_lex= &lex->select_lex;
int res= 0;
/* Skip first table, which is the table we are creating */
@@ -1207,8 +1284,12 @@ static int mysql_test_create_table(Prepared_statement *stmt,
&create_table_local);
if (!(res= create_table_precheck(thd, tables, create_table)) &&
- lex->select_lex.item_list.elements)
+ select_lex->item_list.elements)
+ {
+ select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
res= select_like_statement_test(stmt, tables);
+ select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
+ }
/* put tables back for PS rexecuting */
tables= lex->link_first_table_back(tables, create_table,
@@ -1292,7 +1373,11 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
(TABLE_LIST *)lex->select_lex.table_list.first;
/* Skip first table, which is the table we are inserting in */
lex->select_lex.table_list.first= (byte*) first_local_table->next;
- lex->select_lex.resolve_mode= SELECT_LEX::NOMATTER_MODE;
+ /*
+ insert/replace from SELECT give its SELECT_LEX for SELECT,
+ and item_list belong to SELECT
+ */
+ lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
res= select_like_statement_test(stmt, tables);
/* revert changes*/
lex->select_lex.table_list.first= (byte*) first_local_table;
@@ -1310,7 +1395,7 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
0 success
1 error, sent to client
*/
-static int send_prepare_results(Prepared_statement *stmt)
+static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
@@ -1347,7 +1432,7 @@ static int send_prepare_results(Prepared_statement *stmt)
break;
case SQLCOM_SELECT:
- if ((res= mysql_test_select(stmt, tables)))
+ if ((res= mysql_test_select(stmt, tables, text_protocol)))
goto error;
/* Statement and field info has already been sent */
DBUG_RETURN(0);
@@ -1405,7 +1490,7 @@ static int send_prepare_results(Prepared_statement *stmt)
goto error;
}
if (res == 0)
- DBUG_RETURN(send_prep_stmt(stmt, 0));
+ DBUG_RETURN(text_protocol? 0 : send_prep_stmt(stmt, 0));
error:
if (res < 0)
send_error(thd,thd->killed_errno());
@@ -1446,20 +1531,36 @@ static bool init_param_array(Prepared_statement *stmt)
/*
- Parse the query and send the total number of parameters
- and resultset metadata information back to client (if any),
- without executing the query i.e. without any log/disk
- writes. This will allow the queries to be re-executed
- without re-parsing during execute.
-
- If parameter markers are found in the query, then store
- the information using Item_param along with maintaining a
- list in lex->param_array, so that a fast and direct
- retrieval can be made without going through all field
- items.
+ Given a query string with parameter markers, create a Prepared Statement
+ from it and send PS info back to the client.
+
+ SYNOPSIS
+ mysql_stmt_prepare()
+ packet query to be prepared
+ packet_length query string length, including ignored trailing NULL or
+ quote char.
+ name NULL or statement name. For unnamed statements binary PS
+ protocol is used, for named statements text protocol is
+ used.
+ RETURN
+ 0 OK, statement prepared successfully
+ other Error
+
+ NOTES
+ This function parses the query and sends the total number of parameters
+ and resultset metadata information back to client (if any), without
+ executing the query i.e. without any log/disk writes. This allows the
+ queries to be re-executed without re-parsing during execute.
+
+ If parameter markers are found in the query, then store the information
+ using Item_param along with maintaining a list in lex->param_array, so
+ that a fast and direct retrieval can be made without going through all
+ field items.
+
*/
-void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
+int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
+ LEX_STRING *name)
{
LEX *lex;
Prepared_statement *stmt= new Prepared_statement(thd);
@@ -1471,14 +1572,26 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
if (stmt == 0)
{
send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(1);
+ }
+
+ if (name)
+ {
+ stmt->name.length= name->length;
+ if (!(stmt->name.str= memdup_root(&stmt->mem_root, (char*)name->str,
+ name->length)))
+ {
+ delete stmt;
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ DBUG_RETURN(1);
+ }
}
if (thd->stmt_map.insert(stmt))
{
delete stmt;
send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(1);
}
thd->stmt_backup.set_statement(thd);
@@ -1495,7 +1608,7 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(1);
}
mysql_log.write(thd, COM_PREPARE, "%s", packet);
@@ -1507,7 +1620,7 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
error= yyparse((void *)thd) || thd->is_fatal_error ||
init_param_array(stmt) ||
- send_prepare_results(stmt);
+ send_prepare_results(stmt, test(name));
/* restore to WAIT_PRIOR: QUERY_PRIOR is set inside alloc_query */
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -1530,9 +1643,14 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
{
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
+ stmt= NULL;
/* error is sent inside yyparse/send_prepare_results */
}
- DBUG_VOID_RETURN;
+ else
+ stmt->setup_set_params();
+
+ DBUG_RETURN(!stmt);
+
}
/* Reinit statement before execution */
@@ -1545,6 +1663,9 @@ void reset_stmt_for_execute(THD *thd, LEX *lex)
{
if (!sl->first_execution)
{
+ /* remove option which was put by mysql_explain_union() */
+ sl->options&= ~SELECT_DESCRIBE;
+
/*
Copy WHERE clause pointers to avoid damaging they by optimisation
*/
@@ -1609,13 +1730,21 @@ static void reset_stmt_params(Prepared_statement *stmt)
Executes previously prepared query.
If there is any parameters, then replace markers with the data supplied
from client, and then execute the query.
- SYNOPSYS
+ SYNOPSIS
mysql_stmt_execute()
+ thd Current thread
+ packet Query string
+ packet_length Query string length, including terminator character.
*/
void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{
ulong stmt_id= uint4korr(packet);
+ /*
+ Query text for binary log, or empty string if the query is not put into
+ binary log.
+ */
+ String expanded_query;
#ifndef EMBEDDED_LIBRARY
uchar *packet_end= (uchar *) packet + packet_length - 1;
#endif
@@ -1623,7 +1752,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
DBUG_ENTER("mysql_stmt_execute");
packet+= 9; /* stmt_id + 5 bytes of flags */
-
+
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute",
SEND_ERROR)))
DBUG_VOID_RETURN;
@@ -1637,15 +1766,13 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
DBUG_VOID_RETURN;
}
- thd->stmt_backup.set_statement(thd);
- thd->set_statement(stmt);
- reset_stmt_for_execute(thd, stmt->lex);
#ifndef EMBEDDED_LIBRARY
if (stmt->param_count)
{
uchar *null_array= (uchar *) packet;
if (setup_conversion_functions(stmt, (uchar **) &packet, packet_end) ||
- stmt->set_params(stmt, null_array, (uchar *) packet, packet_end))
+ stmt->set_params(stmt, null_array, (uchar *) packet, packet_end,
+ &expanded_query))
goto set_params_data_err;
}
#else
@@ -1654,55 +1781,126 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
we set params, and also we don't need to parse packet.
So we do it in one function.
*/
- if (stmt->param_count && stmt->set_params_data(stmt))
+ if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query))
goto set_params_data_err;
#endif
-
- if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),QUERY_PRIOR);
-
- /*
- TODO:
- Also, have checks on basic executions such as mysql_insert(),
- mysql_delete(), mysql_update() and mysql_select() to not to
- have re-check on setup_* and other things ..
- */
thd->current_arena= stmt;
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
- mysql_execute_command(thd);
- thd->lex->unit.cleanup();
+ execute_stmt(thd, stmt, &expanded_query, true);
thd->protocol= &thd->protocol_simple; // Use normal protocol
thd->current_arena= 0;
+ DBUG_VOID_RETURN;
- if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(), WAIT_PRIOR);
-
- cleanup_items(stmt->free_list);
+set_params_data_err:
reset_stmt_params(stmt);
- close_thread_tables(thd); // to close derived tables
- thd->set_statement(&thd->stmt_backup);
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_execute");
+ send_error(thd);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Execute prepared statement using parameter values from
+ lex->prepared_stmt_params and send result to the client using text protocol.
+*/
+
+void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
+{
+ Prepared_statement *stmt;
/*
- Free Items that were created during this execution of the PS by query
- optimizer.
+ Query text for binary log, or empty string if the query is not put into
+ binary log.
*/
- free_items(thd->free_list);
+ String expanded_query;
+ DBUG_ENTER("mysql_sql_stmt_execute");
+
+ if (!(stmt= (Prepared_statement*)thd->stmt_map.find_by_name(stmt_name)))
+ {
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), stmt_name->length,
+ stmt_name->str, "EXECUTE");
+ send_error(thd);
+ DBUG_VOID_RETURN;
+ }
+
+ if (stmt->param_count != thd->lex->prepared_stmt_params.elements)
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
+ send_error(thd);
+ DBUG_VOID_RETURN;
+ }
+
+ thd->free_list= NULL;
+ thd->stmt_backup.set_statement(thd);
+ thd->set_statement(stmt);
+ if (stmt->set_params_from_vars(stmt,
+ thd->stmt_backup.lex->prepared_stmt_params,
+ &expanded_query))
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
+ send_error(thd);
+ }
+ execute_stmt(thd, stmt, &expanded_query, false);
DBUG_VOID_RETURN;
+}
-set_params_data_err:
+
+/*
+ Execute prepared statement.
+ SYNOPSIS
+ execute_stmt()
+ thd Current thread
+ stmt Statement to execute
+ expanded_query If binary log is enabled, query string with parameter
+ placeholders replaced with actual values. Otherwise empty
+ string.
+ NOTES
+ Caller must set parameter values and thd::protocol.
+ thd->free_list is assumed to be garbage.
+*/
+
+static void execute_stmt(THD *thd, Prepared_statement *stmt,
+ String *expanded_query, bool set_context)
+{
+ DBUG_ENTER("execute_stmt");
+ if (set_context)
+ {
+ thd->free_list= NULL;
+ thd->stmt_backup.set_statement(thd);
+ thd->set_statement(stmt);
+ }
+ reset_stmt_for_execute(stmt);
+
+ if (expanded_query->length() &&
+ alloc_query(thd, (char *)expanded_query->ptr(),
+ expanded_query->length()+1))
+ {
+ my_error(ER_OUTOFMEMORY, 0, expanded_query->length());
+ DBUG_VOID_RETURN;
+ }
+
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+ mysql_execute_command(thd);
+ thd->lex->unit.cleanup();
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(), WAIT_PRIOR);
+
+ /* Free Items that were created during this execution of the PS. */
+ free_items(thd->free_list);
+ cleanup_items(stmt->free_list);
reset_stmt_params(stmt);
+ close_thread_tables(thd); // to close derived tables
thd->set_statement(&thd->stmt_backup);
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_execute");
- send_error(thd);
DBUG_VOID_RETURN;
}
/*
- Reset a prepared statement in case there was a recoverable error.
+ Reset a prepared statement in case there was a recoverable error.
SYNOPSIS
mysql_stmt_reset()
- thd Thread handle
- packet Packet with stmt id
+ thd Thread handle
+ packet Packet with stmt id
DESCRIPTION
This function resets statement to the state it was right after prepare.
@@ -1842,8 +2040,14 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
get_longdata_error(0)
{
*last_error= '\0';
- if (mysql_bin_log.is_open())
+}
+
+void Prepared_statement::setup_set_params()
+{
+ /* Setup binary logging */
+ if (mysql_bin_log.is_open() && is_update_query(lex->sql_command))
{
+ set_params_from_vars= insert_params_from_vars_with_log;
#ifndef EMBEDDED_LIBRARY
set_params= insert_params_withlog;
#else
@@ -1851,14 +2055,16 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
#endif
}
else
+ {
+ set_params_from_vars= insert_params_from_vars;
#ifndef EMBEDDED_LIBRARY
set_params= insert_params;
#else
set_params_data= emb_insert_params;
#endif
+ }
}
-
Prepared_statement::~Prepared_statement()
{
free_items(free_list);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e28ee52c00f..05676f9058a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -148,14 +148,15 @@ static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
Item *having);
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
ulong offset,Item *having);
-static int remove_dup_with_hash_index(THD *thd, TABLE *table,
+static int remove_dup_with_hash_index(THD *thd,TABLE *table,
uint field_count, Field **first_field,
ulong key_length,Item *having);
static int join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count);
static ulong used_blob_length(CACHE_FIELD **ptr);
static bool store_record_in_cache(JOIN_CACHE *cache);
-static void reset_cache(JOIN_CACHE *cache);
+static void reset_cache_read(JOIN_CACHE *cache);
+static void reset_cache_write(JOIN_CACHE *cache);
static void read_cached_record(JOIN_TAB *tab);
static bool cmp_buffer_with_ref(JOIN_TAB *tab);
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
@@ -643,7 +644,6 @@ JOIN::optimize()
{
zero_result_cause= "no matching row in const table";
DBUG_PRINT("error",("Error: %s", zero_result_cause));
- select_options= 0; //TODO why option in return_zero_rows was droped
error= 0;
DBUG_RETURN(0);
}
@@ -657,22 +657,8 @@ JOIN::optimize()
}
if (const_tables && !thd->locked_tables &&
!(select_options & SELECT_NO_UNLOCK))
- {
- TABLE **curr_table, **end;
- for (curr_table= table, end=curr_table + const_tables ;
- curr_table != end;
- curr_table++)
- {
- /* BDB tables require that we call index_end() before doing an unlock */
- if ((*curr_table)->key_read)
- {
- (*curr_table)->key_read=0;
- (*curr_table)->file->extra(HA_EXTRA_NO_KEYREAD);
- }
- (*curr_table)->file->index_end();
- }
mysql_unlock_some_tables(thd, table, const_tables);
- }
+
if (!conds && outer_join)
{
/* Handle the case where we have an OUTER JOIN without a WHERE */
@@ -977,7 +963,7 @@ JOIN::optimize()
If having is not handled here, it will be checked before the row
is sent to the client.
*/
- if (having &&
+ if (tmp_having &&
(sort_and_group || (exec_tmp_table1->distinct && !group_list)))
having= tmp_having;
@@ -1127,12 +1113,14 @@ JOIN::exec()
DBUG_ENTER("JOIN::exec");
error= 0;
- thd->limit_found_rows= thd->examined_row_count= 0;
if (procedure)
{
if (procedure->change_columns(fields_list) ||
result->prepare(fields_list, unit))
+ {
+ thd->limit_found_rows= thd->examined_row_count= 0;
DBUG_VOID_RETURN;
+ }
}
if (!tables_list)
@@ -1158,8 +1146,10 @@ JOIN::exec()
else
error=(int) result->send_eof();
}
+ thd->limit_found_rows= thd->examined_row_count= 0;
DBUG_VOID_RETURN;
}
+ thd->limit_found_rows= thd->examined_row_count= 0;
if (zero_result_cause)
{
@@ -1578,6 +1568,7 @@ JOIN::cleanup()
}
}
tmp_join->tmp_join= 0;
+ tmp_table_param.copy_field=0;
DBUG_RETURN(tmp_join->cleanup());
}
@@ -2332,12 +2323,13 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
case Item_func::OPTIMIZE_NONE:
break;
case Item_func::OPTIMIZE_KEY:
- // BETWEEN or IN
+ // BETWEEN, IN, NOT
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
add_key_field(key_fields,*and_level,cond_func,
- ((Item_field*) (cond_func->key_item()->real_item()))->
- field, 0,
+ ((Item_field*)(cond_func->key_item()->real_item()))->field,
+ cond_func->argument_count() == 2 &&
+ cond_func->functype() == Item_func::IN_FUNC,
cond_func->arguments()+1, cond_func->argument_count()-1,
usable_tables);
break;
@@ -4848,7 +4840,6 @@ make_join_readinfo(JOIN *join, uint options)
}
delete tab->quick;
tab->quick=0;
- table->file->index_init(tab->ref.key);
tab->read_first_record= join_read_key;
tab->read_record.read_record= join_no_more_records;
if (table->used_keys.is_set(tab->ref.key) &&
@@ -4868,7 +4859,6 @@ make_join_readinfo(JOIN *join, uint options)
}
delete tab->quick;
tab->quick=0;
- table->file->index_init(tab->ref.key);
if (table->used_keys.is_set(tab->ref.key) &&
!table->no_keyread)
{
@@ -4888,7 +4878,6 @@ make_join_readinfo(JOIN *join, uint options)
break;
case JT_FT:
table->status=STATUS_NO_RECORD;
- table->file->index_init(tab->ref.key);
tab->read_first_record= join_ft_read_first;
tab->read_record.read_record= join_ft_read_next;
break;
@@ -4958,7 +4947,6 @@ make_join_readinfo(JOIN *join, uint options)
!(tab->select && tab->select->quick))
{ // Only read index tree
tab->index=find_shortest_key(table, & table->used_keys);
- tab->table->file->index_init(tab->index);
tab->read_first_record= join_read_first;
tab->type=JT_NEXT; // Read with index_first / index_next
}
@@ -5032,9 +5020,7 @@ void JOIN_TAB::cleanup()
table->key_read= 0;
table->file->extra(HA_EXTRA_NO_KEYREAD);
}
- /* Don't free index if we are using read_record */
- if (!read_record.table)
- table->file->index_end();
+ table->file->ha_index_or_rnd_end();
/*
We need to reset this for next select
(Tested in part_of_refkey)
@@ -5060,7 +5046,9 @@ void
JOIN::join_free(bool full)
{
JOIN_TAB *tab,*end;
- DBUG_ENTER("join_free");
+ DBUG_ENTER("JOIN::join_free");
+
+ full= full || !select_lex->uncacheable;
if (table)
{
@@ -5073,36 +5061,49 @@ JOIN::join_free(bool full)
free_io_cache(table[const_tables]);
filesort_free_buffers(table[const_tables]);
}
- if (!full && select_lex->uncacheable)
+
+ for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit;
+ unit= unit->next_unit())
{
- for (tab= join_tab, end= tab+tables; tab != end; tab++)
- {
- if (tab->table)
- {
- /* Don't free index if we are using read_record */
- if (!tab->read_record.table)
- tab->table->file->index_end();
- }
- }
+ JOIN *join;
+ for (SELECT_LEX *sl= unit->first_select_in_union(); sl;
+ sl= sl->next_select())
+ if ((join= sl->join))
+ join->join_free(full);
}
- else
+
+ if (full)
{
for (tab= join_tab, end= tab+tables; tab != end; tab++)
tab->cleanup();
table= 0;
}
+ else
+ {
+ for (tab= join_tab, end= tab+tables; tab != end; tab++)
+ {
+ if (tab->table)
+ tab->table->file->ha_index_or_rnd_end();
+ }
+ }
}
+
/*
We are not using tables anymore
Unlock all tables. We may be in an INSERT .... SELECT statement.
*/
- if ((full || !select_lex->uncacheable) &&
- lock && thd->lock &&
- !(select_options & SELECT_NO_UNLOCK))
+ if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
+ !select_lex->subquery_in_having)
{
- mysql_unlock_read_tables(thd, lock);// Don't free join->lock
- lock=0;
+ // 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)
{
group_fields.delete_elements();
@@ -5324,6 +5325,8 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
DBUG_RETURN(0);
}
+ join->join_free(0);
+
if (send_row)
{
for (TABLE_LIST *table=tables; table ; table=table->next)
@@ -5341,12 +5344,6 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
item->no_rows_in_result();
result->send_data(fields);
}
- if (tables) // Not from do_select()
- {
- /* Close open cursors */
- for (TABLE_LIST *table=tables; table ; table=table->next)
- table->table->file->index_end();
- }
result->send_eof(); // Should be safe
}
/* Update results for FOUND_ROWS */
@@ -6419,6 +6416,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->db_low_byte_first=1; // True for HEAP and MyISAM
table->temp_pool_slot = temp_pool_slot;
table->copy_blobs= 1;
+ table->in_use= thd;
table->keys_for_keyread.init();
table->keys_in_use.init();
table->read_only_keys.init();
@@ -6581,6 +6579,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
recinfo->length=null_pack_length;
recinfo++;
bfill(null_flags,null_pack_length,255); // Set null fields
+
+ table->null_flags= (uchar*) table->record[0];
+ table->null_fields= null_count+ hidden_null_count;
+ table->null_bytes= null_pack_length;
}
null_count= (blob_count == 0) ? 1 : 0;
hidden_field_count=param->hidden_field_count;
@@ -6644,7 +6646,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
param->copy_field_end=copy;
param->recinfo=recinfo;
- store_record(table,default_values); // Make empty default record
+ store_record(table,default_values); // Make empty default record
if (thd->variables.tmp_table_size == ~(ulong) 0) // No limit
table->max_rows= ~(ha_rows) 0;
@@ -6996,8 +6998,8 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
goto err1;
if (table->file->indexes_are_disabled())
new_table.file->disable_indexes(HA_KEY_SWITCH_ALL);
- table->file->index_end();
- table->file->rnd_init();
+ table->file->ha_index_or_rnd_end();
+ table->file->ha_rnd_init(1);
if (table->no_rows)
{
new_table.file->extra(HA_EXTRA_NO_ROWS);
@@ -7019,7 +7021,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
}
/* remove heap table and change to use myisam table */
- (void) table->file->rnd_end();
+ (void) table->file->ha_rnd_end();
(void) table->file->close();
(void) table->file->delete_table(table->real_name);
delete table->file;
@@ -7033,7 +7035,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
err:
DBUG_PRINT("error",("Got error: %d",write_err));
table->file->print_error(error,MYF(0)); // Give table is full error
- (void) table->file->rnd_end();
+ (void) table->file->ha_rnd_end();
(void) new_table.file->close();
err1:
new_table.file->delete_table(new_table.real_name);
@@ -7082,7 +7084,8 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
{
DBUG_PRINT("info",("Using end_update"));
end_select=end_update;
- table->file->index_init(0);
+ if (!table->file->inited)
+ table->file->ha_index_init(0);
}
else
{
@@ -7160,9 +7163,9 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
my_errno= tmp;
error= -1;
}
- if ((tmp=table->file->index_end()))
+ if ((tmp=table->file->ha_index_or_rnd_end()))
{
- DBUG_PRINT("error",("index_end() failed"));
+ DBUG_PRINT("error",("ha_index_or_rnd_end() failed"));
my_errno= tmp;
error= -1;
}
@@ -7541,8 +7544,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
/* read through all records */
if ((error=join_init_read_record(join_tab)))
{
- reset_cache(&join_tab->cache);
- join_tab->cache.records=0; join_tab->cache.ptr_record= (uint) ~0;
+ reset_cache_write(&join_tab->cache);
return -error; /* No records or error */
}
@@ -7565,21 +7567,23 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
!join_tab->cache.select->skip_record()))
{
uint i;
- reset_cache(&join_tab->cache);
+ reset_cache_read(&join_tab->cache);
for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
{
read_cached_record(join_tab);
if (!select || !select->skip_record())
if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
+ {
+ reset_cache_write(&join_tab->cache);
return error; /* purecov: inspected */
+ }
}
}
} while (!(error=info->read_record(info)));
if (skip_last)
read_cached_record(join_tab); // Restore current record
- reset_cache(&join_tab->cache);
- join_tab->cache.records=0; join_tab->cache.ptr_record= (uint) ~0;
+ reset_cache_write(&join_tab->cache);
if (error > 0) // Fatal error
return -1; /* purecov: inspected */
for (JOIN_TAB *tmp2=join->join_tab; tmp2 != join_tab ; tmp2++)
@@ -7650,7 +7654,8 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
else
{
if (!table->key_read && table->used_keys.is_set(tab->ref.key) &&
- !table->no_keyread)
+ !table->no_keyread &&
+ (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
@@ -7663,6 +7668,11 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
if (!table->outer_join || error > 0)
DBUG_RETURN(error);
}
+ if (table->key_read)
+ {
+ table->key_read=0;
+ table->file->extra(HA_EXTRA_NO_KEYREAD);
+ }
}
if (tab->on_expr && !table->null_row)
{
@@ -7741,6 +7751,8 @@ join_read_key(JOIN_TAB *tab)
int error;
TABLE *table= tab->table;
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->ref.key);
if (cmp_buffer_with_ref(tab) ||
(table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW)))
{
@@ -7766,6 +7778,8 @@ join_read_always_key(JOIN_TAB *tab)
int error;
TABLE *table= tab->table;
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->ref.key);
if (cp_buffer_from_ref(&tab->ref))
return -1;
if ((error=table->file->index_read(table->record[0],
@@ -7791,6 +7805,8 @@ join_read_last_key(JOIN_TAB *tab)
int error;
TABLE *table= tab->table;
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->ref.key);
if (cp_buffer_from_ref(&tab->ref))
return -1;
if ((error=table->file->index_read_last(table->record[0],
@@ -7899,6 +7915,8 @@ join_read_first(JOIN_TAB *tab)
tab->read_record.file=table->file;
tab->read_record.index=tab->index;
tab->read_record.record=table->record[0];
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->index);
if ((error=tab->table->file->index_first(tab->table->record[0])))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
@@ -7936,6 +7954,8 @@ join_read_last(JOIN_TAB *tab)
tab->read_record.file=table->file;
tab->read_record.index=tab->index;
tab->read_record.record=table->record[0];
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->index);
if ((error= tab->table->file->index_last(tab->table->record[0])))
return report_error(table, error);
return 0;
@@ -7958,6 +7978,8 @@ join_ft_read_first(JOIN_TAB *tab)
int error;
TABLE *table= tab->table;
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->ref.key);
#if NOT_USED_YET
if (cp_buffer_from_ref(&tab->ref)) // as ft-key doesn't use store_key's
return -1; // see also FT_SELECT::init()
@@ -8048,7 +8070,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
&& !join->send_group_parts && !join->having && !jt->select_cond &&
!(jt->select && jt->select->quick) &&
- !(jt->table->file->table_flags() & HA_NOT_EXACT_COUNT))
+ !(jt->table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
+ (jt->ref.key < 0))
{
/* Join over all rows in table; Return number of found rows */
TABLE *table=jt->table;
@@ -8274,7 +8297,6 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (item->maybe_null)
group->buff[-1]=item->null_value ? 1 : 0;
}
- // table->file->index_init(0);
if (!table->file->index_read(table->record[1],
join->tmp_table_param.group_buff,0,
HA_READ_KEY_EXACT))
@@ -8305,7 +8327,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
error, 0))
DBUG_RETURN(-1); // Not a table_is_full error
/* Change method to update rows */
- table->file->index_init(0);
+ table->file->ha_index_init(0);
join->join_tab[join->tables-1].next_select=end_unique_update;
}
join->send_records++;
@@ -8814,10 +8836,10 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if (tab->ref.key >= 0)
{
tab->ref.key= new_ref_key;
- table->file->index_init(new_ref_key);
}
else
{
+ select->quick->file->ha_index_end();
/*
We have verified above that select->quick is not
index_merge quick select.
@@ -8844,7 +8866,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if (!select->quick->reverse_sorted())
{
int quick_type= select->quick->get_type();
- if (table->file->index_flags(ref_key) & HA_NOT_READ_PREFIX_LAST ||
+ if (!(table->file->index_flags(ref_key) & HA_READ_PREV) ||
quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION)
@@ -8870,7 +8892,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
Use a traversal function that starts by reading the last row
with key part (A) and then traverse the index backwards.
*/
- if (table->file->index_flags(ref_key) & HA_NOT_READ_PREFIX_LAST)
+ if (!(table->file->index_flags(ref_key) & HA_READ_PREV))
DBUG_RETURN(0); // Use filesort
tab->read_first_record= join_read_last_key;
tab->read_record.read_record= join_read_prev_same;
@@ -8924,7 +8946,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
tab->index=nr;
tab->read_first_record= (flag > 0 ? join_read_first:
join_read_last);
- table->file->index_init(nr);
tab->type=JT_NEXT; // Read with index_first(), index_next()
if (table->used_keys.is_set(nr))
{
@@ -9190,7 +9211,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
org_record=(char*) (record=table->record[0])+offset;
new_record=(char*) table->record[1]+offset;
- file->rnd_init();
+ file->ha_rnd_init(1);
error=file->rnd_next(record);
for (;;)
{
@@ -9302,7 +9323,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
(*field_length++)= (*ptr)->pack_length();
}
- file->rnd_init();
+ file->ha_rnd_init(1);
key_pos=key_buffer;
for (;;)
{
@@ -9348,14 +9369,14 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
my_free((char*) key_buffer,MYF(0));
hash_free(&hash);
file->extra(HA_EXTRA_NO_CACHE);
- (void) file->rnd_end();
+ (void) file->ha_rnd_end();
DBUG_RETURN(0);
err:
my_free((char*) key_buffer,MYF(0));
hash_free(&hash);
file->extra(HA_EXTRA_NO_CACHE);
- (void) file->rnd_end();
+ (void) file->ha_rnd_end();
if (error)
file->print_error(error,MYF(0));
DBUG_RETURN(1);
@@ -9482,7 +9503,6 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
}
}
- cache->records=0; cache->ptr_record= (uint) ~0;
cache->length=length+blobs*sizeof(char*);
cache->blobs=blobs;
*blob_ptr=0; /* End sequentel */
@@ -9490,7 +9510,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
if (!(cache->buff=(uchar*) my_malloc(size,MYF(0))))
DBUG_RETURN(1); /* Don't use cache */ /* purecov: inspected */
cache->end=cache->buff+size;
- reset_cache(cache);
+ reset_cache_write(cache);
DBUG_RETURN(0);
}
@@ -9574,13 +9594,21 @@ store_record_in_cache(JOIN_CACHE *cache)
static void
-reset_cache(JOIN_CACHE *cache)
+reset_cache_read(JOIN_CACHE *cache)
{
cache->record_nr=0;
cache->pos=cache->buff;
}
+static void reset_cache_write(JOIN_CACHE *cache)
+{
+ reset_cache_read(cache);
+ cache->records= 0;
+ cache->ptr_record= (uint) ~0;
+}
+
+
static void
read_cached_record(JOIN_TAB *tab)
{
@@ -10029,10 +10057,11 @@ calc_group_buffer(JOIN *join,ORDER *group)
join->tmp_table_param.group_null_parts=null_parts;
}
+
/*
- alloc group fields or take prepared (chached)
+ allocate group fields or take prepared (cached)
- SYNOPSYS
+ SYNOPSIS
make_group_fields()
main_join - join of current select
curr_join - current join (join of current select or temporary copy of it)
@@ -10045,22 +10074,21 @@ calc_group_buffer(JOIN *join,ORDER *group)
static bool
make_group_fields(JOIN *main_join, JOIN *curr_join)
{
- if (main_join->group_fields_cache.elements)
- {
- curr_join->group_fields= main_join->group_fields_cache;
- curr_join->sort_and_group= 1;
- }
- else
- {
- if (alloc_group_fields(curr_join, curr_join->group_list))
- {
- return (1);
- }
- main_join->group_fields_cache= curr_join->group_fields;
- }
- return (0);
+ if (main_join->group_fields_cache.elements)
+ {
+ curr_join->group_fields= main_join->group_fields_cache;
+ curr_join->sort_and_group= 1;
+ }
+ else
+ {
+ if (alloc_group_fields(curr_join, curr_join->group_list))
+ return (1);
+ main_join->group_fields_cache= curr_join->group_fields;
+ }
+ return (0);
}
+
/*
Get a list of buffers for saveing last group
Groups are saved in reverse order for easyer check loop
@@ -10101,7 +10129,6 @@ test_if_group_changed(List<Item_buff> &list)
}
-
/*
Setup copy_fields to save fields at start of new group
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index e481a961288..3e99704e80c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -473,6 +473,8 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
field_list.push_back(item=new Item_empty_string("Name",NAME_LEN));
field_list.push_back(item=new Item_empty_string("Engine",10));
item->maybe_null=1;
+ field_list.push_back(item=new Item_int("Version", (longlong) 0, 21));
+ item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Row_format",10));
item->maybe_null=1;
field_list.push_back(item=new Item_int("Rows",(longlong) 1,21));
@@ -529,11 +531,11 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
}
else
{
- struct tm tm_tmp;
const char *str;
handler *file=table->file;
file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
protocol->store(file->table_type(), system_charset_info);
+ protocol->store((ulonglong) table->frm_version);
str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
"Compressed" :
(table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
@@ -562,24 +564,21 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
protocol->store_null();
else
{
- localtime_r(&file->create_time,&tm_tmp);
- localtime_to_TIME(&time, &tm_tmp);
+ thd->variables.time_zone->gmt_sec_to_TIME(&time, file->create_time);
protocol->store(&time);
}
if (!file->update_time)
protocol->store_null();
else
{
- localtime_r(&file->update_time,&tm_tmp);
- localtime_to_TIME(&time, &tm_tmp);
+ thd->variables.time_zone->gmt_sec_to_TIME(&time, file->update_time);
protocol->store(&time);
}
if (!file->check_time)
protocol->store_null();
else
{
- localtime_r(&file->check_time,&tm_tmp);
- localtime_to_TIME(&time, &tm_tmp);
+ thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
protocol->store(&time);
}
str= (table->table_charset ? table->table_charset->name : "default");
@@ -1251,7 +1250,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(' ');
// check for surprises from the previous call to Field::sql_type()
if (type.ptr() != tmp)
- type.set(tmp, sizeof(tmp),&my_charset_bin);
+ type.set(tmp, sizeof(tmp), system_charset_info);
field->sql_type(type);
packet->append(type.ptr(), type.length(), system_charset_info);
@@ -1540,13 +1539,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
while ((tmp=it++))
{
struct st_my_thread_var *mysys_var;
-#ifndef EMBEDDED_LIBRARY
- if ((tmp->net.vio || tmp->system_thread) &&
+ if ((tmp->vio_ok() || tmp->system_thread) &&
(!user || (tmp->user && !strcmp(tmp->user,user))))
-#else
- if (tmp->system_thread &&
- (!user || (tmp->user && !strcmp(tmp->user,user))))
-#endif
{
thread_info *thd_info=new thread_info;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 4d85438b03f..ba9431f27c4 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -24,7 +24,6 @@
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
-#include <assert.h>
#ifdef HAVE_FCONVERT
#include <floatingpoint.h>
#endif
@@ -371,7 +370,7 @@ bool String::copy(const char *str, uint32 arg_length,
bool String::set_ascii(const char *str, uint32 arg_length)
{
- if (!(str_charset->state & MY_CS_NONTEXT))
+ if (str_charset->mbminlen == 1)
{
set(str, arg_length, str_charset);
return 0;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index d05b5a6cbc7..48bd9e572b0 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -191,7 +191,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
for (table=tables ; table ; table=table->next)
{
char *db=table->db;
- mysql_ha_closeall(thd, table);
+ mysql_ha_close(thd, table, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
if (!close_temporary_table(thd, db, table->real_name))
{
tmp_table_deleted=1;
@@ -254,12 +254,23 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
}
thd->tmp_table_used= tmp_table_deleted;
- if (some_tables_deleted || tmp_table_deleted)
+ error= 0;
+ if (wrong_tables.length())
+ {
+ if (!foreign_key_error)
+ my_error(ER_BAD_TABLE_ERROR,MYF(0), wrong_tables.c_ptr());
+ else
+ my_error(ER_ROW_IS_REFERENCED, MYF(0));
+ error= 1;
+ }
+
+ if (some_tables_deleted || tmp_table_deleted || !error)
{
query_cache_invalidate3(thd, tables, 0);
if (!dont_log_query && mysql_bin_log.is_open())
{
- thd->clear_error();
+ if (!error)
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
tmp_table_deleted && !some_tables_deleted);
mysql_bin_log.write(&qinfo);
@@ -267,15 +278,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
unlock_table_names(thd, tables);
- error= 0;
- if (wrong_tables.length())
- {
- if (!foreign_key_error)
- my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr());
- else
- my_error(ER_ROW_IS_REFERENCED,MYF(0));
- error= 1;
- }
DBUG_RETURN(error);
}
@@ -525,7 +527,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
break;
case FIELD_TYPE_GEOMETRY:
#ifdef HAVE_SPATIAL
- if (!(file->table_flags() & HA_HAS_GEOMETRY))
+ if (!(file->table_flags() & HA_CAN_GEOMETRY))
{
my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
MYF(0), "GEOMETRY");
@@ -663,7 +665,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
continue;
}
(*key_count)++;
- tmp=max(file->max_key_parts(),MAX_REF_PARTS);
+ tmp=file->max_key_parts();
if (key->columns.elements > tmp)
{
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
@@ -715,7 +717,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(-1);
}
}
- tmp=min(file->max_keys(), MAX_KEY);
+ tmp=file->max_keys();
if (*key_count > tmp)
{
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
@@ -852,7 +854,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
sql_field->sql_type != FIELD_TYPE_VAR_STRING &&
!f_is_blob(sql_field->pack_flag)) ||
sql_field->charset == &my_charset_bin ||
- sql_field->charset->state & MY_CS_NONTEXT || // ucs2 doesn't work yet
+ sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
(ft_key_charset && sql_field->charset != ft_key_charset))
{
my_printf_error(ER_BAD_FT_COLUMN,ER(ER_BAD_FT_COLUMN),MYF(0),
@@ -875,7 +877,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (f_is_blob(sql_field->pack_flag))
{
- if (!(file->table_flags() & HA_BLOB_KEY))
+ if (!(file->table_flags() & HA_CAN_INDEX_BLOBS))
{
my_printf_error(ER_BLOB_USED_AS_KEY,ER(ER_BLOB_USED_AS_KEY),MYF(0),
column->field_name);
@@ -912,7 +914,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
else
key_info->flags|= HA_NULL_PART_KEY;
- if (!(file->table_flags() & HA_NULL_KEY))
+ if (!(file->table_flags() & HA_NULL_IN_KEY))
{
my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX),
MYF(0),column->field_name);
@@ -1044,7 +1046,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (!(key_info->flags & HA_NULL_PART_KEY))
unique_key=1;
key_info->key_length=(uint16) key_length;
- uint max_key_length= min(file->max_key_length(), MAX_KEY_LENGTH);
+ uint max_key_length= file->max_key_length();
if (key_length > max_key_length && key->type != Key::FULLTEXT)
{
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
@@ -1136,12 +1138,21 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
alias= table_case_name(create_info, table_name);
file=get_new_handler((TABLE*) 0, create_info->db_type);
+#ifdef NOT_USED
+ /*
+ if there is a technical reason for a handler not to have support
+ for temp. tables this code can be re-enabled.
+ Otherwise, if a handler author has a wish to prohibit usage of
+ temporary tables for his handler he should implement a check in
+ ::create() method
+ */
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
(file->table_flags() & HA_NO_TEMP_TABLES))
{
my_error(ER_ILLEGAL_HA,MYF(0),table_name);
DBUG_RETURN(-1);
}
+#endif
if (mysql_prepare_table(thd, create_info, fields,
keys, tmp_table, db_options, file,
@@ -1707,7 +1718,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
- mysql_ha_closeall(thd, tables);
+ mysql_ha_close(thd, tables, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
for (table = tables; table; table = table->next)
{
char table_name[NAME_LEN*2+2];
@@ -1793,6 +1804,9 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
+send_result_message:
+
+ DBUG_PRINT("info", ("result_code: %d", result_code));
switch (result_code) {
case HA_ADMIN_NOT_IMPLEMENTED:
{
@@ -1836,6 +1850,29 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store("Invalid argument",16, system_charset_info);
break;
+ case HA_ADMIN_TRY_ALTER:
+ {
+ /*
+ This is currently used only by InnoDB. ha_innobase::optimize() answers
+ "try with alter", so here we close the table, do an ALTER TABLE,
+ reopen the table and do ha_innobase::analyze() on it.
+ */
+ close_thread_tables(thd);
+ TABLE_LIST *save_next= table->next;
+ table->next= 0;
+ result_code= mysql_recreate_table(thd, table, 0);
+ close_thread_tables(thd);
+ if (!result_code) // recreation went ok
+ {
+ if ((table->table= open_ltable(thd, table, lock_type)) &&
+ ((result_code= table->table->file->analyze(thd, check_opt)) > 0))
+ result_code= 0; // analyze went ok
+ }
+ result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
+ table->next= save_next;
+ goto send_result_message;
+ }
+
default: // Probably HA_ADMIN_INTERNAL_ERROR
protocol->store("error", 5, system_charset_info);
protocol->store("Unknown - internal error during operation", 41
@@ -2207,7 +2244,7 @@ int mysql_discard_or_import_tablespace(THD *thd,
thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open
and ::external_lock() do not complain when we
lock the table */
- mysql_ha_closeall(thd, table_list);
+ mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
if (!(table=open_ltable(thd,table_list,TL_WRITE)))
{
@@ -2463,7 +2500,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<create_field> &fields, List<Key> &keys,
uint order_num, ORDER *order,
enum enum_duplicates handle_duplicates,
- ALTER_INFO *alter_info)
+ ALTER_INFO *alter_info, bool do_send_ok)
{
TABLE *table,*new_table;
int error;
@@ -2485,7 +2522,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
new_db= db;
used_fields=create_info->used_fields;
- mysql_ha_closeall(thd, table_list);
+ mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
@@ -2540,7 +2577,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
}
else
- new_alias= new_name= table_name;
+ {
+ new_alias= (lower_case_table_names == 2) ? alias : table_name;
+ new_name= table_name;
+ }
old_db_type=table->db_type;
if (create_info->db_type == DB_TYPE_DEFAULT)
@@ -2619,7 +2659,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
- send_ok(thd);
+ if (do_send_ok)
+ send_ok(thd);
}
else
{
@@ -3180,7 +3221,8 @@ end_temporary:
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
(ulong) (copied + deleted), (ulong) deleted,
(ulong) thd->cuted_fields);
- send_ok(thd,copied+deleted,0L,tmp_name);
+ if (do_send_ok)
+ send_ok(thd,copied+deleted,0L,tmp_name);
thd->some_tables_deleted=0;
DBUG_RETURN(0);
@@ -3261,7 +3303,11 @@ copy_data_between_tables(TABLE *from,TABLE *to,
error= 1;
goto err;
}
-
+
+ /* Handler must be told explicitly to retrieve all columns, because
+ this function does not set field->query_id in the columns to the
+ current query id */
+ from->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
if (handle_duplicates == DUP_IGNORE ||
handle_duplicates == DUP_REPLACE)
@@ -3326,6 +3372,40 @@ copy_data_between_tables(TABLE *from,TABLE *to,
}
+/*
+ Recreates tables by calling mysql_alter_table().
+
+ SYNOPSIS
+ mysql_recreate_table()
+ thd Thread handler
+ tables Tables to recreate
+ do_send_ok If we should send_ok() or leave it to caller
+
+ RETURN
+ Like mysql_alter_table().
+*/
+int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
+ bool do_send_ok)
+{
+ DBUG_ENTER("mysql_recreate_table");
+ LEX *lex= thd->lex;
+ HA_CREATE_INFO create_info;
+ lex->create_list.empty();
+ lex->key_list.empty();
+ lex->col_list.empty();
+ lex->alter_info.reset();
+ lex->alter_info.is_simple= 0; // Force full recreate
+ bzero((char*) &create_info,sizeof(create_info));
+ create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.row_type=ROW_TYPE_DEFAULT;
+ create_info.default_table_charset=default_charset_info;
+ DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
+ table_list, lex->create_list,
+ lex->key_list, 0, (ORDER *) 0,
+ DUP_ERROR, &lex->alter_info, do_send_ok));
+}
+
+
int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
{
TABLE_LIST *table;
@@ -3380,7 +3460,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
current query id */
t->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
- if (t->file->rnd_init(1))
+ if (t->file->ha_rnd_init(1))
protocol->store_null();
else
{
@@ -3408,6 +3488,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
crc+= row_crc;
}
protocol->store((ulonglong)crc);
+ t->file->ha_rnd_end();
}
}
thd->clear_error();
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 0953e63765a..e0281c813f1 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -328,6 +328,7 @@ int mysql_update(THD *thd,
error= 1; // Aborted
end_read_record(&info);
free_io_cache(table); // If ORDER BY
+ delete select;
thd->proc_info="end";
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
@@ -342,7 +343,7 @@ int mysql_update(THD *thd,
transactional_table= table->file->has_transactions();
log_delayed= (transactional_table || table->tmp_table);
- if (updated && (error <= 0 || !transactional_table))
+ if ((updated || (error < 0)) && (error <= 0 || !transactional_table))
{
if (mysql_bin_log.is_open())
{
@@ -368,7 +369,6 @@ int mysql_update(THD *thd,
thd->lock=0;
}
- delete select;
free_underlaid_joins(thd, &thd->lex->select_lex);
if (error >= 0)
send_error(thd,thd->killed_errno()); /* purecov: inspected */
@@ -980,25 +980,24 @@ int multi_update::do_updates(bool from_send_error)
TABLE_LIST *cur_table;
int local_error;
ha_rows org_updated;
- TABLE *table;
+ TABLE *table, *tmp_table;
DBUG_ENTER("do_updates");
-
- do_update= 0; // Don't retry this function
+
+ do_update= 0; // Don't retry this function
if (!found)
DBUG_RETURN(0);
for (cur_table= update_tables; cur_table ; cur_table= cur_table->next)
{
byte *ref_pos;
- TABLE *tmp_table;
-
+
table = cur_table->table;
if (table == table_to_update)
continue; // Already updated
org_updated= updated;
tmp_table= tmp_tables[cur_table->shared];
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
- (void) table->file->rnd_init(0);
+ (void) table->file->ha_rnd_init(0);
table->file->extra(HA_EXTRA_NO_CACHE);
/*
@@ -1014,7 +1013,7 @@ int multi_update::do_updates(bool from_send_error)
}
copy_field_end=copy_field_ptr;
- if ((local_error = tmp_table->file->rnd_init(1)))
+ if ((local_error = tmp_table->file->ha_rnd_init(1)))
goto err;
ref_pos= (byte*) tmp_table->field[0]->ptr;
@@ -1065,7 +1064,8 @@ int multi_update::do_updates(bool from_send_error)
else
trans_safe= 0; // Can't do safe rollback
}
- (void) table->file->rnd_end();
+ (void) table->file->ha_rnd_end();
+ (void) tmp_table->file->ha_rnd_end();
}
DBUG_RETURN(0);
@@ -1073,6 +1073,9 @@ err:
if (!from_send_error)
table->file->print_error(local_error,MYF(0));
+ (void) table->file->ha_rnd_end();
+ (void) tmp_table->file->ha_rnd_end();
+
if (updated != org_updated)
{
if (table->tmp_table != NO_TMP_TABLE)
@@ -1108,7 +1111,9 @@ bool multi_update::send_eof()
/*
Write the SQL statement to the binlog if we updated
rows and we succeeded or if we updated some non
- transacational tables
+ transacational tables.
+ Note that if we updated nothing we don't write to the binlog (TODO:
+ fix this).
*/
if (updated && (local_error <= 0 || !trans_safe))
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index bad4a2c7190..cf17d38566d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -44,7 +44,7 @@
int yylex(void *yylval, void *yythd);
-#define yyoverflow(A,B,C,D,E,F) if (my_yyoverflow((B),(D),(int*) (F))) { yyerror((char*) (A)); return 2; }
+#define yyoverflow(A,B,C,D,E,F) {ulong val= *(F); if(my_yyoverflow((B), (D), &val)) { yyerror((char*) (A)); return 2; } else { *(F)= (YYSIZE_T)val; }}
#define WARN_DEPRECATED(A,B) \
push_warning_printf(((THD *)yythd), MYSQL_ERROR::WARN_LEVEL_WARN, \
@@ -98,7 +98,7 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B)
}
%{
-bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
+bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%}
%pure_parser /* We have threads */
@@ -274,7 +274,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token IDENT_QUOTED
%token IGNORE_SYM
%token IMPORT
-%token INDEX
+%token INDEX_SYM
%token INDEXES
%token INFILE
%token INNER_SYM
@@ -340,6 +340,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token NUM
%token OFFSET_SYM
%token ON
+%token ONE_SHOT_SYM
%token OPEN_SYM
%token OPTION
%token OPTIONALLY
@@ -465,6 +466,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MEDIUMTEXT
%token NUMERIC_SYM
%token PRECISION
+%token PREPARE_SYM
+%token DEALLOCATE_SYM
%token QUICK
%token REAL
%token SIGNED_SYM
@@ -643,11 +646,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
opt_table_alias
%type <table>
- table_ident table_ident_ref references
+ table_ident table_ident_nodb references
%type <simple_string>
remember_name remember_end opt_ident opt_db text_or_password
- opt_escape opt_constraint constraint
+ opt_constraint constraint
%type <string>
text_string opt_gconcat_separator
@@ -675,7 +678,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
using_list expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init geometry_function
- signed_literal now_or_signed_literal
+ signed_literal now_or_signed_literal opt_escape
sp_opt_default
simple_ident_nospvar simple_ident_q
@@ -770,6 +773,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
precision subselect_start opt_and charset
subselect_end select_var_list select_var_list_init help opt_len
opt_extended_describe
+ prepare prepare_src execute deallocate
statement sp_suid
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic sp_a_chistic
END_OF_INPUT
@@ -821,10 +825,12 @@ statement:
| checksum
| commit
| create
+ | deallocate
| delete
| describe
| do
| drop
+ | execute
| flush
| grant
| handler
@@ -836,6 +842,7 @@ statement:
| optimize
| keycache
| preload
+ | prepare
| purge
| rename
| repair
@@ -856,6 +863,92 @@ statement:
| use
;
+deallocate:
+ deallocate_or_drop PREPARE_SYM ident
+ {
+ THD *thd=YYTHD;
+ LEX *lex= thd->lex;
+ if (thd->command == COM_PREPARE)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
+ lex->prepared_stmt_name= $3;
+ };
+
+deallocate_or_drop:
+ DEALLOCATE_SYM |
+ DROP
+ ;
+
+
+prepare:
+ PREPARE_SYM ident FROM prepare_src
+ {
+ THD *thd=YYTHD;
+ LEX *lex= thd->lex;
+ if (thd->command == COM_PREPARE)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_PREPARE;
+ lex->prepared_stmt_name= $2;
+ };
+
+prepare_src:
+ TEXT_STRING_sys
+ {
+ THD *thd=YYTHD;
+ LEX *lex= thd->lex;
+ lex->prepared_stmt_code= $1;
+ lex->prepared_stmt_code_is_varref= false;
+ }
+ | '@' ident_or_text
+ {
+ THD *thd=YYTHD;
+ LEX *lex= thd->lex;
+ lex->prepared_stmt_code= $2;
+ lex->prepared_stmt_code_is_varref= true;
+ };
+
+execute:
+ EXECUTE_SYM ident
+ {
+ THD *thd=YYTHD;
+ LEX *lex= thd->lex;
+ if (thd->command == COM_PREPARE)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_EXECUTE;
+ lex->prepared_stmt_name= $2;
+ }
+ execute_using
+ {}
+ ;
+
+execute_using:
+ /* nothing */
+ | USING execute_var_list
+ ;
+
+execute_var_list:
+ execute_var_list ',' execute_var_ident
+ | execute_var_ident
+ ;
+
+execute_var_ident: '@' ident_or_text
+ {
+ LEX *lex=Lex;
+ LEX_STRING *lexstr= (LEX_STRING*)sql_memdup(&$2, sizeof(LEX_STRING));
+ if (!lexstr || lex->prepared_stmt_params.push_back(lexstr))
+ YYABORT;
+ }
+ ;
+
/* help */
help:
@@ -996,7 +1089,7 @@ create:
}
create2
{ Lex->current_select= &Lex->select_lex; }
- | CREATE opt_unique_or_fulltext INDEX ident key_alg ON table_ident
+ | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_CREATE_INDEX;
@@ -2186,7 +2279,7 @@ create_table_option:
| INSERT_METHOD opt_equal merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;}
| DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
{ Lex->create_info.data_file_name= $4.str; }
- | INDEX DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; };
+ | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; };
storage_engines:
ident_or_text
@@ -2379,7 +2472,6 @@ type:
$$=FIELD_TYPE_GEOMETRY;
#else
net_printf(Lex->thd, ER_FEATURE_DISABLED,
- ER(ER_FEATURE_DISABLED),
sym_group_geom.name,
sym_group_geom.needed_define);
YYABORT;
@@ -2697,7 +2789,6 @@ key_type:
$$= Key::SPATIAL;
#else
net_printf(Lex->thd, ER_FEATURE_DISABLED,
- ER(ER_FEATURE_DISABLED),
sym_group_geom.name, sym_group_geom.needed_define);
YYABORT;
#endif
@@ -2709,7 +2800,7 @@ constraint_key_type:
key_or_index:
KEY_SYM {}
- | INDEX {};
+ | INDEX_SYM {};
opt_key_or_index:
/* empty */ {}
@@ -2718,7 +2809,7 @@ opt_key_or_index:
keys_or_index:
KEYS {}
- | INDEX {}
+ | INDEX_SYM {}
| INDEXES {};
opt_unique_or_fulltext:
@@ -2731,7 +2822,6 @@ opt_unique_or_fulltext:
$$= Key::SPATIAL;
#else
net_printf(Lex->thd, ER_FEATURE_DISABLED,
- ER(ER_FEATURE_DISABLED),
sym_group_geom.name, sym_group_geom.needed_define);
YYABORT;
#endif
@@ -2794,7 +2884,7 @@ alter:
lex->create_info.db_type= DB_TYPE_DEFAULT;
lex->create_info.default_table_charset= thd->variables.collation_database;
lex->create_info.row_type= ROW_TYPE_NOT_USED;
- lex->alter_info.clear();
+ lex->alter_info.reset();
lex->alter_info.is_simple= 1;
lex->alter_info.flags= 0;
}
@@ -3228,7 +3318,7 @@ table_to_table:
};
keycache:
- CACHE_SYM INDEX keycache_list IN_SYM key_cache_name
+ CACHE_SYM INDEX_SYM keycache_list IN_SYM key_cache_name
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE;
@@ -3259,7 +3349,7 @@ key_cache_name:
;
preload:
- LOAD INDEX INTO CACHE_SYM
+ LOAD INDEX_SYM INTO CACHE_SYM
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_PRELOAD_KEYS;
@@ -3773,7 +3863,6 @@ simple_expr:
if (!$1.symbol->create_func)
{
net_printf(Lex->thd, ER_FEATURE_DISABLED,
- ER(ER_FEATURE_DISABLED),
$1.symbol->group->name,
$1.symbol->group->needed_define);
YYABORT;
@@ -3785,7 +3874,6 @@ simple_expr:
if (!$1.symbol->create_func)
{
net_printf(Lex->thd, ER_FEATURE_DISABLED,
- ER(ER_FEATURE_DISABLED),
$1.symbol->group->name,
$1.symbol->group->needed_define);
YYABORT;
@@ -3797,7 +3885,6 @@ simple_expr:
if (!$1.symbol->create_func)
{
net_printf(Lex->thd, ER_FEATURE_DISABLED,
- ER(ER_FEATURE_DISABLED),
$1.symbol->group->name,
$1.symbol->group->needed_define);
YYABORT;
@@ -3809,7 +3896,6 @@ simple_expr:
if (!$1.symbol->create_func)
{
net_printf(Lex->thd, ER_FEATURE_DISABLED,
- ER(ER_FEATURE_DISABLED),
$1.symbol->group->name,
$1.symbol->group->needed_define);
YYABORT;
@@ -3908,7 +3994,6 @@ simple_expr:
$$= $1;
#else
net_printf(Lex->thd, ER_FEATURE_DISABLED,
- ER(ER_FEATURE_DISABLED),
sym_group_geom.name, sym_group_geom.needed_define);
YYABORT;
#endif
@@ -4678,9 +4763,9 @@ interval_time_st:
| YEAR_SYM { $$=INTERVAL_YEAR; };
date_time_type:
- DATE_SYM {$$=TIMESTAMP_DATE;}
- | TIME_SYM {$$=TIMESTAMP_TIME;}
- | DATETIME {$$=TIMESTAMP_DATETIME;};
+ DATE_SYM {$$=MYSQL_TIMESTAMP_DATE;}
+ | TIME_SYM {$$=MYSQL_TIMESTAMP_TIME;}
+ | DATETIME {$$=MYSQL_TIMESTAMP_DATETIME;};
table_alias:
/* empty */
@@ -4724,8 +4809,12 @@ having_clause:
;
opt_escape:
- ESCAPE_SYM TEXT_STRING_literal { $$= $2.str; }
- | /* empty */ { $$= (char*) "\\"; };
+ ESCAPE_SYM simple_expr { $$= $2; }
+ | /* empty */
+ {
+ $$= new Item_string("\\", 1, &my_charset_latin1);
+ }
+ ;
/*
@@ -5024,7 +5113,7 @@ drop:
lex->drop_temporary= $2;
lex->drop_if_exists= $4;
}
- | DROP INDEX ident ON table_ident {}
+ | DROP INDEX_SYM ident ON table_ident {}
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_DROP_INDEX;
@@ -5399,13 +5488,12 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
lex->select_lex.db= $2;
- lex->select_lex.options= 0;
}
| TABLE_SYM STATUS_SYM opt_db wild
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->select_lex.options|= SELECT_DESCRIBE;
+ lex->describe= DESCRIBE_EXTENDED;
lex->select_lex.db= $3;
}
| OPEN_SYM TABLES opt_db wild
@@ -5413,7 +5501,6 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
lex->select_lex.db= $3;
- lex->select_lex.options= 0;
}
| ENGINE_SYM storage_engines
{ Lex->create_info.db_type= $2; }
@@ -6096,7 +6183,7 @@ simple_ident_q:
field_ident:
ident { $$=$1;}
- | ident '.' ident { $$=$3;} /* Skipp schema name in create*/
+ | ident '.' ident { $$=$3;} /* Skip schema name in create*/
| '.' ident { $$=$2;} /* For Delphi */;
table_ident:
@@ -6105,9 +6192,8 @@ table_ident:
| '.' ident { $$=new Table_ident($2);} /* For Delphi */
;
-table_ident_ref:
+table_ident_nodb:
ident { LEX_STRING db={(char*) any_db,3}; $$=new Table_ident(YYTHD, db,$1,0); }
- | ident '.' ident { $$=new Table_ident(YYTHD, $1,$3,0);}
;
IDENT_sys:
@@ -6239,6 +6325,7 @@ keyword:
| DATETIME {}
| DATE_SYM {}
| DAY_SYM {}
+ | DEALLOCATE_SYM {}
| DEFINER_SYM {}
| DELAY_KEY_WRITE_SYM {}
| DES_KEY_FILE {}
@@ -6334,12 +6421,14 @@ keyword:
| NVARCHAR_SYM {}
| OFFSET_SYM {}
| OLD_PASSWORD {}
+ | ONE_SHOT_SYM {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PARTIAL {}
| PASSWORD {}
| POINT_SYM {}
| POLYGON {}
+ | PREPARE_SYM {}
| PREV_SYM {}
| PROCESS {}
| PROCESSLIST_SYM {}
@@ -6426,6 +6515,7 @@ set:
lex->sql_command= SQLCOM_SET_OPTION;
lex->option_type=OPT_SESSION;
lex->var_list.empty();
+ lex->one_shot_set= 0;
}
option_value_list
{}
@@ -6444,6 +6534,7 @@ option_type:
| GLOBAL_SYM { Lex->option_type= OPT_GLOBAL; }
| LOCAL_SYM { Lex->option_type= OPT_SESSION; }
| SESSION_SYM { Lex->option_type= OPT_SESSION; }
+ | ONE_SHOT_SYM { Lex->option_type= OPT_SESSION; Lex->one_shot_set= 1; }
;
opt_var_type:
@@ -6687,14 +6778,14 @@ handler:
if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0))
YYABORT;
}
- | HANDLER_SYM table_ident_ref CLOSE_SYM
+ | HANDLER_SYM table_ident_nodb CLOSE_SYM
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_HA_CLOSE;
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
YYABORT;
}
- | HANDLER_SYM table_ident_ref READ_SYM
+ | HANDLER_SYM table_ident_nodb READ_SYM
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_HA_READ;
@@ -6804,7 +6895,7 @@ grant_privilege:
| REFERENCES { Lex->which_columns = REFERENCES_ACL;} opt_column_list {}
| DELETE_SYM { Lex->grant |= DELETE_ACL;}
| USAGE {}
- | INDEX { Lex->grant |= INDEX_ACL;}
+ | INDEX_SYM { Lex->grant |= INDEX_ACL;}
| ALTER { Lex->grant |= ALTER_ACL;}
| CREATE { Lex->grant |= CREATE_ACL;}
| DROP { Lex->grant |= DROP_ACL;}
diff --git a/sql/structs.h b/sql/structs.h
index 2fcba9b3692..9f13ef54ce0 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -130,23 +130,14 @@ typedef struct st_read_record { /* Parameter to read_record */
} READ_RECORD;
-enum timestamp_type
-{
- TIMESTAMP_NONE= -2, TIMESTAMP_DATETIME_ERROR= -1,
- TIMESTAMP_DATE= 0, TIMESTAMP_DATETIME= 1, TIMESTAMP_TIME= 2
-};
-
-/* Parameters to str_to_TIME */
-#define TIME_FUZZY_DATE 1
-#define TIME_DATETIME_ONLY 2
-
-
-typedef struct st_time {
- uint year,month,day,hour,minute,second;
- ulong second_part;
- bool neg;
- timestamp_type time_type;
-} TIME;
+/*
+ Originally MySQL used TIME structure inside server only, but since
+ 4.1 it's exported to user in the new client API. Define aliases for
+ new names to keep existing code simple.
+*/
+
+typedef struct st_mysql_time TIME;
+typedef enum enum_mysql_timestamp_type timestamp_type;
typedef struct {
diff --git a/sql/table.cc b/sql/table.cc
index 73f036aed87..5024015c382 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -126,6 +126,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
goto err_not_open; /* purecov: inspected */
*fn_ext(index_file)='\0'; // Remove .frm extension
+ outparam->frm_version= head[2];
outparam->db_type=ha_checktype((enum db_type) (uint) *(head+3));
outparam->db_create_options=db_create_options=uint2korr(head+30);
outparam->db_options_in_use=outparam->db_create_options;
@@ -494,15 +495,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
for (uint key=0 ; key < outparam->keys ; key++,keyinfo++)
{
uint usable_parts=0;
- ulong index_flags;
keyinfo->name=(char*) outparam->keynames.type_names[key];
/* Fix fulltext keys for old .frm files */
if (outparam->key_info[key].flags & HA_FULLTEXT)
outparam->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT;
/* This has to be done after the above fulltext correction */
- index_flags=outparam->file->index_flags(key);
- if (!(index_flags & HA_KEY_READ_ONLY))
+ if (!(outparam->file->index_flags(key) & HA_KEYREAD_ONLY))
{
outparam->read_only_keys.set_bit(key);
outparam->keys_for_keyread.clear_bit(key);
@@ -577,15 +576,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (field->key_length() == key_part->length &&
!(field->flags & BLOB_FLAG))
{
- if ((index_flags & HA_KEY_READ_ONLY) &&
- (field->key_type() != HA_KEYTYPE_TEXT ||
- (!((ha_option & HA_KEY_READ_WRONG_STR) ||
- (field->flags & BINARY_FLAG)) &&
- !(keyinfo->flags & HA_FULLTEXT))))
+ if (outparam->file->index_flags(key, i) & HA_KEYREAD_ONLY)
field->part_of_key.set_bit(key);
- if ((field->key_type() != HA_KEYTYPE_TEXT ||
- !(keyinfo->flags & HA_FULLTEXT)) &&
- !(index_flags & HA_WRONG_ASCII_ORDER))
+ if (outparam->file->index_flags(key, i) & HA_READ_ORDER)
field->part_of_sortkey.set_bit(key);
}
if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
@@ -1134,7 +1127,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
char fill[IO_SIZE];
#if SIZEOF_OFF_T > 4
- /* Fix this in MySQL 4.0; The current limit is 4G rows (QQ) */
+ /* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */
if (create_info->max_rows > ~(ulong) 0)
create_info->max_rows= ~(ulong) 0;
if (create_info->min_rows > ~(ulong) 0)
diff --git a/sql/table.h b/sql/table.h
index c59b5a03bc4..eaad8bedf90 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -157,7 +157,8 @@ struct st_table {
uint quick_key_parts[MAX_KEY];
key_part_map const_key_parts[MAX_KEY];
ulong query_id;
- uint temp_pool_slot; /* Used by intern temp tables */
+ uchar frm_version;
+ uint temp_pool_slot; /* Used by intern temp tables */
struct st_table_list *pos_in_table_list;/* Element referring to this table */
/* number of select if it is derived table */
uint derived_select_number;
diff --git a/sql/time.cc b/sql/time.cc
index 6d15fa184a1..132612e53c5 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -23,16 +23,26 @@
static ulong const days_at_timestart=719528; /* daynr at 1970.01.01 */
uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037";
- /* Init some variabels needed when using my_local_time */
- /* Currently only my_time_zone is inited */
+/*
+ Offset of system time zone from UTC in seconds used to speed up
+ work of my_system_gmt_sec() function.
+*/
static long my_time_zone=0;
+
+/*
+ Prepare offset of system time zone from UTC for my_system_gmt_sec() func.
+
+ SYNOPSIS
+ init_time()
+*/
void init_time(void)
{
time_t seconds;
struct tm *l_time,tm_tmp;;
TIME my_time;
+ bool not_used;
seconds= (time_t) time((time_t*) 0);
localtime_r(&seconds,&tm_tmp);
@@ -44,33 +54,40 @@ void init_time(void)
my_time.hour= (uint) l_time->tm_hour;
my_time.minute= (uint) l_time->tm_min;
my_time.second= (uint) l_time->tm_sec;
- my_gmt_sec(&my_time, &my_time_zone); /* Init my_time_zone */
+ my_system_gmt_sec(&my_time, &my_time_zone, &not_used); /* Init my_time_zone */
}
+
/*
- Convert current time to sec. since 1970.01.01
- This code handles also day light saving time.
- The idea is to cache the time zone (including daylight saving time)
- for the next call to make things faster.
+ Convert time in TIME representation in system time zone to its
+ my_time_t form (number of seconds in UTC since begginning of Unix Epoch).
-*/
+ SYNOPSIS
+ my_system_gmt_sec()
+ t - time value to be converted
+ my_timezone - pointer to long where offset of system time zone
+ from UTC will be stored for caching
+ in_dst_time_gap - set to true if time falls into spring time-gap
-long my_gmt_sec(TIME *t, long *my_timezone)
+ NOTES
+ The idea is to cache the time zone offset from UTC (including daylight
+ saving time) for the next call to make things faster. But currently we
+ just calculate this offset during startup (by calling init_time()
+ function) and use it all the time.
+ Time value provided should be legal time value (e.g. '2003-01-01 25:00:00'
+ is not allowed).
+
+ RETURN VALUE
+ Time in UTC seconds since Unix Epoch representation.
+*/
+my_time_t
+my_system_gmt_sec(const TIME *t, long *my_timezone, bool *in_dst_time_gap)
{
uint loop;
time_t tmp;
struct tm *l_time,tm_tmp;
long diff, current_timezone;
- if (t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR)
- return 0;
-
- if (t->hour >= 24)
- { /* Fix for time-loop */
- t->day+=t->hour/24;
- t->hour%=24;
- }
-
/*
Calculate the gmt time based on current time and timezone
The -1 on the end is to ensure that if have a date that exists twice
@@ -125,14 +142,13 @@ long my_gmt_sec(TIME *t, long *my_timezone)
tmp+=3600 - t->minute*60 - t->second; // Move to next hour
else if (diff == -3600)
tmp-=t->minute*60 + t->second; // Move to previous hour
+
+ *in_dst_time_gap= 1;
}
*my_timezone= current_timezone;
- if (tmp < TIMESTAMP_MIN_VALUE || tmp > TIMESTAMP_MAX_VALUE)
- tmp= 0;
-
- return (long) tmp;
-} /* my_gmt_sec */
+ return (my_time_t) tmp;
+} /* my_system_gmt_sec */
/* Some functions to calculate dates */
@@ -164,6 +180,7 @@ long calc_daynr(uint year,uint month,uint day)
} /* calc_daynr */
+#ifndef TESTTIME
/* Calc weekday from daynr */
/* Returns 0 for monday, 1 for tuesday .... */
@@ -328,545 +345,167 @@ ulong convert_month_to_period(ulong month)
}
-/* Position for YYYY-DD-MM HH-MM-DD.FFFFFF AM in default format */
-
-static uchar internal_format_positions[]=
-{0, 1, 2, 3, 4, 5, 6, (uchar) 255};
-
-static char time_separator=':';
-
/*
- Convert a timestamp string to a TIME value.
+ Convert a timestamp string to a TIME value and produce a warning
+ if string was truncated during conversion.
- SYNOPSIS
- str_to_TIME()
- str String to parse
- length Length of string
- l_time Date is stored here
- flags Bitmap of following items
- TIME_FUZZY_DATE Set if we should allow partial dates
- TIME_DATETIME_ONLY Set if we only allow full datetimes.
-
- DESCRIPTION
- At least the following formats are recogniced (based on number of digits)
- YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS
- YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS
- YYYYMMDDTHHMMSS where T is a the character T (ISO8601)
- Also dates where all parts are zero are allowed
-
- The second part may have an optional .###### fraction part.
-
- NOTES
- This function should work with a format position vector as long as the
- following things holds:
- - All date are kept together and all time parts are kept together
- - Date and time parts must be separated by blank
- - Second fractions must come after second part and be separated
- by a '.'. (The second fractions are optional)
- - AM/PM must come after second fractions (or after seconds if no fractions)
- - Year must always been specified.
- - If time is before date, then we will use datetime format only if
- the argument consist of two parts, separated by space.
- Otherwise we will assume the argument is a date.
- - The hour part must be specified in hour-minute-second order.
-
- RETURN VALUES
- TIMESTAMP_NONE String wasn't a timestamp, like
- [DD [HH:[MM:[SS]]]].fraction.
- l_time is not changed.
- TIMESTAMP_DATE DATE string (YY MM and DD parts ok)
- TIMESTAMP_DATETIME Full timestamp
- TIMESTAMP_DATETIME_ERROR Timestamp with wrong values.
- All elements in l_time is set to 0
+ NOTE
+ See description of str_to_datetime() for more information.
*/
-
-#define MAX_DATE_PARTS 8
-
timestamp_type
-str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
+str_to_datetime_with_warn(const char *str, uint length, TIME *l_time,
+ uint flags)
{
- uint field_length, year_length, digits, i, number_of_fields;
- uint date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
- uint add_hours= 0, start_loop;
- ulong not_zero_date, allow_space;
- bool is_internal_format;
- const char *pos, *last_field_pos;
- const char *str_begin= str;
- const char *end=str+length;
- const uchar *format_position;
- bool found_delimitier= 0, found_space= 0;
- uint frac_pos, frac_len;
- DBUG_ENTER("str_to_TIME");
- DBUG_PRINT("ENTER",("str: %.*s",length,str));
-
- LINT_INIT(field_length);
- LINT_INIT(year_length);
- LINT_INIT(last_field_pos);
-
- // Skip space at start
- for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
- ;
- if (str == end || ! my_isdigit(&my_charset_latin1, *str))
- DBUG_RETURN(TIMESTAMP_NONE);
-
- is_internal_format= 0;
- /* This has to be changed if want to activate different timestamp formats */
- format_position= internal_format_positions;
-
- /*
- Calculate number of digits in first part.
- If length= 8 or >= 14 then year is of format YYYY.
- (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS)
- */
- for (pos=str; pos != end && my_isdigit(&my_charset_latin1,*pos) ; pos++)
- ;
-
- digits= (uint) (pos-str);
- start_loop= 0; // Start of scan loop
- date_len[format_position[0]]= 0; // Length of year field
- if (pos == end)
- {
- /* Found date in internal format (only numbers like YYYYMMDD) */
- year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
- field_length=year_length-1;
- is_internal_format= 1;
- format_position= internal_format_positions;
- }
- else
- {
- if (format_position[0] >= 3) // If year is after HHMMDD
- {
- /*
- If year is not in first part then we have to determinate if we got
- a date field or a datetime field.
- We do this by checking if there is two numbers separated by
- space in the input.
- */
- while (pos < end && !my_isspace(&my_charset_latin1, *pos))
- pos++;
- while (pos < end && !my_isdigit(&my_charset_latin1, *pos))
- pos++;
- if (pos == end)
- {
- if (flags & TIME_DATETIME_ONLY)
- DBUG_RETURN(TIMESTAMP_NONE); // Can't be a full datetime
- /* Date field. Set hour, minutes and seconds to 0 */
- date[0]= date[1]= date[2]= date[3]= date[4]= 0;
- start_loop= 5; // Start with first date part
- }
- }
- }
-
- /*
- Only allow space in the first "part" of the datetime field and:
- - after days, part seconds
- - before and after AM/PM (handled by code later)
-
- 2003-03-03 20:00:20 AM
- 20:00:20.000000 AM 03-03-2000
- */
- i= max((uint) format_position[0], (uint) format_position[1]);
- set_if_bigger(i, (uint) format_position[2]);
- allow_space= ((1 << i) | (1 << format_position[6]));
- allow_space&= (1 | 2 | 4 | 8);
-
- not_zero_date= 0;
- for (i = start_loop;
- i < MAX_DATE_PARTS-1 && str != end &&
- my_isdigit(&my_charset_latin1,*str);
- i++)
- {
- const char *start= str;
- ulong tmp_value= (uint) (uchar) (*str++ - '0');
- while (str != end && my_isdigit(&my_charset_latin1,str[0]) &&
- (!is_internal_format || field_length--))
- {
- tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0');
- str++;
- }
- date_len[i]= (uint) (str - start);
- if (tmp_value > 999999) // Impossible date part
- DBUG_RETURN(TIMESTAMP_NONE);
- date[i]=tmp_value;
- not_zero_date|= tmp_value;
-
- /* Length-1 of next field */
- field_length= format_position[i+1] == 0 ? 3 : 1;
-
- if ((last_field_pos= str) == end)
- {
- i++; // Register last found part
- break;
- }
- /* Allow a 'T' after day to allow CCYYMMDDT type of fields */
- if (i == format_position[2] && *str == 'T')
- {
- str++; // ISO8601: CCYYMMDDThhmmss
- continue;
- }
- if (i == format_position[5]) // Seconds
- {
- if (*str == '.') // Followed by part seconds
- {
- str++;
- field_length= 5; // 5 digits after first (=6)
- }
- continue;
-
- /* No part seconds */
- date[++i]= 0;
- }
- while (str != end &&
- (my_ispunct(&my_charset_latin1,*str) ||
- my_isspace(&my_charset_latin1,*str)))
- {
- if (my_isspace(&my_charset_latin1,*str))
- {
- if (!(allow_space & (1 << i)))
- DBUG_RETURN(TIMESTAMP_NONE);
- found_space= 1;
- }
- str++;
- found_delimitier= 1; // Should be a 'normal' date
- }
- /* Check if next position is AM/PM */
- if (i == format_position[6]) // Seconds, time for AM/PM
- {
- i++; // Skip AM/PM part
- if (format_position[7] != 255) // If using AM/PM
- {
- if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
- {
- if (str[0] == 'p' || str[0] == 'P')
- add_hours= 12;
- else if (str[0] != 'a' || str[0] != 'A')
- continue; // Not AM/PM
- str+= 2; // Skip AM/PM
- /* Skip space after AM/PM */
- while (str != end && my_isspace(&my_charset_latin1,*str))
- str++;
- }
- }
- }
- last_field_pos= str;
- }
- if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY))
- DBUG_RETURN(TIMESTAMP_NONE); // Can't be a datetime
-
- str= last_field_pos;
-
- number_of_fields= i - start_loop;
- while (i < MAX_DATE_PARTS)
- {
- date_len[i]= 0;
- date[i++]= 0;
- }
+ int was_cut;
+ timestamp_type ts_type= str_to_datetime(str, length, l_time, flags, &was_cut);
+ if (was_cut)
+ make_truncated_value_warning(current_thd, str, length, ts_type);
+ return ts_type;
+}
- if (!is_internal_format)
- {
- year_length= date_len[(uint) format_position[0]];
- if (!year_length) // Year must be specified
- DBUG_RETURN(TIMESTAMP_NONE);
-
- l_time->year= date[(uint) format_position[0]];
- l_time->month= date[(uint) format_position[1]];
- l_time->day= date[(uint) format_position[2]];
- l_time->hour= date[(uint) format_position[3]];
- l_time->minute= date[(uint) format_position[4]];
- l_time->second= date[(uint) format_position[5]];
-
- frac_pos= (uint) format_position[6];
- frac_len= date_len[frac_pos];
- if (frac_len < 6)
- date[frac_pos]*= (uint) log_10_int[6 - frac_len];
- l_time->second_part= date[frac_pos];
-
- if (format_position[7] != (uchar) 255)
- {
- if (l_time->hour > 12)
- goto err;
- l_time->hour= l_time->hour%12 + add_hours;
- }
- }
- else
- {
- l_time->year= date[0];
- l_time->month= date[1];
- l_time->day= date[2];
- l_time->hour= date[3];
- l_time->minute= date[4];
- l_time->second= date[5];
- if (date_len[6] < 6)
- date[6]*= (uint) log_10_int[6 - date_len[6]];
- l_time->second_part=date[6];
- }
- l_time->neg= 0;
- if (year_length == 2 && i >= format_position[1] && i >=format_position[2] &&
- (l_time->month || l_time->day))
- l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);
+/*
+ Convert a datetime from broken-down TIME representation to corresponding
+ TIMESTAMP value.
- if (number_of_fields < 3 || l_time->month > 12 ||
- l_time->day > 31 || l_time->hour > 23 ||
- l_time->minute > 59 || l_time->second > 59 ||
- (!(flags & TIME_FUZZY_DATE) && (l_time->month == 0 || l_time->day == 0)))
- {
- /* Only give warning for a zero date if there is some garbage after */
- if (!not_zero_date) // If zero date
- {
- for (; str != end ; str++)
- {
- if (!my_isspace(&my_charset_latin1, *str))
- {
- not_zero_date= 1; // Give warning
- break;
- }
- }
- }
- if (not_zero_date)
- current_thd->cuted_fields++;
- goto err;
- }
+ SYNOPSIS
+ TIME_to_timestamp()
+ thd - current thread
+ t - datetime in broken-down representation,
+ in_dst_time_gap - pointer to bool which is set to true if t represents
+ value which doesn't exists (falls into the spring
+ time-gap) or to false otherwise.
+
+ RETURN
+ Number seconds in UTC since start of Unix Epoch corresponding to t.
+ 0 - t contains datetime value which is out of TIMESTAMP range.
+
+*/
+my_time_t TIME_to_timestamp(THD *thd, const TIME *t, bool *in_dst_time_gap)
+{
+ my_time_t timestamp;
- l_time->time_type= (number_of_fields <= 3 ?
- TIMESTAMP_DATE : TIMESTAMP_DATETIME);
+ *in_dst_time_gap= 0;
- for (; str != end ; str++)
+ if (t->year < TIMESTAMP_MAX_YEAR && t->year > TIMESTAMP_MIN_YEAR ||
+ t->year == TIMESTAMP_MAX_YEAR && t->month == 1 && t->day == 1 ||
+ t->year == TIMESTAMP_MIN_YEAR && t->month == 12 && t->day == 31)
{
- if (!my_isspace(&my_charset_latin1,*str))
- {
- make_truncated_value_warning(current_thd, str_begin, length,
- l_time->time_type);
- break;
- }
+ thd->time_zone_used= 1;
+ timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap);
+ if (timestamp >= TIMESTAMP_MIN_VALUE && timestamp <= TIMESTAMP_MAX_VALUE)
+ return timestamp;
}
- DBUG_RETURN(l_time->time_type=
- (number_of_fields <= 3 ? TIMESTAMP_DATE : TIMESTAMP_DATETIME));
-
-err:
- bzero((char*) l_time, sizeof(*l_time));
- DBUG_RETURN(TIMESTAMP_DATETIME_ERROR);
-}
-
-
-time_t str_to_timestamp(const char *str,uint length)
-{
- TIME l_time;
- long not_used;
- time_t timestamp= 0;
-
- if (str_to_TIME(str,length,&l_time,0) > TIMESTAMP_DATETIME_ERROR &&
- !(timestamp= my_gmt_sec(&l_time, &not_used)))
- current_thd->cuted_fields++;
- return timestamp;
+ /* If we are here we have range error. */
+ return(0);
}
/*
- Convert a string to datetime.
-
- SYNOPSIS
- str_to_datetime()
- str String to parse (see str_to_TIME() synopsis)
- length Length of str
- fuzzy_date Flags (see str_to_TIME() synopsis)
+ Convert a time string to a TIME struct and produce a warning
+ if string was cut during conversion.
- RETURN
- -1 if error
- datetime value otherwise
+ NOTE
+ See str_to_time() for more info.
*/
-
-longlong str_to_datetime(const char *str,uint length, uint fuzzy_date)
+bool
+str_to_time_with_warn(const char *str, uint length, TIME *l_time)
{
- TIME l_time;
- if (str_to_TIME(str,length,&l_time,fuzzy_date) <= TIMESTAMP_DATETIME_ERROR)
- return -1;
- return (longlong) (l_time.year*LL(10000000000) +
- l_time.month*LL(100000000)+
- l_time.day*LL(1000000)+
- l_time.hour*LL(10000)+
- (longlong) (l_time.minute*100+l_time.second));
+ int was_cut;
+ bool ret_val= str_to_time(str, length, l_time, &was_cut);
+ if (was_cut)
+ make_truncated_value_warning(current_thd, str, length, MYSQL_TIMESTAMP_TIME);
+ return ret_val;
}
/*
- Convert a time string to a TIME struct.
+ Convert datetime value specified as number to broken-down TIME
+ representation and form value of DATETIME type as side-effect.
SYNOPSIS
- str_to_time()
- str A string in full TIMESTAMP format or
- [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS,
- [M]MSS or [S]S
- There may be an optional [.second_part] after seconds
- length Length of str
- l_time Store result here
-
- NOTES
- Because of the extra days argument, this function can only
- work with times where the time arguments are in the above order.
-
- RETURN
- 0 ok
- 1 error
+ number_to_TIME()
+ nr - datetime value as number
+ time_res - pointer for structure for broken-down representation
+ fuzzy_date - indicates whenever we allow fuzzy dates
+ was_cut - set ot 1 if there was some kind of error during
+ conversion or to 0 if everything was OK.
+
+ DESCRIPTION
+ Convert a datetime value of formats YYMMDD, YYYYMMDD, YYMMDDHHMSS,
+ YYYYMMDDHHMMSS to broken-down TIME representation. Return value in
+ YYYYMMDDHHMMSS format as side-effect.
+
+ This function also checks if datetime value fits in DATETIME range.
+
+ RETURN VALUE
+ Datetime value in YYYYMMDDHHMMSS format.
+ If input value is not valid datetime value then 0 is returned.
*/
-bool str_to_time(const char *str,uint length,TIME *l_time)
+longlong number_to_TIME(longlong nr, TIME *time_res, bool fuzzy_date,
+ int *was_cut)
{
- long date[5],value;
- const char *end=str+length, *end_of_days;
- const char *str_begin= str;
- bool found_days,found_hours;
- uint state;
-
- l_time->neg=0;
- for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
- length--;
- if (str != end && *str == '-')
- {
- l_time->neg=1;
- str++;
- length--;
- }
- if (str == end)
- return 1;
+ long part1,part2;
- /* Check first if this is a full TIMESTAMP */
- if (length >= 12)
- { // Probably full timestamp
- enum timestamp_type res= str_to_TIME(str,length,l_time,
- (TIME_FUZZY_DATE |
- TIME_DATETIME_ONLY));
- if ((int) res >= (int) TIMESTAMP_DATETIME_ERROR)
- return res == TIMESTAMP_DATETIME_ERROR;
- }
-
- /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
- for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
- value=value*10L + (long) (*str - '0');
-
- /* Skipp all space after 'days' */
- end_of_days= str;
- for (; str != end && my_isspace(&my_charset_latin1, str[0]) ; str++)
- ;
-
- LINT_INIT(state);
- found_days=found_hours=0;
- if ((uint) (end-str) > 1 && str != end_of_days &&
- my_isdigit(&my_charset_latin1, *str))
- { // Found days part
- date[0]= value;
- state= 1; // Assume next is hours
- found_days= 1;
- }
- else if ((end-str) > 1 && *str == time_separator &&
- my_isdigit(&my_charset_latin1, str[1]))
- {
- date[0]=0; // Assume we found hours
- date[1]=value;
- state=2;
- found_hours=1;
- str++; // skip ':'
- }
- else
- {
- /* String given as one number; assume HHMMSS format */
- date[0]= 0;
- date[1]= value/10000;
- date[2]= value/100 % 100;
- date[3]= value % 100;
- state=4;
- goto fractional;
- }
-
- /* Read hours, minutes and seconds */
- for (;;)
- {
- for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
- value=value*10L + (long) (*str - '0');
- date[state++]=value;
- if (state == 4 || (end-str) < 2 || *str != time_separator ||
- !my_isdigit(&my_charset_latin1,str[1]))
- break;
- str++; // Skip time_separator (':')
- }
-
- if (state != 4)
- { // Not HH:MM:SS
- /* Fix the date to assume that seconds was given */
- if (!found_hours && !found_days)
- {
- bmove_upp((char*) (date+4), (char*) (date+state),
- sizeof(long)*(state-1));
- bzero((char*) date, sizeof(long)*(4-state));
- }
- else
- bzero((char*) (date+state), sizeof(long)*(4-state));
- }
-
-fractional:
- /* Get fractional second part */
- if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
+ *was_cut= 0;
+
+ if (nr == LL(0) || nr >= LL(10000101000000))
+ goto ok;
+ if (nr < 101)
+ goto err;
+ if (nr <= (YY_PART_YEAR-1)*10000L+1231L)
{
- uint field_length=5;
- str++; value=(uint) (uchar) (*str - '0');
- while (++str != end &&
- my_isdigit(&my_charset_latin1,str[0]) &&
- field_length--)
- value=value*10 + (uint) (uchar) (*str - '0');
- if (field_length)
- value*= (long) log_10_int[field_length];
- date[4]=value;
+ nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069
+ goto ok;
}
- else
- date[4]=0;
-
- if (internal_format_positions[7] != 255)
+ if (nr < (YY_PART_YEAR)*10000L+101L)
+ goto err;
+ if (nr <= 991231L)
{
- /* Read a possible AM/PM */
- while (str != end && my_isspace(&my_charset_latin1, *str))
- str++;
- if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
- {
- if (str[0] == 'p' || str[0] == 'P')
- {
- str+= 2;
- date[1]= date[1]%12 + 12;
- }
- else if (str[0] == 'a' || str[0] == 'A')
- str+=2;
- }
+ nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999
+ goto ok;
}
-
- /* Some simple checks */
- if (date[2] >= 60 || date[3] >= 60)
+ if (nr < 10000101L)
+ goto err;
+ if (nr <= 99991231L)
{
- current_thd->cuted_fields++;
- return 1;
+ nr= nr*1000000L;
+ goto ok;
}
- l_time->year= 0; // For protocol::store_time
- l_time->month= 0;
- l_time->day= date[0];
- l_time->hour= date[1];
- l_time->minute= date[2];
- l_time->second= date[3];
- l_time->second_part= date[4];
- l_time->time_type= TIMESTAMP_TIME;
-
- /* Check if there is garbage at end of the TIME specification */
- if (str != end)
+ if (nr < 101000000L)
+ goto err;
+ if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959))
{
- do
- {
- if (!my_isspace(&my_charset_latin1,*str))
- {
- make_truncated_value_warning(current_thd, str_begin, length,
- TIMESTAMP_TIME);
- break;
- }
- } while (++str != end);
+ nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069
+ goto ok;
}
- return 0;
+ if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000))
+ goto err;
+ if (nr <= LL(991231235959))
+ nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999
+
+ ok:
+ part1=(long) (nr/LL(1000000));
+ part2=(long) (nr - (longlong) part1*LL(1000000));
+ time_res->year= (int) (part1/10000L); part1%=10000L;
+ time_res->month= (int) part1 / 100;
+ time_res->day= (int) part1 % 100;
+ time_res->hour= (int) (part2/10000L); part2%=10000L;
+ time_res->minute=(int) part2 / 100;
+ time_res->second=(int) part2 % 100;
+
+ if (time_res->year <= 9999 && time_res->month <= 12 &&
+ time_res->day <= 31 && time_res->hour <= 23 &&
+ time_res->minute <= 59 && time_res->second <= 59 &&
+ (fuzzy_date || (time_res->month != 0 && time_res->day != 0) || nr==0))
+ return nr;
+
+ err:
+
+ *was_cut= 1;
+ return LL(0);
}
@@ -1042,10 +681,10 @@ bool parse_date_time_format(timestamp_type format_type,
The last test is to ensure that %p is used if and only if
it's needed.
*/
- if ((format_type == TIMESTAMP_DATETIME &&
+ if ((format_type == MYSQL_TIMESTAMP_DATETIME &&
!test_all_bits(part_map, (1 | 2 | 4 | 8 | 16 | 32))) ||
- (format_type == TIMESTAMP_DATE && part_map != (1 | 2 | 4)) ||
- (format_type == TIMESTAMP_TIME &&
+ (format_type == MYSQL_TIMESTAMP_DATE && part_map != (1 | 2 | 4)) ||
+ (format_type == MYSQL_TIMESTAMP_TIME &&
!test_all_bits(part_map, 8 | 16 | 32)) ||
!allow_separator || // %option should be last
(need_p && dt_pos[6] +1 != dt_pos[7]) ||
@@ -1088,10 +727,10 @@ bool parse_date_time_format(timestamp_type format_type,
format_str= 0;
switch (format_type) {
- case TIMESTAMP_DATE:
+ case MYSQL_TIMESTAMP_DATE:
format_str= known_date_time_formats[INTERNAL_FORMAT].date_format;
/* fall through */
- case TIMESTAMP_TIME:
+ case MYSQL_TIMESTAMP_TIME:
if (!format_str)
format_str=known_date_time_formats[INTERNAL_FORMAT].time_format;
@@ -1106,7 +745,7 @@ bool parse_date_time_format(timestamp_type format_type,
return 0;
if (separator_map == (1 | 2))
{
- if (format_type == TIMESTAMP_TIME)
+ if (format_type == MYSQL_TIMESTAMP_TIME)
{
if (*(format+2) != *(format+5))
break; // Error
@@ -1116,7 +755,7 @@ bool parse_date_time_format(timestamp_type format_type,
return 0;
}
break;
- case TIMESTAMP_DATETIME:
+ case MYSQL_TIMESTAMP_DATETIME:
/*
If there is no separators, allow the internal format as we can read
this. If separators are used, they must be between each part.
@@ -1235,11 +874,11 @@ const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
timestamp_type type)
{
switch (type) {
- case TIMESTAMP_DATE:
+ case MYSQL_TIMESTAMP_DATE:
return format->date_format;
- case TIMESTAMP_DATETIME:
+ case MYSQL_TIMESTAMP_DATETIME:
return format->datetime_format;
- case TIMESTAMP_TIME:
+ case MYSQL_TIMESTAMP_TIME:
return format->time_format;
default:
DBUG_ASSERT(0); // Impossible
@@ -1307,6 +946,7 @@ void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
str->set_charset(&my_charset_bin);
}
+
void make_truncated_value_warning(THD *thd, const char *str_val,
uint str_length, timestamp_type time_type)
{
@@ -1320,22 +960,20 @@ void make_truncated_value_warning(THD *thd, const char *str_val,
str.append('\0');
switch (time_type) {
- case TIMESTAMP_DATE:
+ case MYSQL_TIMESTAMP_DATE:
type_str= "date";
break;
- case TIMESTAMP_DATETIME:
- type_str= "datetime";
- break;
- case TIMESTAMP_TIME:
+ case MYSQL_TIMESTAMP_TIME:
type_str= "time";
break;
+ case MYSQL_TIMESTAMP_DATETIME: // FALLTHROUGH
default:
- type_str= "string";
+ type_str= "datetime";
break;
}
sprintf(warn_buff, ER(ER_TRUNCATED_WRONG_VALUE),
type_str, str.ptr());
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE, warn_buff);
}
@@ -1398,14 +1036,14 @@ ulonglong TIME_to_ulonglong_time(const TIME *time)
ulonglong TIME_to_ulonglong(const TIME *time)
{
switch (time->time_type) {
- case TIMESTAMP_DATETIME:
+ case MYSQL_TIMESTAMP_DATETIME:
return TIME_to_ulonglong_datetime(time);
- case TIMESTAMP_DATE:
+ case MYSQL_TIMESTAMP_DATE:
return TIME_to_ulonglong_date(time);
- case TIMESTAMP_TIME:
+ case MYSQL_TIMESTAMP_TIME:
return TIME_to_ulonglong_time(time);
- case TIMESTAMP_NONE:
- case TIMESTAMP_DATETIME_ERROR:
+ case MYSQL_TIMESTAMP_NONE:
+ case MYSQL_TIMESTAMP_ERROR:
return ULL(0);
default:
DBUG_ASSERT(0);
@@ -1428,17 +1066,17 @@ ulonglong TIME_to_ulonglong(const TIME *time)
void TIME_to_string(const TIME *time, String *str)
{
switch (time->time_type) {
- case TIMESTAMP_DATETIME:
+ case MYSQL_TIMESTAMP_DATETIME:
make_datetime((DATE_TIME_FORMAT*) 0, time, str);
break;
- case TIMESTAMP_DATE:
+ case MYSQL_TIMESTAMP_DATE:
make_date((DATE_TIME_FORMAT*) 0, time, str);
break;
- case TIMESTAMP_TIME:
+ case MYSQL_TIMESTAMP_TIME:
make_time((DATE_TIME_FORMAT*) 0, time, str);
break;
- case TIMESTAMP_NONE:
- case TIMESTAMP_DATETIME_ERROR:
+ case MYSQL_TIMESTAMP_NONE:
+ case MYSQL_TIMESTAMP_ERROR:
str->length(0);
str->set_charset(&my_charset_bin);
break;
@@ -1446,3 +1084,5 @@ void TIME_to_string(const TIME *time, String *str)
DBUG_ASSERT(0);
}
}
+
+#endif
diff --git a/sql/tzfile.h b/sql/tzfile.h
new file mode 100644
index 00000000000..623cddc1f12
--- /dev/null
+++ b/sql/tzfile.h
@@ -0,0 +1,137 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ This file is based on public domain code from ftp://elsie.ncih.nist.gov/
+ Initial source code is in the public domain, so clarified as of
+ 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+/*
+ Information about time zone files.
+*/
+
+#ifndef TZDIR
+#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
+#endif /* !defined TZDIR */
+
+/*
+ Each file begins with. . .
+*/
+
+#define TZ_MAGIC "TZif"
+
+struct tzhead {
+ char tzh_magic[4]; /* TZ_MAGIC */
+ char tzh_reserved[16]; /* reserved for future use */
+ char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
+ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
+ char tzh_leapcnt[4]; /* coded number of leap seconds */
+ char tzh_timecnt[4]; /* coded number of transition times */
+ char tzh_typecnt[4]; /* coded number of local time types */
+ char tzh_charcnt[4]; /* coded number of abbr. chars */
+};
+
+/*
+ . . .followed by. . .
+
+ tzh_timecnt (char [4])s coded transition times a la time(2)
+ tzh_timecnt (unsigned char)s types of local time starting at above
+ tzh_typecnt repetitions of
+ one (char [4]) coded UTC offset in seconds
+ one (unsigned char) used to set tm_isdst
+ one (unsigned char) that's an abbreviation list index
+ tzh_charcnt (char)s '\0'-terminated zone abbreviations
+ tzh_leapcnt repetitions of
+ one (char [4]) coded leap second transition times
+ one (char [4]) total correction after above
+ tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
+ time is standard time, if FALSE,
+ transition time is wall clock time
+ if absent, transition times are
+ assumed to be wall clock time
+ tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
+ time is UTC, if FALSE,
+ transition time is local time
+ if absent, transition times are
+ assumed to be local time
+*/
+
+/*
+ In the current implementation, we refuse to deal with files that
+ exceed any of the limits below.
+*/
+
+#ifndef TZ_MAX_TIMES
+/*
+ The TZ_MAX_TIMES value below is enough to handle a bit more than a
+ year's worth of solar time (corrected daily to the nearest second) or
+ 138 years of Pacific Presidential Election time
+ (where there are three time zone transitions every fourth year).
+*/
+#define TZ_MAX_TIMES 370
+#endif /* !defined TZ_MAX_TIMES */
+
+#ifndef TZ_MAX_TYPES
+#ifdef SOLAR
+#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
+#else
+/*
+ Must be at least 14 for Europe/Riga as of Jan 12 1995,
+ as noted by Earl Chew <earl@hpato.aus.hp.com>.
+*/
+#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
+#endif /* defined SOLAR */
+#endif /* !defined TZ_MAX_TYPES */
+
+#ifndef TZ_MAX_CHARS
+#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
+ /* (limited by what unsigned chars can hold) */
+#endif /* !defined TZ_MAX_CHARS */
+
+#ifndef TZ_MAX_LEAPS
+#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
+#endif /* !defined TZ_MAX_LEAPS */
+
+#ifndef TZ_MAX_REV_RANGES
+#ifdef SOLAR
+/* Solar (Asia/RiyadhXX) zones need significantly bigger TZ_MAX_REV_RANGES */
+#define TZ_MAX_REV_RANGES (TZ_MAX_TIMES*2+TZ_MAX_LEAPS*2+2)
+#else
+#define TZ_MAX_REV_RANGES (TZ_MAX_TIMES+TZ_MAX_LEAPS+2)
+#endif
+#endif
+
+#define SECS_PER_MIN 60
+#define MINS_PER_HOUR 60
+#define HOURS_PER_DAY 24
+#define DAYS_PER_WEEK 7
+#define DAYS_PER_NYEAR 365
+#define DAYS_PER_LYEAR 366
+#define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
+#define SECS_PER_DAY ((long) SECS_PER_HOUR * HOURS_PER_DAY)
+#define MONS_PER_YEAR 12
+
+#define TM_YEAR_BASE 1900
+
+#define EPOCH_YEAR 1970
+
+/*
+ Accurate only for the past couple of centuries,
+ that will probably do.
+*/
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
diff --git a/sql/tztime.cc b/sql/tztime.cc
new file mode 100644
index 00000000000..aab0d36b61e
--- /dev/null
+++ b/sql/tztime.cc
@@ -0,0 +1,2581 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Most of the following code and structures were derived from
+ public domain code from ftp://elsie.nci.nih.gov/pub
+ (We will refer to this code as to elsie-code further.)
+*/
+
+#ifdef __GNUC__
+#pragma implementation // gcc: Class implementation
+#endif
+
+/*
+ We should not include mysql_priv.h in mysql_tzinfo_to_sql utility since
+ it creates unsolved link dependencies on some platforms.
+*/
+#if !defined(TZINFO2SQL) && !defined(TESTTIME)
+#include "mysql_priv.h"
+#else
+#include <my_global.h>
+#include "tztime.h"
+#include <my_sys.h>
+#endif
+
+#include "tzfile.h"
+#include <m_string.h>
+#include <my_dir.h>
+
+/*
+ Now we don't use abbreviations in server but we will do this in future.
+*/
+#if defined(TZINFO2SQL) || defined(TESTTIME)
+#define ABBR_ARE_USED
+#else
+#if !defined(DBUG_OFF)
+/* Let use abbreviations for debug purposes */
+#undef ABBR_ARE_USED
+#define ABBR_ARE_USED
+#endif /* !defined(DBUG_OFF) */
+#endif /* defined(TZINFO2SQL) || defined(TESTTIME) */
+
+/* Structure describing local time type (e.g. Moscow summer time (MSD)) */
+typedef struct ttinfo
+{
+ long tt_gmtoff; // Offset from UTC in seconds
+ uint tt_isdst; // Is daylight saving time or not. Used to set tm_isdst
+#ifdef ABBR_ARE_USED
+ uint tt_abbrind; // Index of start of abbreviation for this time type.
+#endif
+ /*
+ We don't use tt_ttisstd and tt_ttisgmt members of original elsie-code
+ struct since we don't support POSIX-style TZ descriptions in variables.
+ */
+} TRAN_TYPE_INFO;
+
+/* Structure describing leap-second corrections. */
+typedef struct lsinfo
+{
+ my_time_t ls_trans; // Transition time
+ long ls_corr; // Correction to apply
+} LS_INFO;
+
+/*
+ Structure with information describing ranges of my_time_t shifted to local
+ time (my_time_t + offset). Used for local TIME -> my_time_t conversion.
+ See comments for TIME_to_gmt_sec() for more info.
+*/
+typedef struct revtinfo
+{
+ long rt_offset; // Offset of local time from UTC in seconds
+ uint rt_type; // Type of period 0 - Normal period. 1 - Spring time-gap
+} REVT_INFO;
+
+#ifdef TZNAME_MAX
+#define MY_TZNAME_MAX TZNAME_MAX
+#endif
+#ifndef TZNAME_MAX
+#define MY_TZNAME_MAX 255
+#endif
+
+/*
+ Structure which fully describes time zone which is
+ described in our db or in zoneinfo files.
+*/
+typedef struct st_time_zone_info
+{
+ uint leapcnt; // Number of leap-second corrections
+ uint timecnt; // Number of transitions between time types
+ uint typecnt; // Number of local time types
+ uint charcnt; // Number of characters used for abbreviations
+ uint revcnt; // Number of transition descr. for TIME->my_time_t conversion
+ /* The following are dynamical arrays are allocated in MEM_ROOT */
+ my_time_t *ats; // Times of transitions between time types
+ unsigned char *types; // Local time types for transitions
+ TRAN_TYPE_INFO *ttis; // Local time types descriptions
+#ifdef ABBR_ARE_USED
+ /* Storage for local time types abbreviations. They are stored as ASCIIZ */
+ char *chars;
+#endif
+ /*
+ Leap seconds corrections descriptions, this array is shared by
+ all time zones who use leap seconds.
+ */
+ LS_INFO *lsis;
+ /*
+ Starting points and descriptions of shifted my_time_t (my_time_t + offset)
+ ranges on which shifted my_time_t -> my_time_t mapping is linear or undefined.
+ Used for tm -> my_time_t conversion.
+ */
+ my_time_t *revts;
+ REVT_INFO *revtis;
+ /*
+ Time type which is used for times smaller than first transition or if
+ there are no transitions at all.
+ */
+ TRAN_TYPE_INFO *fallback_tti;
+
+} TIME_ZONE_INFO;
+
+
+static my_bool prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage);
+
+
+#if defined(TZINFO2SQL) || defined(TESTTIME)
+
+/*
+ Load time zone description from zoneinfo (TZinfo) file.
+
+ SYNOPSIS
+ tz_load()
+ name - path to zoneinfo file
+ sp - TIME_ZONE_INFO structure to fill
+
+ RETURN VALUES
+ 0 - Ok
+ 1 - Error
+*/
+static my_bool
+tz_load(const char *name, TIME_ZONE_INFO *sp, MEM_ROOT *storage)
+{
+ char *p;
+ int read_from_file;
+ uint i;
+ FILE *file;
+
+ if (!(file= my_fopen(name, O_RDONLY|O_BINARY, MYF(MY_WME))))
+ return 1;
+ {
+ union
+ {
+ struct tzhead tzhead;
+ char buf[sizeof(struct tzhead) + sizeof(my_time_t) * TZ_MAX_TIMES +
+ TZ_MAX_TIMES + sizeof(TRAN_TYPE_INFO) * TZ_MAX_TYPES +
+#ifdef ABBR_ARE_USED
+ max(TZ_MAX_CHARS + 1, (2 * (MY_TZNAME_MAX + 1))) +
+#endif
+ sizeof(LS_INFO) * TZ_MAX_LEAPS];
+ } u;
+ uint ttisstdcnt;
+ uint ttisgmtcnt;
+ char *tzinfo_buf;
+
+ read_from_file= my_fread(file, u.buf, sizeof(u.buf), MYF(MY_WME));
+
+ if (my_fclose(file, MYF(MY_WME)) != 0)
+ return 1;
+
+ if (read_from_file < (int)sizeof(struct tzhead))
+ return 1;
+
+ ttisstdcnt= int4net(u.tzhead.tzh_ttisgmtcnt);
+ ttisgmtcnt= int4net(u.tzhead.tzh_ttisstdcnt);
+ sp->leapcnt= int4net(u.tzhead.tzh_leapcnt);
+ sp->timecnt= int4net(u.tzhead.tzh_timecnt);
+ sp->typecnt= int4net(u.tzhead.tzh_typecnt);
+ sp->charcnt= int4net(u.tzhead.tzh_charcnt);
+ p= u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
+ if (sp->leapcnt > TZ_MAX_LEAPS ||
+ sp->typecnt == 0 || sp->typecnt > TZ_MAX_TYPES ||
+ sp->timecnt > TZ_MAX_TIMES ||
+ sp->charcnt > TZ_MAX_CHARS ||
+ (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
+ (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
+ return 1;
+ if ((uint)(read_from_file - (p - u.buf)) <
+ sp->timecnt * 4 + /* ats */
+ sp->timecnt + /* types */
+ sp->typecnt * (4 + 2) + /* ttinfos */
+ sp->charcnt + /* chars */
+ sp->leapcnt * (4 + 4) + /* lsinfos */
+ ttisstdcnt + /* ttisstds */
+ ttisgmtcnt) /* ttisgmts */
+ return 1;
+
+ if (!(tzinfo_buf= (char *)alloc_root(storage,
+ ALIGN_SIZE(sp->timecnt *
+ sizeof(my_time_t)) +
+ ALIGN_SIZE(sp->timecnt) +
+ ALIGN_SIZE(sp->typecnt *
+ sizeof(TRAN_TYPE_INFO)) +
+#ifdef ABBR_ARE_USED
+ ALIGN_SIZE(sp->charcnt) +
+#endif
+ sp->leapcnt * sizeof(LS_INFO))))
+ return 1;
+
+ sp->ats= (my_time_t *)tzinfo_buf;
+ tzinfo_buf+= ALIGN_SIZE(sp->timecnt * sizeof(my_time_t));
+ sp->types= (unsigned char *)tzinfo_buf;
+ tzinfo_buf+= ALIGN_SIZE(sp->timecnt);
+ sp->ttis= (TRAN_TYPE_INFO *)tzinfo_buf;
+ tzinfo_buf+= ALIGN_SIZE(sp->typecnt * sizeof(TRAN_TYPE_INFO));
+#ifdef ABBR_ARE_USED
+ sp->chars= tzinfo_buf;
+ tzinfo_buf+= ALIGN_SIZE(sp->charcnt);
+#endif
+ sp->lsis= (LS_INFO *)tzinfo_buf;
+
+ for (i= 0; i < sp->timecnt; i++, p+= 4)
+ sp->ats[i]= int4net(p);
+
+ for (i= 0; i < sp->timecnt; i++)
+ {
+ sp->types[i]= (unsigned char) *p++;
+ if (sp->types[i] >= sp->typecnt)
+ return 1;
+ }
+ for (i= 0; i < sp->typecnt; i++)
+ {
+ TRAN_TYPE_INFO * ttisp;
+
+ ttisp= &sp->ttis[i];
+ ttisp->tt_gmtoff= int4net(p);
+ p+= 4;
+ ttisp->tt_isdst= (unsigned char) *p++;
+ if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
+ return 1;
+ ttisp->tt_abbrind= (unsigned char) *p++;
+ if (ttisp->tt_abbrind > sp->charcnt)
+ return 1;
+ }
+ for (i= 0; i < sp->charcnt; i++)
+ sp->chars[i]= *p++;
+ sp->chars[i]= '\0'; /* ensure '\0' at end */
+ for (i= 0; i < sp->leapcnt; i++)
+ {
+ LS_INFO *lsisp;
+
+ lsisp= &sp->lsis[i];
+ lsisp->ls_trans= int4net(p);
+ p+= 4;
+ lsisp->ls_corr= int4net(p);
+ p+= 4;
+ }
+ /*
+ Since we don't support POSIX style TZ definitions in variables we
+ don't read further like glibc or elsie code.
+ */
+ }
+
+ return prepare_tz_info(sp, storage);
+}
+#endif /* defined(TZINFO2SQL) || defined(TESTTIME) */
+
+
+/*
+ Finish preparation of time zone description for use in TIME_to_gmt_sec()
+ and gmt_sec_to_TIME() functions.
+
+ SYNOPSIS
+ prepare_tz_info()
+ sp - pointer to time zone description
+ storage - pointer to MEM_ROOT where arrays for map allocated
+
+ DESCRIPTION
+ First task of this function is to find fallback time type which will
+ be used if there are no transitions or we have moment in time before
+ any transitions.
+ Second task is to build "shifted my_time_t" -> my_time_t map used in
+ TIME -> my_time_t conversion.
+ Note: See description of TIME_to_gmt_sec() function first.
+ In order to perform TIME -> my_time_t conversion we need to build table
+ which defines "shifted by tz offset and leap seconds my_time_t" ->
+ my_time_t function wich is almost the same (except ranges of ambiguity)
+ as reverse function to piecewise linear function used for my_time_t ->
+ "shifted my_time_t" conversion and which is also specified as table in
+ zoneinfo file or in our db (It is specified as start of time type ranges
+ and time type offsets). So basic idea is very simple - let us iterate
+ through my_time_t space from one point of discontinuity of my_time_t ->
+ "shifted my_time_t" function to another and build our approximation of
+ reverse function. (Actually we iterate through ranges on which
+ my_time_t -> "shifted my_time_t" is linear function).
+
+ RETURN VALUES
+ 0 Ok
+ 1 Error
+*/
+static my_bool
+prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage)
+{
+ my_time_t cur_t= MY_TIME_T_MIN;
+ my_time_t cur_l, end_t, end_l;
+ my_time_t cur_max_seen_l= MY_TIME_T_MIN;
+ long cur_offset, cur_corr, cur_off_and_corr;
+ uint next_trans_idx, next_leap_idx;
+ uint i;
+ /*
+ Temporary arrays where we will store tables. Needed because
+ we don't know table sizes ahead. (Well we can estimate their
+ upper bound but this will take extra space.)
+ */
+ my_time_t revts[TZ_MAX_REV_RANGES];
+ REVT_INFO revtis[TZ_MAX_REV_RANGES];
+
+ LINT_INIT(end_l);
+
+ /*
+ Let us setup fallback time type which will be used if we have not any
+ transitions or if we have moment of time before first transition.
+ We will find first non-DST local time type and use it (or use first
+ local time type if all of them are DST types).
+ */
+ for (i= 0; i < sp->typecnt && sp->ttis[i].tt_isdst; i++)
+ /* no-op */ ;
+ if (i == sp->typecnt)
+ i= 0;
+ sp->fallback_tti= &(sp->ttis[i]);
+
+
+ /*
+ Let us build shifted my_time_t -> my_time_t map.
+ */
+ sp->revcnt= 0;
+
+ /* Let us find initial offset */
+ if (sp->timecnt == 0 || cur_t < sp->ats[0])
+ {
+ /*
+ If we have not any transitions or t is before first transition we are using
+ already found fallback time type which index is already in i.
+ */
+ next_trans_idx= 0;
+ }
+ else
+ {
+ /* cur_t == sp->ats[0] so we found transition */
+ i= sp->types[0];
+ next_trans_idx= 1;
+ }
+
+ cur_offset= sp->ttis[i].tt_gmtoff;
+
+
+ /* let us find leap correction... unprobable, but... */
+ for (next_leap_idx= 0; next_leap_idx < sp->leapcnt &&
+ cur_t >= sp->lsis[next_leap_idx].ls_trans;
+ ++next_leap_idx)
+ continue;
+
+ if (next_leap_idx > 0)
+ cur_corr= sp->lsis[next_leap_idx - 1].ls_corr;
+ else
+ cur_corr= 0;
+
+ /* Iterate trough t space */
+ while (sp->revcnt < TZ_MAX_REV_RANGES - 1)
+ {
+ cur_off_and_corr= cur_offset - cur_corr;
+
+ /*
+ We assuming that cur_t could be only overflowed downwards,
+ we also assume that end_t won't be overflowed in this case.
+ */
+ if (cur_off_and_corr < 0 &&
+ cur_t < MY_TIME_T_MIN - cur_off_and_corr)
+ cur_t= MY_TIME_T_MIN - cur_off_and_corr;
+
+ cur_l= cur_t + cur_off_and_corr;
+
+ /*
+ Let us choose end_t as point before next time type change or leap
+ second correction.
+ */
+ end_t= min((next_trans_idx < sp->timecnt) ? sp->ats[next_trans_idx] - 1:
+ MY_TIME_T_MAX,
+ (next_leap_idx < sp->leapcnt) ?
+ sp->lsis[next_leap_idx].ls_trans - 1: MY_TIME_T_MAX);
+ /*
+ again assuming that end_t can be overlowed only in positive side
+ we also assume that end_t won't be overflowed in this case.
+ */
+ if (cur_off_and_corr > 0 &&
+ end_t > MY_TIME_T_MAX - cur_off_and_corr)
+ end_t= MY_TIME_T_MAX - cur_off_and_corr;
+
+ end_l= end_t + cur_off_and_corr;
+
+
+ if (end_l > cur_max_seen_l)
+ {
+ /* We want special handling in the case of first range */
+ if (cur_max_seen_l == MY_TIME_T_MIN)
+ {
+ revts[sp->revcnt]= cur_l;
+ revtis[sp->revcnt].rt_offset= cur_off_and_corr;
+ revtis[sp->revcnt].rt_type= 0;
+ sp->revcnt++;
+ cur_max_seen_l= end_l;
+ }
+ else
+ {
+ if (cur_l > cur_max_seen_l + 1)
+ {
+ /* We have a spring time-gap and we are not at the first range */
+ revts[sp->revcnt]= cur_max_seen_l + 1;
+ revtis[sp->revcnt].rt_offset= revtis[sp->revcnt-1].rt_offset;
+ revtis[sp->revcnt].rt_type= 1;
+ sp->revcnt++;
+ if (sp->revcnt == TZ_MAX_TIMES + TZ_MAX_LEAPS + 1)
+ break; /* That was too much */
+ cur_max_seen_l= cur_l - 1;
+ }
+
+ /* Assume here end_l > cur_max_seen_l (because end_l>=cur_l) */
+
+ revts[sp->revcnt]= cur_max_seen_l + 1;
+ revtis[sp->revcnt].rt_offset= cur_off_and_corr;
+ revtis[sp->revcnt].rt_type= 0;
+ sp->revcnt++;
+ cur_max_seen_l= end_l;
+ }
+ }
+
+ if (end_t == MY_TIME_T_MAX ||
+ (cur_off_and_corr > 0) &&
+ (end_t >= MY_TIME_T_MAX - cur_off_and_corr))
+ /* end of t space */
+ break;
+
+ cur_t= end_t + 1;
+
+ /*
+ Let us find new offset and correction. Because of our choice of end_t
+ cur_t can only be point where new time type starts or/and leap
+ correction is performed.
+ */
+ if (sp->timecnt != 0 && cur_t >= sp->ats[0]) /* else reuse old offset */
+ if (next_trans_idx < sp->timecnt &&
+ cur_t == sp->ats[next_trans_idx])
+ {
+ /* We are at offset point */
+ cur_offset= sp->ttis[sp->types[next_trans_idx]].tt_gmtoff;
+ ++next_trans_idx;
+ }
+
+ if (next_leap_idx < sp->leapcnt &&
+ cur_t == sp->lsis[next_leap_idx].ls_trans)
+ {
+ /* we are at leap point */
+ cur_corr= sp->lsis[next_leap_idx].ls_corr;
+ ++next_leap_idx;
+ }
+ }
+
+ /* check if we have had enough space */
+ if (sp->revcnt == TZ_MAX_REV_RANGES - 1)
+ return 1;
+
+ /* set maximum end_l as finisher */
+ revts[sp->revcnt]= end_l;
+
+ /* Allocate arrays of proper size in sp and copy result there */
+ if (!(sp->revts= (my_time_t *)alloc_root(storage,
+ sizeof(my_time_t) * (sp->revcnt + 1))) ||
+ !(sp->revtis= (REVT_INFO *)alloc_root(storage,
+ sizeof(REVT_INFO) * sp->revcnt)))
+ return 1;
+
+ memcpy(sp->revts, revts, sizeof(my_time_t) * (sp->revcnt + 1));
+ memcpy(sp->revtis, revtis, sizeof(REVT_INFO) * sp->revcnt);
+
+ return 0;
+}
+
+
+#if !defined(TZINFO2SQL)
+
+static const uint mon_lengths[2][MONS_PER_YEAR]=
+{
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static const uint mon_starts[2][MONS_PER_YEAR]=
+{
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
+};
+
+static const uint year_lengths[2]=
+{
+ DAYS_PER_NYEAR, DAYS_PER_LYEAR
+};
+
+#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
+
+
+/*
+ Converts time from my_time_t representation (seconds in UTC since Epoch)
+ to broken down representation using given local time zone offset.
+
+ SYNOPSIS
+ sec_to_TIME()
+ tmp - pointer to structure for broken down representation
+ t - my_time_t value to be converted
+ offset - local time zone offset
+
+ DESCRIPTION
+ Convert my_time_t with offset to TIME struct. Differs from timesub
+ (from elsie code) because doesn't contain any leap correction and
+ TM_GMTOFF and is_dst setting and contains some MySQL specific
+ initialization. Funny but with removing of these we almost have
+ glibc's offtime function.
+*/
+static void
+sec_to_TIME(TIME * tmp, my_time_t t, long offset)
+{
+ long days;
+ long rem;
+ int y;
+ int yleap;
+ const uint *ip;
+
+ days= t / SECS_PER_DAY;
+ rem= t % SECS_PER_DAY;
+
+ /*
+ We do this as separate step after dividing t, because this
+ allows us handle times near my_time_t bounds without overflows.
+ */
+ rem+= offset;
+ while (rem < 0)
+ {
+ rem+= SECS_PER_DAY;
+ days--;
+ }
+ while (rem >= SECS_PER_DAY)
+ {
+ rem -= SECS_PER_DAY;
+ days++;
+ }
+ tmp->hour= (uint)(rem / SECS_PER_HOUR);
+ rem= rem % SECS_PER_HOUR;
+ tmp->minute= (uint)(rem / SECS_PER_MIN);
+ /*
+ A positive leap second requires a special
+ representation. This uses "... ??:59:60" et seq.
+ */
+ tmp->second= (uint)(rem % SECS_PER_MIN);
+
+ y= EPOCH_YEAR;
+ while (days < 0 || days >= (long)year_lengths[yleap= isleap(y)])
+ {
+ int newy;
+
+ newy= y + days / DAYS_PER_NYEAR;
+ if (days < 0)
+ newy--;
+ days-= (newy - y) * DAYS_PER_NYEAR +
+ LEAPS_THRU_END_OF(newy - 1) -
+ LEAPS_THRU_END_OF(y - 1);
+ y= newy;
+ }
+ tmp->year= y;
+
+ ip= mon_lengths[yleap];
+ for (tmp->month= 0; days >= (long) ip[tmp->month]; tmp->month++)
+ days= days - (long) ip[tmp->month];
+ tmp->month++;
+ tmp->day= (uint)(days + 1);
+
+ /* filling MySQL specific TIME members */
+ tmp->neg= 0; tmp->second_part= 0;
+ tmp->time_type= MYSQL_TIMESTAMP_DATETIME;
+}
+
+
+/*
+ Find time range wich contains given my_time_t value
+
+ SYNOPSIS
+ find_time_range()
+ t - my_time_t value for which we looking for range
+ range_boundaries - sorted array of range starts.
+ higher_bound - number of ranges
+
+ DESCRIPTION
+ Performs binary search for range which contains given my_time_t value.
+ It has sense if number of ranges is greater than zero and my_time_t value
+ is greater or equal than beginning of first range. It also assumes that
+ t belongs to some range specified or end of last is MY_TIME_T_MAX.
+
+ With this localtime_r on real data may takes less time than with linear
+ search (I've seen 30% speed up).
+
+ RETURN VALUE
+ Index of range to which t belongs
+*/
+static uint
+find_time_range(my_time_t t, const my_time_t *range_boundaries,
+ uint higher_bound)
+{
+ uint i, lower_bound= 0;
+
+ /*
+ Function will work without this assertion but result would be meaningless.
+ */
+ DBUG_ASSERT(higher_bound > 0 && t >= range_boundaries[0]);
+
+ /*
+ Do binary search for minimal interval which contain t. We preserve:
+ range_boundaries[lower_bound] <= t < range_boundaries[higher_bound]
+ invariant and decrease this higher_bound - lower_bound gap twice
+ times on each step.
+ */
+
+ while (higher_bound - lower_bound > 1)
+ {
+ i= (lower_bound + higher_bound) >> 1;
+ if (range_boundaries[i] <= t)
+ lower_bound= i;
+ else
+ higher_bound= i;
+ }
+ return lower_bound;
+}
+
+/*
+ Find local time transition for given my_time_t.
+
+ SYNOPSIS
+ find_transition_type()
+ t - my_time_t value to be converted
+ sp - pointer to struct with time zone description
+
+ RETURN VALUE
+ Pointer to structure in time zone description describing
+ local time type for given my_time_t.
+*/
+static
+const TRAN_TYPE_INFO *
+find_transition_type(my_time_t t, const TIME_ZONE_INFO *sp)
+{
+ if (unlikely(sp->timecnt == 0 || t < sp->ats[0]))
+ {
+ /*
+ If we have not any transitions or t is before first transition let
+ us use fallback time type.
+ */
+ return sp->fallback_tti;
+ }
+
+ /*
+ Do binary search for minimal interval between transitions which
+ contain t. With this localtime_r on real data may takes less
+ time than with linear search (I've seen 30% speed up).
+ */
+ return &(sp->ttis[sp->types[find_time_range(t, sp->ats, sp->timecnt)]]);
+}
+
+
+/*
+ Converts time in my_time_t representation (seconds in UTC since Epoch) to
+ broken down TIME representation in local time zone.
+
+ SYNOPSIS
+ gmt_sec_to_TIME()
+ tmp - pointer to structure for broken down represenatation
+ sec_in_utc - my_time_t value to be converted
+ sp - pointer to struct with time zone description
+
+ TODO
+ We can improve this function by creating joined array of transitions and
+ leap corrections. This will require adding extra field to TRAN_TYPE_INFO
+ for storing number of "extra" seconds to minute occured due to correction
+ (60th and 61st second, look how we calculate them as "hit" in this
+ function).
+ Under realistic assumptions about frequency of transitions the same array
+ can be used fot TIME -> my_time_t conversion. For this we need to
+ implement tweaked binary search which will take into account that some
+ TIME has two matching my_time_t ranges and some of them have none.
+*/
+static void
+gmt_sec_to_TIME(TIME *tmp, my_time_t sec_in_utc, const TIME_ZONE_INFO *sp)
+{
+ const TRAN_TYPE_INFO *ttisp;
+ const LS_INFO *lp;
+ long corr= 0;
+ int hit= 0;
+ int i;
+
+ /*
+ Find proper transition (and its local time type) for our sec_in_utc value.
+ Funny but again by separating this step in function we receive code
+ which very close to glibc's code. No wonder since they obviously use
+ the same base and all steps are sensible.
+ */
+ ttisp= find_transition_type(sec_in_utc, sp);
+
+ /*
+ Let us find leap correction for our sec_in_utc value and number of extra
+ secs to add to this minute.
+ This loop is rarely used because most users will use time zones without
+ leap seconds, and even in case when we have such time zone there won't
+ be many iterations (we have about 22 corrections at this moment (2004)).
+ */
+ for ( i= sp->leapcnt; i-- > 0; )
+ {
+ lp= &sp->lsis[i];
+ if (sec_in_utc >= lp->ls_trans)
+ {
+ if (sec_in_utc == lp->ls_trans)
+ {
+ hit= ((i == 0 && lp->ls_corr > 0) ||
+ lp->ls_corr > sp->lsis[i - 1].ls_corr);
+ if (hit)
+ {
+ while (i > 0 &&
+ sp->lsis[i].ls_trans == sp->lsis[i - 1].ls_trans + 1 &&
+ sp->lsis[i].ls_corr == sp->lsis[i - 1].ls_corr + 1)
+ {
+ hit++;
+ i--;
+ }
+ }
+ }
+ corr= lp->ls_corr;
+ break;
+ }
+ }
+
+ sec_to_TIME(tmp, sec_in_utc, ttisp->tt_gmtoff - corr);
+
+ tmp->second+= hit;
+}
+
+
+/*
+ Converts local time in broken down representation to local
+ time zone analog of my_time_t represenation.
+
+ SYNOPSIS
+ sec_since_epoch()
+ year, mon, mday, hour, min, sec - broken down representation.
+
+ DESCRIPTION
+ Converts time in broken down representation to my_time_t representation
+ ignoring time zone. Note that we cannot convert back some valid _local_
+ times near ends of my_time_t range because of my_time_t overflow. But we
+ ignore this fact now since MySQL will never pass such argument.
+
+ RETURN VALUE
+ Seconds since epoch time representation.
+*/
+static my_time_t
+sec_since_epoch(int year, int mon, int mday, int hour, int min ,int sec)
+{
+#ifndef WE_WANT_TO_HANDLE_UNORMALIZED_DATES
+ /*
+ It turns out that only whenever month is normalized or unnormalized
+ plays role.
+ */
+ DBUG_ASSERT(mon > 0 && mon < 13);
+ long days= year * DAYS_PER_NYEAR - EPOCH_YEAR * DAYS_PER_NYEAR +
+ LEAPS_THRU_END_OF(year - 1) -
+ LEAPS_THRU_END_OF(EPOCH_YEAR - 1);
+ days+= mon_starts[isleap(year)][mon - 1];
+#else
+ long norm_month= (mon - 1) % MONS_PER_YEAR;
+ long a_year= year + (mon - 1)/MONS_PER_YEAR - (int)(norm_month < 0);
+ long days= a_year * DAYS_PER_NYEAR - EPOCH_YEAR * DAYS_PER_NYEAR +
+ LEAPS_THRU_END_OF(a_year - 1) -
+ LEAPS_THRU_END_OF(EPOCH_YEAR - 1);
+ days+= mon_starts[isleap(a_year)]
+ [norm_month + (norm_month < 0 ? MONS_PER_YEAR : 0)];
+#endif
+ days+= mday - 1;
+
+ return ((days * HOURS_PER_DAY + hour) * MINS_PER_HOUR + min) *
+ SECS_PER_MIN + sec;
+}
+
+
+/*
+ Converts local time in broken down TIME representation to my_time_t
+ representation.
+
+ SYNOPSIS
+ TIME_to_gmt_sec()
+ t - pointer to structure for broken down represenatation
+ sp - pointer to struct with time zone description
+ in_dst_time_gap - pointer to bool which is set to true if datetime
+ value passed doesn't really exist (i.e. falls into
+ spring time-gap) and is not touched otherwise.
+
+ DESCRIPTION
+ This is mktime analog for MySQL. It is essentially different
+ from mktime (or hypotetical my_mktime) because:
+ - It has no idea about tm_isdst member so if it
+ has two answers it will give the smaller one
+ - If we are in spring time gap then it will return
+ beginning of the gap
+ - It can give wrong results near the ends of my_time_t due to
+ overflows, but we are safe since in MySQL we will never
+ call this function for such dates (its restriction for year
+ between 1970 and 2038 gives us several days of reserve).
+ - By default it doesn't support un-normalized input. But if
+ sec_since_epoch() function supports un-normalized dates
+ then this function should handle un-normalized input right,
+ altough it won't normalize structure TIME.
+
+ Traditional approach to problem of conversion from broken down
+ representation to time_t is iterative. Both elsie's and glibc
+ implementation try to guess what time_t value should correspond to
+ this broken-down value. They perform localtime_r function on their
+ guessed value and then calculate the difference and try to improve
+ their guess. Elsie's code guesses time_t value in bit by bit manner,
+ Glibc's code tries to add difference between broken-down value
+ corresponding to guess and target broken-down value to current guess.
+ It also uses caching of last found correction... So Glibc's approach
+ is essentially faster but introduces some undetermenism (in case if
+ is_dst member of broken-down representation (tm struct) is not known
+ and we have two possible answers).
+
+ We use completely different approach. It is better since it is both
+ faster than iterative implementations and fully determenistic. If you
+ look at my_time_t to TIME conversion then you'll find that it consist
+ of two steps:
+ The first is calculating shifted my_time_t value and the second - TIME
+ calculation from shifted my_time_t value (well it is a bit simplified
+ picture). The part in which we are interested in is my_time_t -> shifted
+ my_time_t conversion. It is piecewise linear function which is defined
+ by combination of transition times as break points and times offset
+ as changing function parameter. The possible inverse function for this
+ converison would be ambiguos but with MySQL's restrictions we can use
+ some function which is the same as inverse function on unambigiuos
+ ranges and coincides with one of branches of inverse function in
+ other ranges. Thus we just need to build table which will determine
+ this shifted my_time_t -> my_time_t conversion similar to existing
+ (my_time_t -> shifted my_time_t table). We do this in
+ prepare_tz_info function.
+
+ TODO
+ If we can even more improve this function. For doing this we will need to
+ build joined map of transitions and leap corrections for gmt_sec_to_TIME()
+ function (similar to revts/revtis). Under realistic assumptions about
+ frequency of transitions we can use the same array for TIME_to_gmt_sec().
+ We need to implement special version of binary search for this. Such step
+ will be beneficial to CPU cache since we will decrease data-set used for
+ conversion twice.
+
+ RETURN VALUE
+ Seconds in UTC since Epoch.
+ 0 in case of error.
+*/
+static my_time_t
+TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap)
+{
+ my_time_t local_t;
+ uint saved_seconds;
+ uint i;
+
+ DBUG_ENTER("TIME_to_gmt_sec");
+
+ /* We need this for correct leap seconds handling */
+ if (t->second < SECS_PER_MIN)
+ saved_seconds= 0;
+ else
+ saved_seconds= t->second;
+
+ /*
+ NOTE If we want to convert full my_time_t range without MySQL
+ restrictions we should catch overflow here somehow.
+ */
+
+ local_t= sec_since_epoch(t->year, t->month, t->day,
+ t->hour, t->minute,
+ saved_seconds ? 0 : t->second);
+
+ /* We have at least one range */
+ DBUG_ASSERT(sp->revcnt >= 1);
+
+ if (local_t < sp->revts[0] || local_t > sp->revts[sp->revcnt])
+ {
+ /*
+ This means that source time can't be represented as my_time_t due to
+ limited my_time_t range.
+ */
+ DBUG_RETURN(0);
+ }
+
+ /* binary search for our range */
+ i= find_time_range(local_t, sp->revts, sp->revcnt);
+
+ if (sp->revtis[i].rt_type)
+ {
+ /*
+ Oops! We are in spring time gap.
+ May be we should return error here?
+ Now we are returning my_time_t value corresponding to the
+ beginning of the gap.
+ */
+ *in_dst_time_gap= 1;
+ DBUG_RETURN(sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds);
+ }
+ else
+ DBUG_RETURN(local_t - sp->revtis[i].rt_offset + saved_seconds);
+}
+
+
+/*
+ End of elsie derived code.
+*/
+#endif /* !defined(TZINFO2SQL) */
+
+
+#if !defined(TESTTIME) && !defined(TZINFO2SQL)
+
+/*
+ String with names of SYSTEM time zone.
+*/
+static const String tz_SYSTEM_name("SYSTEM", 6, &my_charset_latin1);
+
+
+/*
+ Instance of this class represents local time zone used on this system
+ (specified by TZ environment variable or via any other system mechanism).
+ It uses system functions (localtime_r, my_system_gmt_sec) for conversion
+ and is always available. Because of this it is used by default - if there
+ were no explicit time zone specified. On the other hand because of this
+ conversion methods provided by this class is significantly slower and
+ possibly less multi-threaded-friendly than corresponding Time_zone_db
+ methods so the latter should be preffered there it is possible.
+*/
+class Time_zone_system : public Time_zone
+{
+public:
+ virtual my_time_t TIME_to_gmt_sec(const TIME *t,
+ bool *in_dst_time_gap) const;
+ virtual void gmt_sec_to_TIME(TIME *tmp, my_time_t t) const;
+ virtual const String * get_name() const;
+};
+
+
+/*
+ Converts local time in system time zone in TIME representation
+ to its my_time_t representation.
+
+ SYNOPSIS
+ TIME_to_gmt_sec()
+ t - pointer to TIME structure with local time in
+ broken-down representation.
+ in_dst_time_gap - pointer to bool which is set to true if datetime
+ value passed doesn't really exist (i.e. falls into
+ spring time-gap) and is not touched otherwise.
+
+ DESCRIPTION
+ This method uses system function (localtime_r()) for conversion
+ local time in system time zone in TIME structure to its my_time_t
+ representation. Unlike the same function for Time_zone_db class
+ it it won't handle unnormalized input properly. Still it will
+ return lowest possible my_time_t in case of ambiguity or if we
+ provide time corresponding to the time-gap.
+
+ You should call init_time() function before using this function.
+
+ RETURN VALUE
+ Corresponding my_time_t value or 0 in case of error
+*/
+my_time_t
+Time_zone_system::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const
+{
+ long not_used;
+ return my_system_gmt_sec(t, &not_used, in_dst_time_gap);
+}
+
+
+/*
+ Converts time from UTC seconds since Epoch (my_time_t) representation
+ to system local time zone broken-down representation.
+
+ SYNOPSIS
+ gmt_sec_to_TIME()
+ tmp - pointer to TIME structure to fill-in
+ t - my_time_t value to be converted
+
+ NOTE
+ We assume that value passed to this function will fit into time_t range
+ supported by localtime_r. This conversion is putting restriction on
+ TIMESTAMP range in MySQL. If we can get rid of SYSTEM time zone at least
+ for interaction with client then we can extend TIMESTAMP range down to
+ the 1902 easily.
+*/
+void
+Time_zone_system::gmt_sec_to_TIME(TIME *tmp, my_time_t t) const
+{
+ struct tm tmp_tm;
+ time_t tmp_t= (time_t)t;
+
+ localtime_r(&tmp_t, &tmp_tm);
+ localtime_to_TIME(tmp, &tmp_tm);
+ tmp->time_type= MYSQL_TIMESTAMP_DATETIME;
+}
+
+
+/*
+ Get name of time zone
+
+ SYNOPSIS
+ get_name()
+
+ RETURN VALUE
+ Name of time zone as String
+*/
+const String *
+Time_zone_system::get_name() const
+{
+ return &tz_SYSTEM_name;
+}
+
+
+/*
+ Instance of this class represents UTC time zone. It uses system gmtime_r
+ function for conversions and is always available. It is used only for
+ my_time_t -> TIME conversions in various UTC_... functions, it is not
+ intended for TIME -> my_time_t conversions and shouldn't be exposed to user.
+*/
+class Time_zone_utc : public Time_zone
+{
+public:
+ virtual my_time_t TIME_to_gmt_sec(const TIME *t,
+ bool *in_dst_time_gap) const;
+ virtual void gmt_sec_to_TIME(TIME *tmp, my_time_t t) const;
+ virtual const String * get_name() const;
+};
+
+
+/*
+ Convert UTC time from TIME representation to its my_time_t representation.
+
+ SYNOPSIS
+ TIME_to_gmt_sec()
+ t - pointer to TIME structure with local time
+ in broken-down representation.
+ in_dst_time_gap - pointer to bool which is set to true if datetime
+ value passed doesn't really exist (i.e. falls into
+ spring time-gap) and is not touched otherwise.
+
+ DESCRIPTION
+ Since Time_zone_utc is used only internally for my_time_t -> TIME
+ conversions, this function of Time_zone interface is not implemented for
+ this class and should not be called.
+
+ RETURN VALUE
+ 0
+*/
+my_time_t
+Time_zone_utc::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const
+{
+ /* Should be never called */
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+
+/*
+ Converts time from UTC seconds since Epoch (my_time_t) representation
+ to broken-down representation (also in UTC).
+
+ SYNOPSIS
+ gmt_sec_to_TIME()
+ tmp - pointer to TIME structure to fill-in
+ t - my_time_t value to be converted
+
+ NOTE
+ See note for apropriate Time_zone_system method.
+*/
+void
+Time_zone_utc::gmt_sec_to_TIME(TIME *tmp, my_time_t t) const
+{
+ struct tm tmp_tm;
+ time_t tmp_t= (time_t)t;
+ gmtime_r(&tmp_t, &tmp_tm);
+ localtime_to_TIME(tmp, &tmp_tm);
+ tmp->time_type= MYSQL_TIMESTAMP_DATETIME;
+}
+
+
+/*
+ Get name of time zone
+
+ SYNOPSIS
+ get_name()
+
+ DESCRIPTION
+ Since Time_zone_utc is used only internally by SQL's UTC_* functions it
+ is not accessible directly, and hence this function of Time_zone
+ interface is not implemented for this class and should not be called.
+
+ RETURN VALUE
+ 0
+*/
+const String *
+Time_zone_utc::get_name() const
+{
+ /* Should be never called */
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+
+/*
+ Instance of this class represents some time zone which is
+ described in mysql.time_zone family of tables.
+*/
+class Time_zone_db : public Time_zone
+{
+public:
+ Time_zone_db(TIME_ZONE_INFO *tz_info_arg, const String * tz_name_arg);
+ virtual my_time_t TIME_to_gmt_sec(const TIME *t,
+ bool *in_dst_time_gap) const;
+ virtual void gmt_sec_to_TIME(TIME *tmp, my_time_t t) const;
+ virtual const String * get_name() const;
+private:
+ TIME_ZONE_INFO *tz_info;
+ const String *tz_name;
+};
+
+
+/*
+ Initializes object representing time zone described by mysql.time_zone
+ tables.
+
+ SYNOPSIS
+ Time_zone_db()
+ tz_info_arg - pointer to TIME_ZONE_INFO structure which is filled
+ according to db or other time zone description
+ (for example by my_tz_init()).
+ Several Time_zone_db instances can share one
+ TIME_ZONE_INFO structure.
+ tz_name_arg - name of time zone.
+*/
+Time_zone_db::Time_zone_db(TIME_ZONE_INFO *tz_info_arg,
+ const String *tz_name_arg):
+ tz_info(tz_info_arg), tz_name(tz_name_arg)
+{
+}
+
+
+/*
+ Converts local time in time zone described from TIME
+ representation to its my_time_t representation.
+
+ SYNOPSIS
+ TIME_to_gmt_sec()
+ t - pointer to TIME structure with local time
+ in broken-down representation.
+ in_dst_time_gap - pointer to bool which is set to true if datetime
+ value passed doesn't really exist (i.e. falls into
+ spring time-gap) and is not touched otherwise.
+
+ DESCRIPTION
+ Please see ::TIME_to_gmt_sec for function description and
+ parameter restrictions.
+
+ RETURN VALUE
+ Corresponding my_time_t value or 0 in case of error
+*/
+my_time_t
+Time_zone_db::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const
+{
+ return ::TIME_to_gmt_sec(t, tz_info, in_dst_time_gap);
+}
+
+
+/*
+ Converts time from UTC seconds since Epoch (my_time_t) representation
+ to local time zone described in broken-down representation.
+
+ SYNOPSIS
+ gmt_sec_to_TIME()
+ tmp - pointer to TIME structure to fill-in
+ t - my_time_t value to be converted
+*/
+void
+Time_zone_db::gmt_sec_to_TIME(TIME *tmp, my_time_t t) const
+{
+ ::gmt_sec_to_TIME(tmp, t, tz_info);
+}
+
+
+/*
+ Get name of time zone
+
+ SYNOPSIS
+ get_name()
+
+ RETURN VALUE
+ Name of time zone as ASCIIZ-string
+*/
+const String *
+Time_zone_db::get_name() const
+{
+ return tz_name;
+}
+
+
+/*
+ Instance of this class represents time zone which
+ was specified as offset from UTC.
+*/
+class Time_zone_offset : public Time_zone
+{
+public:
+ Time_zone_offset(long tz_offset_arg);
+ virtual my_time_t TIME_to_gmt_sec(const TIME *t,
+ bool *in_dst_time_gap) const;
+ virtual void gmt_sec_to_TIME(TIME *tmp, my_time_t t) const;
+ virtual const String * get_name() const;
+ /*
+ This have to be public because we want to be able to access it from
+ my_offset_tzs_get_key() function
+ */
+ long offset;
+private:
+ /* Extra reserve because of snprintf */
+ char name_buff[7+16];
+ String name;
+};
+
+
+/*
+ Initializes object representing time zone described by its offset from UTC.
+
+ SYNOPSIS
+ Time_zone_offset()
+ tz_offset_arg - offset from UTC in seconds.
+ Positive for direction to east.
+*/
+Time_zone_offset::Time_zone_offset(long tz_offset_arg):
+ offset(tz_offset_arg)
+{
+ uint hours= abs((int)(offset / SECS_PER_HOUR));
+ uint minutes= abs((int)(offset % SECS_PER_HOUR / SECS_PER_MIN));
+ ulong length= my_snprintf(name_buff, sizeof(name_buff), "%s%02d:%02d",
+ (offset>=0) ? "+" : "-", hours, minutes);
+ name.set(name_buff, length, &my_charset_latin1);
+}
+
+
+/*
+ Converts local time in time zone described as offset from UTC
+ from TIME representation to its my_time_t representation.
+
+ SYNOPSIS
+ TIME_to_gmt_sec()
+ t - pointer to TIME structure with local time
+ in broken-down representation.
+ in_dst_time_gap - pointer to bool which should be set to true if
+ datetime value passed doesn't really exist
+ (i.e. falls into spring time-gap) and is not
+ touched otherwise.
+ It is not really used in this class.
+
+ RETURN VALUE
+ Corresponding my_time_t value or 0 in case of error
+*/
+my_time_t
+Time_zone_offset::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const
+{
+ return sec_since_epoch(t->year, t->month, t->day,
+ t->hour, t->minute, t->second) -
+ offset;
+}
+
+
+/*
+ Converts time from UTC seconds since Epoch (my_time_t) representation
+ to local time zone described as offset from UTC and in broken-down
+ representation.
+
+ SYNOPSIS
+ gmt_sec_to_TIME()
+ tmp - pointer to TIME structure to fill-in
+ t - my_time_t value to be converted
+*/
+void
+Time_zone_offset::gmt_sec_to_TIME(TIME *tmp, my_time_t t) const
+{
+ sec_to_TIME(tmp, t, offset);
+}
+
+
+/*
+ Get name of time zone
+
+ SYNOPSIS
+ get_name()
+
+ RETURN VALUE
+ Name of time zone as pointer to String object
+*/
+const String *
+Time_zone_offset::get_name() const
+{
+ return &name;
+}
+
+
+static Time_zone_utc tz_UTC;
+static Time_zone_system tz_SYSTEM;
+
+Time_zone *my_tz_UTC= &tz_UTC;
+Time_zone *my_tz_SYSTEM= &tz_SYSTEM;
+
+static HASH tz_names;
+static HASH offset_tzs;
+static MEM_ROOT tz_storage;
+
+/*
+ These mutex protects offset_tzs and tz_storage.
+ These protection needed only when we are trying to set
+ time zone which is specified as offset, and searching for existing
+ time zone in offset_tzs or creating if it didn't existed before in
+ tz_storage. So contention is low.
+*/
+static pthread_mutex_t tz_LOCK;
+static bool tz_inited= 0;
+
+/*
+ This two static variables are inteded for holding info about leap seconds
+ shared by all time zones.
+*/
+static uint tz_leapcnt= 0;
+static LS_INFO *tz_lsis= 0;
+
+
+typedef struct st_tz_names_entry: public Sql_alloc
+{
+ String name;
+ Time_zone *tz;
+} TZ_NAMES_ENTRY;
+
+
+/*
+ We are going to call both of these functions from C code so
+ they should obey C calling conventions.
+*/
+
+extern "C" byte* my_tz_names_get_key(TZ_NAMES_ENTRY *entry, uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length= entry->name.length();
+ return (byte*) entry->name.ptr();
+}
+
+extern "C" byte* my_offset_tzs_get_key(Time_zone_offset *entry, uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length= sizeof(long);
+ return (byte*) &entry->offset;
+}
+
+
+/*
+ Initialize time zone support infrastructure.
+
+ SYNOPSIS
+ my_tz_init()
+ thd - current thread object
+ default_tzname - default time zone or 0 if none.
+ bootstrap - indicates whenever we are in bootstrap mode
+
+ DESCRIPTION
+ This function will init memory structures needed for time zone support,
+ it will register mandatory SYSTEM time zone in them. It will try to open
+ mysql.time_zone_leap_seconds table and and load information which further
+ will be shared among all time zones loaded. It will also try to load
+ information about default time zone. If system tables with time zone
+ descriptions don't exist it won't fail (unless default_tzname is time zone
+ from tables). If bootstrap parameter is true then this routine assumes that
+ we are in bootstrap mode and won't load time zone descriptions unless someone
+ specifies default time zone which is supposedly stored in those tables.
+ It'll also set default time zone if it is specified.
+
+ RETURN VALUES
+ 0 - ok
+ 1 - Error
+*/
+my_bool
+my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
+{
+ THD *thd;
+ TABLE_LIST tables;
+ TABLE *table;
+ TABLE *lock_ptr;
+ MYSQL_LOCK *lock;
+ TZ_NAMES_ENTRY *tmp_tzname;
+ my_bool return_val= 1;
+ int res;
+ uint not_used;
+ DBUG_ENTER("my_tz_init");
+
+ /*
+ To be able to run this from boot, we allocate a temporary THD
+ */
+ if (!(thd= new THD))
+ DBUG_RETURN(1);
+ thd->store_globals();
+
+ /* Init all memory structures that require explicit destruction */
+ if (hash_init(&tz_names, &my_charset_latin1, 20,
+ 0, 0, (hash_get_key)my_tz_names_get_key, 0, 0))
+ {
+ sql_print_error("Fatal error: OOM while initializing time zones");
+ goto end;
+ }
+ if (hash_init(&offset_tzs, &my_charset_latin1, 26, 0, 0,
+ (hash_get_key)my_offset_tzs_get_key, 0, 0))
+ {
+ sql_print_error("Fatal error: OOM while initializing time zones");
+ hash_free(&tz_names);
+ goto end;
+ }
+ init_alloc_root(&tz_storage, 32 * 1024, 0);
+ VOID(pthread_mutex_init(&tz_LOCK, MY_MUTEX_INIT_FAST));
+ tz_inited= 1;
+
+ /* Add 'SYSTEM' time zone to tz_names hash */
+ if (!(tmp_tzname= new (&tz_storage) TZ_NAMES_ENTRY()))
+ {
+ sql_print_error("Fatal error: OOM while initializing time zones");
+ goto end_with_cleanup;
+ }
+ tmp_tzname->name.set("SYSTEM", 6, &my_charset_latin1);
+ tmp_tzname->tz= my_tz_SYSTEM;
+ if (my_hash_insert(&tz_names, (const byte *)tmp_tzname))
+ {
+ sql_print_error("Fatal error: OOM while initializing time zones");
+ goto end_with_cleanup;
+ }
+
+ if (bootstrap)
+ {
+ /* If we are in bootstrap mode we should not load time zone tables */
+ return_val= 0;
+ goto end_with_setting_default_tz;
+ }
+
+ /*
+ After this point all memory structures are inited and we even can live
+ without time zone description tables. Now try to load information about
+ leap seconds shared by all time zones.
+ */
+
+ thd->db= my_strdup("mysql",MYF(0));
+ thd->db_length= 5; // Safety
+ bzero((char*) &tables,sizeof(tables));
+ tables.alias= tables.real_name= (char*)"time_zone_leap_second";
+ tables.lock_type= TL_READ;
+ tables.db= thd->db;
+
+ if (open_tables(thd, &tables, &not_used))
+ {
+ sql_print_error("Warning: Can't open time zone table: %s "
+ "trying to live without them", thd->net.last_error);
+ /* We will try emulate that everything is ok */
+ return_val= 0;
+ goto end_with_setting_default_tz;
+ }
+
+ lock_ptr= tables.table;
+ if (!(lock= mysql_lock_tables(thd, &lock_ptr, 1)))
+ {
+ sql_print_error("Fatal error: Can't lock time zone table: %s",
+ thd->net.last_error);
+ goto end_with_close;
+ }
+
+
+ /*
+ Now we are going to load leap seconds descriptions that are shared
+ between all time zones that use them. We are using index for getting
+ records in proper order. Since we share the same MEM_ROOT between
+ all time zones we just allocate enough memory for it first.
+ */
+ if (!(tz_lsis= (LS_INFO*) alloc_root(&tz_storage,
+ sizeof(LS_INFO) * TZ_MAX_LEAPS)))
+ {
+ sql_print_error("Fatal error: Out of memory while loading "
+ "mysql.time_zone_leap_second table");
+ goto end_with_unlock;
+ }
+
+ table= tables.table;
+ table->file->ha_index_init(0);
+ tz_leapcnt= 0;
+
+ res= table->file->index_first(table->record[0]);
+
+ while (!res)
+ {
+ if (tz_leapcnt + 1 > TZ_MAX_LEAPS)
+ {
+ sql_print_error("Fatal error: While loading mysql.time_zone_leap_second"
+ " table: too much leaps");
+ table->file->ha_index_end();
+ goto end_with_unlock;
+ }
+
+ tz_lsis[tz_leapcnt].ls_trans= (my_time_t)table->field[0]->val_int();
+ tz_lsis[tz_leapcnt].ls_corr= (long)table->field[1]->val_int();
+
+ tz_leapcnt++;
+
+ DBUG_PRINT("info",
+ ("time_zone_leap_second table: tz_leapcnt=%u tt_time=%lld offset=%ld",
+ tz_leapcnt, (longlong)tz_lsis[tz_leapcnt-1].ls_trans,
+ tz_lsis[tz_leapcnt-1].ls_corr));
+
+ res= table->file->index_next(table->record[0]);
+ }
+
+ table->file->ha_index_end();
+
+ if (res != HA_ERR_END_OF_FILE)
+ {
+ sql_print_error("Fatal error: Error while loading "
+ "mysql.time_zone_leap_second table");
+ goto end_with_unlock;
+ }
+
+ /*
+ Loading of info about leap seconds succeeded
+ */
+
+ return_val= 0;
+
+
+end_with_unlock:
+ mysql_unlock_tables(thd, lock);
+
+end_with_close:
+ close_thread_tables(thd);
+ thd->version--; /* Force close to free memory */
+
+end_with_setting_default_tz:
+ /* If not an error and have default time zone try to load it */
+ if (!return_val && default_tzname)
+ {
+ String tzname(default_tzname, &my_charset_latin1);
+ if (!(global_system_variables.time_zone= my_tz_find(thd, &tzname)))
+ {
+ sql_print_error("Fatal error: Illegal or unknown default time zone '%s'",
+ default_tzname);
+ return_val= 1;
+ }
+ }
+
+end_with_cleanup:
+
+ /* if there were error free time zone describing structs */
+ if (return_val)
+ my_tz_free();
+end:
+ delete thd;
+ if (org_thd)
+ org_thd->store_globals(); /* purecov: inspected */
+ else
+ {
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+ my_pthread_setspecific_ptr(THR_MALLOC, 0);
+ }
+ DBUG_RETURN(return_val);
+}
+
+
+/*
+ Free resources used by time zone support infrastructure.
+
+ SYNOPSIS
+ my_tz_free()
+*/
+
+void my_tz_free()
+{
+ if (tz_inited)
+ {
+ tz_inited= 0;
+ VOID(pthread_mutex_destroy(&tz_LOCK));
+ hash_free(&offset_tzs);
+ hash_free(&tz_names);
+ free_root(&tz_storage, MYF(0));
+ }
+}
+
+
+/*
+ Load time zone description from system tables.
+
+ SYNOPSIS
+ tz_load_from_db()
+ thd - current thread object
+ tz_name - name of time zone that should be loaded.
+
+ DESCRIPTION
+ This function will try to open system tables describing time zones
+ and to load information about time zone specified. It will also update
+ information in hash used for time zones lookup.
+
+ RETURN VALUES
+ Returns pointer to newly created Time_zone object or 0 in case of error.
+
+*/
+static Time_zone*
+tz_load_from_db(THD *thd, const String *tz_name)
+{
+ TABLE_LIST tables[4];
+ TABLE *table= 0;
+ TABLE *lock_ptr[4];
+ MYSQL_LOCK *lock;
+ char system_db_name[]= "mysql";
+ char *db_save;
+ uint db_length_save;
+ TIME_ZONE_INFO *tz_info;
+ TZ_NAMES_ENTRY *tmp_tzname;
+ Time_zone *return_val= 0;
+ int res;
+ uint tzid, ttid;
+ my_time_t ttime;
+ char buff[MAX_FIELD_WIDTH];
+ String abbr(buff, sizeof(buff), &my_charset_latin1);
+ char *alloc_buff, *tz_name_buff;
+ /*
+ Temporary arrays that are used for loading of data for filling
+ TIME_ZONE_INFO structure
+ */
+ my_time_t ats[TZ_MAX_TIMES];
+ unsigned char types[TZ_MAX_TIMES];
+ TRAN_TYPE_INFO ttis[TZ_MAX_TYPES];
+#ifdef ABBR_ARE_USED
+ char chars[max(TZ_MAX_CHARS + 1, (2 * (MY_TZNAME_MAX + 1)))];
+#endif
+ uint not_used;
+
+ DBUG_ENTER("tz_load_from_db");
+
+
+ /* Prepare tz_info for loading also let us make copy of time zone name */
+ if (!(alloc_buff= alloc_root(&tz_storage, sizeof(TIME_ZONE_INFO) +
+ tz_name->length() + 1)))
+ {
+ sql_print_error("Error: Out of memory while loading time zone "
+ "description");
+ return 0;
+ }
+ tz_info= (TIME_ZONE_INFO *)alloc_buff;
+ bzero(tz_info, sizeof(TIME_ZONE_INFO));
+ tz_name_buff= alloc_buff + sizeof(TIME_ZONE_INFO);
+ /*
+ By writing zero to the end we guarantee that we can call ptr()
+ instead of c_ptr() for time zone name.
+ */
+ strmake(tz_name_buff, tz_name->ptr(), tz_name->length());
+
+ /*
+ Open and lock time zone description tables
+ */
+ db_save= thd->db;
+ db_length_save= thd->db_length;
+ thd->db= system_db_name;
+ thd->db_length= 5;
+
+ bzero((char*) &tables,sizeof(tables));
+ tables[0].alias= tables[0].real_name= (char*)"time_zone_name";
+ tables[1].alias= tables[1].real_name= (char*)"time_zone";
+ tables[2].alias= tables[2].real_name= (char*)"time_zone_transition";
+ tables[3].alias= tables[3].real_name= (char*)"time_zone_transition_type";
+ tables[0].next= tables+1;
+ tables[1].next= tables+2;
+ tables[2].next= tables+3;
+ tables[0].lock_type= tables[1].lock_type= tables[2].lock_type=
+ tables[3].lock_type= TL_READ;
+ tables[0].db= tables[1].db= tables[2].db= tables[3].db= thd->db;
+ if (open_tables(thd, tables, &not_used))
+ {
+ sql_print_error("Error: Can't open time zone tables: %s",
+ thd->net.last_error);
+ goto end;
+ }
+
+ lock_ptr[0]= tables[0].table;
+ lock_ptr[1]= tables[1].table;
+ lock_ptr[2]= tables[2].table;
+ lock_ptr[3]= tables[3].table;
+ if (!(lock= mysql_lock_tables(thd, lock_ptr, 4)))
+ {
+ sql_print_error("Error: Can't lock time zone tables: %s",
+ thd->net.last_error);
+ goto end_with_close;
+ }
+
+ /*
+ Let us find out time zone id by its name (there is only one index
+ and it is specifically for this purpose).
+ */
+ table= tables[0].table;
+
+ table->field[0]->store(tz_name->ptr(), tz_name->length(), &my_charset_latin1);
+ table->file->ha_index_init(0);
+
+ if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
+ 0, HA_READ_KEY_EXACT))
+ {
+ sql_print_error("Error: Can't find description of time zone.");
+ goto end_with_unlock;
+ }
+
+ tzid= (uint)table->field[1]->val_int();
+
+ table->file->ha_index_end();
+
+ /*
+ Now we need to lookup record in mysql.time_zone table in order to
+ understand whenever this timezone uses leap seconds (again we are
+ using the only index in this table).
+ */
+ table= tables[1].table;
+ table->field[0]->store((longlong)tzid);
+ table->file->ha_index_init(0);
+
+ if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
+ 0, HA_READ_KEY_EXACT))
+ {
+ sql_print_error("Error: Can't find description of time zone.");
+ goto end_with_unlock;
+ }
+
+ /* If Uses_leap_seconds == 'Y' */
+ if (table->field[1]->val_int() == 1)
+ {
+ tz_info->leapcnt= tz_leapcnt;
+ tz_info->lsis= tz_lsis;
+ }
+
+ table->file->ha_index_end();
+
+ /*
+ Now we will iterate through records for out time zone in
+ mysql.time_zone_transition_type table. Because we want records
+ only for our time zone guess what are we doing?
+ Right - using special index.
+ */
+ table= tables[3].table;
+ table->field[0]->store((longlong)tzid);
+ table->file->ha_index_init(0);
+
+ // FIXME Is there any better approach than explicitly specifying 4 ???
+ res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
+ 4, HA_READ_KEY_EXACT);
+ while (!res)
+ {
+ ttid= (uint)table->field[1]->val_int();
+
+ if (ttid > TZ_MAX_TYPES)
+ {
+ sql_print_error("Error while loading time zone description from "
+ "mysql.time_zone_transition_type table: too big "
+ "transition type id");
+ goto end_with_unlock;
+ }
+
+ ttis[ttid].tt_gmtoff= (long)table->field[2]->val_int();
+ ttis[ttid].tt_isdst= (table->field[3]->val_int() > 0);
+
+#ifdef ABBR_ARE_USED
+ // FIXME should we do something with duplicates here ?
+ table->field[4]->val_str(&abbr, &abbr);
+ if (tz_info->charcnt + abbr.length() + 1 > sizeof(chars))
+ {
+ sql_print_error("Error while loading time zone description from "
+ "mysql.time_zone_transition_type table: not enough "
+ "room for abbreviations");
+ goto end_with_unlock;
+ }
+ ttis[ttid].tt_abbrind= tz_info->charcnt;
+ memcpy(chars + tz_info->charcnt, abbr.ptr(), abbr.length());
+ tz_info->charcnt+= abbr.length();
+ chars[tz_info->charcnt]= 0;
+ tz_info->charcnt++;
+
+ DBUG_PRINT("info",
+ ("time_zone_transition_type table: tz_id=%u tt_id=%u tt_gmtoff=%ld "
+ "abbr='%s' tt_isdst=%u", tzid, ttid, ttis[ttid].tt_gmtoff,
+ chars + ttis[ttid].tt_abbrind, ttis[ttid].tt_isdst));
+#else
+ DBUG_PRINT("info",
+ ("time_zone_transition_type table: tz_id=%u tt_id=%u tt_gmtoff=%ld "
+ "tt_isdst=%u", tzid, ttid, ttis[ttid].tt_gmtoff, ttis[ttid].tt_isdst));
+#endif
+
+ /* ttid is increasing because we are reading using index */
+ DBUG_ASSERT(ttid >= tz_info->typecnt);
+
+ tz_info->typecnt= ttid + 1;
+
+ res= table->file->index_next_same(table->record[0],
+ (byte*)table->field[0]->ptr, 4);
+ }
+
+ if (res != HA_ERR_END_OF_FILE)
+ {
+ sql_print_error("Error while loading time zone description from "
+ "mysql.time_zone_transition_type table");
+ goto end_with_unlock;
+ }
+
+ table->file->ha_index_end();
+
+
+ /*
+ At last we are doing the same thing for records in
+ mysql.time_zone_transition table. Here we additionaly need records
+ in ascending order by index scan also satisfies us.
+ */
+ table= tables[2].table;
+ table->field[0]->store((longlong)tzid);
+ table->file->ha_index_init(0);
+
+ // FIXME Is there any better approach than explicitly specifying 4 ???
+ res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
+ 4, HA_READ_KEY_EXACT);
+ while (!res)
+ {
+ ttime= (my_time_t)table->field[1]->val_int();
+ ttid= (uint)table->field[2]->val_int();
+
+ if (tz_info->timecnt + 1 > TZ_MAX_TIMES)
+ {
+ sql_print_error("Error while loading time zone description from "
+ "mysql.time_zone_transition table: "
+ "too much transitions");
+ goto end_with_unlock;
+ }
+ if (ttid + 1 > tz_info->typecnt)
+ {
+ sql_print_error("Error while loading time zone description from "
+ "mysql.time_zone_transition table: "
+ "bad transition type id");
+ goto end_with_unlock;
+ }
+
+ ats[tz_info->timecnt]= ttime;
+ types[tz_info->timecnt]= ttid;
+ tz_info->timecnt++;
+
+ DBUG_PRINT("info",
+ ("time_zone_transition table: tz_id=%u tt_time=%lld tt_id=%u",
+ tzid, (longlong)ttime, ttid));
+
+ res= table->file->index_next_same(table->record[0],
+ (byte*)table->field[0]->ptr, 4);
+ }
+
+ /*
+ We have to allow HA_ERR_KEY_NOT_FOUND because some time zones
+ for example UTC have no transitons.
+ */
+ if (res != HA_ERR_END_OF_FILE && res != HA_ERR_KEY_NOT_FOUND)
+ {
+ sql_print_error("Error while loading time zone description from "
+ "mysql.time_zone_transition table");
+ goto end_with_unlock;
+ }
+
+ table->file->ha_index_end();
+ table= 0;
+
+ /*
+ Now we will allocate memory and init TIME_ZONE_INFO structure.
+ */
+ if (!(alloc_buff= alloc_root(&tz_storage,
+ ALIGN_SIZE(sizeof(my_time_t) *
+ tz_info->timecnt) +
+ ALIGN_SIZE(tz_info->timecnt) +
+#ifdef ABBR_ARE_USED
+ ALIGN_SIZE(tz_info->charcnt) +
+#endif
+ sizeof(TRAN_TYPE_INFO) * tz_info->typecnt)))
+ {
+ sql_print_error("Error: Out of memory while loading time zone "
+ "description");
+ goto end_with_unlock;
+ }
+
+
+ tz_info->ats= (my_time_t *)alloc_buff;
+ memcpy(tz_info->ats, ats, tz_info->timecnt * sizeof(my_time_t));
+ alloc_buff+= ALIGN_SIZE(sizeof(my_time_t) * tz_info->timecnt);
+ tz_info->types= (unsigned char *)alloc_buff;
+ memcpy(tz_info->types, types, tz_info->timecnt);
+ alloc_buff+= ALIGN_SIZE(tz_info->timecnt);
+#ifdef ABBR_ARE_USED
+ tz_info->chars= alloc_buff;
+ memcpy(tz_info->chars, chars, tz_info->charcnt);
+ alloc_buff+= ALIGN_SIZE(tz_info->charcnt);
+#endif
+ tz_info->ttis= (TRAN_TYPE_INFO *)alloc_buff;
+ memcpy(tz_info->ttis, ttis, tz_info->typecnt * sizeof(TRAN_TYPE_INFO));
+
+ /*
+ Let us check how correct our time zone description and build
+ reversed map. We don't check for tz->timecnt < 1 since it ok for GMT.
+ */
+ if (tz_info->typecnt < 1)
+ {
+ sql_print_error("Error: loading time zone without transition types");
+ goto end_with_unlock;
+ }
+ if (prepare_tz_info(tz_info, &tz_storage))
+ {
+ sql_print_error("Error: Unable to build mktime map for time zone");
+ goto end_with_unlock;
+ }
+
+
+ if (!(tmp_tzname= new (&tz_storage) TZ_NAMES_ENTRY()) ||
+ !(tmp_tzname->tz= new (&tz_storage) Time_zone_db(tz_info,
+ &(tmp_tzname->name))) ||
+ (tmp_tzname->name.set(tz_name_buff, tz_name->length(),
+ &my_charset_latin1),
+ my_hash_insert(&tz_names, (const byte *)tmp_tzname)))
+ {
+ sql_print_error("Error: Out of memory while loading time zone");
+ goto end_with_unlock;
+ }
+
+ /*
+ Loading of time zone succeeded
+ */
+ return_val= tmp_tzname->tz;
+
+end_with_unlock:
+
+ if (table)
+ table->file->ha_index_end();
+
+ mysql_unlock_tables(thd, lock);
+
+end_with_close:
+ close_thread_tables(thd);
+
+end:
+ thd->db= db_save;
+ thd->db_length= db_length_save;
+ DBUG_RETURN(return_val);
+}
+
+
+/*
+ Parse string that specifies time zone as offset from UTC.
+
+ SYNOPSIS
+ str_to_offset()
+ str - pointer to string which contains offset
+ length - length of string
+ offset - out parameter for storing found offset in seconds.
+
+ DESCRIPTION
+ This function parses string which contains time zone offset
+ in form similar to '+10:00' and converts found value to
+ seconds from UTC form (east is positive).
+
+ RETURN VALUE
+ 0 - Ok
+ 1 - String doesn't contain valid time zone offset
+*/
+my_bool
+str_to_offset(const char *str, uint length, long *offset)
+{
+ const char *end= str + length;
+ my_bool negative;
+ ulong number_tmp;
+ long offset_tmp;
+
+ if (length < 4)
+ return 1;
+
+ if (*str == '+')
+ negative= 0;
+ else if (*str == '-')
+ negative= 1;
+ else
+ return 1;
+ str++;
+
+ number_tmp= 0;
+
+ while (str < end && my_isdigit(&my_charset_latin1, *str))
+ {
+ number_tmp= number_tmp*10 + *str - '0';
+ str++;
+ }
+
+ if (str + 1 >= end || *str != ':')
+ return 1;
+ str++;
+
+ offset_tmp = number_tmp * MINS_PER_HOUR; number_tmp= 0;
+
+ while (str < end && my_isdigit(&my_charset_latin1, *str))
+ {
+ number_tmp= number_tmp * 10 + *str - '0';
+ str++;
+ }
+
+ if (str != end)
+ return 1;
+
+ offset_tmp= (offset_tmp + number_tmp) * SECS_PER_MIN;
+
+ if (negative)
+ offset_tmp= -offset_tmp;
+
+ /*
+ Check if offset is in range prescribed by standard
+ (from -12:59 to 13:00).
+ */
+
+ if (number_tmp > 59 || offset_tmp < -13 * SECS_PER_HOUR + 1 ||
+ offset_tmp > 13 * SECS_PER_HOUR)
+ return 1;
+
+ *offset= offset_tmp;
+
+ return 0;
+}
+
+
+/*
+ Get Time_zone object for specified time zone.
+
+ SYNOPSIS
+ my_tz_find()
+ thd - current thread
+ name - time zone specification
+
+ DESCRIPTION
+ This function checks if name is one of time zones described in db,
+ predefined SYSTEM time zone or valid time zone specification as
+ offset from UTC (In last case it will create proper Time_zone_offset
+ object if there were not any.). If name is ok it returns corresponding
+ Time_zone object.
+
+ Clients of this function are not responsible for releasing resources
+ occupied by returned Time_zone object so they can just forget pointers
+ to Time_zone object if they are not needed longer.
+
+ Other important property of this function: if some Time_zone found once
+ it will be for sure found later, so this function can also be used for
+ checking if proper Time_zone object exists (and if there will be error
+ it will be reported during first call).
+
+ If name pointer is 0 then this function returns 0 (this allows to pass 0
+ values as parameter without additional external check and this property
+ is used by @@time_zone variable handling code).
+
+ It will perform lookup in system tables (mysql.time_zone*) if needed.
+
+ RETURN VALUE
+ Pointer to corresponding Time_zone object. 0 - in case of bad time zone
+ specification or other error.
+
+*/
+Time_zone *
+my_tz_find(THD *thd, const String * name)
+{
+ TZ_NAMES_ENTRY *tmp_tzname;
+ Time_zone *result_tz= 0;
+ long offset;
+
+ DBUG_ENTER("my_tz_find");
+ DBUG_PRINT("enter", ("time zone name='%s'",
+ name ? ((String *)name)->c_ptr() : "NULL"));
+
+ if (!name)
+ DBUG_RETURN(0);
+
+ VOID(pthread_mutex_lock(&tz_LOCK));
+
+ if (!str_to_offset(name->ptr(), name->length(), &offset))
+ {
+
+ if (!(result_tz= (Time_zone_offset *)hash_search(&offset_tzs,
+ (const byte *)&offset,
+ sizeof(long))))
+ {
+ DBUG_PRINT("info", ("Creating new Time_zone_offset object"));
+
+ if (!(result_tz= new (&tz_storage) Time_zone_offset(offset)) ||
+ my_hash_insert(&offset_tzs, (const byte *) result_tz))
+ {
+ sql_print_error("Fatal error: Out of memory "
+ "while setting new time zone");
+ result_tz= 0;
+ }
+ }
+ } else {
+ if ((tmp_tzname= (TZ_NAMES_ENTRY *)hash_search(&tz_names,
+ (const byte *)name->ptr(),
+ name->length())))
+ result_tz= tmp_tzname->tz;
+ else
+ result_tz= tz_load_from_db(thd, name);
+ }
+
+ VOID(pthread_mutex_unlock(&tz_LOCK));
+
+ DBUG_RETURN(result_tz);
+}
+
+#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
+
+
+#ifdef TZINFO2SQL
+/*
+ This code belongs to mysql_tzinfo_to_sql converter command line utility.
+ This utility should be used by db admin for populating mysql.time_zone
+ tables.
+*/
+
+
+/*
+ Print info about time zone described by TIME_ZONE_INFO struct as
+ SQL statements populating mysql.time_zone* tables.
+
+ SYNOPSIS
+ print_tz_as_sql()
+ tz_name - name of time zone
+ sp - structure describing time zone
+*/
+void
+print_tz_as_sql(const char* tz_name, const TIME_ZONE_INFO *sp)
+{
+ uint i;
+
+ /* Here we assume that all time zones have same leap correction tables */
+ printf("INSERT INTO time_zone (Use_leap_seconds) VALUES ('%s');\n",
+ sp->leapcnt ? "Y" : "N");
+ printf("SET @time_zone_id= LAST_INSERT_ID();\n");
+ printf("INSERT INTO time_zone_name (Name, Time_zone_id) VALUES \
+('%s', @time_zone_id);\n", tz_name);
+
+ if (sp->timecnt)
+ {
+ printf("INSERT INTO time_zone_transition \
+(Time_zone_id, Transition_time, Transition_type_id) VALUES\n");
+ for (i= 0; i < sp->timecnt; i++)
+ printf("%s(@time_zone_id, %ld, %u)\n", (i == 0 ? " " : ","), sp->ats[i],
+ (uint)sp->types[i]);
+ printf(";\n");
+ }
+
+ printf("INSERT INTO time_zone_transition_type \
+(Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES\n");
+
+ for (i= 0; i < sp->typecnt; i++)
+ printf("%s(@time_zone_id, %u, %ld, %d, '%s')\n", (i == 0 ? " " : ","), i,
+ sp->ttis[i].tt_gmtoff, sp->ttis[i].tt_isdst,
+ sp->chars + sp->ttis[i].tt_abbrind);
+ printf(";\n");
+}
+
+
+/*
+ Print info about leap seconds in time zone as SQL statements
+ populating mysql.time_zone_leap_second table.
+
+ SYNOPSIS
+ print_tz_leaps_as_sql()
+ sp - structure describing time zone
+*/
+void
+print_tz_leaps_as_sql(const TIME_ZONE_INFO *sp)
+{
+ uint i;
+
+ /*
+ We are assuming that there are only one list of leap seconds
+ For all timezones.
+ */
+ printf("TRUNCATE TABLE time_zone_leap_second;\n");
+
+ if (sp->leapcnt)
+ {
+ printf("INSERT INTO time_zone_leap_second \
+(Transition_time, Correction) VALUES\n");
+ for (i= 0; i < sp->leapcnt; i++)
+ printf("%s(%ld, %ld)\n", (i == 0 ? " " : ","),
+ sp->lsis[i].ls_trans, sp->lsis[i].ls_corr);
+ printf(";\n");
+ }
+
+ printf("ALTER TABLE time_zone_leap_second ORDER BY Transition_time;\n");
+}
+
+
+/*
+ Some variables used as temporary or as parameters
+ in recursive scan_tz_dir() code.
+*/
+TIME_ZONE_INFO tz_info;
+MEM_ROOT tz_storage;
+char fullname[FN_REFLEN + 1];
+char *root_name_end;
+
+
+/*
+ Recursively scan zoneinfo directory and print all found time zone
+ descriptions as SQL.
+
+ SYNOPSIS
+ scan_tz_dir()
+ name_end - pointer to end of path to directory to be searched.
+
+ DESCRIPTION
+ This auxiliary recursive function also uses several global
+ variables as in parameters and for storing temporary values.
+
+ fullname - path to directory that should be scanned.
+ root_name_end - pointer to place in fullname where part with
+ path to initial directory ends.
+ current_tz_id - last used time zone id
+
+ RETURN VALUE
+ 0 - Ok, 1 - Fatal error
+
+*/
+my_bool
+scan_tz_dir(char * name_end)
+{
+ MY_DIR *cur_dir;
+ char *name_end_tmp;
+ uint i;
+
+ if (!(cur_dir= my_dir(fullname, MYF(MY_WANT_STAT))))
+ return 1;
+
+ name_end= strmake(name_end, "/", FN_REFLEN - (name_end - fullname));
+
+ for (i= 0; i < cur_dir->number_off_files; i++)
+ {
+ if (cur_dir->dir_entry[i].name[0] != '.')
+ {
+ name_end_tmp= strmake(name_end, cur_dir->dir_entry[i].name,
+ FN_REFLEN - (name_end - fullname));
+
+ if (MY_S_ISDIR(cur_dir->dir_entry[i].mystat->st_mode))
+ {
+ if (scan_tz_dir(name_end_tmp))
+ {
+ my_dirend(cur_dir);
+ return 1;
+ }
+ }
+ else if (MY_S_ISREG(cur_dir->dir_entry[i].mystat->st_mode))
+ {
+ init_alloc_root(&tz_storage, 32768, 0);
+ if (!tz_load(fullname, &tz_info, &tz_storage))
+ print_tz_as_sql(root_name_end + 1, &tz_info);
+ else
+ fprintf(stderr,
+ "Warning: Unable to load '%s' as time zone. Skipping it.\n",
+ fullname);
+ free_root(&tz_storage, MYF(0));
+ }
+ else
+ fprintf(stderr, "Warning: '%s' is not regular file or directory\n",
+ fullname);
+ }
+ }
+
+ my_dirend(cur_dir);
+
+ return 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ MY_INIT(argv[0]);
+
+ if (argc != 2 && argc != 3)
+ {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s timezonedir\n", argv[0]);
+ fprintf(stderr, " %s timezonefile timezonename\n", argv[0]);
+ fprintf(stderr, " %s --leap timezonefile\n", argv[0]);
+ return 1;
+ }
+
+ if (argc == 2)
+ {
+ root_name_end= strmake(fullname, argv[1], FN_REFLEN);
+
+ printf("TRUNCATE TABLE time_zone;\n");
+ printf("TRUNCATE TABLE time_zone_name;\n");
+ printf("TRUNCATE TABLE time_zone_transition;\n");
+ printf("TRUNCATE TABLE time_zone_transition_type;\n");
+
+ if (scan_tz_dir(root_name_end))
+ {
+ fprintf(stderr, "There were fatal errors during processing "
+ "of zoneinfo directory\n");
+ return 1;
+ }
+
+ printf("ALTER TABLE time_zone_transition "
+ "ORDER BY Time_zone_id, Transition_time;\n");
+ printf("ALTER TABLE time_zone_transition_type "
+ "ORDER BY Time_zone_id, Transition_type_id;\n");
+ }
+ else
+ {
+ init_alloc_root(&tz_storage, 32768, 0);
+
+ if (strcmp(argv[1], "--leap") == 0)
+ {
+ if (tz_load(argv[2], &tz_info, &tz_storage))
+ {
+ fprintf(stderr, "Problems with zoneinfo file '%s'\n", argv[2]);
+ return 1;
+ }
+ print_tz_leaps_as_sql(&tz_info);
+ }
+ else
+ {
+ if (tz_load(argv[1], &tz_info, &tz_storage))
+ {
+ fprintf(stderr, "Problems with zoneinfo file '%s'\n", argv[2]);
+ return 1;
+ }
+ print_tz_as_sql(argv[2], &tz_info);
+ }
+
+ free_root(&tz_storage, MYF(0));
+ }
+
+ return 0;
+}
+
+#endif /* defined(TZINFO2SQL) */
+
+
+#ifdef TESTTIME
+
+/*
+ Some simple brute-force test wich allowed to catch a pair of bugs.
+ Also can provide interesting facts about system's time zone support
+ implementation.
+*/
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#ifndef TYPE_BIT
+#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
+#endif
+
+#ifndef TYPE_SIGNED
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+#endif
+
+my_bool
+is_equal_TIME_tm(const TIME* time_arg, const struct tm * tm_arg)
+{
+ return (time_arg->year == (uint)tm_arg->tm_year+TM_YEAR_BASE) &&
+ (time_arg->month == (uint)tm_arg->tm_mon+1) &&
+ (time_arg->day == (uint)tm_arg->tm_mday) &&
+ (time_arg->hour == (uint)tm_arg->tm_hour) &&
+ (time_arg->minute == (uint)tm_arg->tm_min) &&
+ (time_arg->second == (uint)tm_arg->tm_sec) &&
+ time_arg->second_part == 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ my_bool localtime_negative;
+ TIME_ZONE_INFO tz_info;
+ struct tm tmp;
+ TIME time_tmp;
+ time_t t, t1, t2;
+ char fullname[FN_REFLEN+1];
+ char *str_end;
+ long not_used;
+ bool not_used_2;
+ MEM_ROOT tz_storage;
+
+ MY_INIT(argv[0]);
+
+ init_alloc_root(&tz_storage, 32768, 0);
+
+ /* let us set some well known timezone */
+ setenv("TZ", "MET", 1);
+ tzset();
+
+ /* Some initial time zone related system info */
+ printf("time_t: %s %u bit\n", TYPE_SIGNED(time_t) ? "signed" : "unsigned",
+ (uint)TYPE_BIT(time_t));
+ if (TYPE_SIGNED(time_t))
+ {
+ t= -100;
+ localtime_negative= test(localtime_r(&t, &tmp) != 0);
+ printf("localtime_r %s negative params \
+ (time_t=%d is %d-%d-%d %d:%d:%d)\n",
+ (localtime_negative ? "supports" : "doesn't support"), (int)t,
+ TM_YEAR_BASE + tmp.tm_year, tmp.tm_mon + 1, tmp.tm_mday,
+ tmp.tm_hour, tmp.tm_min, tmp.tm_sec);
+
+ printf("mktime %s negative results (%d)\n",
+ (t == mktime(&tmp) ? "doesn't support" : "supports"),
+ (int)mktime(&tmp));
+ }
+
+ tmp.tm_year= 103; tmp.tm_mon= 2; tmp.tm_mday= 30;
+ tmp.tm_hour= 2; tmp.tm_min= 30; tmp.tm_sec= 0; tmp.tm_isdst= -1;
+ t= mktime(&tmp);
+ printf("mktime returns %s for spring time gap (%d)\n",
+ (t != (time_t)-1 ? "something" : "error"), (int)t);
+
+ tmp.tm_year= 103; tmp.tm_mon= 8; tmp.tm_mday= 1;
+ tmp.tm_hour= 0; tmp.tm_min= 0; tmp.tm_sec= 0; tmp.tm_isdst= 0;
+ t= mktime(&tmp);
+ printf("mktime returns %s for non existing date (%d)\n",
+ (t != (time_t)-1 ? "something" : "error"), (int)t);
+
+ tmp.tm_year= 103; tmp.tm_mon= 8; tmp.tm_mday= 1;
+ tmp.tm_hour= 25; tmp.tm_min=0; tmp.tm_sec=0; tmp.tm_isdst=1;
+ t= mktime(&tmp);
+ printf("mktime %s unnormalized input (%d)\n",
+ (t != (time_t)-1 ? "handles" : "doesn't handle"), (int)t);
+
+ tmp.tm_year= 103; tmp.tm_mon= 9; tmp.tm_mday= 26;
+ tmp.tm_hour= 0; tmp.tm_min= 30; tmp.tm_sec= 0; tmp.tm_isdst= 1;
+ mktime(&tmp);
+ tmp.tm_hour= 2; tmp.tm_isdst= -1;
+ t= mktime(&tmp);
+ tmp.tm_hour= 4; tmp.tm_isdst= 0;
+ mktime(&tmp);
+ tmp.tm_hour= 2; tmp.tm_isdst= -1;
+ t1= mktime(&tmp);
+ printf("mktime is %s (%d %d)\n",
+ (t == t1 ? "determenistic" : "is non-determenistic"),
+ (int)t, (int)t1);
+
+ /* Let us load time zone description */
+ str_end= strmake(fullname, TZDIR, FN_REFLEN);
+ strmake(str_end, "/MET", FN_REFLEN - (str_end - fullname));
+
+ if (tz_load(fullname, &tz_info, &tz_storage))
+ {
+ printf("Unable to load time zone info from '%s'\n", fullname);
+ free_root(&tz_storage, MYF(0));
+ return 1;
+ }
+
+ printf("Testing our implementation\n");
+
+ if (TYPE_SIGNED(time_t) && localtime_negative)
+ {
+ for (t= -40000; t < 20000; t++)
+ {
+ localtime_r(&t, &tmp);
+ gmt_sec_to_TIME(&time_tmp, (my_time_t)t, &tz_info);
+ if (!is_equal_TIME_tm(&time_tmp, &tmp))
+ {
+ printf("Problem with negative time_t = %d\n", (int)t);
+ free_root(&tz_storage, MYF(0));
+ return 1;
+ }
+ }
+ printf("gmt_sec_to_TIME = localtime for time_t in [-40000,20000) range\n");
+ }
+
+ for (t= 1000000000; t < 1100000000; t+= 13)
+ {
+ localtime_r(&t,&tmp);
+ gmt_sec_to_TIME(&time_tmp, (my_time_t)t, &tz_info);
+
+ if (!is_equal_TIME_tm(&time_tmp, &tmp))
+ {
+ printf("Problem with time_t = %d\n", (int)t);
+ free_root(&tz_storage, MYF(0));
+ return 1;
+ }
+ }
+ printf("gmt_sec_to_TIME = localtime for time_t in [1000000000,1100000000) range\n");
+
+ init_time();
+
+ /*
+ Be careful here! my_system_gmt_sec doesn't fully handle unnormalized
+ dates.
+ */
+ for (time_tmp.year= 1980; time_tmp.year < 2010; time_tmp.year++)
+ for (time_tmp.month= 1; time_tmp.month < 13; time_tmp.month++)
+ for (time_tmp.day= 1;
+ time_tmp.day < mon_lengths[isleap(time_tmp.year)][time_tmp.month-1];
+ time_tmp.day++)
+ for (time_tmp.hour= 0; time_tmp.hour < 24; time_tmp.hour++)
+ for (time_tmp.minute= 0; time_tmp.minute < 60; time_tmp.minute+= 5)
+ for (time_tmp.second=0; time_tmp.second<60; time_tmp.second+=25)
+ {
+ t= (time_t)my_system_gmt_sec(&time_tmp, &not_used, &not_used_2);
+ t1= (time_t)TIME_to_gmt_sec(&time_tmp, &tz_info, &not_used_2);
+ if (t != t1)
+ {
+ /*
+ We need special handling during autumn since my_system_gmt_sec
+ prefers greater time_t values (in MET) for ambiguity.
+ And BTW that is a bug which should be fixed !!!
+ */
+ tmp.tm_year= time_tmp.year - TM_YEAR_BASE;
+ tmp.tm_mon= time_tmp.month - 1;
+ tmp.tm_mday= time_tmp.day;
+ tmp.tm_hour= time_tmp.hour;
+ tmp.tm_min= time_tmp.minute;
+ tmp.tm_sec= time_tmp.second;
+ tmp.tm_isdst= 1;
+
+ t2= mktime(&tmp);
+
+ if (t1 == t2)
+ continue;
+
+ printf("Problem: %u/%u/%u %u:%u:%u with times t=%d, t1=%d\n",
+ time_tmp.year, time_tmp.month, time_tmp.day,
+ time_tmp.hour, time_tmp.minute, time_tmp.second,
+ (int)t,(int)t1);
+
+ free_root(&tz_storage, MYF(0));
+ return 1;
+ }
+ }
+
+ printf("TIME_to_gmt_sec = my_system_gmt_sec for test range\n");
+
+ free_root(&tz_storage, MYF(0));
+ return 0;
+}
+
+#endif /* defined(TESTTIME) */
diff --git a/sql/tztime.h b/sql/tztime.h
new file mode 100644
index 00000000000..334b14f4fc4
--- /dev/null
+++ b/sql/tztime.h
@@ -0,0 +1,79 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#ifdef __GNUC__
+#pragma interface /* gcc class interface */
+#endif
+
+/*
+ Portable time_t replacement.
+ Should be signed and hold seconds for 1902-2038 range.
+*/
+typedef long my_time_t;
+#define MY_TIME_T_MAX LONG_MAX
+#define MY_TIME_T_MIN LONG_MIN
+
+#if !defined(TESTTIME) && !defined(TZINFO2SQL)
+/*
+ This class represents abstract time zone and provides
+ basic interface for TIME <-> my_time_t conversion.
+ Actual time zones which are specified by DB, or via offset
+ or use system functions are its descendants.
+*/
+class Time_zone: public Sql_alloc
+{
+public:
+ /*
+ Converts local time in broken down TIME representation to
+ my_time_t (UTC seconds since Epoch) represenation.
+ Returns 0 in case of error. Sets in_dst_time_gap to true if date provided
+ falls into spring time-gap (or lefts it untouched otherwise).
+ */
+ virtual my_time_t TIME_to_gmt_sec(const TIME *t,
+ bool *in_dst_time_gap) const = 0;
+ /*
+ Converts time in my_time_t representation to local time in
+ broken down TIME representation.
+ */
+ virtual void gmt_sec_to_TIME(TIME *tmp, my_time_t t) const = 0;
+ /*
+ Because of constness of String returned by get_name() time zone name
+ have to be already zeroended to be able to use String::ptr() instead
+ of c_ptr().
+ */
+ virtual const String * get_name() const = 0;
+
+ /*
+ We need this only for surpressing warnings, objects of this type are
+ allocated on MEM_ROOT and should not require destruction.
+ */
+ virtual ~Time_zone() {};
+};
+
+extern Time_zone * my_tz_UTC;
+extern Time_zone * my_tz_SYSTEM;
+extern Time_zone * my_tz_find(THD *thd, const String *name);
+extern my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap);
+extern void my_tz_free();
+
+/*
+ Maximum length of time zone name that we support
+ (Time zone name is char(64) in db)
+*/
+#define MAX_TIME_ZONE_NAME_LENGTH 72
+
+#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
diff --git a/sql/unireg.cc b/sql/unireg.cc
index bab021aed59..b5f6c3546a4 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -29,7 +29,6 @@
#include <m_ctype.h>
#define FCOMP 17 /* Bytes for a packed field */
-#define FCOMP 17 /* Bytes for a packed field */
static uchar * pack_screens(List<create_field> &create_fields,
uint *info_length, uint *screens, bool small_file);
@@ -633,6 +632,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
DBUG_RETURN(1);
}
+ table.in_use= current_thd;
table.db_low_byte_first= handler->low_byte_first();
table.blob_ptr_size=portable_sizeof_char_ptr;
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 2071759ddae..ff53f61c053 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -251,11 +251,12 @@ static int my_strnncoll_big5_internal(const uchar **a_res,
static int my_strnncoll_big5(CHARSET_INFO *cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool b_is_prefix)
{
uint length= min(a_length, b_length);
int res= my_strnncoll_big5_internal(&a, &b, length);
- return res ? res : (int) (a_length - b_length);
+ return res ? res : (int)((b_is_prefix ? length : a_length) - b_length);
}
@@ -402,7 +403,7 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == escape && ptr+1 != end)
{
- ptr++; /* Skipp escape */
+ ptr++; /* Skip escape */
*min_str++= *max_str++ = *ptr;
continue;
}
@@ -6269,6 +6270,7 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)),
static MY_COLLATION_HANDLER my_collation_big5_chinese_ci_handler =
{
+ NULL, /* init */
my_strnncoll_big5,
my_strnncollsp_big5,
my_strnxfrm_big5,
@@ -6281,6 +6283,7 @@ static MY_COLLATION_HANDLER my_collation_big5_chinese_ci_handler =
static MY_CHARSET_HANDLER my_charset_big5_handler=
{
+ NULL, /* init */
ismbchar_big5,
mbcharlen_big5,
my_numchars_mb,
@@ -6297,7 +6300,6 @@ static MY_CHARSET_HANDLER my_charset_big5_handler=
my_long10_to_str_8bit,
my_longlong10_to_str_8bit,
my_fill_8bit,
-
my_strntol_8bit,
my_strntoul_8bit,
my_strntoll_8bit,
@@ -6313,20 +6315,22 @@ CHARSET_INFO my_charset_big5_chinese_ci=
"big5", /* cs name */
"big5_chinese_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_big5,
to_lower_big5,
to_upper_big5,
sort_order_big5,
+ NULL, /* contractions */
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_big5_handler,
&my_collation_big5_chinese_ci_handler
};
@@ -6339,20 +6343,22 @@ CHARSET_INFO my_charset_big5_bin=
"big5", /* cs name */
"big5_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_big5,
to_lower_big5,
to_upper_big5,
sort_order_big5,
+ NULL, /* contractions */
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_big5_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 7cac8c7c337..cc83471f264 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -91,10 +91,20 @@ static uchar bin_char_array[] =
static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool t_is_prefix)
{
- int cmp= memcmp(s,t,min(slen,tlen));
- return cmp ? cmp : (int) (slen - tlen);
+ uint len=min(slen,tlen);
+ int cmp= memcmp(s,t,len);
+ return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
+}
+
+
+static int my_strnncollsp_binary(CHARSET_INFO * cs __attribute__((unused)),
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ return my_strnncoll_binary(cs,s,slen,t,tlen,0);
}
@@ -333,8 +343,9 @@ skip:
MY_COLLATION_HANDLER my_collation_8bit_bin_handler =
{
+ NULL, /* init */
my_strnncoll_binary,
- my_strnncoll_binary,
+ my_strnncollsp_binary,
my_strnxfrm_bin,
my_like_range_simple,
my_wildcmp_bin,
@@ -346,6 +357,7 @@ MY_COLLATION_HANDLER my_collation_8bit_bin_handler =
static MY_CHARSET_HANDLER my_charset_handler=
{
+ NULL, /* init */
NULL, /* ismbchar */
my_mbcharlen_8bit, /* mbcharlen */
my_numchars_8bit,
@@ -378,15 +390,17 @@ CHARSET_INFO my_charset_bin =
"binary", /* cs name */
"binary", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_bin, /* ctype */
bin_char_array, /* to_lower */
bin_char_array, /* to_upper */
bin_char_array, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index 2eb2fac46e9..6f9e9f74d35 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -242,12 +242,16 @@ while (1) \
static int my_strnncoll_czech(CHARSET_INFO *cs __attribute__((unused)),
const uchar * s1, uint len1,
- const uchar * s2, uint len2)
+ const uchar * s2, uint len2,
+ my_bool s2_is_prefix)
{
int v1, v2;
const uchar * p1, * p2, * store1, * store2;
int pass1 = 0, pass2 = 0;
+ if (s2_is_prefix && len1 > len2)
+ len1=len2;
+
p1 = s1; p2 = s2;
store1 = s1; store2 = s2;
@@ -276,7 +280,7 @@ int my_strnncollsp_czech(CHARSET_INFO * cs,
{
for ( ; slen && s[slen-1] == ' ' ; slen--);
for ( ; tlen && t[tlen-1] == ' ' ; tlen--);
- return my_strnncoll_czech(cs,s,slen,t,tlen);
+ return my_strnncoll_czech(cs,s,slen,t,tlen,0);
}
@@ -572,6 +576,7 @@ static MY_UNI_IDX idx_uni_8859_2[]={
static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler =
{
+ NULL, /* init */
my_strnncoll_czech,
my_strnncollsp_czech,
my_strnxfrm_czech,
@@ -589,14 +594,17 @@ CHARSET_INFO my_charset_latin2_czech_ci =
"latin2", /* cs name */
"latin2_czech_cs", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_czech,
to_lower_czech,
to_upper_czech,
sort_order_czech,
+ NULL, /* contractions */
NULL, /* sort_order_big*/
tab_8859_2_uni, /* tab_to_uni */
idx_uni_8859_2, /* tab_from_uni */
- "","",
+ NULL, /* state_map */
+ NULL, /* ident_map */
4, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index 8f955c15a73..fd8659a181c 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -8637,6 +8637,7 @@ my_mb_wc_euc_kr(CHARSET_INFO *cs __attribute__((unused)),
static MY_COLLATION_HANDLER my_collation_ci_handler =
{
+ NULL, /* init */
my_strnncoll_simple, /* strnncoll */
my_strnncollsp_simple,
my_strnxfrm_simple, /* strnxfrm */
@@ -8649,6 +8650,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
static MY_CHARSET_HANDLER my_charset_handler=
{
+ NULL, /* init */
ismbchar_euc_kr,
mbcharlen_euc_kr,
my_numchars_mb,
@@ -8681,20 +8683,22 @@ CHARSET_INFO my_charset_euckr_korean_ci=
"euckr", /* cs name */
"euckr_korean_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_euc_kr,
to_lower_euc_kr,
to_upper_euc_kr,
sort_order_euc_kr,
+ NULL, /* contractions */
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -8707,20 +8711,22 @@ CHARSET_INFO my_charset_euckr_bin=
"euckr", /* cs name */
"euckr_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_euc_kr,
to_lower_euc_kr,
to_upper_euc_kr,
sort_order_euc_kr,
+ NULL, /* contractions */
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c
index 51a9531fbf5..3672dcd0b33 100644
--- a/strings/ctype-extra.c
+++ b/strings/ctype-extra.c
@@ -24,20 +24,23 @@ CHARSET_INFO compiled_charsets[] = {
NullS, /* cs name */
NullS, /* name */
NullS, /* comment */
- NULL,
- NULL,
- NULL,
- NULL,
+ NULL, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- "","",
- 0,
- 0,
- 0,
- 0,
- 0,
- NULL,
- NULL
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 0, /* strxfrm_mul */
+ 0, /* mbminlen */
+ 0, /* mbmaxlen */
+ 0, /* min_sort_ord */
+ 0, /* max_sort_ord */
+ NULL, /* cset handler */
+ NULL /* coll handler */
}
};
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index b76511fc4f3..b9f61256717 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -5688,6 +5688,7 @@ my_mb_wc_gb2312(CHARSET_INFO *cs __attribute__((unused)),
static MY_COLLATION_HANDLER my_collation_ci_handler =
{
+ NULL, /* init */
my_strnncoll_simple, /* strnncoll */
my_strnncollsp_simple,
my_strnxfrm_simple, /* strnxfrm */
@@ -5700,6 +5701,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
static MY_CHARSET_HANDLER my_charset_handler=
{
+ NULL, /* init */
ismbchar_gb2312,
mbcharlen_gb2312,
my_numchars_mb,
@@ -5732,20 +5734,22 @@ CHARSET_INFO my_charset_gb2312_chinese_ci=
"gb2312", /* cs name */
"gb2312_chinese_ci",/* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_gb2312,
to_lower_gb2312,
to_upper_gb2312,
sort_order_gb2312,
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -5757,20 +5761,22 @@ CHARSET_INFO my_charset_gb2312_bin=
"gb2312", /* cs name */
"gb2312_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_gb2312,
to_lower_gb2312,
to_upper_gb2312,
sort_order_gb2312,
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index cc0f226d01c..2ef75e27d9a 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -2614,11 +2614,12 @@ int my_strnncoll_gbk_internal(const uchar **a_res, const uchar **b_res,
int my_strnncoll_gbk(CHARSET_INFO *cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool b_is_prefix)
{
uint length= min(a_length, b_length);
int res= my_strnncoll_gbk_internal(&a, &b, length);
- return res ? res : (int) (a_length - b_length);
+ return res ? res : (int) ((b_is_prefix ? length : a_length) - b_length);
}
@@ -2715,7 +2716,7 @@ static my_bool my_like_range_gbk(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == escape && ptr+1 != end)
{
- ptr++; /* Skipp escape */
+ ptr++; /* Skip escape */
*min_str++= *max_str++ = *ptr;
continue;
}
@@ -9918,6 +9919,7 @@ my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)),
static MY_COLLATION_HANDLER my_collation_ci_handler =
{
+ NULL, /* init */
my_strnncoll_gbk,
my_strnncollsp_gbk,
my_strnxfrm_gbk,
@@ -9930,6 +9932,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
static MY_CHARSET_HANDLER my_charset_handler=
{
+ NULL, /* init */
ismbchar_gbk,
mbcharlen_gbk,
my_numchars_mb,
@@ -9962,20 +9965,22 @@ CHARSET_INFO my_charset_gbk_chinese_ci=
"gbk", /* cs name */
"gbk_chinese_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_gbk,
to_lower_gbk,
to_upper_gbk,
sort_order_gbk,
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -9987,20 +9992,22 @@ CHARSET_INFO my_charset_gbk_bin=
"gbk", /* cs name */
"gbk_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_gbk,
to_lower_gbk,
to_upper_gbk,
sort_order_gbk,
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index 0b439964c7c..652794fa84d 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -380,6 +380,7 @@ int my_wc_mb_latin1(CHARSET_INFO *cs __attribute__((unused)),
static MY_CHARSET_HANDLER my_charset_handler=
{
+ NULL, /* init */
NULL,
my_mbcharlen_8bit,
my_numchars_8bit,
@@ -412,19 +413,22 @@ CHARSET_INFO my_charset_latin1=
"latin1", /* cs name */
"latin1_swedish_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_latin1,
to_lower_latin1,
to_upper_latin1,
sort_order_latin1,
+ NULL, /* contractions */
NULL, /* sort_order_big*/
cs_to_uni, /* tab_to_uni */
NULL, /* tab_from_uni */
- "","",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_8bit_simple_ci_handler
};
@@ -525,7 +529,8 @@ uchar combo2map[]={
static int my_strnncoll_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool b_is_prefix)
{
const uchar *a_end= a + a_length;
const uchar *b_end= b + b_length;
@@ -558,7 +563,7 @@ static int my_strnncoll_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
A simple test of string lengths won't work -- we test to see
which string ran out first
*/
- return ((a < a_end || a_extend) ? 1 :
+ return ((a < a_end || a_extend) ? (b_is_prefix ? 0 : 1) :
(b < b_end || b_extend) ? -1 : 0);
}
@@ -672,6 +677,7 @@ void my_hash_sort_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
static MY_COLLATION_HANDLER my_collation_german2_ci_handler=
{
+ NULL, /* init */
my_strnncoll_latin1_de,
my_strnncollsp_latin1_de,
my_strnxfrm_latin1_de,
@@ -690,19 +696,22 @@ CHARSET_INFO my_charset_latin1_german2_ci=
"latin1", /* cs name */
"latin1_german2_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_latin1,
to_lower_latin1,
to_upper_latin1,
sort_order_latin1_de,
+ NULL, /* contractions */
NULL, /* sort_order_big*/
cs_to_uni, /* tab_to_uni */
NULL, /* tab_from_uni */
- "","",
+ NULL, /* state_map */
+ NULL, /* ident_map */
2, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 247, /* max_sort_char */
&my_charset_handler,
&my_collation_german2_ci_handler
};
@@ -715,20 +724,22 @@ CHARSET_INFO my_charset_latin1_bin=
"latin1", /* cs name */
"latin1_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_latin1,
to_lower_latin1,
to_upper_latin1,
sort_order_latin1_de,
+ NULL, /* contractions */
NULL, /* sort_order_big*/
cs_to_uni, /* tab_to_uni */
NULL, /* tab_from_uni */
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_8bit_bin_handler
};
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 9b02cd3b3da..7b0dadcfa19 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -322,7 +322,7 @@ uint my_instr_mb(CHARSET_INFO *cs,
int mblen;
if (!cs->coll->strnncoll(cs, (unsigned char*) b, s_length,
- (unsigned char*) s, s_length))
+ (unsigned char*) s, s_length, 0))
{
if (nmatch)
{
@@ -352,10 +352,19 @@ uint my_instr_mb(CHARSET_INFO *cs,
static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool t_is_prefix)
{
- int cmp= memcmp(s,t,min(slen,tlen));
- return cmp ? cmp : (int) (slen - tlen);
+ uint len=min(slen,tlen);
+ int cmp= memcmp(s,t,len);
+ return cmp ? cmp : (int) ((t_is_prefix ? len : slen) - tlen);
+}
+
+static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ return my_strnncoll_mb_bin(cs,s,slen,t,tlen,0);
}
@@ -512,8 +521,9 @@ static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
MY_COLLATION_HANDLER my_collation_mb_bin_handler =
{
+ NULL, /* init */
my_strnncoll_mb_bin,
- my_strnncoll_mb_bin,
+ my_strnncollsp_mb_bin,
my_strnxfrm_mb_bin,
my_like_range_simple,
my_wildcmp_mb_bin,
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index ba1fc1c424a..8e295b9e13e 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -20,7 +20,6 @@
#include <errno.h>
#include "stdarg.h"
-#include "assert.h"
int my_strnxfrm_simple(CHARSET_INFO * cs,
@@ -47,16 +46,19 @@ int my_strnxfrm_simple(CHARSET_INFO * cs,
}
int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool t_is_prefix)
{
int len = ( slen > tlen ) ? tlen : slen;
uchar *map= cs->sort_order;
+ if (t_is_prefix && slen > tlen)
+ slen=tlen;
while (len--)
{
if (map[*s++] != map[*t++])
return ((int) map[s[-1]] - (int) map[t[-1]]);
}
- return (int) (slen-tlen);
+ return (int) (slen - tlen);
}
@@ -1143,8 +1145,133 @@ skip:
}
+typedef struct
+{
+ int nchars;
+ MY_UNI_IDX uidx;
+} uni_idx;
+
+#define PLANE_SIZE 0x100
+#define PLANE_NUM 0x100
+#define PLANE_NUMBER(x) (((x)>>8) % PLANE_NUM)
+
+static int pcmp(const void * f, const void * s)
+{
+ const uni_idx *F= (const uni_idx*) f;
+ const uni_idx *S= (const uni_idx*) s;
+ int res;
+
+ if (!(res=((S->nchars)-(F->nchars))))
+ res=((F->uidx.from)-(S->uidx.to));
+ return res;
+}
+
+static my_bool create_fromuni(CHARSET_INFO *cs, void *(*alloc)(uint))
+{
+ uni_idx idx[PLANE_NUM];
+ int i,n;
+
+ /* Clear plane statistics */
+ bzero(idx,sizeof(idx));
+
+ /* Count number of characters in each plane */
+ for (i=0; i< 0x100; i++)
+ {
+ uint16 wc=cs->tab_to_uni[i];
+ int pl= PLANE_NUMBER(wc);
+
+ if (wc || !i)
+ {
+ if (!idx[pl].nchars)
+ {
+ idx[pl].uidx.from=wc;
+ idx[pl].uidx.to=wc;
+ }else
+ {
+ idx[pl].uidx.from=wc<idx[pl].uidx.from?wc:idx[pl].uidx.from;
+ idx[pl].uidx.to=wc>idx[pl].uidx.to?wc:idx[pl].uidx.to;
+ }
+ idx[pl].nchars++;
+ }
+ }
+
+ /* Sort planes in descending order */
+ qsort(&idx,PLANE_NUM,sizeof(uni_idx),&pcmp);
+
+ for (i=0; i < PLANE_NUM; i++)
+ {
+ int ch,numchars;
+
+ /* Skip empty plane */
+ if (!idx[i].nchars)
+ break;
+
+ numchars=idx[i].uidx.to-idx[i].uidx.from+1;
+ if (!(idx[i].uidx.tab=(uchar*) alloc(numchars * sizeof(*idx[i].uidx.tab))))
+ return TRUE;
+
+ bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab));
+
+ for (ch=1; ch < PLANE_SIZE; ch++)
+ {
+ uint16 wc=cs->tab_to_uni[ch];
+ if (wc >= idx[i].uidx.from && wc <= idx[i].uidx.to && wc)
+ {
+ int ofs= wc - idx[i].uidx.from;
+ idx[i].uidx.tab[ofs]= ch;
+ }
+ }
+ }
+
+ /* Allocate and fill reverse table for each plane */
+ n=i;
+ if (!(cs->tab_from_uni= (MY_UNI_IDX*) alloc(sizeof(MY_UNI_IDX)*(n+1))))
+ return TRUE;
+
+ for (i=0; i< n; i++)
+ cs->tab_from_uni[i]= idx[i].uidx;
+
+ /* Set end-of-list marker */
+ bzero(&cs->tab_from_uni[i],sizeof(MY_UNI_IDX));
+ return FALSE;
+}
+
+static my_bool my_cset_init_8bit(CHARSET_INFO *cs, void *(*alloc)(uint))
+{
+ return create_fromuni(cs, alloc);
+}
+
+static void set_max_sort_char(CHARSET_INFO *cs)
+{
+ uchar max_char;
+ uint i;
+
+ if (!cs->sort_order)
+ return;
+
+ max_char=cs->sort_order[(uchar) cs->max_sort_char];
+ for (i= 0; i < 256; i++)
+ {
+ if ((uchar) cs->sort_order[i] > max_char)
+ {
+ max_char=(uchar) cs->sort_order[i];
+ cs->max_sort_char= i;
+ }
+ }
+}
+
+static my_bool my_coll_init_simple(CHARSET_INFO *cs,
+ void *(*alloc)(uint) __attribute__((unused)))
+{
+ set_max_sort_char(cs);
+ return FALSE;
+}
+
+
+
MY_CHARSET_HANDLER my_charset_8bit_handler=
{
+ my_cset_init_8bit,
NULL, /* ismbchar */
my_mbcharlen_8bit, /* mbcharlen */
my_numchars_8bit,
@@ -1171,6 +1298,7 @@ MY_CHARSET_HANDLER my_charset_8bit_handler=
MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler =
{
+ my_coll_init_simple, /* init */
my_strnncoll_simple,
my_strnncollsp_simple,
my_strnxfrm_simple,
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 72666175a1f..5fd005f842e 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -232,9 +232,12 @@ static int my_strnncoll_sjis_internal(CHARSET_INFO *cs,
static int my_strnncoll_sjis(CHARSET_INFO *cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool b_is_prefix)
{
int res= my_strnncoll_sjis_internal(cs, &a, a_length, &b, b_length);
+ if (b_is_prefix && a_length > b_length)
+ a_length= b_length;
return res ? res : (int) (a_length - b_length);
}
@@ -4534,6 +4537,7 @@ my_mb_wc_sjis(CHARSET_INFO *cs __attribute__((unused)),
static MY_COLLATION_HANDLER my_collation_ci_handler =
{
+ NULL, /* init */
my_strnncoll_sjis,
my_strnncollsp_sjis,
my_strnxfrm_sjis,
@@ -4547,6 +4551,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
static MY_CHARSET_HANDLER my_charset_handler=
{
+ NULL, /* init */
ismbchar_sjis,
mbcharlen_sjis,
my_numchars_mb,
@@ -4579,20 +4584,22 @@ CHARSET_INFO my_charset_sjis_japanese_ci=
"sjis", /* cs name */
"sjis_japanese_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_sjis,
to_lower_sjis,
to_upper_sjis,
sort_order_sjis,
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -4604,20 +4611,22 @@ CHARSET_INFO my_charset_sjis_bin=
"sjis", /* cs name */
"sjis_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_sjis,
to_lower_sjis,
to_upper_sjis,
sort_order_sjis,
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 1b6b1edc8b9..c7d859a6ead 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -529,12 +529,16 @@ static uint thai2sortable(uchar *tstr, uint len)
static
int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)),
const uchar * s1, uint len1,
- const uchar * s2, uint len2)
+ const uchar * s2, uint len2,
+ my_bool s2_is_prefix)
{
uchar buf[80] ;
uchar *tc1, *tc2;
int i;
+ if (s2_is_prefix && len1 > len2)
+ len1= len2;
+
tc1= buf;
if ((len1 + len2 +2) > (int) sizeof(buf))
tc1= (uchar*) malloc(len1+len2);
@@ -671,7 +675,7 @@ my_bool my_like_range_tis620(CHARSET_INFO *cs __attribute__((unused)),
{
if (*ptr == escape && ptr+1 != end)
{
- ptr++; /* Skipp escape */
+ ptr++; /* Skip escape */
*min_str++ = *max_str++ = *ptr;
continue;
}
@@ -906,6 +910,7 @@ int my_wc_mb_tis620(CHARSET_INFO *cs __attribute__((unused)),
static MY_COLLATION_HANDLER my_collation_ci_handler =
{
+ NULL, /* init */
my_strnncoll_tis620,
my_strnncollsp_tis620,
my_strnxfrm_tis620,
@@ -918,6 +923,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
static MY_CHARSET_HANDLER my_charset_handler=
{
+ NULL, /* init */
NULL, /* ismbchar */
my_mbcharlen_8bit, /* mbcharlen */
my_numchars_8bit,
@@ -951,15 +957,17 @@ CHARSET_INFO my_charset_tis620_thai_ci=
"tis620", /* cs name */
"tis620_thai_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_tis620,
to_lower_tis620,
to_upper_tis620,
sort_order_tis620,
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
4, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
@@ -976,15 +984,17 @@ CHARSET_INFO my_charset_tis620_bin=
"tis620", /* cs name */
"tis620_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_tis620,
to_lower_tis620,
to_upper_tis620,
sort_order_tis620,
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index 81073d47554..5bb710946b1 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -19,14 +19,15 @@
UCA (Unicode Collation Algorithm) support.
Written by Alexander Barkov <bar@mysql.com>
- Currently supports only subset of the full UCA.
-
+ Currently supports only subset of the full UCA:
- Only Primary level key comparison
+ - Basic Latin letters contraction is implemented
- Variable weighting is done for Non-ignorable option
+
+ Features that are not implemented yet:
- No Normalization From D is done
+ No decomposition is done
+ No Thai/Lao orderding is done
- - No contraction is done
- No combining marks processing is done
*/
@@ -36,8 +37,6 @@
#include "m_ctype.h"
-#ifdef HAVE_CHARSET_ucs2
-
#define MY_UCA_NPAGES 256
#define MY_UCA_NCHARS 256
#define MY_UCA_CMASK 255
@@ -6521,6 +6520,139 @@ NULL ,page0F9data,page0FAdata,page0FBdata,
page0FCdata,page0FDdata,page0FEdata,page0FFdata
};
+/*
+ Some sources treat LETTER A WITH DIARESIS (00E4,00C4)
+ secondary greater than LETTER AE (00E6,00C6).
+ http://www.evertype.com/alphabets/icelandic.pdf
+ http://developer.mimer.com/collations/charts/icelandic.htm
+
+ Other sources do not provide any special rules
+ for LETTER A WITH DIARESIS:
+ http://www.omniglot.com/writing/icelandic.htm
+ http://en.wikipedia.org/wiki/Icelandic_alphabet
+ http://oss.software.ibm.com/icu/charts/collation/is.html
+
+ Let's go the first way.
+*/
+
+static const char icelandic[]=
+ "& A < \\u00E1 <<< \\u00C1 "
+ "& D < \\u00F0 <<< \\u00D0 "
+ "& E < \\u00E9 <<< \\u00C9 "
+ "& I < \\u00ED <<< \\u00CD "
+ "& O < \\u00F3 <<< \\u00D3 "
+ "& U < \\u00FA <<< \\u00DA "
+ "& Y < \\u00FD <<< \\u00DD "
+ "& Z < \\u00FE <<< \\u00DE "
+ "< \\u00E6 <<< \\u00C6 << \\u00E4 <<< \\u00C4 "
+ "< \\u00F6 <<< \\u00D6 << \\u00F8 <<< \\u00D8 "
+ "< \\u00E5 <<< \\u00C5 ";
+
+/*
+ Some sources treat I and Y primary different.
+ Other sources treat I and Y the same on primary level.
+ We'll go the first way.
+*/
+
+static const char latvian[]=
+ "& C < \\u010D <<< \\u010C "
+ "& G < \\u0123 <<< \\u0122 "
+ "& I < \\u0079 <<< \\u0059 "
+ "& K < \\u0137 <<< \\u0136 "
+ "& L < \\u013C <<< \\u013B "
+ "& N < \\u0146 <<< \\u0145 "
+ "& R < \\u0157 <<< \\u0156 "
+ "& S < \\u0161 <<< \\u0160 "
+ "& Z < \\u017E <<< \\u017D ";
+
+
+static const char romanian[]=
+ "& A < \\u0103 <<< \\u0102 < \\u00E2 <<< \\u00C2 "
+ "& I < \\u00EE <<< \\u00CE "
+ "& S < \\u0219 <<< \\u0218 << \\u015F <<< \\u015E "
+ "& T < \\u021B <<< \\u021A << \\u0163 <<< \\u0162 ";
+
+static const char slovenian[]=
+ "& C < \\u010D <<< \\u010C "
+ "& S < \\u0161 <<< \\u0160 "
+ "& Z < \\u017E <<< \\u017D ";
+
+
+static const char polish[]=
+ "& A < \\u0105 <<< \\u0104 "
+ "& C < \\u0107 <<< \\u0106 "
+ "& E < \\u0119 <<< \\u0118 "
+ "& L < \\u0142 <<< \\u0141 "
+ "& N < \\u0144 <<< \\u0143 "
+ "& O < \\u00F3 <<< \\u00D3 "
+ "& S < \\u015B <<< \\u015A "
+ "& Z < \\u017A <<< \\u0179 < \\u017C <<< \\u017B";
+
+static const char estonian[]=
+ "& S < \\u0161 <<< \\u0160 "
+ " < \\u007A <<< \\u005A "
+ " < \\u017E <<< \\u017D "
+ "& W < \\u00F5 <<< \\u00D5 "
+ "< \\u00E4 <<< \\u00C4 "
+ "< \\u00F6 <<< \\u00D6 "
+ "< \\u00FC <<< \\u00DC ";
+
+static const char spanish[]= "& N < \\u00F1 <<< \\u00D1 ";
+
+/*
+ Some sources treat V and W as similar on primary level.
+ We'll treat V and W as different on primary level.
+*/
+
+static const char swedish[]=
+ "& Y <<\\u00FC <<< \\u00DC "
+ "& Z < \\u00E5 <<< \\u00C5 "
+ "< \\u00E4 <<< \\u00C4 << \\u00E6 <<< \\u00C6 "
+ "< \\u00F6 <<< \\u00D6 << \\u00F8 <<< \\u00D8 ";
+
+static const char turkish[]=
+ "& C < \\u00E7 <<< \\u00C7 "
+ "& G < \\u011F <<< \\u011E "
+ "& H < \\u0131 <<< \\u0049 "
+ "& O < \\u00F6 <<< \\u00D6 "
+ "& S < \\u015F <<< \\u015E "
+ "& U < \\u00FC <<< \\u00DC ";
+
+
+static const char czech[]=
+ "& C < \\u010D <<< \\u010C "
+ "& H < ch <<< Ch <<< CH"
+ "& R < \\u0159 <<< \\u0158"
+ "& S < \\u0161 <<< \\u0160"
+ "& Z < \\u017E <<< \\u017D";
+
+static const char danish[]= /* Also good for Norwegian */
+ "& Y << \\u00FC <<< \\u00DC << \\u0171 <<< \\u0170"
+ "& Z < \\u00E6 <<< \\u00C6 << \\u00E4 <<< \\u00C4"
+ " < \\u00F8 <<< \\u00D8 << \\u00F6 <<< \\u00D6 << \\u0151 <<< \\u0150"
+ " < \\u00E5 <<< \\u00C5 << aa <<< Aa <<< AA";
+
+static const char lithuanian[]=
+ "& C << ch <<< Ch <<< CH< \\u010D <<< \\u010C"
+ "& E << \\u0119 <<< \\u0118 << \\u0117 <<< \\u0116"
+ "& I << y <<< Y"
+ "& S < \\u0161 <<< \\u0160"
+ "& Z < \\u017E <<< \\u017D";
+
+static const char slovak[]=
+ "& A < \\u00E4 <<< \\u00C4"
+ "& C < \\u010D <<< \\u010C"
+ "& H < ch <<< Ch <<< CH"
+ "& O < \\u00F4 <<< \\u00D4"
+ "& S < \\u0161 <<< \\u0160"
+ "& Z < \\u017E <<< \\017D";
+
+static const char spanish2[]= /* Also good for Asturian and Galician */
+ "&C < ch <<< Ch <<< CH"
+ "&L < ll <<< Ll <<< LL"
+ "&N < \\u00F1 <<< \\u00D1"
+ "&R << rr <<< Rr <<< RR";
+
/*
Unicode Collation Algorithm:
@@ -6535,12 +6667,28 @@ typedef struct my_uca_scanner_st
const uchar *send; /* End of the input string */
uchar *uca_length;
uint16 **uca_weight;
+ uint16 *contractions;
uint16 implicit[2];
int page;
int code;
+ CHARSET_INFO *cs;
} my_uca_scanner;
+/*
+ Charset dependent scanner part, to optimize
+ some character sets.
+*/
+typedef struct my_uca_scanner_handler_st
+{
+ void (*init)(my_uca_scanner *scanner, CHARSET_INFO *cs,
+ const uchar *str, uint length);
+ int (*next)(my_uca_scanner *scanner);
+} my_uca_scanner_handler;
+
+static uint16 nochar[]= {0};
+
+#ifdef HAVE_CHARSET_ucs2
/*
Initialize collation weight scanner
@@ -6552,15 +6700,15 @@ typedef struct my_uca_scanner_st
length Length of the string.
NOTES:
+ Optimized for UCS2
RETURN
N/A
*/
-static uint16 nochar[]= {0};
-static void my_uca_scanner_init(my_uca_scanner *scanner,
- CHARSET_INFO *cs __attribute__((unused)),
- const uchar *str, uint length)
+static void my_uca_scanner_init_ucs2(my_uca_scanner *scanner,
+ CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *str, uint length)
{
/* Note, no needs to initialize scanner->wbeg */
scanner->sbeg= str;
@@ -6568,6 +6716,7 @@ static void my_uca_scanner_init(my_uca_scanner *scanner,
scanner->wbeg= nochar;
scanner->uca_length= cs->sort_order;
scanner->uca_weight= cs->sort_order_big;
+ scanner->contractions= cs->contractions;
}
@@ -6580,6 +6729,8 @@ static void my_uca_scanner_init(my_uca_scanner *scanner,
scanner Address of a previously initialized scanner strucuture
NOTES:
+ Optimized for UCS2
+
Checks if the current character's weight string has been fully scanned,
if no, then returns the next weight for this character,
else scans the next character and returns its first weight.
@@ -6610,7 +6761,7 @@ static void my_uca_scanner_init(my_uca_scanner *scanner,
Or -1 on error (END-OF-STRING or ILLEGAL MULTIBYTE SEQUENCE)
*/
-static int my_uca_scanner_next(my_uca_scanner *scanner)
+static int my_uca_scanner_next_ucs2(my_uca_scanner *scanner)
{
/*
@@ -6634,6 +6785,22 @@ static int my_uca_scanner_next(my_uca_scanner *scanner)
scanner->code= (unsigned char)scanner->sbeg[1];
scanner->sbeg+= 2;
+ if (scanner->contractions && (scanner->sbeg <= scanner->send))
+ {
+ int cweight;
+
+ if (!scanner->page && !scanner->sbeg[0] &&
+ (scanner->sbeg[1] > 0x40) && (scanner->sbeg[1] < 0x80) &&
+ (scanner->code > 0x40) && (scanner->code < 0x80) &&
+ (cweight= scanner->contractions[(scanner->code-0x40)*0x40+scanner->sbeg[1]-0x40]))
+ {
+ scanner->implicit[0]= 0;
+ scanner->wbeg= scanner->implicit;
+ scanner->sbeg+=2;
+ return cweight;
+ }
+ }
+
if (!ucaw[scanner->page])
goto implicit;
scanner->wbeg= ucaw[scanner->page] + scanner->code * ucal[scanner->page];
@@ -6660,6 +6827,111 @@ implicit:
return scanner->page;
}
+static my_uca_scanner_handler my_ucs2_uca_scanner_handler=
+{
+ my_uca_scanner_init_ucs2,
+ my_uca_scanner_next_ucs2
+};
+
+#endif
+
+
+/*
+ The same two functions for any character set
+*/
+static void my_uca_scanner_init_any(my_uca_scanner *scanner,
+ CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *str, uint length)
+{
+ /* Note, no needs to initialize scanner->wbeg */
+ scanner->sbeg= str;
+ scanner->send= str + length;
+ scanner->wbeg= nochar;
+ scanner->uca_length= cs->sort_order;
+ scanner->uca_weight= cs->sort_order_big;
+ scanner->contractions= cs->contractions;
+ scanner->cs= cs;
+}
+
+static int my_uca_scanner_next_any(my_uca_scanner *scanner)
+{
+
+ /*
+ Check if the weights for the previous character have been
+ already fully scanned. If yes, then get the next character and
+ initialize wbeg and wlength to its weight string.
+ */
+
+ if (scanner->wbeg[0])
+ return *scanner->wbeg++;
+
+ do
+ {
+ uint16 **ucaw= scanner->uca_weight;
+ uchar *ucal= scanner->uca_length;
+ my_wc_t wc;
+ int mblen;
+
+ if (((mblen= scanner->cs->cset->mb_wc(scanner->cs, &wc,
+ scanner->sbeg, scanner->send)) < 0))
+ return -1;
+
+ scanner->page= wc >> 8;
+ scanner->code= wc & 0xFF;
+ scanner->sbeg+= mblen;
+
+ if (scanner->contractions && !scanner->page &&
+ (scanner->code > 0x40) && (scanner->code < 0x80))
+ {
+ uint page1, code1, cweight;
+
+ if (((mblen= scanner->cs->cset->mb_wc(scanner->cs, &wc,
+ scanner->sbeg,
+ scanner->send)) >=0) &&
+ (!(page1= (wc >> 8))) &&
+ ((code1= (wc & 0xFF)) > 0x40) &&
+ (code1 < 0x80) &&
+ (cweight= scanner->contractions[(scanner->code-0x40)*0x40 + code1-0x40]))
+ {
+ scanner->implicit[0]= 0;
+ scanner->wbeg= scanner->implicit;
+ scanner->sbeg+= mblen;
+ return cweight;
+ }
+ }
+
+ if (!ucaw[scanner->page])
+ goto implicit;
+ scanner->wbeg= ucaw[scanner->page] + scanner->code * ucal[scanner->page];
+ } while (!scanner->wbeg[0]);
+
+ return *scanner->wbeg++;
+
+implicit:
+
+ scanner->code= (scanner->page << 8) + scanner->code;
+ scanner->implicit[0]= (scanner->code & 0x7FFF) | 0x8000;
+ scanner->implicit[1]= 0;
+ scanner->wbeg= scanner->implicit;
+
+ scanner->page= scanner->page >> 7;
+
+ if (scanner->code >= 0x3400 && scanner->code <= 0x4DB5)
+ scanner->page+= 0xFB80;
+ else if (scanner->code >= 0x4E00 && scanner->code <= 0x9FA5)
+ scanner->page+= 0xFB40;
+ else
+ scanner->page+= 0xFBC0;
+
+ return scanner->page;
+}
+
+
+static my_uca_scanner_handler my_any_uca_scanner_handler=
+{
+ my_uca_scanner_init_any,
+ my_uca_scanner_next_any
+};
/*
Compares two strings according to the collation
@@ -6703,28 +6975,28 @@ implicit:
*/
static int my_strnncoll_uca(CHARSET_INFO *cs,
+ my_uca_scanner_handler *scanner_handler,
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool t_is_prefix)
{
my_uca_scanner sscanner;
my_uca_scanner tscanner;
int s_res;
int t_res;
- my_uca_scanner_init(&sscanner, cs, s, slen);
- my_uca_scanner_init(&tscanner, cs, t, tlen);
+ scanner_handler->init(&sscanner, cs, s, slen);
+ scanner_handler->init(&tscanner, cs, t, tlen);
do
{
- s_res= my_uca_scanner_next(&sscanner);
- t_res= my_uca_scanner_next(&tscanner);
+ s_res= scanner_handler->next(&sscanner);
+ t_res= scanner_handler->next(&tscanner);
} while ( s_res == t_res && s_res >0);
- return ( s_res - t_res );
+ return (t_is_prefix && t_res < 0) ? 0 : (s_res - t_res);
}
-
-
/*
Compares two strings according to the collation,
ignoring trailing spaces.
@@ -6749,8 +7021,9 @@ static int my_strnncoll_uca(CHARSET_INFO *cs,
*/
static int my_strnncollsp_uca(CHARSET_INFO *cs,
- const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ my_uca_scanner_handler *scanner_handler,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
{
my_uca_scanner sscanner;
my_uca_scanner tscanner;
@@ -6760,19 +7033,18 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
slen= cs->cset->lengthsp(cs, (char*) s, slen);
tlen= cs->cset->lengthsp(cs, (char*) t, tlen);
- my_uca_scanner_init(&sscanner, cs, s, slen);
- my_uca_scanner_init(&tscanner, cs, t, tlen);
+ scanner_handler->init(&sscanner, cs, s, slen);
+ scanner_handler->init(&tscanner, cs, t, tlen);
do
{
- s_res= my_uca_scanner_next(&sscanner);
- t_res= my_uca_scanner_next(&tscanner);
+ s_res= scanner_handler->next(&sscanner);
+ t_res= scanner_handler->next(&tscanner);
} while ( s_res == t_res && s_res >0);
return ( s_res - t_res );
}
-
/*
Calculates hash value for the given string,
according to the collation, and ignoring trailing spaces.
@@ -6797,6 +7069,7 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
*/
static void my_hash_sort_uca(CHARSET_INFO *cs,
+ my_uca_scanner_handler *scanner_handler,
const uchar *s, uint slen,
ulong *n1, ulong *n2)
{
@@ -6804,9 +7077,9 @@ static void my_hash_sort_uca(CHARSET_INFO *cs,
my_uca_scanner scanner;
slen= cs->cset->lengthsp(cs, (char*) s, slen);
- my_uca_scanner_init(&scanner, cs, s, slen);
+ scanner_handler->init(&scanner, cs, s, slen);
- while ((s_res= my_uca_scanner_next(&scanner)) >0)
+ while ((s_res= scanner_handler->next(&scanner)) >0)
{
n1[0]^= (((n1[0] & 63)+n2[0])*(s_res >> 8))+ (n1[0] << 8);
n2[0]+=3;
@@ -6848,24 +7121,28 @@ static void my_hash_sort_uca(CHARSET_INFO *cs,
*/
static int my_strnxfrm_uca(CHARSET_INFO *cs,
- uchar *dst, uint dstlen,
- const uchar *src, uint srclen)
+ my_uca_scanner_handler *scanner_handler,
+ uchar *dst, uint dstlen,
+ const uchar *src, uint srclen)
{
uchar *de = dst + dstlen;
const uchar *dst_orig = dst;
int s_res;
my_uca_scanner scanner;
- my_uca_scanner_init(&scanner, cs, src, srclen);
+ scanner_handler->init(&scanner, cs, src, srclen);
- while (dst < de && (s_res= my_uca_scanner_next(&scanner)) >0)
+ while (dst < de && (s_res= scanner_handler->next(&scanner)) >0)
{
dst[0]= s_res >> 8;
dst[1]= s_res & 0xFF;
dst+= 2;
}
+ for ( ; dst < de; *dst++='\0');
return dst - dst_orig;
}
+
+
/*
This function compares if two characters are the same.
The sign +1 or -1 does not matter. The only
@@ -7036,34 +7313,660 @@ int my_wildcmp_uca(CHARSET_INFO *cs,
}
+/*
+ Collation language is implemented according to
+ subset of ICU Collation Customization (tailorings):
+ http://oss.software.ibm.com/icu/userguide/Collate_Customization.html
+
+ Collation language elements:
+ Delimiters:
+ space - skipped
+
+ <char> := A-Z | a-z | \uXXXX
+
+ Shift command:
+ <shift> := & - reset at this letter.
+
+ Diff command:
+ <d1> := < - Identifies a primary difference.
+ <d2> := << - Identifies a secondary difference.
+ <d3> := <<< - Idenfifies a tertiary difference.
+
+
+ Collation rules:
+ <ruleset> := <rule> { <ruleset> }
+
+ <rule> := <d1> <string>
+ | <d2> <string>
+ | <d3> <string>
+ | <shift> <char>
+
+ <string> := <char> [ <string> ]
+
+ An example, Polish collation:
+
+ &A < \u0105 <<< \u0104
+ &C < \u0107 <<< \u0106
+ &E < \u0119 <<< \u0118
+ &L < \u0142 <<< \u0141
+ &N < \u0144 <<< \u0143
+ &O < \u00F3 <<< \u00D3
+ &S < \u015B <<< \u015A
+ &Z < \u017A <<< \u017B
+*/
+
+
+typedef enum my_coll_lexem_num_en
+{
+ MY_COLL_LEXEM_EOF = 0,
+ MY_COLL_LEXEM_DIFF = 1,
+ MY_COLL_LEXEM_SHIFT = 4,
+ MY_COLL_LEXEM_CHAR = 5,
+ MY_COLL_LEXEM_ERROR = 6
+} my_coll_lexem_num;
+
+
+typedef struct my_coll_lexem_st
+{
+ const char *beg;
+ const char *end;
+ const char *prev;
+ int diff;
+ int code;
+} MY_COLL_LEXEM;
+
+
+/*
+ Initialize collation rule lexical anilizer
+
+ SYNOPSIS
+ my_coll_lexem_init
+ lexem Lex analizer to init
+ str Const string to parse
+ strend End of the string
+ USAGE
+
+ RETURN VALUES
+ N/A
+*/
+
+static void my_coll_lexem_init(MY_COLL_LEXEM *lexem,
+ const char *str, const char *strend)
+{
+ lexem->beg= str;
+ lexem->prev= str;
+ lexem->end= strend;
+ lexem->diff= 0;
+ lexem->code= 0;
+}
+
+
+/*
+ Print collation customization expression parse error, with context.
+
+ SYNOPSIS
+ my_coll_lexem_print_error
+ lexem Lex analizer to take context from
+ errstr sting to write error to
+ errsize errstr size
+ txt error message
+ USAGE
+
+ RETURN VALUES
+ N/A
+*/
+
+static void my_coll_lexem_print_error(MY_COLL_LEXEM *lexem,
+ char *errstr, size_t errsize,
+ const char *txt)
+{
+ char tail[30];
+ size_t len= lexem->end - lexem->prev;
+ strmake (tail, lexem->prev, min(len, sizeof(tail)-1));
+ errstr[errsize-1]= '\0';
+ my_snprintf(errstr,errsize-1,"%s at '%s'", txt, tail);
+}
+
+
+/*
+ Convert a hex digit into its numeric value
+
+ SYNOPSIS
+ ch2x
+ ch hex digit to convert
+ USAGE
+
+ RETURN VALUES
+ an integer value in the range 0..15
+ -1 on error
+*/
+
+static int ch2x(int ch)
+{
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+
+ if (ch >= 'a' && ch <= 'f')
+ return 10 + ch - 'a';
+
+ if (ch >= 'A' && ch <= 'F')
+ return 10 + ch - 'A';
+
+ return -1;
+}
+
+
+/*
+ Collation language lexical parser:
+ Scans the next lexem.
+
+ SYNOPSIS
+ my_coll_lexem_next
+ lexem Lex analizer, previously initialized by
+ my_coll_lexem_init.
+ USAGE
+ Call this function in a loop
+
+ RETURN VALUES
+ Lexem number: eof, diff, shift, char or error.
+*/
+
+static my_coll_lexem_num my_coll_lexem_next(MY_COLL_LEXEM *lexem)
+{
+ const char *beg;
+ my_coll_lexem_num rc;
+
+ for (beg= lexem->beg ; beg < lexem->end ; beg++)
+ {
+ if (*beg == ' ' || *beg == '\t' || *beg == '\r' || *beg == '\n')
+ continue;
+
+ if (*beg == '&')
+ {
+ beg++;
+ rc= MY_COLL_LEXEM_SHIFT;
+ goto ex;
+ }
+
+ if (beg[0] == '<')
+ {
+ for (beg++, lexem->diff= 1;
+ (beg < lexem->end) &&
+ (*beg == '<') && (lexem->diff<3);
+ beg++, lexem->diff++);
+ rc= MY_COLL_LEXEM_DIFF;
+ goto ex;
+ }
+
+ if ((*beg >= 'a' && *beg <= 'z') || (*beg >= 'A' && *beg <= 'Z'))
+ {
+ lexem->code= *beg++;
+ rc= MY_COLL_LEXEM_CHAR;
+ goto ex;
+ }
+
+ if ((*beg == '\\') && (beg+2 < lexem->end) && (beg[1] == 'u'))
+ {
+ int ch;
+
+ beg+= 2;
+ lexem->code= 0;
+ while ((beg < lexem->end) && ((ch= ch2x(beg[0])) >= 0))
+ {
+ lexem->code= (lexem->code << 4) + ch;
+ beg++;
+ }
+ rc= MY_COLL_LEXEM_CHAR;
+ goto ex;
+ }
+
+ rc= MY_COLL_LEXEM_ERROR;
+ goto ex;
+ }
+ rc= MY_COLL_LEXEM_EOF;
+
+ex:
+ lexem->prev= lexem->beg;
+ lexem->beg= beg;
+ return rc;
+}
+
+
+/*
+ Collation rule item
+*/
+
+typedef struct my_coll_rule_item_st
+{
+ uint base; /* Base character */
+ uint curr[2]; /* Current character */
+ int diff[3]; /* Primary, Secondary and Tertiary difference */
+} MY_COLL_RULE;
+
+
+/*
+ Collation language syntax parser.
+ Uses lexical parser.
+
+ SYNOPSIS
+ my_coll_rule_parse
+ rule Collation rule list to load to.
+ str A string containin collation language expression.
+ strend End of the string.
+ USAGE
+
+ RETURN VALUES
+ A positive number means the number of rules loaded.
+ -1 means ERROR, e.g. too many items, syntax error, etc.
+*/
+
+static int my_coll_rule_parse(MY_COLL_RULE *rule, size_t mitems,
+ const char *str, const char *strend,
+ char *errstr, size_t errsize)
+{
+ MY_COLL_LEXEM lexem;
+ my_coll_lexem_num lexnum;
+ my_coll_lexem_num prevlexnum= MY_COLL_LEXEM_ERROR;
+ MY_COLL_RULE item;
+ int state= 0;
+ size_t nitems= 0;
+
+ /* Init all variables */
+ errstr[0]= '\0';
+ bzero(&item, sizeof(item));
+ my_coll_lexem_init(&lexem, str, strend);
+
+ while ((lexnum= my_coll_lexem_next(&lexem)))
+ {
+ if (lexnum == MY_COLL_LEXEM_ERROR)
+ {
+ my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Unknown character");
+ return -1;
+ }
+
+ switch (state) {
+ case 0:
+ if (lexnum != MY_COLL_LEXEM_SHIFT)
+ {
+ my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& expected");
+ return -1;
+ }
+ prevlexnum= lexnum;
+ state= 2;
+ continue;
+
+ case 1:
+ if (lexnum != MY_COLL_LEXEM_SHIFT && lexnum != MY_COLL_LEXEM_DIFF)
+ {
+ my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& or < expected");
+ return -1;
+ }
+ prevlexnum= lexnum;
+ state= 2;
+ continue;
+
+ case 2:
+ if (lexnum != MY_COLL_LEXEM_CHAR)
+ {
+ my_coll_lexem_print_error(&lexem,errstr,errsize-1,"character expected");
+ return -1;
+ }
+
+ if (prevlexnum == MY_COLL_LEXEM_SHIFT)
+ {
+ item.base= lexem.code;
+ item.diff[0]= 0;
+ item.diff[1]= 0;
+ item.diff[2]= 0;
+ }
+ else if (prevlexnum == MY_COLL_LEXEM_DIFF)
+ {
+ MY_COLL_LEXEM savlex;
+ savlex= lexem;
+ item.curr[0]= lexem.code;
+ if ((lexnum= my_coll_lexem_next(&lexem)) == MY_COLL_LEXEM_CHAR)
+ {
+ item.curr[1]= lexem.code;
+ }
+ else
+ {
+ item.curr[1]= 0;
+ lexem=savlex; /* Restore previous parser state */
+ }
+ if (lexem.diff == 3)
+ {
+ item.diff[2]++;
+ }
+ else if (lexem.diff == 2)
+ {
+ item.diff[1]++;
+ item.diff[2]= 0;
+ }
+ else if (lexem.diff == 1)
+ {
+ item.diff[0]++;
+ item.diff[1]= 0;
+ item.diff[2]= 0;
+ }
+ if (nitems >= mitems)
+ {
+ my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Too many rules");
+ return -1;
+ }
+ rule[nitems++]= item;
+ }
+ else
+ {
+ my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Should never happen");
+ return -1;
+ }
+ state= 1;
+ continue;
+ }
+ }
+ return (size_t) nitems;
+}
+
+#define MY_MAX_COLL_RULE 64
+
+/*
+ This function copies an UCS2 collation from
+ the default Unicode Collation Algorithm (UCA)
+ weights applying tailorings, i.e. a set of
+ alternative weights for some characters.
+
+ The default UCA weights are stored in uca_weight/uca_length.
+ They consist of 256 pages, 256 character each.
+
+ If a page is not overwritten by tailoring rules,
+ it is copies as is from UCA as is.
+
+ If a page contains some overwritten characters, it is
+ allocated. Untouched characters are copied from the
+ default weights.
+*/
+
+static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(uint))
+{
+ MY_COLL_RULE rule[MY_MAX_COLL_RULE];
+ char errstr[128];
+ uchar *newlengths;
+ uint16 **newweights;
+ const uchar *deflengths= uca_length;
+ uint16 **defweights= uca_weight;
+ int rc, i;
+ int ncontractions= 0;
+
+ if (!cs->tailoring)
+ return 1;
+
+ /* Parse ICU Collation Customization expression */
+ if ((rc= my_coll_rule_parse(rule, MY_MAX_COLL_RULE,
+ cs->tailoring,
+ cs->tailoring + strlen(cs->tailoring),
+ errstr, sizeof(errstr))) < 0)
+ {
+ /*
+ TODO: add error message reporting.
+ printf("Error: %d '%s'\n", rc, errstr);
+ */
+ return 1;
+ }
+
+ if (!(newweights= (uint16**) (*alloc)(256*sizeof(uint16*))))
+ return 1;
+ bzero(newweights, 256*sizeof(uint16*));
+
+ if (!(newlengths= (uchar*) (*alloc)(256)))
+ return 1;
+
+ memcpy(newlengths, deflengths, 256);
+
+ /*
+ Calculate maximum lenghts for the pages
+ which will be overwritten.
+ */
+ for (i=0; i < rc; i++)
+ {
+ if (!rule[i].curr[1]) /* If not a contraction */
+ {
+ uint pageb= (rule[i].base >> 8) & 0xFF;
+ uint pagec= (rule[i].curr[0] >> 8) & 0xFF;
+
+ if (newlengths[pagec] < deflengths[pageb])
+ newlengths[pagec]= deflengths[pageb];
+ }
+ else
+ ncontractions++;
+ }
+
+ for (i=0; i < rc; i++)
+ {
+ uint pageb= (rule[i].base >> 8) & 0xFF;
+ uint pagec= (rule[i].curr[0] >> 8) & 0xFF;
+ uint chb, chc;
+
+ if (rule[i].curr[1]) /* Skip contraction */
+ continue;
+
+ if (!newweights[pagec])
+ {
+ /* Alloc new page and copy the default UCA weights */
+ uint size= 256*newlengths[pagec]*sizeof(uint16);
+
+ if (!(newweights[pagec]= (uint16*) (*alloc)(size)))
+ return 1;
+ bzero((void*) newweights[pagec], size);
+
+ for (chc=0 ; chc < 256; chc++)
+ {
+ memcpy(newweights[pagec] + chc*newlengths[pagec],
+ defweights[pagec] + chc*deflengths[pagec],
+ deflengths[pagec]*sizeof(uint16));
+ }
+ }
+
+ /*
+ Aply the alternative rule:
+ shift to the base character and primary difference.
+ */
+ chc= rule[i].curr[0] & 0xFF;
+ chb= rule[i].base & 0xFF;
+ memcpy(newweights[pagec] + chc*newlengths[pagec],
+ defweights[pageb] + chb*deflengths[pageb],
+ deflengths[pageb]*sizeof(uint16));
+ /* Apply primary difference */
+ newweights[pagec][chc*newlengths[pagec]]+= rule[i].diff[0];
+ }
+
+ /* Copy non-overwritten pages from the default UCA weights */
+ for (i= 0; i < 256 ; i++)
+ {
+ if (!newweights[i])
+ newweights[i]= defweights[i];
+ }
+
+ cs->sort_order= newlengths;
+ cs->sort_order_big= newweights;
+ cs->contractions= NULL;
+
+ /* Now process contractions */
+ if (ncontractions)
+ {
+ uint size= 0x40*0x40*sizeof(uint16); /* 8K, for basic latin letter only */
+ if (!(cs->contractions= (uint16*) (*alloc)(size)))
+ return 1;
+ bzero((void*)cs->contractions, size);
+ for (i=0; i < rc; i++)
+ {
+ if (rule[i].curr[1])
+ {
+ uint pageb= (rule[i].base >> 8) & 0xFF;
+ uint chb= rule[i].base & 0xFF;
+ uint16 *offsb= defweights[pageb] + chb*deflengths[pageb];
+ uint offsc;
+
+ if (offsb[1] ||
+ rule[i].curr[0] < 0x40 || rule[i].curr[0] > 0x7f ||
+ rule[i].curr[1] < 0x40 || rule[i].curr[1] > 0x7f)
+ {
+ /*
+ TODO: add error reporting;
+ We support only basic latin letters contractions at this point.
+ Also, We don't support contractions with weight longer than one.
+ Otherwise, we'd need much more memory.
+ */
+ return 1;
+ }
+ offsc= (rule[i].curr[0]-0x40)*0x40+(rule[i].curr[1]-0x40);
+
+ /* Copy base weight applying primary difference */
+ cs->contractions[offsc]= offsb[0] + rule[i].diff[0];
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*
+ Universal CHARSET_INFO compatible wrappers
+ for the above internal functions.
+ Should work for any character set.
+*/
+
+static my_bool my_coll_init_uca(CHARSET_INFO *cs, void *(*alloc)(uint))
+{
+ return create_tailoring(cs, alloc);
+}
+
+static int my_strnncoll_any_uca(CHARSET_INFO *cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen,
+ my_bool t_is_prefix)
+{
+ return my_strnncoll_uca(cs, &my_any_uca_scanner_handler,
+ s, slen, t, tlen, t_is_prefix);
+}
+
+static int my_strnncollsp_any_uca(CHARSET_INFO *cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ return my_strnncollsp_uca(cs, &my_any_uca_scanner_handler,
+ s, slen, t, tlen);
+}
+
+static void my_hash_sort_any_uca(CHARSET_INFO *cs,
+ const uchar *s, uint slen,
+ ulong *n1, ulong *n2)
+{
+ my_hash_sort_uca(cs, &my_any_uca_scanner_handler, s, slen, n1, n2);
+}
+
+static int my_strnxfrm_any_uca(CHARSET_INFO *cs,
+ uchar *dst, uint dstlen,
+ const uchar *src, uint srclen)
+{
+ return my_strnxfrm_uca(cs, &my_any_uca_scanner_handler,
+ dst, dstlen, src, srclen);
+}
+
+
+#ifdef HAVE_CHARSET_ucs2
+/*
+ UCS2 optimized CHARSET_INFO compatible wrappers.
+*/
+static int my_strnncoll_ucs2_uca(CHARSET_INFO *cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen,
+ my_bool t_is_prefix)
+{
+ return my_strnncoll_uca(cs, &my_ucs2_uca_scanner_handler,
+ s, slen, t, tlen, t_is_prefix);
+}
+
+static int my_strnncollsp_ucs2_uca(CHARSET_INFO *cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ return my_strnncollsp_uca(cs, &my_ucs2_uca_scanner_handler,
+ s, slen, t, tlen);
+}
+
+static void my_hash_sort_ucs2_uca(CHARSET_INFO *cs,
+ const uchar *s, uint slen,
+ ulong *n1, ulong *n2)
+{
+ my_hash_sort_uca(cs, &my_ucs2_uca_scanner_handler, s, slen, n1, n2);
+}
+
+static int my_strnxfrm_ucs2_uca(CHARSET_INFO *cs,
+ uchar *dst, uint dstlen,
+ const uchar *src, uint srclen)
+{
+ return my_strnxfrm_uca(cs, &my_ucs2_uca_scanner_handler,
+ dst, dstlen, src, srclen);
+}
+
MY_COLLATION_HANDLER my_collation_ucs2_uca_handler =
{
- my_strnncoll_uca,
- my_strnncollsp_uca,
- my_strnxfrm_uca,
+ my_coll_init_uca, /* init */
+ my_strnncoll_ucs2_uca,
+ my_strnncollsp_ucs2_uca,
+ my_strnxfrm_ucs2_uca,
my_like_range_simple,
my_wildcmp_uca,
NULL,
my_instr_mb,
- my_hash_sort_uca
+ my_hash_sort_ucs2_uca
};
CHARSET_INFO my_charset_ucs2_general_uca=
{
- 45,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONTEXT,
+ 128,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
"ucs2", /* cs name */
- "ucs2_general_uca", /* name */
+ "ucs2_unicode_ci", /* name */
"", /* comment */
+ "", /* tailoring */
NULL, /* ctype */
NULL, /* to_lower */
NULL, /* to_upper */
uca_length, /* sort_order */
+ NULL, /* contractions */
uca_weight, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_icelandic_uca_ci=
+{
+ 129,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_icelandic_ci",/* name */
+ "", /* comment */
+ icelandic, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
8, /* strxfrm_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
@@ -7073,5 +7976,807 @@ CHARSET_INFO my_charset_ucs2_general_uca=
&my_collation_ucs2_uca_handler
};
+CHARSET_INFO my_charset_ucs2_latvian_uca_ci=
+{
+ 130,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_latvian_ci", /* name */
+ "", /* comment */
+ latvian, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+CHARSET_INFO my_charset_ucs2_romanian_uca_ci=
+{
+ 131,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_romanian_ci", /* name */
+ "", /* comment */
+ romanian, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_slovenian_uca_ci=
+{
+ 132,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_slovenian_ci",/* name */
+ "", /* comment */
+ slovenian, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_polish_uca_ci=
+{
+ 133,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_polish_ci", /* name */
+ "", /* comment */
+ polish, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_estonian_uca_ci=
+{
+ 134,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_estonian_ci", /* name */
+ "", /* comment */
+ estonian, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_spanish_uca_ci=
+{
+ 135,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_spanish_ci", /* name */
+ "", /* comment */
+ spanish, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_swedish_uca_ci=
+{
+ 136,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_swedish_ci", /* name */
+ "", /* comment */
+ swedish, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_turkish_uca_ci=
+{
+ 137,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_turkish_ci", /* name */
+ "", /* comment */
+ turkish, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_czech_uca_ci=
+{
+ 138,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_czech_ci", /* name */
+ "", /* comment */
+ czech, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+
+CHARSET_INFO my_charset_ucs2_danish_uca_ci=
+{
+ 139,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_danish_ci", /* name */
+ "", /* comment */
+ danish, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci=
+{
+ 140,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_lithuanian_ci",/* name */
+ "", /* comment */
+ lithuanian, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_slovak_uca_ci=
+{
+ 141,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_slovak_ci", /* name */
+ "", /* comment */
+ slovak, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+CHARSET_INFO my_charset_ucs2_spanish2_uca_ci=
+{
+ 142,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_spanish2_ci", /* name */
+ "", /* comment */
+ spanish2, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+#endif
+
+
+#ifdef HAVE_CHARSET_utf8
+MY_COLLATION_HANDLER my_collation_any_uca_handler =
+{
+ my_coll_init_uca, /* init */
+ my_strnncoll_any_uca,
+ my_strnncollsp_any_uca,
+ my_strnxfrm_any_uca,
+ my_like_range_simple,
+ my_wildcmp_uca,
+ NULL,
+ my_instr_mb,
+ my_hash_sort_any_uca
+};
+
+/*
+ We consider bytes with code more than 127 as a letter.
+ This garantees that word boundaries work fine with regular
+ expressions. Note, there is no need to mark byte 255 as a
+ letter, it is illegal byte in UTF8.
+*/
+static uchar ctype_utf8[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0
+};
+
+extern MY_CHARSET_HANDLER my_charset_utf8_handler;
+
+CHARSET_INFO my_charset_utf8_general_uca_ci=
+{
+ 192,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_unicode_ci", /* name */
+ "", /* comment */
+ "", /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ uca_length, /* sort_order */
+ NULL, /* contractions */
+ uca_weight, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 3, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+
+CHARSET_INFO my_charset_utf8_icelandic_uca_ci=
+{
+ 193,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_icelandic_ci",/* name */
+ "", /* comment */
+ icelandic, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_latvian_uca_ci=
+{
+ 194,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_latvian_ci", /* name */
+ "", /* comment */
+ latvian, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_romanian_uca_ci=
+{
+ 195,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_romanian_ci", /* name */
+ "", /* comment */
+ romanian, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_slovenian_uca_ci=
+{
+ 196,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_slovenian_ci",/* name */
+ "", /* comment */
+ slovenian, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_polish_uca_ci=
+{
+ 197,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_polish_ci", /* name */
+ "", /* comment */
+ polish, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_estonian_uca_ci=
+{
+ 198,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_estonian_ci", /* name */
+ "", /* comment */
+ estonian, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_spanish_uca_ci=
+{
+ 199,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_spanish_ci", /* name */
+ "", /* comment */
+ spanish, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_swedish_uca_ci=
+{
+ 200,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_swedish_ci", /* name */
+ "", /* comment */
+ swedish, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_turkish_uca_ci=
+{
+ 201,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_turkish_ci", /* name */
+ "", /* comment */
+ turkish, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_czech_uca_ci=
+{
+ 202,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_czech_ci", /* name */
+ "", /* comment */
+ czech, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+
+CHARSET_INFO my_charset_utf8_danish_uca_ci=
+{
+ 203,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_danish_ci", /* name */
+ "", /* comment */
+ danish, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_lithuanian_uca_ci=
+{
+ 204,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_lithuanian_ci",/* name */
+ "", /* comment */
+ lithuanian, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_slovak_uca_ci=
+{
+ 205,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_slovak_ci", /* name */
+ "", /* comment */
+ slovak, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_spanish2_uca_ci=
+{
+ 206,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_spanish2_ci", /* name */
+ "", /* comment */
+ spanish2, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
#endif
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 67340fdd4f4..20a5ff58d3a 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -182,7 +182,8 @@ static void my_casedn_str_ucs2(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncoll_ucs2(CHARSET_INFO *cs,
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool t_is_prefix)
{
int s_res,t_res;
my_wc_t s_wc,t_wc;
@@ -213,7 +214,14 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return ( (se-s) - (te-t) );
+ return t_is_prefix ? t-te : ((se-s) - (te-t));
+}
+
+static int my_strnncollsp_ucs2(CHARSET_INFO *cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ return my_strnncoll_ucs2(cs,s,slen,t,tlen,0);
}
@@ -312,7 +320,6 @@ static int my_mbcharlen_ucs2(CHARSET_INFO *cs __attribute__((unused)) ,
#include <m_string.h>
#include <stdarg.h>
-#include <assert.h>
static int my_vsnprintf_ucs2(char *dst, uint n, const char* fmt, va_list ap)
{
@@ -1224,8 +1231,9 @@ int my_wildcmp_ucs2_bin(CHARSET_INFO *cs,
static
int my_strnncoll_ucs2_bin(CHARSET_INFO *cs,
- const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen,
+ my_bool t_is_prefix)
{
int s_res,t_res;
my_wc_t s_wc,t_wc;
@@ -1250,7 +1258,14 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return ( (se-s) - (te-t) );
+ return t_is_prefix ? t-te : ((se-s) - (te-t));
+}
+
+static int my_strnncollsp_ucs2_bin(CHARSET_INFO *cs,
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen)
+{
+ return my_strnncoll_ucs2_bin(cs,s,slen,t,tlen,0);
}
@@ -1373,8 +1388,9 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler =
{
+ NULL, /* init */
my_strnncoll_ucs2,
- my_strnncoll_ucs2,
+ my_strnncollsp_ucs2,
my_strnxfrm_ucs2,
my_like_range_ucs2,
my_wildcmp_ucs2_ci,
@@ -1386,8 +1402,9 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler =
static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler =
{
+ NULL, /* init */
my_strnncoll_ucs2_bin,
- my_strnncoll_ucs2_bin,
+ my_strnncollsp_ucs2_bin,
my_strnxfrm_ucs2_bin,
my_like_range_simple,
my_wildcmp_ucs2_bin,
@@ -1399,6 +1416,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler =
MY_CHARSET_HANDLER my_charset_ucs2_handler=
{
+ NULL, /* init */
my_ismbchar_ucs2, /* ismbchar */
my_mbcharlen_ucs2, /* mbcharlen */
my_numchars_ucs2,
@@ -1427,19 +1445,21 @@ MY_CHARSET_HANDLER my_charset_ucs2_handler=
CHARSET_INFO my_charset_ucs2_general_ci=
{
35,0,0, /* number */
- MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONTEXT,
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE,
"ucs2", /* cs name */
"ucs2_general_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_ucs2, /* ctype */
to_lower_ucs2, /* to_lower */
to_upper_ucs2, /* to_upper */
to_upper_ucs2, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
@@ -1452,19 +1472,21 @@ CHARSET_INFO my_charset_ucs2_general_ci=
CHARSET_INFO my_charset_ucs2_bin=
{
90,0,0, /* number */
- MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE|MY_CS_NONTEXT,
+ MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE,
"ucs2", /* cs name */
"ucs2_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_ucs2, /* ctype */
to_lower_ucs2, /* to_lower */
to_upper_ucs2, /* to_upper */
to_upper_ucs2, /* sort_order */
+ NULL, /* contractions */
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index fd3692553be..3f53a07f527 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -8423,6 +8423,7 @@ my_wc_mb_euc_jp(CHARSET_INFO *c,my_wc_t wc, unsigned char *s, unsigned char *e)
static MY_COLLATION_HANDLER my_collation_ci_handler =
{
+ NULL, /* init */
my_strnncoll_simple,/* strnncoll */
my_strnncollsp_simple,
my_strnxfrm_simple, /* strnxfrm */
@@ -8435,14 +8436,15 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
static MY_CHARSET_HANDLER my_charset_handler=
{
+ NULL, /* init */
ismbchar_ujis,
mbcharlen_ujis,
my_numchars_mb,
my_charpos_mb,
my_well_formed_len_mb,
my_lengthsp_8bit,
- my_mb_wc_euc_jp, /* mb_wc */
- my_wc_mb_euc_jp, /* wc_mb */
+ my_mb_wc_euc_jp, /* mb_wc */
+ my_wc_mb_euc_jp, /* wc_mb */
my_caseup_str_mb,
my_casedn_str_mb,
my_caseup_mb,
@@ -8468,20 +8470,22 @@ CHARSET_INFO my_charset_ujis_japanese_ci=
"ujis", /* cs name */
"ujis_japanese_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_ujis,
to_lower_ujis,
to_upper_ujis,
sort_order_ujis,
+ NULL, /* sort_order_big*/
+ NULL, /* contractions */
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_ci_handler
};
@@ -8494,20 +8498,22 @@ CHARSET_INFO my_charset_ujis_bin=
"ujis", /* cs name */
"ujis_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_ujis,
to_lower_ujis,
to_upper_ujis,
sort_order_ujis,
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 255, /* max_sort_char */
&my_charset_handler,
&my_collation_mb_bin_handler
};
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index 29d2c5d1358..bf2d8a17fb4 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -1524,8 +1524,12 @@ MY_UNICASE_INFO *uni_plane[256]={
#ifdef HAVE_CHARSET_utf8
-/* These arrays are taken from usa7 implementation */
-
+/*
+ We consider bytes with code more than 127 as a letter.
+ This garantees that word boundaries work fine with regular
+ expressions. Note, there is no need to mark byte 255 as a
+ letter, it is illegal byte in UTF8.
+*/
static uchar ctype_utf8[] = {
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
@@ -1536,16 +1540,18 @@ static uchar ctype_utf8[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0
};
+/* The below are taken from usa7 implementation */
+
static uchar to_lower_utf8[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
@@ -1802,7 +1808,8 @@ static void my_casedn_str_utf8(CHARSET_INFO *cs, char * s)
static int my_strnncoll_utf8(CHARSET_INFO *cs,
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool t_is_prefix)
{
int s_res,t_res;
my_wc_t s_wc,t_wc;
@@ -1833,7 +1840,7 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return ( (se-s) - (te-t) );
+ return t_is_prefix ? t-te : ((se-s) - (te-t));
}
@@ -2039,6 +2046,7 @@ static int my_mbcharlen_utf8(CHARSET_INFO *cs __attribute__((unused)) , uint c)
static MY_COLLATION_HANDLER my_collation_ci_handler =
{
+ NULL, /* init */
my_strnncoll_utf8,
my_strnncollsp_utf8,
my_strnxfrm_utf8,
@@ -2049,8 +2057,9 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_hash_sort_utf8
};
-static MY_CHARSET_HANDLER my_charset_handler=
+MY_CHARSET_HANDLER my_charset_utf8_handler=
{
+ NULL, /* init */
my_ismbchar_utf8,
my_mbcharlen_utf8,
my_numchars_mb,
@@ -2084,21 +2093,23 @@ CHARSET_INFO my_charset_utf8_general_ci=
"utf8", /* cs name */
"utf8_general_ci", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_utf8, /* ctype */
to_lower_utf8, /* to_lower */
to_upper_utf8, /* to_upper */
to_upper_utf8, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
- &my_charset_handler,
+ 255, /* max_sort_char */
+ &my_charset_utf8_handler,
&my_collation_ci_handler
};
@@ -2110,27 +2121,28 @@ CHARSET_INFO my_charset_utf8_bin=
"utf8", /* cs name */
"utf8_bin", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_utf8, /* ctype */
to_lower_utf8, /* to_lower */
to_upper_utf8, /* to_upper */
to_upper_utf8, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
- NULL, /* sort_order_big*/
- "",
- "",
+ NULL, /* state_map */
+ NULL, /* ident_map */
1, /* strxfrm_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
- &my_charset_handler,
+ 255, /* max_sort_char */
+ &my_charset_utf8_handler,
&my_collation_mb_bin_handler
};
#ifdef MY_TEST_UTF8
-
#include <stdio.h>
static void test_mb(CHARSET_INFO *cs, uchar *s)
@@ -2162,7 +2174,7 @@ int main()
test_mb(cs,(uchar*)str);
- pr1;2cintf("orig :'%s'\n",str);
+ printf("orig :'%s'\n",str);
my_caseup_utf8(cs,str,15);
printf("caseup :'%s'\n",str);
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index 2eefb570170..b4dbda3e8ed 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -448,20 +448,25 @@ static struct wordvalue doubles[] = {
static int my_strnncoll_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
const uchar * s1, uint len1,
- const uchar * s2, uint len2)
+ const uchar * s2, uint len2,
+ my_bool s2_is_prefix)
{
int v1, v2;
const uchar * p1, * p2;
int pass1 = 0, pass2 = 0;
int diff;
+ if (s2_is_prefix && len1 > len2)
+ len1=len2;
+
p1 = s1; p2 = s2;
- do {
+ do
+ {
NEXT_CMP_VALUE(s1, p1, pass1, v1, (int)len1);
NEXT_CMP_VALUE(s2, p2, pass2, v2, (int)len2);
- diff = v1 - v2;
- if (diff != 0) return diff;
+ if ((diff = v1 - v2))
+ return diff;
} while (v1);
return 0;
}
@@ -478,7 +483,7 @@ int my_strnncollsp_win1250ch(CHARSET_INFO * cs,
{
for ( ; slen && s[slen-1] == ' ' ; slen--);
for ( ; tlen && t[tlen-1] == ' ' ; tlen--);
- return my_strnncoll_win1250ch(cs,s,slen,t,tlen);
+ return my_strnncoll_win1250ch(cs,s,slen,t,tlen,0);
}
@@ -605,6 +610,7 @@ my_like_range_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
static MY_COLLATION_HANDLER my_collation_czech_ci_handler =
{
+ NULL, /* init */
my_strnncoll_win1250ch,
my_strnncollsp_win1250ch,
my_strnxfrm_win1250ch,
@@ -623,14 +629,17 @@ CHARSET_INFO my_charset_cp1250_czech_ci =
"cp1250", /* cs name */
"cp1250_czech_cs", /* name */
"", /* comment */
+ NULL, /* tailoring */
ctype_win1250ch,
to_lower_win1250ch,
to_upper_win1250ch,
sort_order_win1250ch,
+ NULL, /* contractions */
NULL, /* sort_order_big*/
tab_cp1250_uni, /* tab_to_uni */
idx_uni_cp1250, /* tab_from_uni */
- "","",
+ NULL, /* state_map */
+ NULL, /* ident_map */
2, /* strxfrm_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
diff --git a/strings/ctype.c b/strings/ctype.c
index cbd13111b70..4454d3c45e1 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -22,6 +22,23 @@
#endif
+/*
+
+ This files implements routines which parse XML based
+ character set and collation description files.
+
+ Unicode collations are encoded according to
+
+ Unicode Technical Standard #35
+ Locale Data Markup Language (LDML)
+ http://www.unicode.org/reports/tr35/
+
+ and converted into ICU string according to
+
+ Collation Customization
+ http://oss.software.ibm.com/icu/userguide/Collate_Customization.html
+
+*/
static char *mstr(char *str,const char *src,uint l1,uint l2)
{
@@ -54,6 +71,11 @@ struct my_cs_file_section_st
#define _CS_PRIMARY_ID 15
#define _CS_BINARY_ID 16
#define _CS_CSDESCRIPT 17
+#define _CS_RESET 18
+#define _CS_DIFF1 19
+#define _CS_DIFF2 20
+#define _CS_DIFF3 21
+
static struct my_cs_file_section_st sec[] =
{
@@ -83,6 +105,10 @@ static struct my_cs_file_section_st sec[] =
{_CS_ORDER, "charsets.charset.collation.order"},
{_CS_FLAG, "charsets.charset.collation.flag"},
{_CS_COLLMAP, "charsets.charset.collation.map"},
+ {_CS_RESET, "charsets.charset.collation.rules.reset"},
+ {_CS_DIFF1, "charsets.charset.collation.rules.p"},
+ {_CS_DIFF2, "charsets.charset.collation.rules.s"},
+ {_CS_DIFF3, "charsets.charset.collation.rules.t"},
{0, NULL}
};
@@ -98,6 +124,7 @@ static struct my_cs_file_section_st * cs_file_sec(const char *attr, uint len)
}
#define MY_CS_CSDESCR_SIZE 64
+#define MY_CS_TAILORING_SIZE 128
typedef struct my_cs_file_info
{
@@ -109,6 +136,8 @@ typedef struct my_cs_file_info
uchar sort_order[MY_CS_SORT_ORDER_TABLE_SIZE];
uint16 tab_to_uni[MY_CS_TO_UNI_TABLE_SIZE];
char comment[MY_CS_CSDESCR_SIZE];
+ char tailoring[MY_CS_TAILORING_SIZE];
+ size_t tailoring_length;
CHARSET_INFO cs;
int (*add_collation)(CHARSET_INFO *cs);
} MY_CHARSET_LOADER;
@@ -156,9 +185,11 @@ static int cs_enter(MY_XML_PARSER *st,const char *attr, uint len)
struct my_cs_file_section_st *s= cs_file_sec(attr,len);
if ( s && (s->state == _CS_CHARSET))
- {
bzero(&i->cs,sizeof(i->cs));
- }
+
+ if (s && (s->state == _CS_COLLATION))
+ i->tailoring_length= 0;
+
return MY_XML_OK;
}
@@ -242,6 +273,26 @@ static int cs_value(MY_XML_PARSER *st,const char *attr, uint len)
fill_uchar(i->ctype,MY_CS_CTYPE_TABLE_SIZE,attr,len);
i->cs.ctype=i->ctype;
break;
+ case _CS_RESET:
+ case _CS_DIFF1:
+ case _CS_DIFF2:
+ case _CS_DIFF3:
+ {
+ /*
+ Convert collation description from
+ Locale Data Markup Language (LDML)
+ into ICU Collation Customization expression.
+ */
+ char arg[16];
+ const char *cmd[]= {"&","<","<<","<<<"};
+ i->cs.tailoring= i->tailoring;
+ mstr(arg,attr,len,sizeof(arg)-1);
+ if (i->tailoring_length + 20 < sizeof(i->tailoring))
+ {
+ char *dst= i->tailoring_length + i->tailoring;
+ i->tailoring_length+= sprintf(dst," %s %s",cmd[state-_CS_RESET],arg);
+ }
+ }
}
return MY_XML_OK;
}
diff --git a/strings/int2str.c b/strings/int2str.c
index 38e8a5182a3..be86e9735ab 100644
--- a/strings/int2str.c
+++ b/strings/int2str.c
@@ -14,82 +14,95 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*
- Defines: int2str(), itoa(), ltoa()
-
- int2str(dst, radix, val)
- converts the (long) integer "val" to character form and moves it to
- the destination string "dst" followed by a terminating NUL. The
- result is normally a pointer to this NUL character, but if the radix
- is dud the result will be NullS and nothing will be changed.
-
- If radix is -2..-36, val is taken to be SIGNED.
- If radix is 2.. 36, val is taken to be UNSIGNED.
- That is, val is signed if and only if radix is. You will normally
- use radix -10 only through itoa and ltoa, for radix 2, 8, or 16
- unsigned is what you generally want.
-
- _dig_vec is public just in case someone has a use for it.
- The definitions of itoa and ltoa are actually macros in m_string.h,
- but this is where the code is.
-
- Note: The standard itoa() returns a pointer to the argument, when int2str
- returns the pointer to the end-null.
- itoa assumes that 10 -base numbers are allways signed and other arn't.
-*/
-
#include <my_global.h>
#include "m_string.h"
-char NEAR _dig_vec[] =
+/*
+ _dig_vec arrays are public because they are used in several outer places.
+*/
+char NEAR _dig_vec_upper[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+char NEAR _dig_vec_lower[] =
+ "0123456789abcdefghijklmnopqrstuvwxyz";
-char *int2str(register long int val, register char *dst, register int radix)
+/*
+ Convert integer to its string representation in given scale of notation.
+
+ SYNOPSIS
+ int2str()
+ val - value to convert
+ dst - points to buffer where string representation should be stored
+ radix - radix of scale of notation
+ upcase - set to 1 if we should use upper-case digits
+
+ DESCRIPTION
+ Converts the (long) integer value to its character form and moves it to
+ the destination buffer followed by a terminating NUL.
+ If radix is -2..-36, val is taken to be SIGNED, if radix is 2..36, val is
+ taken to be UNSIGNED. That is, val is signed if and only if radix is.
+ All other radixes treated as bad and nothing will be changed in this case.
+
+ For conversion to decimal representation (radix is -10 or 10) one can use
+ optimized int10_to_str() function.
+
+ RETURN VALUE
+ Pointer to ending NUL character or NullS if radix is bad.
+*/
+
+char *
+int2str(register long int val, register char *dst, register int radix,
+ int upcase)
{
char buffer[65];
register char *p;
long int new_val;
+ char *dig_vec= upcase ? _dig_vec_upper : _dig_vec_lower;
- if (radix < 0) {
- if (radix < -36 || radix > -2) return NullS;
- if (val < 0) {
+ if (radix < 0)
+ {
+ if (radix < -36 || radix > -2)
+ return NullS;
+ if (val < 0)
+ {
*dst++ = '-';
val = -val;
}
radix = -radix;
- } else {
- if (radix > 36 || radix < 2) return NullS;
}
- /* The slightly contorted code which follows is due to the
- fact that few machines directly support unsigned long / and %.
- Certainly the VAX C compiler generates a subroutine call. In
- the interests of efficiency (hollow laugh) I let this happen
- for the first digit only; after that "val" will be in range so
- that signed integer division will do. Sorry 'bout that.
- CHECK THE CODE PRODUCED BY YOUR C COMPILER. The first % and /
- should be unsigned, the second % and / signed, but C compilers
- tend to be extraordinarily sensitive to minor details of style.
- This works on a VAX, that's all I claim for it.
- */
+ else if (radix > 36 || radix < 2)
+ return NullS;
+
+ /*
+ The slightly contorted code which follows is due to the fact that
+ few machines directly support unsigned long / and %. Certainly
+ the VAX C compiler generates a subroutine call. In the interests
+ of efficiency (hollow laugh) I let this happen for the first digit
+ only; after that "val" will be in range so that signed integer
+ division will do. Sorry 'bout that. CHECK THE CODE PRODUCED BY
+ YOUR C COMPILER. The first % and / should be unsigned, the second
+ % and / signed, but C compilers tend to be extraordinarily
+ sensitive to minor details of style. This works on a VAX, that's
+ all I claim for it.
+ */
p = &buffer[sizeof(buffer)-1];
*p = '\0';
new_val=(ulong) val / (ulong) radix;
- *--p = _dig_vec[(uchar) ((ulong) val- (ulong) new_val*(ulong) radix)];
+ *--p = dig_vec[(uchar) ((ulong) val- (ulong) new_val*(ulong) radix)];
val = new_val;
#ifdef HAVE_LDIV
while (val != 0)
{
ldiv_t res;
res=ldiv(val,radix);
- *--p = _dig_vec[res.rem];
+ *--p = dig_vec[res.rem];
val= res.quot;
}
#else
while (val != 0)
{
new_val=val/radix;
- *--p = _dig_vec[(uchar) (val-new_val*radix)];
+ *--p = dig_vec[(uchar) (val-new_val*radix)];
val= new_val;
}
#endif
@@ -99,8 +112,21 @@ char *int2str(register long int val, register char *dst, register int radix)
/*
- This is a faster version of the above optimized for the normal case of
- radix 10 / -10
+ Converts integer to its string representation in decimal notation.
+
+ SYNOPSIS
+ int10_to_str()
+ val - value to convert
+ dst - points to buffer where string representation should be stored
+ radix - flag that shows whenever val should be taken as signed or not
+
+ DESCRIPTION
+ This is version of int2str() function which is optimized for normal case
+ of radix 10/-10. It takes only sign of radix parameter into account and
+ not its absolute value.
+
+ RETURN VALUE
+ Pointer to ending NUL character.
*/
char *int10_to_str(long int val,char *dst,int radix)
@@ -133,22 +159,3 @@ char *int10_to_str(long int val,char *dst,int radix)
while ((*dst++ = *p++) != 0) ;
return dst-1;
}
-
-
-#ifdef USE_MY_ITOA
-
- /* Change to less general itoa interface */
-
-char *my_itoa(int val, char *dst, int radix)
-{
- VOID(int2str((long) val,dst,(radix == 10 ? -10 : radix)));
- return dst;
-}
-
-char *my_ltoa(long int val, char *dst, int radix)
-{
- VOID(int2str((long) val,dst,(radix == 10 ? -10 : radix)));
- return dst;
-}
-
-#endif
diff --git a/strings/longlong2str-x86.s b/strings/longlong2str-x86.s
index 8476bf49b75..fcc57810224 100644
--- a/strings/longlong2str-x86.s
+++ b/strings/longlong2str-x86.s
@@ -83,7 +83,7 @@ longlong2str:
divl %ebx
decl %ecx
movl %eax,%esi # quotent in ebp:esi
- movb _dig_vec(%edx),%al # al is faster than dl
+ movb _dig_vec_upper(%edx),%al # al is faster than dl
movb %al,(%ecx) # store value in buff
.align 4
.L155:
@@ -93,7 +93,7 @@ longlong2str:
jl .L153
je .L10_mov # Ready
movl %esi,%eax
- movl $_dig_vec,%ebp
+ movl $_dig_vec_upper,%ebp
.align 4
.L154: # Do rest with integer precision
diff --git a/strings/longlong2str.c b/strings/longlong2str.c
index a991c57b4d9..096531095db 100644
--- a/strings/longlong2str.c
+++ b/strings/longlong2str.c
@@ -43,8 +43,6 @@
#if defined(HAVE_LONG_LONG) && !defined(longlong2str) && !defined(HAVE_LONGLONG2STR)
-extern char NEAR _dig_vec[];
-
/*
This assumes that longlong multiplication is faster than longlong division.
*/
@@ -81,14 +79,14 @@ char *longlong2str(longlong val,char *dst,int radix)
{
ulonglong quo=(ulonglong) val/(uint) radix;
uint rem= (uint) (val- quo* (uint) radix);
- *--p = _dig_vec[rem];
+ *--p = _dig_vec_upper[rem];
val= quo;
}
long_val= (long) val;
while (long_val != 0)
{
long quo= long_val/radix;
- *--p = _dig_vec[(uchar) (long_val - quo*radix)];
+ *--p = _dig_vec_upper[(uchar) (long_val - quo*radix)];
long_val= quo;
}
while ((*dst++ = *p++) != 0) ;
@@ -126,14 +124,14 @@ char *longlong10_to_str(longlong val,char *dst,int radix)
{
ulonglong quo=(ulonglong) val/(uint) 10;
uint rem= (uint) (val- quo* (uint) 10);
- *--p = _dig_vec[rem];
+ *--p = _dig_vec_upper[rem];
val= quo;
}
long_val= (long) val;
while (long_val != 0)
{
long quo= long_val/10;
- *--p = _dig_vec[(uchar) (long_val - quo*10)];
+ *--p = _dig_vec_upper[(uchar) (long_val - quo*10)];
long_val= quo;
}
while ((*dst++ = *p++) != 0) ;
diff --git a/strings/my_strtoll10.c b/strings/my_strtoll10.c
index 493d0d63de2..5217564087c 100644
--- a/strings/my_strtoll10.c
+++ b/strings/my_strtoll10.c
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
-#include <my_sys.h>
+#include <my_sys.h> /* Needed for MY_ERRNO_ERANGE */
#include <m_string.h>
#undef ULONGLONG_MAX
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
index d9d80263d31..784c4762724 100644
--- a/strings/my_vsnprintf.c
+++ b/strings/my_vsnprintf.c
@@ -18,7 +18,6 @@
#include <m_string.h>
#include <stdarg.h>
#include <m_ctype.h>
-#include <assert.h>
/*
Limited snprintf() implementations
@@ -118,7 +117,7 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
if (*fmt== 'u')
store_end= int10_to_str(larg, store_start, 10);
else
- store_end= int2str(larg, store_start, 16);
+ store_end= int2str(larg, store_start, 16, 0);
if ((res_length= (uint) (store_end - store_start)) > to_length)
break; /* num doesn't fit in output */
/* If %#d syntax was used, we have to pre-zero/pre-space the string */
diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh
index 5fdde0d2963..d25686f1c21 100644
--- a/support-files/my-huge.cnf.sh
+++ b/support-files/my-huge.cnf.sh
@@ -1,6 +1,6 @@
-# Example mysql config file for very large systems.
+# Example MySQL config file for very large systems.
#
-# This is for large system with memory of 1G-2G where the system runs mainly
+# This is for a large system with memory of 1G-2G where the system runs mainly
# MySQL.
#
# You can copy this file to
@@ -9,9 +9,9 @@
# installation this directory is @localstatedir@) or
# ~/.my.cnf to set user-specific options.
#
-# One can in this file use all long options that the program supports.
+# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
-# with the --help option.
+# with the "--help" option.
# The following options will be passed to all MySQL clients
[client]
diff --git a/support-files/my-innodb-heavy-4G.cnf.sh b/support-files/my-innodb-heavy-4G.cnf.sh
index 54df6a8bfe6..6def311f474 100644
--- a/support-files/my-innodb-heavy-4G.cnf.sh
+++ b/support-files/my-innodb-heavy-4G.cnf.sh
@@ -13,8 +13,8 @@
# (@localstatedir@ for this installation) or to
# ~/.my.cnf to set user-specific options.
#
-# In this file, you can use all long options that the program supports.
-# If you want to know the options a program supports, run the program
+# In this file, you can use all long options that a program supports.
+# If you want to know which options a program supports, run the program
# with the "--help" option.
#
# More detailed information about the individual options can also be
diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh
index a17ec7b5227..59aca4b32f2 100644
--- a/support-files/my-large.cnf.sh
+++ b/support-files/my-large.cnf.sh
@@ -1,6 +1,6 @@
-# Example mysql config file for large systems.
+# Example MySQL config file for large systems.
#
-# This is for large system with memory = 512M where the system runs mainly
+# This is for a large system with memory = 512M where the system runs mainly
# MySQL.
#
# You can copy this file to
@@ -9,9 +9,9 @@
# installation this directory is @localstatedir@) or
# ~/.my.cnf to set user-specific options.
#
-# One can in this file use all long options that the program supports.
+# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
-# with the --help option.
+# with the "--help" option.
# The following options will be passed to all MySQL clients
[client]
diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh
index d50d0717c17..529740d59f0 100644
--- a/support-files/my-medium.cnf.sh
+++ b/support-files/my-medium.cnf.sh
@@ -1,4 +1,4 @@
-# Example mysql config file for medium systems.
+# Example MySQL config file for medium systems.
#
# This is for a system with little memory (32M - 64M) where MySQL plays
# an important part, or systems up to 128M where MySQL is used together with
@@ -10,9 +10,9 @@
# installation this directory is @localstatedir@) or
# ~/.my.cnf to set user-specific options.
#
-# One can in this file use all long options that the program supports.
+# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
-# with the --help option.
+# with the "--help" option.
# The following options will be passed to all MySQL clients
[client]
diff --git a/support-files/my-small.cnf.sh b/support-files/my-small.cnf.sh
index 2ae62fb48f1..b2ecca6127e 100644
--- a/support-files/my-small.cnf.sh
+++ b/support-files/my-small.cnf.sh
@@ -1,4 +1,4 @@
-# Example mysql config file for small systems.
+# Example MySQL config file for small systems.
#
# This is for a system with little memory (<= 64M) where MySQL is only used
# from time to time and it's important that the mysqld daemon
@@ -10,9 +10,9 @@
# installation this directory is @localstatedir@) or
# ~/.my.cnf to set user-specific options.
#
-# One can in this file use all long options that the program supports.
+# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
-# with the --help option.
+# with the "--help" option.
# The following options will be passed to all MySQL clients
[client]
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 8583b623392..d5c43e61f9d 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -292,7 +292,7 @@ install -m 644 libmysqld/libmysqld.a $RBR%{_libdir}/mysql
# Save manual to avoid rebuilding
mv Docs/manual.ps Docs/manual.ps.save
-make distclean
+make clean
mv Docs/manual.ps.save Docs/manual.ps
# RPM:s destroys Makefile.in files, so we generate them here
@@ -397,7 +397,7 @@ useradd -M -r -d $mysql_datadir -s /bin/bash -c "MySQL server" mysql 2> /dev/nul
chown -R mysql $mysql_datadir
# Initiate databases
-mysql_install_db --rpm
+mysql_install_db --rpm --user=mysql
# Change permissions again to fix any new files.
chown -R mysql $mysql_datadir
@@ -482,6 +482,7 @@ fi
%attr(755, root, root) %{_bindir}/mysql_install_db
%attr(755, root, root) %{_bindir}/mysql_secure_installation
%attr(755, root, root) %{_bindir}/mysql_setpermission
+%attr(755, root, root) %{_bindir}/mysql_tzinfo_to_sql
%attr(755, root, root) %{_bindir}/mysql_zap
%attr(755, root, root) %{_bindir}/mysqlbug
%attr(755, root, root) %{_bindir}/mysqld_multi
@@ -578,6 +579,16 @@ fi
# The spec file changelog only includes changes made to the spec file
# itself
%changelog
+* Wed Jun 30 2004 Lenz Grimmer <lenz@mysql.com>
+
+- fixed server postinstall (mysql_install_db was called with the wrong
+ parameter)
+
+* Thu Jun 24 2004 Lenz Grimmer <lenz@mysql.com>
+
+- added mysql_tzinfo_to_sql to the server subpackage
+- run "make clean" instead of "make distclean"
+
* Mon Apr 05 2004 Lenz Grimmer <lenz@mysql.com>
- added ncurses-devel to the build prerequisites (BUG 3377)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5d6e6a68ae2..5d0e4627b69 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -36,7 +36,6 @@ LIBS = @CLIENT_LIBS@
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la
client_test_LDADD= $(LDADD) $(CXXLDFLAGS)
client_test_SOURCES= client_test.c
-client_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
select_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
diff --git a/tests/client_test.c b/tests/client_test.c
index 21155840115..3652c0f7c8e 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -19,12 +19,6 @@
protocol
Main author: venu ( venu@mysql.com )
-
- NOTES:
- - To be able to test which fields are used, we are not clearing
- the MYSQL_BIND with bzero() but instead just clearing the fields that
- are used by the API.
-
***************************************************************************/
#include <my_global.h>
@@ -38,16 +32,16 @@
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
/* set default options */
-static char *opt_db=0;
-static char *opt_user=0;
-static char *opt_password=0;
-static char *opt_host=0;
-static char *opt_unix_socket=0;
+static char *opt_db= 0;
+static char *opt_user= 0;
+static char *opt_password= 0;
+static char *opt_host= 0;
+static char *opt_unix_socket= 0;
static unsigned int opt_port;
-static my_bool tty_password=0;
+static my_bool tty_password= 0;
-static MYSQL *mysql=0;
-static char query[MAX_TEST_QUERY_LENGTH];
+static MYSQL *mysql= 0;
+static char query[MAX_TEST_QUERY_LENGTH];
static char current_db[]= "client_test_db";
static unsigned int test_count= 0;
static unsigned int opt_count= 0;
@@ -56,20 +50,20 @@ static unsigned int iter_count= 0;
static time_t start_time, end_time;
static double total_time;
-const char *default_dbug_option="d:t:o,/tmp/client_test.trace";
+const char *default_dbug_option= "d:t:o,/tmp/client_test.trace";
#define myheader(str) \
{ \
- fprintf(stdout,"\n\n#####################################\n"); \
- fprintf(stdout,"%d of (%d/%d): %s",test_count++, iter_count,\
+ fprintf(stdout, "\n\n#####################################\n"); \
+ fprintf(stdout, "%d of (%d/%d): %s", test_count++, iter_count, \
opt_count, str); \
- fprintf(stdout," \n#####################################\n"); \
+ fprintf(stdout, " \n#####################################\n"); \
}
#define myheader_r(str) \
{ \
- fprintf(stdout,"\n\n#####################################\n"); \
- fprintf(stdout,"%s", str); \
- fprintf(stdout," \n#####################################\n"); \
+ fprintf(stdout, "\n\n#####################################\n"); \
+ fprintf(stdout, "%s", str); \
+ fprintf(stdout, " \n#####################################\n"); \
}
static void print_error(const char *msg);
@@ -93,17 +87,17 @@ if (r) \
assert(r != 0); \
}
-#define check_execute(stmt,r) \
+#define check_execute(stmt, r) \
{ \
if (r) \
- mysterror(stmt,NULL); \
+ mysterror(stmt, NULL); \
assert(r == 0);\
}
-#define check_execute_r(stmt,r) \
+#define check_execute_r(stmt, r) \
{ \
if (r) \
- mysterror(stmt,NULL); \
+ mysterror(stmt, NULL); \
assert(r != 0);\
}
@@ -119,46 +113,50 @@ assert(stmt != 0); \
if (stmt == 0) \
myerror(NULL);\
assert(stmt == 0);\
-}
+}
#define mytest(x) if (!x) {myerror(NULL);assert(TRUE);}
#define mytest_r(x) if (x) {myerror(NULL);assert(TRUE);}
-/********************************************************
-* print the error message *
-*********************************************************/
+
+/* Print the error message */
+
static void print_error(const char *msg)
-{
+{
if (mysql && mysql_errno(mysql))
{
if (mysql->server_version)
- fprintf(stdout,"\n [MySQL-%s]",mysql->server_version);
+ fprintf(stdout, "\n [MySQL-%s]", mysql->server_version);
else
- fprintf(stdout,"\n [MySQL]");
- fprintf(stdout,"[%d] %s\n",mysql_errno(mysql),mysql_error(mysql));
+ fprintf(stdout, "\n [MySQL]");
+ fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql));
}
else if (msg) fprintf(stderr, " [MySQL] %s\n", msg);
}
+
static void print_st_error(MYSQL_STMT *stmt, const char *msg)
-{
+{
if (stmt && mysql_stmt_errno(stmt))
{
if (stmt->mysql && stmt->mysql->server_version)
- fprintf(stdout,"\n [MySQL-%s]",stmt->mysql->server_version);
+ fprintf(stdout, "\n [MySQL-%s]", stmt->mysql->server_version);
else
- fprintf(stdout,"\n [MySQL]");
+ fprintf(stdout, "\n [MySQL]");
- fprintf(stdout,"[%d] %s\n",mysql_stmt_errno(stmt),
+ fprintf(stdout, "[%d] %s\n", mysql_stmt_errno(stmt),
mysql_stmt_error(stmt));
}
- else if (msg) fprintf(stderr, " [MySQL] %s\n", msg);
+ else if (msg)
+ fprintf(stderr, " [MySQL] %s\n", msg);
}
+
/*
This is to be what mysql_query() is for mysql_real_query(), for
- mysql_prepare(): a variant without the 'length' parameter.
+ mysql_simple_prepare(): a variant without the 'length' parameter.
*/
+
MYSQL_STMT *STDCALL
mysql_simple_prepare(MYSQL *mysql, const char *query)
{
@@ -172,196 +170,198 @@ mysql_simple_prepare(MYSQL *mysql, const char *query)
}
-/********************************************************
-* connect to the server *
-*********************************************************/
+/* Connect to the server */
+
static void client_connect()
{
int rc;
- myheader_r("client_connect");
+ myheader_r("client_connect");
- fprintf(stdout, "\n Establishing a connection to '%s' ...", opt_host);
-
- if (!(mysql = mysql_init(NULL)))
- {
+ fprintf(stdout, "\n Establishing a connection to '%s' ...",
+ opt_host ? opt_host : "");
+
+ if (!(mysql= mysql_init(NULL)))
+ {
myerror("mysql_init() failed");
exit(0);
}
-
- if (!(mysql_real_connect(mysql,opt_host,opt_user,
+
+ if (!(mysql_real_connect(mysql, opt_host, opt_user,
opt_password, opt_db ? opt_db:"test", opt_port,
opt_unix_socket, 0)))
{
- myerror("connection failed");
+ myerror("connection failed");
mysql_close(mysql);
- fprintf(stdout,"\n Check the connection options using --help or -?\n");
+ fprintf(stdout, "\n Check the connection options using --help or -?\n");
exit(0);
- }
-
- fprintf(stdout," OK");
+ }
+
+ fprintf(stdout, " OK");
/* set AUTOCOMMIT to ON*/
mysql_autocommit(mysql, TRUE);
-
+
fprintf(stdout, "\n Creating a test database '%s' ...", current_db);
- strxmov(query,"CREATE DATABASE IF NOT EXISTS ", current_db, NullS);
-
- rc = mysql_query(mysql, query);
+ strxmov(query, "CREATE DATABASE IF NOT EXISTS ", current_db, NullS);
+
+ rc= mysql_query(mysql, query);
myquery(rc);
-
- strxmov(query,"USE ", current_db, NullS);
- rc = mysql_query(mysql, query);
+
+ strxmov(query, "USE ", current_db, NullS);
+ rc= mysql_query(mysql, query);
myquery(rc);
-
- fprintf(stdout," OK");
+
+ fprintf(stdout, " OK");
}
-/********************************************************
-* close the connection *
-*********************************************************/
+
+/* Close the connection */
+
static void client_disconnect()
-{
- myheader_r("client_disconnect");
+{
+ myheader_r("client_disconnect");
if (mysql)
{
fprintf(stdout, "\n droping the test database '%s' ...", current_db);
- strxmov(query,"DROP DATABASE IF EXISTS ", current_db, NullS);
-
+ strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS);
+
mysql_query(mysql, query);
fprintf(stdout, " OK");
-
+
fprintf(stdout, "\n closing the connection ...");
mysql_close(mysql);
fprintf(stdout, " OK\n");
}
}
-/********************************************************
-* query processing *
-*********************************************************/
+
+/* Query processing */
+
static void client_query()
{
int rc;
myheader("client_query");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS myclient_test");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS myclient_test");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE myclient_test(id int primary key auto_increment,\
- name varchar(20))");
+ rc= mysql_query(mysql, "CREATE TABLE myclient_test("
+ "id int primary key auto_increment, "
+ "name varchar(20))");
myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE myclient_test(id int, name varchar(20))");
+
+ rc= mysql_query(mysql, "CREATE TABLE myclient_test(id int, name varchar(20))");
myquery_r(rc);
-
- rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('mysql')");
+
+ rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('mysql')");
myquery(rc);
-
- rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('monty')");
+
+ rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('monty')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('venu')");
+ rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('venu')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('deleted')");
+ rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('deleted')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO myclient_test(name) VALUES('deleted')");
+ rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('deleted')");
myquery(rc);
- rc = mysql_query(mysql,"UPDATE myclient_test SET name='updated' WHERE name='deleted'");
+ rc= mysql_query(mysql, "UPDATE myclient_test SET name= 'updated' "
+ "WHERE name= 'deleted'");
myquery(rc);
- rc = mysql_query(mysql,"UPDATE myclient_test SET id=3 WHERE name='updated'");
+ rc= mysql_query(mysql, "UPDATE myclient_test SET id= 3 WHERE name= 'updated'");
myquery_r(rc);
}
-/********************************************************
-* print dashes *
-*********************************************************/
+
+/* Print dashes */
+
static void my_print_dashes(MYSQL_RES *result)
{
MYSQL_FIELD *field;
- unsigned int i,j;
+ unsigned int i, j;
- mysql_field_seek(result,0);
- fputc('\t',stdout);
+ mysql_field_seek(result, 0);
+ fputc('\t', stdout);
fputc('+', stdout);
- for(i=0; i< mysql_num_fields(result); i++)
+ for(i= 0; i< mysql_num_fields(result); i++)
{
- field = mysql_fetch_field(result);
- for(j=0; j < field->max_length+2; j++)
- fputc('-',stdout);
- fputc('+',stdout);
+ field= mysql_fetch_field(result);
+ for(j= 0; j < field->max_length+2; j++)
+ fputc('-', stdout);
+ fputc('+', stdout);
}
- fputc('\n',stdout);
+ fputc('\n', stdout);
}
-/********************************************************
-* print resultset metadata information *
-*********************************************************/
+
+/* Print resultset metadata information */
+
static void my_print_result_metadata(MYSQL_RES *result)
{
MYSQL_FIELD *field;
- unsigned int i,j;
+ unsigned int i, j;
unsigned int field_count;
- mysql_field_seek(result,0);
+ mysql_field_seek(result, 0);
fputc('\n', stdout);
fputc('\n', stdout);
- field_count = mysql_num_fields(result);
- for(i=0; i< field_count; i++)
+ field_count= mysql_num_fields(result);
+ for(i= 0; i< field_count; i++)
{
- field = mysql_fetch_field(result);
- j = strlen(field->name);
+ field= mysql_fetch_field(result);
+ j= strlen(field->name);
if (j < field->max_length)
- j = field->max_length;
+ j= field->max_length;
if (j < 4 && !IS_NOT_NULL(field->flags))
- j = 4;
- field->max_length = j;
+ j= 4;
+ field->max_length= j;
}
my_print_dashes(result);
- fputc('\t',stdout);
+ fputc('\t', stdout);
fputc('|', stdout);
- mysql_field_seek(result,0);
- for(i=0; i< field_count; i++)
+ mysql_field_seek(result, 0);
+ for(i= 0; i< field_count; i++)
{
- field = mysql_fetch_field(result);
- fprintf(stdout, " %-*s |",(int) field->max_length, field->name);
+ field= mysql_fetch_field(result);
+ fprintf(stdout, " %-*s |", (int) field->max_length, field->name);
}
fputc('\n', stdout);
my_print_dashes(result);
}
-/********************************************************
-* process the result set *
-*********************************************************/
+
+/* Process the result set */
+
int my_process_result_set(MYSQL_RES *result)
{
MYSQL_ROW row;
MYSQL_FIELD *field;
unsigned int i;
- unsigned int row_count=0;
-
+ unsigned int row_count= 0;
+
if (!result)
return 0;
my_print_result_metadata(result);
- while ((row = mysql_fetch_row(result)) != NULL)
+ while ((row= mysql_fetch_row(result)) != NULL)
{
- mysql_field_seek(result,0);
- fputc('\t',stdout);
- fputc('|',stdout);
+ mysql_field_seek(result, 0);
+ fputc('\t', stdout);
+ fputc('|', stdout);
- for(i=0; i< mysql_num_fields(result); i++)
+ for(i= 0; i< mysql_num_fields(result); i++)
{
- field = mysql_fetch_field(result);
+ field= mysql_fetch_field(result);
if (row[i] == NULL)
fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
else if (IS_NUM(field->type))
@@ -369,38 +369,39 @@ int my_process_result_set(MYSQL_RES *result)
else
fprintf(stdout, " %-*s |", (int) field->max_length, row[i]);
}
- fputc('\t',stdout);
- fputc('\n',stdout);
+ fputc('\t', stdout);
+ fputc('\n', stdout);
row_count++;
}
- if (row_count)
+ if (row_count)
my_print_dashes(result);
if (mysql_errno(mysql) != 0)
fprintf(stderr, "\n\tmysql_fetch_row() failed\n");
else
- fprintf(stdout,"\n\t%d %s returned\n", row_count,
+ fprintf(stdout, "\n\t%d %s returned\n", row_count,
row_count == 1 ? "row" : "rows");
return row_count;
}
+
int my_process_result(MYSQL *mysql)
{
MYSQL_RES *result;
int row_count;
- if (!(result = mysql_store_result(mysql)))
+ if (!(result= mysql_store_result(mysql)))
return 0;
-
+
row_count= my_process_result_set(result);
-
+
mysql_free_result(result);
return row_count;
}
-/********************************************************
-* process the stmt result set *
-*********************************************************/
+
+/* Process the statement result set */
+
#define MAX_RES_FIELDS 50
#define MAX_FIELD_DATA_SIZE 255
@@ -416,45 +417,50 @@ uint my_process_stmt_result(MYSQL_STMT *stmt)
my_bool is_null[MAX_RES_FIELDS];
int rc, i;
- if (!(result= mysql_get_metadata(stmt))) /* No meta info */
+ if (!(result= mysql_stmt_result_metadata(stmt))) /* No meta info */
{
- while (!mysql_fetch(stmt))
+ while (!mysql_stmt_fetch(stmt))
row_count++;
return row_count;
}
-
+
field_count= min(mysql_num_fields(result), MAX_RES_FIELDS);
- for(i=0; i < field_count; i++)
+
+ bzero((char*) buffer, sizeof(buffer));
+ bzero((char*) length, sizeof(length));
+ bzero((char*) is_null, sizeof(is_null));
+
+ for(i= 0; i < field_count; i++)
{
buffer[i].buffer_type= MYSQL_TYPE_STRING;
buffer[i].buffer_length= MAX_FIELD_DATA_SIZE;
buffer[i].length= &length[i];
- buffer[i].buffer= (char*) data[i];
+ buffer[i].buffer= (void *) data[i];
buffer[i].is_null= &is_null[i];
}
my_print_result_metadata(result);
- rc= mysql_bind_result(stmt,buffer);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, buffer);
+ check_execute(stmt, rc);
rc= mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
-
- mysql_field_seek(result, 0);
- while (mysql_fetch(stmt) == 0)
- {
- fputc('\t',stdout);
- fputc('|',stdout);
-
- mysql_field_seek(result,0);
- for (i=0; i < field_count; i++)
+ check_execute(stmt, rc);
+
+ mysql_field_seek(result, 0);
+ while (mysql_stmt_fetch(stmt) == 0)
+ {
+ fputc('\t', stdout);
+ fputc('|', stdout);
+
+ mysql_field_seek(result, 0);
+ for (i= 0; i < field_count; i++)
{
- field = mysql_fetch_field(result);
+ field= mysql_fetch_field(result);
if (is_null[i])
fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
else if (length[i] == 0)
{
- data[i][0]='\0'; /* unmodified buffer */
+ data[i][0]= '\0'; /* unmodified buffer */
fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
}
else if (IS_NUM(field->type))
@@ -462,179 +468,183 @@ uint my_process_stmt_result(MYSQL_STMT *stmt)
else
fprintf(stdout, " %-*s |", (int) field->max_length, data[i]);
}
- fputc('\t',stdout);
- fputc('\n',stdout);
+ fputc('\t', stdout);
+ fputc('\n', stdout);
row_count++;
}
if (row_count)
my_print_dashes(result);
- fprintf(stdout,"\n\t%d %s returned\n", row_count,
+ fprintf(stdout, "\n\t%d %s returned\n", row_count,
row_count == 1 ? "row" : "rows");
mysql_free_result(result);
return row_count;
}
-/********************************************************
-* process the stmt result set *
-*********************************************************/
+
+/* Prepare statement, execute, and process result set for given query */
+
uint my_stmt_result(const char *buff)
{
MYSQL_STMT *stmt;
uint row_count;
int rc;
- fprintf(stdout,"\n\n %s", buff);
- stmt= mysql_simple_prepare(mysql,buff);
+ fprintf(stdout, "\n\n %s", buff);
+ stmt= mysql_simple_prepare(mysql, buff);
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
row_count= my_process_stmt_result(stmt);
mysql_stmt_close(stmt);
-
+
return row_count;
}
-/*
- Utility function to verify a particular column data
-*/
-static void verify_col_data(const char *table, const char *col,
+
+/* Utility function to verify a particular column data */
+
+static void verify_col_data(const char *table, const char *col,
const char *exp_data)
{
MYSQL_RES *result;
MYSQL_ROW row;
int rc, field= 1;
-
+
if (table && col)
{
- strxmov(query,"SELECT ",col," FROM ",table," LIMIT 1", NullS);
- fprintf(stdout,"\n %s", query);
- rc = mysql_query(mysql, query);
+ strxmov(query, "SELECT ", col, " FROM ", table, " LIMIT 1", NullS);
+ fprintf(stdout, "\n %s", query);
+ rc= mysql_query(mysql, query);
myquery(rc);
field= 0;
}
- result = mysql_use_result(mysql);
+ result= mysql_use_result(mysql);
mytest(result);
if (!(row= mysql_fetch_row(result)) || !row[field])
{
- fprintf(stdout,"\n *** ERROR: FAILED TO GET THE RESULT ***");
+ fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***");
exit(1);
}
- if (strcmp(row[field],exp_data))
+ if (strcmp(row[field], exp_data))
{
- fprintf(stdout,"\n obtained: `%s` (expected: `%s`)",
- row[field], exp_data);
+ fprintf(stdout, "\n obtained: `%s` (expected: `%s`)",
+ row[field], exp_data);
assert(0);
}
mysql_free_result(result);
}
-/*
- Utility function to verify the field members
-*/
-static void verify_prepare_field(MYSQL_RES *result,
- unsigned int no,const char *name, const char *org_name,
- enum enum_field_types type, const char *table,
- const char *org_table, const char *db,
+/* Utility function to verify the field members */
+
+static void verify_prepare_field(MYSQL_RES *result,
+ unsigned int no, const char *name, const char *org_name,
+ enum enum_field_types type, const char *table,
+ const char *org_table, const char *db,
unsigned long length, const char *def)
{
MYSQL_FIELD *field;
- if (!(field= mysql_fetch_field_direct(result,no)))
+ if (!(field= mysql_fetch_field_direct(result, no)))
{
- fprintf(stdout,"\n *** ERROR: FAILED TO GET THE RESULT ***");
+ fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***");
exit(1);
}
- fprintf(stdout,"\n field[%d]:", no);
- fprintf(stdout,"\n name :`%s`\t(expected: `%s`)", field->name, name);
- fprintf(stdout,"\n org_name :`%s`\t(expected: `%s`)", field->org_name, org_name);
- fprintf(stdout,"\n type :`%d`\t(expected: `%d`)", field->type, type);
- fprintf(stdout,"\n table :`%s`\t(expected: `%s`)", field->table, table);
- fprintf(stdout,"\n org_table:`%s`\t(expected: `%s`)", field->org_table, org_table);
- fprintf(stdout,"\n database :`%s`\t(expected: `%s`)", field->db, db);
- fprintf(stdout,"\n length :`%ld`\t(expected: `%ld`)", field->length, length);
- fprintf(stdout,"\n maxlength:`%ld`", field->max_length);
- fprintf(stdout,"\n charsetnr:`%d`", field->charsetnr);
- fprintf(stdout,"\n default :`%s`\t(expected: `%s`)", field->def ? field->def : "(null)", def ? def: "(null)");
- fprintf(stdout,"\n");
- assert(strcmp(field->name,name) == 0);
- assert(strcmp(field->org_name,org_name) == 0);
+ fprintf(stdout, "\n field[%d]:", no);
+ fprintf(stdout, "\n name :`%s`\t(expected: `%s`)", field->name, name);
+ fprintf(stdout, "\n org_name :`%s`\t(expected: `%s`)",
+ field->org_name, org_name);
+ fprintf(stdout, "\n type :`%d`\t(expected: `%d`)", field->type, type);
+ fprintf(stdout, "\n table :`%s`\t(expected: `%s`)",
+ field->table, table);
+ fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)",
+ field->org_table, org_table);
+ fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db);
+ fprintf(stdout, "\n length :`%ld`\t(expected: `%ld`)",
+ field->length, length);
+ fprintf(stdout, "\n maxlength:`%ld`", field->max_length);
+ fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr);
+ fprintf(stdout, "\n default :`%s`\t(expected: `%s`)",
+ field->def ? field->def : "(null)", def ? def: "(null)");
+ fprintf(stdout, "\n");
+ assert(strcmp(field->name, name) == 0);
+ assert(strcmp(field->org_name, org_name) == 0);
assert(field->type == type);
- assert(strcmp(field->table,table) == 0);
- assert(strcmp(field->org_table,org_table) == 0);
- assert(strcmp(field->db,db) == 0);
+ assert(strcmp(field->table, table) == 0);
+ assert(strcmp(field->org_table, org_table) == 0);
+ assert(strcmp(field->db, db) == 0);
assert(field->length == length);
if (def)
- assert(strcmp(field->def,def) == 0);
+ assert(strcmp(field->def, def) == 0);
}
-/*
- Utility function to verify the parameter count
-*/
+
+/* Utility function to verify the parameter count */
+
static void verify_param_count(MYSQL_STMT *stmt, long exp_count)
{
- long param_count= mysql_param_count(stmt);
- fprintf(stdout,"\n total parameters in stmt: `%ld` (expected: `%ld`)",
+ long param_count= mysql_stmt_param_count(stmt);
+ fprintf(stdout, "\n total parameters in stmt: `%ld` (expected: `%ld`)",
param_count, exp_count);
assert(param_count == exp_count);
}
-/*
- Utility function to verify the total affected rows
-*/
+
+/* Utility function to verify the total affected rows */
+
static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count)
{
ulonglong affected_rows= mysql_stmt_affected_rows(stmt);
- fprintf(stdout,"\n total affected rows: `%lld` (expected: `%lld`)",
+ fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
affected_rows, exp_count);
assert(affected_rows == exp_count);
}
-/*
- Utility function to verify the total affected rows
-*/
+
+/* Utility function to verify the total affected rows */
+
static void verify_affected_rows(ulonglong exp_count)
{
ulonglong affected_rows= mysql_affected_rows(mysql);
- fprintf(stdout,"\n total affected rows: `%lld` (expected: `%lld`)",
+ fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
affected_rows, exp_count);
assert(affected_rows == exp_count);
}
-/*
- Utility function to verify the total fields count
-*/
+
+/* Utility function to verify the total fields count */
+
static void verify_field_count(MYSQL_RES *result, uint exp_count)
{
uint field_count= mysql_num_fields(result);
- fprintf(stdout,"\n total fields in the result set: `%d` (expected: `%d`)",
+ fprintf(stdout, "\n total fields in the result set: `%d` (expected: `%d`)",
field_count, exp_count);
assert(field_count == exp_count);
}
-/*
- Utility function to execute a query using prepare-execute
-*/
+
+/* Utility function to execute a query using prepare-execute */
+
static void execute_prepare_query(const char *query, ulonglong exp_count)
{
MYSQL_STMT *stmt;
ulonglong affected_rows;
int rc;
- stmt= mysql_simple_prepare(mysql,query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc = mysql_execute(stmt);
- myquery(rc);
+ rc= mysql_stmt_execute(stmt);
+ myquery(rc);
affected_rows= mysql_stmt_affected_rows(stmt);
- fprintf(stdout,"\n total affected rows: `%lld` (expected: `%lld`)",
+ fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
affected_rows, exp_count);
assert(affected_rows == exp_count);
@@ -642,9 +652,8 @@ static void execute_prepare_query(const char *query, ulonglong exp_count)
}
-/********************************************************
-* store result processing *
-*********************************************************/
+/* Store result processing */
+
static void client_store_result()
{
MYSQL_RES *result;
@@ -652,63 +661,63 @@ static void client_store_result()
myheader("client_store_result");
- rc = mysql_query(mysql, "SELECT * FROM myclient_test");
+ rc= mysql_query(mysql, "SELECT * FROM myclient_test");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
my_process_result_set(result);
mysql_free_result(result);
}
-/********************************************************
-* fetch the results
-*********************************************************/
+
+/* Fetch the results */
+
static void client_use_result()
{
MYSQL_RES *result;
int rc;
myheader("client_use_result");
- rc = mysql_query(mysql, "SELECT * FROM myclient_test");
+ rc= mysql_query(mysql, "SELECT * FROM myclient_test");
myquery(rc);
/* get the result */
- result = mysql_use_result(mysql);
+ result= mysql_use_result(mysql);
mytest(result);
my_process_result_set(result);
mysql_free_result(result);
}
-/*
- Separate thread query to test some cases
-*/
+
+/* Separate thread query to test some cases */
+
static my_bool thread_query(char *query)
{
MYSQL *l_mysql;
my_bool error;
error= 0;
- fprintf(stdout,"\n in thread_query(%s)", query);
- if (!(l_mysql = mysql_init(NULL)))
- {
+ fprintf(stdout, "\n in thread_query(%s)", query);
+ if (!(l_mysql= mysql_init(NULL)))
+ {
myerror("mysql_init() failed");
return 1;
}
- if (!(mysql_real_connect(l_mysql,opt_host,opt_user,
- opt_password, current_db, opt_port,
- opt_unix_socket, 0)))
+ if (!(mysql_real_connect(l_mysql, opt_host, opt_user,
+ opt_password, current_db, opt_port,
+ opt_unix_socket, 0)))
{
- myerror("connection failed");
+ myerror("connection failed");
error= 1;
goto end;
- }
- if (mysql_query(l_mysql,(char *)query))
+ }
+ if (mysql_query(l_mysql, (char *)query))
{
- fprintf(stderr,"Query failed (%s)\n",mysql_error(l_mysql));
+ fprintf(stderr, "Query failed (%s)\n", mysql_error(l_mysql));
error= 1;
goto end;
}
@@ -719,9 +728,8 @@ end:
}
-/********************************************************
-* query processing *
-*********************************************************/
+/* Query processing */
+
static void test_debug_example()
{
int rc;
@@ -729,35 +737,38 @@ static void test_debug_example()
myheader("test_debug_example");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_debug_example");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_debug_example");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_debug_example(id int primary key auto_increment,\
- name varchar(20),xxx int)");
+ rc= mysql_query(mysql, "CREATE TABLE test_debug_example("
+ "id INT PRIMARY KEY AUTO_INCREMENT, "
+ "name VARCHAR(20), xxx INT)");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_debug_example(name) VALUES('mysql')");
+ rc= mysql_query(mysql, "INSERT INTO test_debug_example (name) "
+ "VALUES ('mysql')");
myquery(rc);
- rc = mysql_query(mysql,"UPDATE test_debug_example SET name='updated' WHERE name='deleted'");
+ rc= mysql_query(mysql, "UPDATE test_debug_example SET name='updated' "
+ "WHERE name='deleted'");
myquery(rc);
- rc = mysql_query(mysql,"SELECT * FROM test_debug_example where name='mysql'");
+ rc= mysql_query(mysql, "SELECT * FROM test_debug_example where name='mysql'");
myquery(rc);
- result = mysql_use_result(mysql);
+ result= mysql_use_result(mysql);
mytest(result);
my_process_result_set(result);
mysql_free_result(result);
- rc = mysql_query(mysql,"DROP TABLE test_debug_example");
+ rc= mysql_query(mysql, "DROP TABLE test_debug_example");
myquery(rc);
}
-/********************************************************
-* to test autocommit feature *
-*********************************************************/
+
+/* Test autocommit feature for BDB tables */
+
static void test_tran_bdb()
{
MYSQL_RES *result;
@@ -767,76 +778,71 @@ static void test_tran_bdb()
myheader("test_tran_bdb");
/* set AUTOCOMMIT to OFF */
- rc = mysql_autocommit(mysql, FALSE);
+ rc= mysql_autocommit(mysql, FALSE);
myquery(rc);
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS my_demo_transaction");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_demo_transaction");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
/* create the table 'mytran_demo' of type BDB' or 'InnoDB' */
- rc = mysql_query(mysql,"CREATE TABLE my_demo_transaction(col1 int ,col2 varchar(30)) TYPE = BDB");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE my_demo_transaction( "
+ "col1 int , col2 varchar(30)) TYPE= BDB");
myquery(rc);
/* insert a row and commit the transaction */
- rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(10,'venu')");
+ rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(10, 'venu')");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* now insert the second row, and rollback the transaction */
- rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(20,'mysql')");
+ rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(20, 'mysql')");
myquery(rc);
- rc = mysql_rollback(mysql);
+ rc= mysql_rollback(mysql);
myquery(rc);
/* delete first row, and rollback it */
- rc = mysql_query(mysql,"DELETE FROM my_demo_transaction WHERE col1 = 10");
+ rc= mysql_query(mysql, "DELETE FROM my_demo_transaction WHERE col1= 10");
myquery(rc);
- rc = mysql_rollback(mysql);
+ rc= mysql_rollback(mysql);
myquery(rc);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM my_demo_transaction");
+ rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
my_process_result_set(result);
mysql_free_result(result);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM my_demo_transaction");
+ rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
myquery(rc);
/* get the result */
- result = mysql_use_result(mysql);
+ result= mysql_use_result(mysql);
mytest(result);
- row = mysql_fetch_row(result);
+ row= mysql_fetch_row(result);
mytest(row);
- row = mysql_fetch_row(result);
+ row= mysql_fetch_row(result);
mytest_r(row);
mysql_free_result(result);
- mysql_autocommit(mysql,TRUE);
+ mysql_autocommit(mysql, TRUE);
}
-/********************************************************
-* to test autocommit feature *
-*********************************************************/
+
+/* Test autocommit feature for InnoDB tables */
+
static void test_tran_innodb()
{
MYSQL_RES *result;
@@ -846,76 +852,69 @@ static void test_tran_innodb()
myheader("test_tran_innodb");
/* set AUTOCOMMIT to OFF */
- rc = mysql_autocommit(mysql, FALSE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS my_demo_transaction");
+ rc= mysql_autocommit(mysql, FALSE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_demo_transaction");
myquery(rc);
/* create the table 'mytran_demo' of type BDB' or 'InnoDB' */
- rc = mysql_query(mysql,"CREATE TABLE my_demo_transaction(col1 int ,col2 varchar(30)) TYPE = InnoDB");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE my_demo_transaction(col1 int, "
+ "col2 varchar(30)) TYPE= InnoDB");
myquery(rc);
/* insert a row and commit the transaction */
- rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(10,'venu')");
+ rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(10, 'venu')");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* now insert the second row, and rollback the transaction */
- rc = mysql_query(mysql,"INSERT INTO my_demo_transaction VALUES(20,'mysql')");
+ rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(20, 'mysql')");
myquery(rc);
- rc = mysql_rollback(mysql);
+ rc= mysql_rollback(mysql);
myquery(rc);
/* delete first row, and rollback it */
- rc = mysql_query(mysql,"DELETE FROM my_demo_transaction WHERE col1 = 10");
+ rc= mysql_query(mysql, "DELETE FROM my_demo_transaction WHERE col1= 10");
myquery(rc);
- rc = mysql_rollback(mysql);
+ rc= mysql_rollback(mysql);
myquery(rc);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM my_demo_transaction");
+ rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
my_process_result_set(result);
mysql_free_result(result);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM my_demo_transaction");
+ rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
myquery(rc);
/* get the result */
- result = mysql_use_result(mysql);
+ result= mysql_use_result(mysql);
mytest(result);
- row = mysql_fetch_row(result);
+ row= mysql_fetch_row(result);
mytest(row);
- row = mysql_fetch_row(result);
+ row= mysql_fetch_row(result);
mytest_r(row);
mysql_free_result(result);
- mysql_autocommit(mysql,TRUE);
+ mysql_autocommit(mysql, TRUE);
}
-/********************************************************
- To test simple prepares of all DML statements
-*********************************************************/
+/* Test simple prepares of all DML statements */
static void test_prepare_simple()
{
@@ -924,69 +923,66 @@ static void test_prepare_simple()
myheader("test_prepare_simple");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_simple");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_simple");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_prepare_simple(id int, name varchar(50))");
+ rc= mysql_query(mysql, "CREATE TABLE test_prepare_simple("
+ "id int, name varchar(50))");
myquery(rc);
/* insert */
- strmov(query,"INSERT INTO test_prepare_simple VALUES(?,?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_prepare_simple VALUES(?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
mysql_stmt_close(stmt);
/* update */
- strmov(query,"UPDATE test_prepare_simple SET id=? WHERE id=? AND name= ?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "UPDATE test_prepare_simple SET id=? WHERE id=? AND name= ?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,3);
+ verify_param_count(stmt, 3);
mysql_stmt_close(stmt);
/* delete */
- strmov(query,"DELETE FROM test_prepare_simple WHERE id=10");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "DELETE FROM test_prepare_simple WHERE id=10");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,0);
+ verify_param_count(stmt, 0);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
mysql_stmt_close(stmt);
/* delete */
- strmov(query,"DELETE FROM test_prepare_simple WHERE id=?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "DELETE FROM test_prepare_simple WHERE id=?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,1);
+ verify_param_count(stmt, 1);
mysql_stmt_close(stmt);
/* select */
- strmov(query,"SELECT * FROM test_prepare_simple WHERE id=? AND name= ?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "SELECT * FROM test_prepare_simple WHERE id=? AND name= ?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
}
-/********************************************************
-* to test simple prepare field results *
-*********************************************************/
+/* Test simple prepare field results */
+
static void test_prepare_field_result()
{
MYSQL_STMT *stmt;
@@ -995,41 +991,38 @@ static void test_prepare_field_result()
myheader("test_prepare_field_result");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_field_result");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_field_result");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_prepare_field_result(int_c int, "
+ "var_c varchar(50), ts_c timestamp(14), "
+ "char_c char(3), date_c date, extra tinyint)");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_prepare_field_result(int_c int, \
- var_c varchar(50), ts_c timestamp(14),\
- char_c char(3), date_c date,extra tinyint)");
- myquery(rc);
-
/* insert */
- strmov(query,"SELECT int_c,var_c,date_c as date,ts_c,char_c FROM \
- test_prepare_field_result as t1 WHERE int_c=?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "SELECT int_c, var_c, date_c as date, ts_c, char_c FROM "
+ " test_prepare_field_result as t1 WHERE int_c=?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,1);
+ verify_param_count(stmt, 1);
- result = mysql_get_metadata(stmt);
+ result= mysql_stmt_result_metadata(stmt);
mytest(result);
-
+
my_print_result_metadata(result);
- fprintf(stdout,"\n\n field attributes:\n");
- verify_prepare_field(result,0,"int_c","int_c",MYSQL_TYPE_LONG,
- "t1","test_prepare_field_result",current_db,11,0);
- verify_prepare_field(result,1,"var_c","var_c",MYSQL_TYPE_VAR_STRING,
- "t1","test_prepare_field_result",current_db,50,0);
- verify_prepare_field(result,2,"date","date_c",MYSQL_TYPE_DATE,
- "t1","test_prepare_field_result",current_db,10,0);
- verify_prepare_field(result,3,"ts_c","ts_c",MYSQL_TYPE_TIMESTAMP,
- "t1","test_prepare_field_result",current_db,19,0);
- verify_prepare_field(result,4,"char_c","char_c",MYSQL_TYPE_STRING,
- "t1","test_prepare_field_result",current_db,3,0);
+ fprintf(stdout, "\n\n field attributes:\n");
+ verify_prepare_field(result, 0, "int_c", "int_c", MYSQL_TYPE_LONG,
+ "t1", "test_prepare_field_result", current_db, 11, 0);
+ verify_prepare_field(result, 1, "var_c", "var_c", MYSQL_TYPE_VAR_STRING,
+ "t1", "test_prepare_field_result", current_db, 50, 0);
+ verify_prepare_field(result, 2, "date", "date_c", MYSQL_TYPE_DATE,
+ "t1", "test_prepare_field_result", current_db, 10, 0);
+ verify_prepare_field(result, 3, "ts_c", "ts_c", MYSQL_TYPE_TIMESTAMP,
+ "t1", "test_prepare_field_result", current_db, 19, 0);
+ verify_prepare_field(result, 4, "char_c", "char_c", MYSQL_TYPE_STRING,
+ "t1", "test_prepare_field_result", current_db, 3, 0);
verify_field_count(result, 5);
mysql_free_result(result);
@@ -1037,9 +1030,8 @@ static void test_prepare_field_result()
}
-/********************************************************
-* to test simple prepare field results *
-*********************************************************/
+/* Test simple prepare field results */
+
static void test_prepare_syntax()
{
MYSQL_STMT *stmt;
@@ -1047,32 +1039,29 @@ static void test_prepare_syntax()
myheader("test_prepare_syntax");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_syntax");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_syntax");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_prepare_syntax("
+ "id int, name varchar(50), extra int)");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_prepare_syntax(id int, name varchar(50), extra int)");
- myquery(rc);
-
- strmov(query,"INSERT INTO test_prepare_syntax VALUES(?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_prepare_syntax VALUES(?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt_r(stmt);
- strmov(query,"SELECT id,name FROM test_prepare_syntax WHERE id=? AND WHERE");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "SELECT id, name FROM test_prepare_syntax WHERE id=? AND WHERE");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt_r(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
}
-/********************************************************
-* to test simple prepare *
-*********************************************************/
+/* Test a simple prepare */
+
static void test_prepare()
{
MYSQL_STMT *stmt;
@@ -1090,50 +1079,49 @@ static void test_prepare()
myheader("test_prepare");
- rc = mysql_autocommit(mysql, TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS my_prepare");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_prepare");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE my_prepare(col1 tinyint,\
- col2 varchar(15), col3 int,\
- col4 smallint, col5 bigint, \
- col6 float, col7 double )");
+ rc= mysql_query(mysql, "CREATE TABLE my_prepare(col1 tinyint, "
+ "col2 varchar(15), col3 int, "
+ "col4 smallint, col5 bigint, "
+ "col6 float, col7 double )");
myquery(rc);
/* insert by prepare */
- strxmov(query,"INSERT INTO my_prepare VALUES(?,?,?,?,?,?,?)",NullS);
- stmt = mysql_simple_prepare(mysql, query);
+ strxmov(query, "INSERT INTO my_prepare VALUES(?, ?, ?, ?, ?, ?, ?)", NullS);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,7);
+ verify_param_count(stmt, 7);
+
+ bzero((char*) bind, sizeof(bind));
/* tinyint */
- bind[0].buffer_type=FIELD_TYPE_TINY;
- bind[0].buffer= (char *)&tiny_data;
+ bind[0].buffer_type= MYSQL_TYPE_TINY;
+ bind[0].buffer= (void *)&tiny_data;
/* string */
- bind[1].buffer_type=FIELD_TYPE_STRING;
- bind[1].buffer= (char *)str_data;
- bind[1].buffer_length= 1000; /* Max string length */
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= (void *)str_data;
+ bind[1].buffer_length= 1000; /* Max string length */
/* integer */
- bind[2].buffer_type=FIELD_TYPE_LONG;
- bind[2].buffer= (char *)&int_data;
+ bind[2].buffer_type= MYSQL_TYPE_LONG;
+ bind[2].buffer= (void *)&int_data;
/* short */
- bind[3].buffer_type=FIELD_TYPE_SHORT;
- bind[3].buffer= (char *)&small_data;
+ bind[3].buffer_type= MYSQL_TYPE_SHORT;
+ bind[3].buffer= (void *)&small_data;
/* bigint */
- bind[4].buffer_type=FIELD_TYPE_LONGLONG;
- bind[4].buffer= (char *)&big_data;
+ bind[4].buffer_type= MYSQL_TYPE_LONGLONG;
+ bind[4].buffer= (void *)&big_data;
/* float */
- bind[5].buffer_type=FIELD_TYPE_FLOAT;
- bind[5].buffer= (char *)&real_data;
+ bind[5].buffer_type= MYSQL_TYPE_FLOAT;
+ bind[5].buffer= (void *)&real_data;
/* double */
- bind[6].buffer_type=FIELD_TYPE_DOUBLE;
- bind[6].buffer= (char *)&double_data;
+ bind[6].buffer_type= MYSQL_TYPE_DOUBLE;
+ bind[6].buffer= (void *)&double_data;
for (i= 0; i < (int) array_elements(bind); i++)
{
@@ -1142,20 +1130,20 @@ static void test_prepare()
is_null[i]= 0;
}
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- int_data = 320;
- small_data = 1867;
- big_data = 1000;
- real_data = 2;
- double_data = 6578.001;
+ int_data= 320;
+ small_data= 1867;
+ big_data= 1000;
+ real_data= 2;
+ double_data= 6578.001;
/* now, execute the prepared statement to insert 10 records.. */
- for (tiny_data=0; tiny_data < 100; tiny_data++)
+ for (tiny_data= 0; tiny_data < 100; tiny_data++)
{
- length[1]= my_sprintf(str_data,(str_data, "MySQL%d",int_data));
- rc = mysql_execute(stmt);
+ length[1]= my_sprintf(str_data, (str_data, "MySQL%d", int_data));
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
int_data += 25;
small_data += 10;
@@ -1167,45 +1155,45 @@ static void test_prepare()
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* test the results now, only one row should exists */
assert(tiny_data == (char) my_stmt_result("SELECT * FROM my_prepare"));
-
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM my_prepare");
+
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM my_prepare");
check_stmt(stmt);
- rc = mysql_bind_result(stmt, bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
/* get the result */
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
- o_int_data = 320;
- o_small_data = 1867;
- o_big_data = 1000;
- o_real_data = 2;
- o_double_data = 6578.001;
+
+ o_int_data= 320;
+ o_small_data= 1867;
+ o_big_data= 1000;
+ o_real_data= 2;
+ o_double_data= 6578.001;
/* now, execute the prepared statement to insert 10 records.. */
- for (o_tiny_data=0; o_tiny_data < 100; o_tiny_data++)
+ for (o_tiny_data= 0; o_tiny_data < 100; o_tiny_data++)
{
- len = my_sprintf(data, (data, "MySQL%d",o_int_data));
-
- rc = mysql_fetch(stmt);
+ len= my_sprintf(data, (data, "MySQL%d", o_int_data));
+
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
fprintf(stdout, "\n");
-
- fprintf(stdout, "\n\t tiny : %d (%lu)", tiny_data,length[0]);
- fprintf(stdout, "\n\t short : %d (%lu)", small_data,length[3]);
- fprintf(stdout, "\n\t int : %d (%lu)", int_data,length[2]);
- fprintf(stdout, "\n\t big : %lld (%lu)", big_data,length[4]);
- fprintf(stdout, "\n\t float : %f (%lu)", real_data,length[5]);
- fprintf(stdout, "\n\t double : %f (%lu)", double_data,length[6]);
+ fprintf(stdout, "\n\t tiny : %d (%lu)", tiny_data, length[0]);
+ fprintf(stdout, "\n\t short : %d (%lu)", small_data, length[3]);
+ fprintf(stdout, "\n\t int : %d (%lu)", int_data, length[2]);
+ fprintf(stdout, "\n\t big : %lld (%lu)", big_data, length[4]);
+
+ fprintf(stdout, "\n\t float : %f (%lu)", real_data, length[5]);
+ fprintf(stdout, "\n\t double : %f (%lu)", double_data, length[6]);
fprintf(stdout, "\n\t str : %s (%lu)", str_data, length[1]);
@@ -1215,22 +1203,22 @@ static void test_prepare()
assert(int_data == o_int_data);
assert(length[2] == 4);
-
+
assert(small_data == o_small_data);
assert(length[3] == 2);
-
+
assert(big_data == o_big_data);
assert(length[4] == 8);
-
+
assert(real_data == o_real_data);
assert(length[5] == 4);
-
+
assert(double_data == o_double_data);
assert(length[6] == 8);
-
- assert(strcmp(data,str_data) == 0);
+
+ assert(strcmp(data, str_data) == 0);
assert(length[1] == len);
-
+
o_int_data += 25;
o_small_data += 10;
o_big_data += 100;
@@ -1238,7 +1226,7 @@ static void test_prepare()
o_double_data += 10.09;
}
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
@@ -1246,9 +1234,8 @@ static void test_prepare()
}
-/********************************************************
-* to test double comparision *
-*********************************************************/
+/* Test double comparision */
+
static void test_double_compare()
{
MYSQL_STMT *stmt;
@@ -1257,61 +1244,56 @@ static void test_double_compare()
double double_data;
MYSQL_RES *result;
MYSQL_BIND bind[3];
- ulong length[3];
+ ulong length[3];
myheader("test_double_compare");
- rc = mysql_autocommit(mysql, TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_double_compare");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_double_compare");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_double_compare(col1 tinyint,\
- col2 float, col3 double )");
+ rc= mysql_query(mysql, "CREATE TABLE test_double_compare(col1 tinyint, "
+ " col2 float, col3 double )");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_double_compare VALUES(1,10.2,34.5)");
+ rc= mysql_query(mysql, "INSERT INTO test_double_compare "
+ "VALUES (1, 10.2, 34.5)");
myquery(rc);
- strmov(query, "UPDATE test_double_compare SET col1=100 WHERE col1 = ? AND col2 = ? AND COL3 = ?");
- stmt = mysql_simple_prepare(mysql,query);
+ strmov(query, "UPDATE test_double_compare SET col1=100 "
+ "WHERE col1 = ? AND col2 = ? AND COL3 = ?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,3);
+ verify_param_count(stmt, 3);
+
+ /* Always bzero bind array because there can be internal members */
+ bzero((char*) bind, sizeof(bind));
/* tinyint */
- bind[0].buffer_type=FIELD_TYPE_TINY;
- bind[0].buffer=(char *)&tiny_data;
- bind[0].buffer_length= 0;
- bind[0].length= 0;
- bind[0].is_null= 0; /* Can never be null */
+ bind[0].buffer_type= MYSQL_TYPE_TINY;
+ bind[0].buffer= (void *)&tiny_data;
/* string->float */
- bind[1].buffer_type=FIELD_TYPE_STRING;
- bind[1].buffer= (char *)&real_data;
- bind[1].buffer_length=sizeof(real_data);
- bind[1].is_null= 0;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= (void *)&real_data;
+ bind[1].buffer_length= sizeof(real_data);
bind[1].length= &length[1];
- length[1]= 10;
+ length[1]= 10;
/* double */
- bind[2].buffer_type=FIELD_TYPE_DOUBLE;
- bind[2].buffer= (char *)&double_data;
- bind[2].buffer_length= 0;
- bind[2].length= 0;
- bind[2].is_null= 0;
+ bind[2].buffer_type= MYSQL_TYPE_DOUBLE;
+ bind[2].buffer= (void *)&double_data;
- tiny_data = 1;
- strmov(real_data,"10.2");
- double_data = 34.5;
- rc = mysql_bind_param(stmt,bind);
+ tiny_data= 1;
+ strmov(real_data, "10.2");
+ double_data= 34.5;
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_affected_rows(0);
@@ -1319,15 +1301,15 @@ static void test_double_compare()
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM test_double_compare");
+ rc= mysql_query(mysql, "SELECT * FROM test_double_compare");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert((int)tiny_data == my_process_result_set(result));
@@ -1335,9 +1317,8 @@ static void test_double_compare()
}
-/********************************************************
-* to test simple null *
-*********************************************************/
+/* Test simple null */
+
static void test_null()
{
MYSQL_STMT *stmt;
@@ -1348,39 +1329,38 @@ static void test_null()
myheader("test_null");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_null");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_null");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_null(col1 int,col2 varchar(50))");
+ rc= mysql_query(mysql, "CREATE TABLE test_null(col1 int, col2 varchar(50))");
myquery(rc);
/* insert by prepare, wrong column name */
- strmov(query,"INSERT INTO test_null(col3,col2) VALUES(?,?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_null(col3, col2) VALUES(?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt_r(stmt);
- strmov(query,"INSERT INTO test_null(col1,col2) VALUES(?,?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_null(col1, col2) VALUES(?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
- bind[0].buffer_type=MYSQL_TYPE_LONG;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].is_null= &is_null[0];
- bind[0].length= 0;
is_null[0]= 1;
- bind[1]=bind[0];
+ bind[1]= bind[0];
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
/* now, execute the prepared statement to insert 10 records.. */
- for (nData=0; nData<10; nData++)
+ for (nData= 0; nData<10; nData++)
{
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
}
@@ -1389,19 +1369,19 @@ static void test_null()
is_null[0]= 0; /* reset */
bind[1]= bind[0];
- rc = mysql_bind_param(stmt,bind);
- check_execute(stmt,rc);
-
- for (nData=0; nData<10; nData++)
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ for (nData= 0; nData<10; nData++)
{
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
}
-
+
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
nData*= 2;
@@ -1409,24 +1389,24 @@ static void test_null()
/* Fetch results */
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&nData; /* this buffer won't be altered */
+ bind[0].buffer= (void *)&nData; /* this buffer won't be altered */
bind[0].length= 0;
bind[1]= bind[0];
bind[0].is_null= &is_null[0];
bind[1].is_null= &is_null[1];
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_null");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_null");
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_bind_result(stmt,bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
rc= 0;
is_null[0]= is_null[1]= 0;
- while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
{
assert(is_null[0]);
assert(is_null[1]);
@@ -1437,24 +1417,24 @@ static void test_null()
mysql_stmt_close(stmt);
}
-/*********************************************************
-* Test for NULL as PS parameter (BUG#3367, BUG#3371) *
-**********************************************************/
+
+/* Test for NULL as PS parameter (BUG#3367, BUG#3371) */
+
static void test_ps_null_param()
{
MYSQL_STMT *stmt;
int rc;
-
+
MYSQL_BIND in_bind;
my_bool in_is_null;
long int in_long;
-
+
MYSQL_BIND out_bind;
- ulong out_length;
+ ulong out_length;
my_bool out_is_null;
char out_str_data[20];
- const char *queries[]= {"select ?", "select ?+1",
+ const char *queries[]= {"select ?", "select ?+1",
"select col1 from test_ps_nulls where col1 <=> ?",
NULL
};
@@ -1462,118 +1442,118 @@ static void test_ps_null_param()
myheader("test_null_ps_param_in_result");
- rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_ps_nulls");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ps_nulls");
myquery(rc);
- rc= mysql_query(mysql,"CREATE TABLE test_ps_nulls(col1 int)");
+ rc= mysql_query(mysql, "CREATE TABLE test_ps_nulls(col1 int)");
myquery(rc);
- rc= mysql_query(mysql,"INSERT INTO test_ps_nulls values (1),(null)");
+ rc= mysql_query(mysql, "INSERT INTO test_ps_nulls values (1), (null)");
myquery(rc);
+ /* Always bzero all members of bind parameter */
+ bzero((char*) &in_bind, sizeof(in_bind));
+ bzero((char*) &out_bind, sizeof(out_bind));
+
in_bind.buffer_type= MYSQL_TYPE_LONG;
in_bind.is_null= &in_is_null;
in_bind.length= 0;
- in_bind.buffer= (char*)&in_long;
+ in_bind.buffer= (void *)&in_long;
in_is_null= 1;
in_long= 1;
- out_bind.buffer_type=FIELD_TYPE_STRING;
+ out_bind.buffer_type= MYSQL_TYPE_STRING;
out_bind.is_null= &out_is_null;
out_bind.length= &out_length;
out_bind.buffer= out_str_data;
- out_bind.buffer_length= array_elements(out_str_data);
-
+ out_bind.buffer_length= array_elements(out_str_data);
+
/* Execute several queries, all returning NULL in result. */
for(cur_query= queries; *cur_query; cur_query++)
{
strmov(query, *cur_query);
- stmt = mysql_simple_prepare(mysql, query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,1);
+ verify_param_count(stmt, 1);
- rc = mysql_bind_param(stmt,&in_bind);
+ rc= mysql_stmt_bind_param(stmt, &in_bind);
check_execute(stmt, rc);
- rc= mysql_bind_result(stmt,&out_bind);
+ rc= mysql_stmt_bind_result(stmt, &out_bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc= mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc != MYSQL_NO_DATA);
assert(out_is_null);
- rc= mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
}
-/********************************************************
-* to test fetch null *
-*********************************************************/
+
+/* Test fetch null */
+
static void test_fetch_null()
{
MYSQL_STMT *stmt;
int rc;
int i, nData;
MYSQL_BIND bind[11];
- ulong length[11];
+ ulong length[11];
my_bool is_null[11];
myheader("test_fetch_null");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_fetch_null");
- myquery(rc);
-
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_fetch_null(col1 tinyint, col2 smallint, \
- col3 int, col4 bigint, \
- col5 float, col6 double, \
- col7 date, col8 time, \
- col9 varbinary(10), \
- col10 varchar(50),\
- col11 char(20))");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_fetch_null");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_fetch_null("
+ " col1 tinyint, col2 smallint, "
+ " col3 int, col4 bigint, "
+ " col5 float, col6 double, "
+ " col7 date, col8 time, "
+ " col9 varbinary(10), "
+ " col10 varchar(50), "
+ " col11 char(20))");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_fetch_null(col11) VALUES(1000),(88),(389789)");
+ rc= mysql_query(mysql, "INSERT INTO test_fetch_null (col11) "
+ "VALUES (1000), (88), (389789)");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* fetch */
for (i= 0; i < (int) array_elements(bind); i++)
{
- bind[i].buffer_type=FIELD_TYPE_LONG;
+ bind[i].buffer_type= MYSQL_TYPE_LONG;
bind[i].is_null= &is_null[i];
bind[i].length= &length[i];
}
- bind[i-1].buffer=(char *)&nData; /* Last column is not null */
+ bind[i-1].buffer= (void *)&nData; /* Last column is not null */
strmov((char *)query , "SELECT * FROM test_fetch_null");
assert(3 == my_stmt_result(query));
- stmt = mysql_simple_prepare(mysql, query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc = mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
rc= 0;
- while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
{
rc++;
- for (i=0; i < 10; i++)
+ for (i= 0; i < 10; i++)
{
- fprintf(stdout, "\n data[%d] : %s", i,
+ fprintf(stdout, "\n data[%d] : %s", i,
is_null[i] ? "NULL" : "NOT NULL");
assert(is_null[i]);
}
@@ -1587,9 +1567,8 @@ static void test_fetch_null()
}
-/********************************************************
-* to test simple select *
-*********************************************************/
+/* Test simple select */
+
static void test_select_version()
{
MYSQL_STMT *stmt;
@@ -1597,21 +1576,21 @@ static void test_select_version()
myheader("test_select_version");
- stmt = mysql_simple_prepare(mysql, "SELECT @@version");
+ stmt= mysql_simple_prepare(mysql, "SELECT @@version");
check_stmt(stmt);
- verify_param_count(stmt,0);
+ verify_param_count(stmt, 0);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
my_process_stmt_result(stmt);
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test simple show *
-*********************************************************/
+
+/* Test simple show */
+
static void test_select_show_table()
{
MYSQL_STMT *stmt;
@@ -1619,14 +1598,14 @@ static void test_select_show_table()
myheader("test_select_show_table");
- stmt = mysql_simple_prepare(mysql, "SHOW TABLES FROM mysql");
+ stmt= mysql_simple_prepare(mysql, "SHOW TABLES FROM mysql");
check_stmt(stmt);
- verify_param_count(stmt,0);
+ verify_param_count(stmt, 0);
for (i= 1; i < 3; i++)
{
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
}
@@ -1635,46 +1614,39 @@ static void test_select_show_table()
}
-/********************************************************
-* to test simple select to debug *
-*********************************************************/
+/* Test simple select to debug */
+
static void test_select_direct()
{
int rc;
MYSQL_RES *result;
myheader("test_select_direct");
-
- rc = mysql_autocommit(mysql,TRUE);
- myquery(rc);
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_select(id int, id1 tinyint, \
- id2 float, \
- id3 double, \
- name varchar(50))");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_select(id int, id1 tinyint, "
+ " id2 float, "
+ " id3 double, "
+ " name varchar(50))");
myquery(rc);
/* insert a row and commit the transaction */
- rc = mysql_query(mysql,"INSERT INTO test_select VALUES(10,5,2.3,4.5,'venu')");
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 5, 2.3, 4.5, 'venu')");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
- rc = mysql_query(mysql,"SELECT * FROM test_select");
+ rc= mysql_query(mysql, "SELECT * FROM test_select");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
my_process_result_set(result);
@@ -1682,148 +1654,124 @@ static void test_select_direct()
}
-/********************************************************
-* to test simple select with prepare *
-*********************************************************/
+/* Test simple select with prepare */
+
static void test_select_prepare()
{
int rc;
MYSQL_STMT *stmt;
myheader("test_select_prepare");
-
- rc = mysql_autocommit(mysql,TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
- myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_select(id int, name varchar(50))");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_select(id int, name varchar(50))");
myquery(rc);
/* insert a row and commit the transaction */
- rc = mysql_query(mysql,"INSERT INTO test_select VALUES(10,'venu')");
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 'venu')");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_select");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_select");
check_stmt(stmt);
-
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt);
- rc = mysql_query(mysql,"DROP TABLE test_select");
+ rc= mysql_query(mysql, "DROP TABLE test_select");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_select(id tinyint, id1 int, \
- id2 float, id3 float, \
- name varchar(50))");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_select(id tinyint, id1 int, "
+ " id2 float, id3 float, "
+ " name varchar(50))");
myquery(rc);
/* insert a row and commit the transaction */
- rc = mysql_query(mysql,"INSERT INTO test_select(id,id1,id2,name) VALUES(10,5,2.3,'venu')");
+ rc= mysql_query(mysql, "INSERT INTO test_select(id, id1, id2, name) VALUES(10, 5, 2.3, 'venu')");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_select");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_select");
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test simple select *
-*********************************************************/
+/* Test simple select */
+
static void test_select()
{
MYSQL_STMT *stmt;
int rc;
char szData[25];
- int nData=1;
+ int nData= 1;
MYSQL_BIND bind[2];
ulong length[2];
myheader("test_select");
- rc = mysql_autocommit(mysql,TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_select(id int,name varchar(50))");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_select(id int, name varchar(50))");
myquery(rc);
/* insert a row and commit the transaction */
- rc = mysql_query(mysql,"INSERT INTO test_select VALUES(10,'venu')");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 'venu')");
myquery(rc);
/* now insert the second row, and rollback the transaction */
- rc = mysql_query(mysql,"INSERT INTO test_select VALUES(20,'mysql')");
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES(20, 'mysql')");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
- strmov(query,"SELECT * FROM test_select WHERE id=? AND name=?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "SELECT * FROM test_select WHERE id= ? AND name=?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
/* string data */
- nData=10;
- strmov(szData,(char *)"venu");
- bind[1].buffer_type=FIELD_TYPE_STRING;
- bind[1].buffer=(char *)szData;
+ nData= 10;
+ strmov(szData, (char *)"venu");
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= (void *)szData;
bind[1].buffer_length= 4;
bind[1].length= &length[1];
length[1]= 4;
- bind[1].is_null=0;
- bind[0].buffer=(char *)&nData;
- bind[0].buffer_type=FIELD_TYPE_LONG;
- bind[0].buffer_length= 0;
- bind[0].length= 0;
- bind[0].is_null= 0;
+ bind[0].buffer= (void *)&nData;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(my_process_stmt_result(stmt) == 1);
@@ -1831,56 +1779,58 @@ static void test_select()
mysql_stmt_close(stmt);
}
+
/*
- Test for BUG#3420 ("select id1,value1 from t where id=? or value=?"
+ Test for BUG#3420 ("select id1, value1 from t where id= ? or value= ?"
returns all rows in the table)
*/
+
static void test_ps_conj_select()
{
MYSQL_STMT *stmt;
int rc;
MYSQL_BIND bind[2];
long int int_data;
- char str_data[32];
+ char str_data[32];
unsigned long str_length;
myheader("test_ps_conj_select");
-
+
rc= mysql_query(mysql, "drop table if exists t1");
myquery(rc);
-
- rc= mysql_query(mysql, "create table t1 (id1 int(11) NOT NULL default '0',"
+
+ rc= mysql_query(mysql, "create table t1 (id1 int(11) NOT NULL default '0', "
"value2 varchar(100), value1 varchar(100))");
myquery(rc);
- rc= mysql_query(mysql, "insert into t1 values (1,'hh','hh'),(2,'hh','hh'),"
- "(1,'ii','ii'),(2,'ii','ii')");
+ rc= mysql_query(mysql, "insert into t1 values (1, 'hh', 'hh'), "
+ "(2, 'hh', 'hh'), (1, 'ii', 'ii'), (2, 'ii', 'ii')");
myquery(rc);
-
- strmov(query, "select id1,value1 from t1 where id1=? or value1=?");
+
+ strmov(query, "select id1, value1 from t1 where id1= ? or value1= ?");
stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&int_data;
- bind[0].is_null= 0;
- bind[0].length= 0;
+ bind[0].buffer= (void *)&int_data;
bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
- bind[1].buffer= (char *)str_data;
- bind[1].buffer_length= array_elements(str_data);
- bind[1].is_null= 0;
+ bind[1].buffer= (void *)str_data;
+ bind[1].buffer_length= array_elements(str_data);
bind[1].length= &str_length;
-
- rc = mysql_bind_param(stmt,bind);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
int_data= 1;
- strcpy(str_data, "hh");
+ strcpy(str_data, "hh");
str_length= strlen(str_data);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(my_process_stmt_result(stmt) == 3);
@@ -1888,9 +1838,9 @@ static void test_ps_conj_select()
mysql_stmt_close(stmt);
}
-/*
- test BUG#1115 (incorrect string parameter value allocation)
-*/
+
+/* Test BUG#1115 (incorrect string parameter value allocation) */
+
static void test_bug1115()
{
MYSQL_STMT *stmt;
@@ -1901,69 +1851,91 @@ static void test_bug1115()
myheader("test_bug1115");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_select(\
+ rc= mysql_query(mysql, "CREATE TABLE test_select(\
session_id char(9) NOT NULL, \
a int(8) unsigned NOT NULL, \
b int(5) NOT NULL, \
c int(5) NOT NULL, \
d datetime NOT NULL)");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_select VALUES (\"abc\",1,2,3,2003-08-30), (\"abd\",1,2,3,2003-08-30), (\"abf\",1,2,3,2003-08-30), (\"abg\",1,2,3,2003-08-30), (\"abh\",1,2,3,2003-08-30), (\"abj\",1,2,3,2003-08-30), (\"abk\",1,2,3,2003-08-30), (\"abl\",1,2,3,2003-08-30), (\"abq\",1,2,3,2003-08-30), (\"abw\",1,2,3,2003-08-30), (\"abe\",1,2,3,2003-08-30), (\"abr\",1,2,3,2003-08-30), (\"abt\",1,2,3,2003-08-30), (\"aby\",1,2,3,2003-08-30), (\"abu\",1,2,3,2003-08-30), (\"abi\",1,2,3,2003-08-30), (\"abo\",1,2,3,2003-08-30), (\"abp\",1,2,3,2003-08-30), (\"abz\",1,2,3,2003-08-30), (\"abx\",1,2,3,2003-08-30)");
- myquery(rc);
-
- strmov(query,"SELECT * FROM test_select WHERE session_id = ?");
- stmt = mysql_simple_prepare(mysql, query);
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES "
+ "(\"abc\", 1, 2, 3, 2003-08-30), "
+ "(\"abd\", 1, 2, 3, 2003-08-30), "
+ "(\"abf\", 1, 2, 3, 2003-08-30), "
+ "(\"abg\", 1, 2, 3, 2003-08-30), "
+ "(\"abh\", 1, 2, 3, 2003-08-30), "
+ "(\"abj\", 1, 2, 3, 2003-08-30), "
+ "(\"abk\", 1, 2, 3, 2003-08-30), "
+ "(\"abl\", 1, 2, 3, 2003-08-30), "
+ "(\"abq\", 1, 2, 3, 2003-08-30), "
+ "(\"abw\", 1, 2, 3, 2003-08-30), "
+ "(\"abe\", 1, 2, 3, 2003-08-30), "
+ "(\"abr\", 1, 2, 3, 2003-08-30), "
+ "(\"abt\", 1, 2, 3, 2003-08-30), "
+ "(\"aby\", 1, 2, 3, 2003-08-30), "
+ "(\"abu\", 1, 2, 3, 2003-08-30), "
+ "(\"abi\", 1, 2, 3, 2003-08-30), "
+ "(\"abo\", 1, 2, 3, 2003-08-30), "
+ "(\"abp\", 1, 2, 3, 2003-08-30), "
+ "(\"abz\", 1, 2, 3, 2003-08-30), "
+ "(\"abx\", 1, 2, 3, 2003-08-30)");
+ myquery(rc);
+
+ strmov(query, "SELECT * FROM test_select WHERE session_id= ?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,1);
+ verify_param_count(stmt, 1);
- strmov(szData,(char *)"abc");
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer=(char *)szData;
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
+
+ strmov(szData, (char *)"abc");
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *)szData;
bind[0].buffer_length= 10;
bind[0].length= &length[0];
length[0]= 3;
- bind[0].is_null=0;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(my_process_stmt_result(stmt) == 1);
- strmov(szData,(char *)"venu");
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer=(char *)szData;
+ strmov(szData, (char *)"venu");
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *)szData;
bind[0].buffer_length= 10;
bind[0].length= &length[0];
length[0]= 4;
- bind[0].is_null=0;
+ bind[0].is_null= 0;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(my_process_stmt_result(stmt) == 0);
- strmov(szData,(char *)"abc");
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer=(char *)szData;
+ strmov(szData, (char *)"abc");
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *)szData;
bind[0].buffer_length= 10;
bind[0].length= &length[0];
length[0]= 3;
- bind[0].is_null=0;
+ bind[0].is_null= 0;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(my_process_stmt_result(stmt) == 1);
@@ -1971,9 +1943,9 @@ session_id char(9) NOT NULL, \
mysql_stmt_close(stmt);
}
-/*
- test BUG#1180 (optimized away part of WHERE clause)
-*/
+
+/* Test BUG#1180 (optimized away part of WHERE clause) */
+
static void test_bug1180()
{
MYSQL_STMT *stmt;
@@ -1984,64 +1956,68 @@ static void test_bug1180()
myheader("test_select_bug");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_select(session_id char(9) NOT NULL)");
+ rc= mysql_query(mysql, "CREATE TABLE test_select(session_id char(9) NOT NULL)");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_select VALUES (\"abc\")");
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES (\"abc\")");
myquery(rc);
- strmov(query,"SELECT * FROM test_select WHERE ?=\"1111\" and session_id = \"abc\"");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "SELECT * FROM test_select WHERE ?= \"1111\" and "
+ "session_id= \"abc\"");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,1);
+ verify_param_count(stmt, 1);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
- strmov(szData,(char *)"abc");
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer=(char *)szData;
+ strmov(szData, (char *)"abc");
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *)szData;
bind[0].buffer_length= 10;
bind[0].length= &length[0];
length[0]= 3;
- bind[0].is_null=0;
+ bind[0].is_null= 0;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(my_process_stmt_result(stmt) == 0);
- strmov(szData,(char *)"1111");
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer=(char *)szData;
+ strmov(szData, (char *)"1111");
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *)szData;
bind[0].buffer_length= 10;
bind[0].length= &length[0];
length[0]= 4;
- bind[0].is_null=0;
+ bind[0].is_null= 0;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(my_process_stmt_result(stmt) == 1);
- strmov(szData,(char *)"abc");
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer=(char *)szData;
+ strmov(szData, (char *)"abc");
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *)szData;
bind[0].buffer_length= 10;
bind[0].length= &length[0];
length[0]= 3;
- bind[0].is_null=0;
+ bind[0].is_null= 0;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(my_process_stmt_result(stmt) == 0);
@@ -2049,10 +2025,12 @@ static void test_bug1180()
mysql_stmt_close(stmt);
}
+
/*
- test BUG#1644 (Insertion of more than 3 NULL columns with
- parameter binding fails)
+ Test BUG#1644 (Insertion of more than 3 NULL columns with parameter
+ binding fails)
*/
+
static void test_bug1644()
{
MYSQL_STMT *stmt;
@@ -2069,51 +2047,52 @@ static void test_bug1644()
myquery(rc);
rc= mysql_query(mysql,
- "CREATE TABLE foo_dfr(col1 int, col2 int, col3 int, col4 int);");
+ "CREATE TABLE foo_dfr(col1 int, col2 int, col3 int, col4 int);");
myquery(rc);
- strmov(query, "INSERT INTO foo_dfr VALUES (?,?,?,? )");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO foo_dfr VALUES (?, ?, ?, ? )");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
verify_param_count(stmt, 4);
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
+
num= 22;
isnull= 0;
- for (i = 0 ; i < 4 ; i++)
+ for (i= 0 ; i < 4 ; i++)
{
- bind[i].buffer_type= FIELD_TYPE_LONG;
- bind[i].buffer= (char *)&num;
- bind[i].buffer_length= 0;
- bind[i].length= 0;
+ bind[i].buffer_type= MYSQL_TYPE_LONG;
+ bind[i].buffer= (void *)&num;
bind[i].is_null= &isnull;
}
- rc= mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
isnull= 1;
- for (i = 0 ; i < 4 ; i++)
+ for (i= 0 ; i < 4 ; i++)
bind[i].is_null= &isnull;
- rc= mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
isnull= 0;
num= 88;
- for (i = 0 ; i < 4 ; i++)
+ for (i= 0 ; i < 4 ; i++)
bind[i].is_null= &isnull;
- rc= mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
mysql_stmt_close(stmt);
@@ -2130,19 +2109,19 @@ static void test_bug1644()
row= mysql_fetch_row(result);
mytest(row);
- for (i = 0 ; i < 4 ; i++)
+ for (i= 0 ; i < 4 ; i++)
{
assert(strcmp(row[i], "22") == 0);
}
row= mysql_fetch_row(result);
mytest(row);
- for (i = 0 ; i < 4 ; i++)
+ for (i= 0 ; i < 4 ; i++)
{
assert(row[i] == 0);
}
row= mysql_fetch_row(result);
mytest(row);
- for (i = 0 ; i < 4 ; i++)
+ for (i= 0 ; i < 4 ; i++)
{
assert(strcmp(row[i], "88") == 0);
}
@@ -2153,9 +2132,8 @@ static void test_bug1644()
}
-/********************************************************
-* to test simple select show *
-*********************************************************/
+/* Test simple select show */
+
static void test_select_show()
{
MYSQL_STMT *stmt;
@@ -2163,51 +2141,52 @@ static void test_select_show()
myheader("test_select_show");
- mysql_autocommit(mysql,TRUE);
+ mysql_autocommit(mysql, TRUE);
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS test_show");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_show");
myquery(rc);
-
- rc = mysql_query(mysql, "CREATE TABLE test_show(id int(4) NOT NULL primary key, name char(2))");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_show(id int(4) NOT NULL primary "
+ " key, name char(2))");
myquery(rc);
- stmt = mysql_simple_prepare(mysql, "show columns from test_show");
+ stmt= mysql_simple_prepare(mysql, "show columns from test_show");
check_stmt(stmt);
- verify_param_count(stmt,0);
+ verify_param_count(stmt, 0);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
my_process_stmt_result(stmt);
mysql_stmt_close(stmt);
-
- stmt = mysql_simple_prepare(mysql, "show tables from mysql like ?");
+
+ stmt= mysql_simple_prepare(mysql, "show tables from mysql like ?");
check_stmt_r(stmt);
-
- strxmov(query,"show tables from ", current_db, " like \'test_show\'", NullS);
- stmt = mysql_simple_prepare(mysql, query);
+
+ strxmov(query, "show tables from ", current_db, " like \'test_show\'", NullS);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
my_process_stmt_result(stmt);
mysql_stmt_close(stmt);
-
- stmt = mysql_simple_prepare(mysql, "describe test_show");
+
+ stmt= mysql_simple_prepare(mysql, "describe test_show");
check_stmt(stmt);
-
- rc = mysql_execute(stmt);
+
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
my_process_stmt_result(stmt);
mysql_stmt_close(stmt);
-
- stmt = mysql_simple_prepare(mysql, "show keys from test_show");
+
+ stmt= mysql_simple_prepare(mysql, "show keys from test_show");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
@@ -2215,85 +2194,77 @@ static void test_select_show()
}
-/********************************************************
-* to test simple update *
-*********************************************************/
+/* Test simple update */
+
static void test_simple_update()
{
MYSQL_STMT *stmt;
int rc;
char szData[25];
- int nData=1;
+ int nData= 1;
MYSQL_RES *result;
- MYSQL_BIND bind[2];
- ulong length[2];
+ MYSQL_BIND bind[2];
+ ulong length[2];
myheader("test_simple_update");
- rc = mysql_autocommit(mysql,TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_update");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_update(col1 int,\
- col2 varchar(50), col3 int )");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_update");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_update(col1 int, "
+ " col2 varchar(50), col3 int )");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_update VALUES(1,'MySQL',100)");
+ rc= mysql_query(mysql, "INSERT INTO test_update VALUES(1, 'MySQL', 100)");
myquery(rc);
verify_affected_rows(1);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* insert by prepare */
- strmov(query,"UPDATE test_update SET col2=? WHERE col1=?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "UPDATE test_update SET col2= ? WHERE col1= ?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
- nData=1;
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer=szData; /* string data */
- bind[0].buffer_length=sizeof(szData);
+ nData= 1;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= szData; /* string data */
+ bind[0].buffer_length= sizeof(szData);
bind[0].length= &length[0];
- bind[0].is_null= 0;
- length[0]= my_sprintf(szData, (szData,"updated-data"));
+ length[0]= my_sprintf(szData, (szData, "updated-data"));
- bind[1].buffer=(char *) &nData;
- bind[1].buffer_type=FIELD_TYPE_LONG;
- bind[1].buffer_length= 0;
- bind[1].length= 0;
- bind[1].is_null= 0;
+ bind[1].buffer= (void *) &nData;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_affected_rows(1);
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM test_update");
+ rc= mysql_query(mysql, "SELECT * FROM test_update");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
@@ -2301,203 +2272,185 @@ static void test_simple_update()
}
-/********************************************************
-* to test simple long data handling *
-*********************************************************/
+/* Test simple long data handling */
+
static void test_long_data()
{
MYSQL_STMT *stmt;
int rc, int_data;
- char *data=NullS;
+ char *data= NullS;
MYSQL_RES *result;
MYSQL_BIND bind[3];
myheader("test_long_data");
- rc = mysql_autocommit(mysql,TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_long_data(col1 int,\
- col2 long varchar, col3 long varbinary)");
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data(col1 int, "
+ " col2 long varchar, col3 long varbinary)");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- strmov(query,"INSERT INTO test_long_data(col1,col2) VALUES(?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_long_data(col1, col2) VALUES(?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt_r(stmt);
- strmov(query,"INSERT INTO test_long_data(col1,col2,col3) VALUES(?,?,?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_long_data(col1, col2, col3) VALUES(?, ?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,3);
+ verify_param_count(stmt, 3);
- bind[0].buffer=(char *)&int_data;
- bind[0].buffer_type=FIELD_TYPE_LONG;
- bind[0].is_null=0;
- bind[0].buffer_length= 0;
- bind[0].length= 0;
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
- bind[1].buffer_type=FIELD_TYPE_STRING;
- bind[1].is_null=0;
- bind[1].buffer_length=0; /* Will not be used */
- bind[1].length=0; /* Will not be used */
+ bind[0].buffer= (void *)&int_data;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[2]=bind[1];
- rc = mysql_bind_param(stmt,bind);
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+
+ bind[2]= bind[1];
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
int_data= 999;
- data = (char *)"Michael";
+ data= (char *)"Michael";
/* supply data in pieces */
- rc = mysql_send_long_data(stmt,1,data,strlen(data));
- data = (char *)" 'Monty' Widenius";
- rc = mysql_send_long_data(stmt,1,data,strlen(data));
+ rc= mysql_stmt_send_long_data(stmt, 1, data, strlen(data));
+ data= (char *)" 'Monty' Widenius";
+ rc= mysql_stmt_send_long_data(stmt, 1, data, strlen(data));
check_execute(stmt, rc);
- rc = mysql_send_long_data(stmt,2,"Venu (venu@mysql.com)",4);
+ rc= mysql_stmt_send_long_data(stmt, 2, "Venu (venu@mysql.com)", 4);
check_execute(stmt, rc);
/* execute */
- rc = mysql_execute(stmt);
- fprintf(stdout," mysql_execute() returned %d\n",rc);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
+ check_execute(stmt, rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* now fetch the results ..*/
- rc = mysql_query(mysql,"SELECT * FROM test_long_data");
+ rc= mysql_query(mysql, "SELECT * FROM test_long_data");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
mysql_free_result(result);
- verify_col_data("test_long_data","col1","999");
- verify_col_data("test_long_data","col2","Michael 'Monty' Widenius");
- verify_col_data("test_long_data","col3","Venu");
+ verify_col_data("test_long_data", "col1", "999");
+ verify_col_data("test_long_data", "col2", "Michael 'Monty' Widenius");
+ verify_col_data("test_long_data", "col3", "Venu");
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test long data (string) handling *
-*********************************************************/
+/* Test long data (string) handling */
+
static void test_long_data_str()
{
MYSQL_STMT *stmt;
int rc, i;
char data[255];
long length;
- ulong length1;
+ ulong length1;
MYSQL_RES *result;
MYSQL_BIND bind[2];
my_bool is_null[2];
myheader("test_long_data_str");
- rc = mysql_autocommit(mysql,TRUE);
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data_str");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_str");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data_str(id int, longstr long varchar)");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_long_data_str(id int, longstr long varchar)");
- myquery(rc);
-
- rc = mysql_commit(mysql);
- myquery(rc);
-
- strmov(query,"INSERT INTO test_long_data_str VALUES(?,?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_long_data_str VALUES(?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
- bind[0].buffer = (char *)&length;
- bind[0].buffer_type = FIELD_TYPE_LONG;
+ bind[0].buffer= (void *)&length;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].is_null= &is_null[0];
- bind[0].buffer_length= 0;
- bind[0].length= 0;
- is_null[0]=0;
+ is_null[0]= 0;
length= 0;
- bind[1].buffer=data; /* string data */
- bind[1].buffer_type=FIELD_TYPE_STRING;
+ bind[1].buffer= data; /* string data */
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
bind[1].length= &length1;
- bind[1].buffer_length=0; /* Will not be used */
bind[1].is_null= &is_null[1];
- is_null[1]=0;
- rc = mysql_bind_param(stmt,bind);
+ is_null[1]= 0;
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- length = 40;
- strmov(data,"MySQL AB");
+ length= 40;
+ strmov(data, "MySQL AB");
/* supply data in pieces */
- for(i=0; i < 4; i++)
+ for(i= 0; i < 4; i++)
{
- rc = mysql_send_long_data(stmt,1,(char *)data,5);
+ rc= mysql_stmt_send_long_data(stmt, 1, (char *)data, 5);
check_execute(stmt, rc);
}
/* execute */
- rc = mysql_execute(stmt);
- fprintf(stdout," mysql_execute() returned %d\n",rc);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
+ check_execute(stmt, rc);
mysql_stmt_close(stmt);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* now fetch the results ..*/
- rc = mysql_query(mysql,"SELECT LENGTH(longstr), longstr FROM test_long_data_str");
+ rc= mysql_query(mysql, "SELECT LENGTH(longstr), longstr FROM test_long_data_str");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
mysql_free_result(result);
- my_sprintf(data,(data,"%d", i*5));
- verify_col_data("test_long_data_str","LENGTH(longstr)", data);
- data[0]='\0';
+ my_sprintf(data, (data, "%d", i*5));
+ verify_col_data("test_long_data_str", "LENGTH(longstr)", data);
+ data[0]= '\0';
while (i--)
- strxmov(data,data,"MySQL",NullS);
- verify_col_data("test_long_data_str","longstr", data);
+ strxmov(data, data, "MySQL", NullS);
+ verify_col_data("test_long_data_str", "longstr", data);
- rc = mysql_query(mysql,"DROP TABLE test_long_data_str");
+ rc= mysql_query(mysql, "DROP TABLE test_long_data_str");
myquery(rc);
}
-/********************************************************
-* to test long data (string) handling *
-*********************************************************/
+/* Test long data (string) handling */
+
static void test_long_data_str1()
{
MYSQL_STMT *stmt;
int rc, i;
char data[255];
long length;
- ulong max_blob_length, blob_length, length1;
+ ulong max_blob_length, blob_length, length1;
my_bool true_value;
MYSQL_RES *result;
MYSQL_BIND bind[2];
@@ -2505,67 +2458,63 @@ static void test_long_data_str1()
myheader("test_long_data_str1");
- rc = mysql_autocommit(mysql,TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data_str");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_long_data_str(longstr long varchar,blb long varbinary)");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_str");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data_str(longstr long varchar, blb long varbinary)");
myquery(rc);
- strmov(query,"INSERT INTO test_long_data_str VALUES(?,?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_long_data_str VALUES(?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
- bind[0].buffer=data; /* string data */
+ bind[0].buffer= data; /* string data */
bind[0].buffer_length= sizeof(data);
bind[0].length= &length1;
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].is_null= 0;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
length1= 0;
- bind[1] = bind[0];
- bind[1].buffer_type=FIELD_TYPE_BLOB;
+ bind[1]= bind[0];
+ bind[1].buffer_type= MYSQL_TYPE_BLOB;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- length = my_sprintf(data, (data, "MySQL AB"));
+ length= my_sprintf(data, (data, "MySQL AB"));
/* supply data in pieces */
- for (i=0; i < 3; i++)
+ for (i= 0; i < 3; i++)
{
- rc = mysql_send_long_data(stmt,0,data,length);
+ rc= mysql_stmt_send_long_data(stmt, 0, data, length);
check_execute(stmt, rc);
- rc = mysql_send_long_data(stmt,1,data,2);
+ rc= mysql_stmt_send_long_data(stmt, 1, data, 2);
check_execute(stmt, rc);
}
/* execute */
- rc = mysql_execute(stmt);
- fprintf(stdout," mysql_execute() returned %d\n",rc);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
+ check_execute(stmt, rc);
mysql_stmt_close(stmt);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* now fetch the results ..*/
- rc = mysql_query(mysql,"SELECT LENGTH(longstr),longstr,LENGTH(blb),blb FROM test_long_data_str");
+ rc= mysql_query(mysql, "SELECT LENGTH(longstr), longstr, LENGTH(blb), blb FROM test_long_data_str");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mysql_field_seek(result, 1);
field= mysql_fetch_field(result);
@@ -2576,24 +2525,24 @@ static void test_long_data_str1()
assert(1 == my_process_result_set(result));
mysql_free_result(result);
- my_sprintf(data,(data,"%ld",(long)i*length));
- verify_col_data("test_long_data_str","length(longstr)",data);
+ my_sprintf(data, (data, "%ld", (long)i*length));
+ verify_col_data("test_long_data_str", "length(longstr)", data);
- my_sprintf(data,(data,"%d",i*2));
- verify_col_data("test_long_data_str","length(blb)",data);
+ my_sprintf(data, (data, "%d", i*2));
+ verify_col_data("test_long_data_str", "length(blb)", data);
/* Test length of field->max_length */
stmt= mysql_simple_prepare(mysql, "SELECT * from test_long_data_str");
check_stmt(stmt);
- verify_param_count(stmt,0);
-
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ verify_param_count(stmt, 0);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
rc= mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
+ check_execute(stmt, rc);
- result= mysql_get_metadata(stmt);
+ result= mysql_stmt_result_metadata(stmt);
field= mysql_fetch_fields(result);
/* First test what happens if STMT_ATTR_UPDATE_MAX_LENGTH is not used */
@@ -2603,13 +2552,13 @@ static void test_long_data_str1()
/* Enable updating of field->max_length */
true_value= 1;
mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &true_value);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
rc= mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
+ check_execute(stmt, rc);
- result= mysql_get_metadata(stmt);
+ result= mysql_stmt_result_metadata(stmt);
field= mysql_fetch_fields(result);
DBUG_ASSERT(field->max_length == max_blob_length);
@@ -2617,20 +2566,20 @@ static void test_long_data_str1()
/* Fetch results into a data buffer that is smaller than data */
bzero((char*) bind, sizeof(*bind));
bind[0].buffer_type= MYSQL_TYPE_BLOB;
- bind[0].buffer= (char *) &data; /* this buffer won't be altered */
+ bind[0].buffer= (void *) &data; /* this buffer won't be altered */
bind[0].buffer_length= 16;
bind[0].length= &blob_length;
- rc= mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
data[16]= 0;
- DBUG_ASSERT((mysql_fetch(stmt) == 0));
+ DBUG_ASSERT((mysql_stmt_fetch(stmt) == 0));
DBUG_ASSERT(strlen(data) == 16);
DBUG_ASSERT(blob_length == max_blob_length);
/* Fetch all data */
bzero((char*) (bind+1), sizeof(*bind));
bind[1].buffer_type= MYSQL_TYPE_BLOB;
- bind[1].buffer= (char *) &data; /* this buffer won't be altered */
+ bind[1].buffer= (void *) &data; /* this buffer won't be altered */
bind[1].buffer_length= sizeof(data);
bind[1].length= &blob_length;
bzero(data, sizeof(data));
@@ -2641,14 +2590,13 @@ static void test_long_data_str1()
mysql_stmt_close(stmt);
/* Drop created table */
- rc = mysql_query(mysql,"DROP TABLE test_long_data_str");
+ rc= mysql_query(mysql, "DROP TABLE test_long_data_str");
myquery(rc);
}
-/********************************************************
-* to test long data (binary) handling *
-*********************************************************/
+/* Test long data (binary) handling */
+
static void test_long_data_bin()
{
MYSQL_STMT *stmt;
@@ -2661,69 +2609,61 @@ static void test_long_data_bin()
myheader("test_long_data_bin");
- rc = mysql_autocommit(mysql,TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data_bin");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_bin");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_long_data_bin(id int, longbin long varbinary)");
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data_bin(id int, longbin long varbinary)");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- strmov(query,"INSERT INTO test_long_data_bin VALUES(?,?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_long_data_bin VALUES(?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
- bind[0].buffer = (char *)&length;
- bind[0].buffer_type = FIELD_TYPE_LONG;
- bind[0].buffer_length= 0;
- bind[0].length= 0;
- bind[0].is_null= 0;
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
+
+ bind[0].buffer= (void *)&length;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
length= 0;
- bind[1].buffer=data; /* string data */
- bind[1].buffer_type=FIELD_TYPE_LONG_BLOB;
- bind[1].length= 0; /* Will not be used */
- bind[1].is_null= 0;
- rc = mysql_bind_param(stmt,bind);
+ bind[1].buffer= data; /* string data */
+ bind[1].buffer_type= MYSQL_TYPE_LONG_BLOB;
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- length = 10;
- strmov(data,"MySQL AB");
+ length= 10;
+ strmov(data, "MySQL AB");
/* supply data in pieces */
{
int i;
- for (i=0; i < 100; i++)
+ for (i= 0; i < 100; i++)
{
- rc = mysql_send_long_data(stmt,1,(char *)data,4);
+ rc= mysql_stmt_send_long_data(stmt, 1, (char *)data, 4);
check_execute(stmt, rc);
}
}
/* execute */
- rc = mysql_execute(stmt);
- fprintf(stdout," mysql_execute() returned %d\n",rc);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
+ check_execute(stmt, rc);
mysql_stmt_close(stmt);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* now fetch the results ..*/
- rc = mysql_query(mysql,"SELECT LENGTH(longbin), longbin FROM test_long_data_bin");
+ rc= mysql_query(mysql, "SELECT LENGTH(longbin), longbin FROM test_long_data_bin");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
@@ -2731,71 +2671,63 @@ static void test_long_data_bin()
}
-/********************************************************
-* to test simple delete *
-*********************************************************/
+/* Test simple delete */
+
static void test_simple_delete()
{
MYSQL_STMT *stmt;
int rc;
- char szData[30]={0};
- int nData=1;
+ char szData[30]= {0};
+ int nData= 1;
MYSQL_RES *result;
MYSQL_BIND bind[2];
ulong length[2];
myheader("test_simple_delete");
- rc = mysql_autocommit(mysql,TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_simple_delete");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_simple_delete");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_simple_delete(col1 int,\
+ rc= mysql_query(mysql, "CREATE TABLE test_simple_delete(col1 int, \
col2 varchar(50), col3 int )");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"INSERT INTO test_simple_delete VALUES(1,'MySQL',100)");
+ rc= mysql_query(mysql, "INSERT INTO test_simple_delete VALUES(1, 'MySQL', 100)");
myquery(rc);
verify_affected_rows(1);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* insert by prepare */
- strmov(query,"DELETE FROM test_simple_delete WHERE col1=? AND col2=? AND col3=100");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "DELETE FROM test_simple_delete WHERE col1= ? AND col2= ? AND col3= 100");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
- nData=1;
- strmov(szData,"MySQL");
- bind[1].buffer_type=FIELD_TYPE_STRING;
- bind[1].buffer= szData; /* string data */
- bind[1].buffer_length=sizeof(szData);
+ nData= 1;
+ strmov(szData, "MySQL");
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= szData; /* string data */
+ bind[1].buffer_length= sizeof(szData);
bind[1].length= &length[1];
- bind[1].is_null= 0;
length[1]= 5;
- bind[0].buffer=(char *)&nData;
- bind[0].buffer_type=FIELD_TYPE_LONG;
- bind[0].buffer_length= 0;
- bind[0].length= 0;
- bind[0].is_null= 0;
+ bind[0].buffer= (void *)&nData;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_affected_rows(1);
@@ -2803,15 +2735,15 @@ static void test_simple_delete()
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM test_simple_delete");
+ rc= mysql_query(mysql, "SELECT * FROM test_simple_delete");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(0 == my_process_result_set(result));
@@ -2819,105 +2751,98 @@ static void test_simple_delete()
}
+/* Test simple update */
-/********************************************************
-* to test simple update *
-*********************************************************/
static void test_update()
{
MYSQL_STMT *stmt;
int rc;
char szData[25];
- int nData=1;
+ int nData= 1;
MYSQL_RES *result;
MYSQL_BIND bind[2];
ulong length[2];
myheader("test_update");
- rc = mysql_autocommit(mysql,TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_update");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_update");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_update(col1 int primary key auto_increment,\
- col2 varchar(50), col3 int )");
+ rc= mysql_query(mysql, "CREATE TABLE test_update("
+ "col1 int primary key auto_increment, "
+ "col2 varchar(50), col3 int )");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- strmov(query,"INSERT INTO test_update(col2,col3) VALUES(?,?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_update(col2, col3) VALUES(?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
/* string data */
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer=szData;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= szData;
bind[0].buffer_length= sizeof(szData);
bind[0].length= &length[0];
length[0]= my_sprintf(szData, (szData, "inserted-data"));
- bind[0].is_null= 0;
- bind[1].buffer=(char *)&nData;
- bind[1].buffer_type=FIELD_TYPE_LONG;
- bind[1].buffer_length= 0;
- bind[1].length= 0;
- bind[1].is_null= 0;
+ bind[1].buffer= (void *)&nData;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- nData=100;
- rc = mysql_execute(stmt);
+ nData= 100;
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_affected_rows(1);
mysql_stmt_close(stmt);
- strmov(query,"UPDATE test_update SET col2=? WHERE col3=?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "UPDATE test_update SET col2= ? WHERE col3= ?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
- nData=100;
+ verify_param_count(stmt, 2);
+ nData= 100;
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer=szData;
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= szData;
bind[0].buffer_length= sizeof(szData);
bind[0].length= &length[0];
length[0]= my_sprintf(szData, (szData, "updated-data"));
- bind[1].buffer=(char *)&nData;
- bind[1].buffer_type=FIELD_TYPE_LONG;
- bind[1].buffer_length= 0;
- bind[1].length= 0;
- bind[1].is_null= 0;
- rc = mysql_bind_param(stmt,bind);
+ bind[1].buffer= (void *)&nData;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_affected_rows(1);
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM test_update");
+ rc= mysql_query(mysql, "SELECT * FROM test_update");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
@@ -2925,9 +2850,8 @@ static void test_update()
}
-/********************************************************
-* to test simple prepare *
-*********************************************************/
+/* Test prepare without parameters */
+
static void test_prepare_noparam()
{
MYSQL_STMT *stmt;
@@ -2936,38 +2860,35 @@ static void test_prepare_noparam()
myheader("test_prepare_noparam");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS my_prepare");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_prepare");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE my_prepare(col1 int ,col2 varchar(50))");
+ rc= mysql_query(mysql, "CREATE TABLE my_prepare(col1 int, col2 varchar(50))");
myquery(rc);
-
/* insert by prepare */
- strmov(query,"INSERT INTO my_prepare VALUES(10,'venu')");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO my_prepare VALUES(10, 'venu')");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,0);
+ verify_param_count(stmt, 0);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM my_prepare");
+ rc= mysql_query(mysql, "SELECT * FROM my_prepare");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
@@ -2975,103 +2896,95 @@ static void test_prepare_noparam()
}
-/********************************************************
-* to test simple bind result *
-*********************************************************/
+/* Test simple bind result */
+
static void test_bind_result()
{
MYSQL_STMT *stmt;
int rc;
int nData;
- ulong length, length1;
+ ulong length, length1;
char szData[100];
MYSQL_BIND bind[2];
my_bool is_null[2];
myheader("test_bind_result");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_bind_result(col1 int ,col2 varchar(50))");
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_result(col1 int , col2 varchar(50))");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES(10, 'venu')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(10,'venu')");
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES(20, 'MySQL')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(20,'MySQL')");
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result(col2) VALUES('monty')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_bind_result(col2) VALUES('monty')");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* fetch */
- bind[0].buffer_type=FIELD_TYPE_LONG;
- bind[0].buffer= (char *) &nData; /* integer data */
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void *) &nData; /* integer data */
bind[0].is_null= &is_null[0];
bind[0].length= 0;
- bind[1].buffer_type=FIELD_TYPE_STRING;
- bind[1].buffer=szData; /* string data */
- bind[1].buffer_length=sizeof(szData);
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= szData; /* string data */
+ bind[1].buffer_length= sizeof(szData);
bind[1].length= &length1;
bind[1].is_null= &is_null[1];
- stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_bind_result");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_bind_result");
check_stmt(stmt);
- rc = mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 1: %d,%s(%lu)",nData, szData, length1);
+ fprintf(stdout, "\n row 1: %d, %s(%lu)", nData, szData, length1);
assert(nData == 10);
- assert(strcmp(szData,"venu")==0);
+ assert(strcmp(szData, "venu") == 0);
assert(length1 == 4);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 2: %d,%s(%lu)",nData, szData, length1);
+ fprintf(stdout, "\n row 2: %d, %s(%lu)", nData, szData, length1);
assert(nData == 20);
- assert(strcmp(szData,"MySQL")==0);
+ assert(strcmp(szData, "MySQL") == 0);
assert(length1 == 5);
- length=99;
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
-
+ length= 99;
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
if (is_null[0])
- fprintf(stdout,"\n row 3: NULL,%s(%lu)", szData, length1);
+ fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1);
assert(is_null[0]);
- assert(strcmp(szData,"monty")==0);
+ assert(strcmp(szData, "monty") == 0);
assert(length1 == 5);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test ext bind result *
-*********************************************************/
+/* Test ext bind result */
+
static void test_bind_result_ext()
{
MYSQL_STMT *stmt;
@@ -3085,33 +2998,28 @@ static void test_bind_result_ext()
char szData[20], bData[20];
ulong szLength, bLength;
MYSQL_BIND bind[8];
- ulong length[8];
+ ulong length[8];
my_bool is_null[8];
myheader("test_bind_result_ext");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_bind_result(c1 tinyint, c2 smallint, \
- c3 int, c4 bigint, \
- c5 float, c6 double, \
- c7 varbinary(10), \
- c8 varchar(50))");
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_result(c1 tinyint, "
+ " c2 smallint, "
+ " c3 int, c4 bigint, "
+ " c5 float, c6 double, "
+ " c7 varbinary(10), "
+ " c8 varchar(50))");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result "
+ "VALUES (19, 2999, 3999, 4999999, "
+ " 2345.6, 5678.89563, 'venu', 'mysql')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(19,2999,3999,4999999,\
- 2345.6,5678.89563,\
- 'venu','mysql')");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
for (i= 0; i < (int) array_elements(bind); i++)
@@ -3120,45 +3028,45 @@ static void test_bind_result_ext()
bind[i].is_null= &is_null[i];
}
- bind[0].buffer_type=MYSQL_TYPE_TINY;
- bind[0].buffer=(char *)&t_data;
+ bind[0].buffer_type= MYSQL_TYPE_TINY;
+ bind[0].buffer= (void *)&t_data;
- bind[1].buffer_type=MYSQL_TYPE_SHORT;
- bind[2].buffer_type=MYSQL_TYPE_LONG;
-
- bind[3].buffer_type=MYSQL_TYPE_LONGLONG;
- bind[1].buffer=(char *)&s_data;
-
- bind[2].buffer=(char *)&i_data;
- bind[3].buffer=(char *)&b_data;
+ bind[1].buffer_type= MYSQL_TYPE_SHORT;
+ bind[2].buffer_type= MYSQL_TYPE_LONG;
- bind[4].buffer_type=MYSQL_TYPE_FLOAT;
- bind[4].buffer=(char *)&f_data;
+ bind[3].buffer_type= MYSQL_TYPE_LONGLONG;
+ bind[1].buffer= (void *)&s_data;
- bind[5].buffer_type=MYSQL_TYPE_DOUBLE;
- bind[5].buffer=(char *)&d_data;
+ bind[2].buffer= (void *)&i_data;
+ bind[3].buffer= (void *)&b_data;
- bind[6].buffer_type=MYSQL_TYPE_STRING;
- bind[6].buffer= (char *)szData;
+ bind[4].buffer_type= MYSQL_TYPE_FLOAT;
+ bind[4].buffer= (void *)&f_data;
+
+ bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
+ bind[5].buffer= (void *)&d_data;
+
+ bind[6].buffer_type= MYSQL_TYPE_STRING;
+ bind[6].buffer= (void *)szData;
bind[6].buffer_length= sizeof(szData);
bind[6].length= &szLength;
- bind[7].buffer_type=MYSQL_TYPE_TINY_BLOB;
- bind[7].buffer=(char *)&bData;
+ bind[7].buffer_type= MYSQL_TYPE_TINY_BLOB;
+ bind[7].buffer= (void *)&bData;
bind[7].length= &bLength;
bind[7].buffer_length= sizeof(bData);
- stmt = mysql_simple_prepare(mysql, "select * from test_bind_result");
+ stmt= mysql_simple_prepare(mysql, "select * from test_bind_result");
check_stmt(stmt);
- rc = mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
fprintf(stdout, "\n data (tiny) : %d", t_data);
fprintf(stdout, "\n data (short) : %d", s_data);
@@ -3180,25 +3088,24 @@ static void test_bind_result_ext()
assert(b_data == 4999999);
/*assert(f_data == 2345.60);*/
/*assert(d_data == 5678.89563);*/
- assert(strcmp(szData,"venu")==0);
- assert(strncmp(bData,"mysql",5)==0);
+ assert(strcmp(szData, "venu") == 0);
+ assert(strncmp(bData, "mysql", 5) == 0);
assert(szLength == 4);
assert(bLength == 5);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test ext bind result *
-*********************************************************/
+/* Test ext bind result */
+
static void test_bind_result_ext1()
{
MYSQL_STMT *stmt;
- uint i;
+ uint i;
int rc;
char t_data[20];
float s_data;
@@ -3213,60 +3120,54 @@ static void test_bind_result_ext1()
my_bool is_null[8];
myheader("test_bind_result_ext1");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_bind_result(c1 tinyint, c2 smallint, \
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_result(c1 tinyint, c2 smallint, \
c3 int, c4 bigint, \
c5 float, c6 double, \
c7 varbinary(10), \
c8 varchar(10))");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES(120, 2999, 3999, 54, \
+ 2.6, 58.89, \
+ '206', '6.7')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(120,2999,3999,54,\
- 2.6,58.89,\
- '206','6.7')");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
- bind[0].buffer_type=MYSQL_TYPE_STRING;
- bind[0].buffer=(char *) t_data;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *) t_data;
bind[0].buffer_length= sizeof(t_data);
- bind[1].buffer_type=MYSQL_TYPE_FLOAT;
- bind[1].buffer=(char *)&s_data;
+ bind[1].buffer_type= MYSQL_TYPE_FLOAT;
+ bind[1].buffer= (void *)&s_data;
bind[1].buffer_length= 0;
- bind[2].buffer_type=MYSQL_TYPE_SHORT;
- bind[2].buffer=(char *)&i_data;
+ bind[2].buffer_type= MYSQL_TYPE_SHORT;
+ bind[2].buffer= (void *)&i_data;
bind[2].buffer_length= 0;
- bind[3].buffer_type=MYSQL_TYPE_TINY;
- bind[3].buffer=(char *)&b_data;
+ bind[3].buffer_type= MYSQL_TYPE_TINY;
+ bind[3].buffer= (void *)&b_data;
bind[3].buffer_length= 0;
- bind[4].buffer_type=MYSQL_TYPE_LONG;
- bind[4].buffer=(char *)&f_data;
+ bind[4].buffer_type= MYSQL_TYPE_LONG;
+ bind[4].buffer= (void *)&f_data;
bind[4].buffer_length= 0;
- bind[5].buffer_type=MYSQL_TYPE_STRING;
- bind[5].buffer=(char *)d_data;
+ bind[5].buffer_type= MYSQL_TYPE_STRING;
+ bind[5].buffer= (void *)d_data;
bind[5].buffer_length= sizeof(d_data);
- bind[6].buffer_type=MYSQL_TYPE_LONG;
- bind[6].buffer=(char *)&bData;
+ bind[6].buffer_type= MYSQL_TYPE_LONG;
+ bind[6].buffer= (void *)&bData;
bind[6].buffer_length= 0;
- bind[7].buffer_type=MYSQL_TYPE_DOUBLE;
- bind[7].buffer=(char *)&szData;
+ bind[7].buffer_type= MYSQL_TYPE_DOUBLE;
+ bind[7].buffer= (void *)&szData;
bind[7].buffer_length= 0;
for (i= 0; i < array_elements(bind); i++)
@@ -3275,17 +3176,17 @@ static void test_bind_result_ext1()
bind[i].length= &length[i];
}
- stmt = mysql_simple_prepare(mysql, "select * from test_bind_result");
+ stmt= mysql_simple_prepare(mysql, "select * from test_bind_result");
check_stmt(stmt);
- rc = mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
fprintf(stdout, "\n data (tiny) : %s(%lu)", t_data, length[0]);
fprintf(stdout, "\n data (short) : %f(%lu)", s_data, length[1]);
@@ -3298,10 +3199,10 @@ static void test_bind_result_ext1()
fprintf(stdout, "\n data (bin) : %ld(%lu)", bData, length[6]);
fprintf(stdout, "\n data (str) : %g(%lu)", szData, length[7]);
- assert(strcmp(t_data,"120")==0);
+ assert(strcmp(t_data, "120") == 0);
assert(i_data == 3999);
assert(f_data == 2);
- assert(strcmp(d_data,"58.89")==0);
+ assert(strcmp(d_data, "58.89") == 0);
assert(b_data == 54);
assert(length[0] == 3);
@@ -3313,56 +3214,61 @@ static void test_bind_result_ext1()
assert(length[6] == 4);
assert(length[7] == 8);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/*
- Generalized fetch conversion routine for all basic types
-*/
+
+/* Generalized fetch conversion routine for all basic types */
+
static void bind_fetch(int row_count)
-{
+{
MYSQL_STMT *stmt;
int rc, i, count= row_count;
- ulong bit;
long data[10];
+ int8 i8_data;
+ int16 i16_data;
+ int32 i32_data;
+ longlong i64_data;
float f_data;
double d_data;
char s_data[10];
- ulong length[10];
+ ulong length[10];
MYSQL_BIND bind[7];
- my_bool is_null[7];
+ my_bool is_null[7];
- stmt = mysql_simple_prepare(mysql,"INSERT INTO test_bind_fetch VALUES(?,?,?,?,?,?,?)");
+ stmt= mysql_simple_prepare(mysql, "INSERT INTO test_bind_fetch VALUES "
+ "(?, ?, ?, ?, ?, ?, ?)");
check_stmt(stmt);
verify_param_count(stmt, 7);
-
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
+
for (i= 0; i < (int) array_elements(bind); i++)
- {
+ {
bind[i].buffer_type= MYSQL_TYPE_LONG;
- bind[i].buffer= (char *) &data[i];
- bind[i].length= 0;
- bind[i].is_null= 0;
- }
- rc = mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
-
+ bind[i].buffer= (void *) &data[i];
+ }
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
while (count--)
{
rc= 10+count;
for (i= 0; i < (int) array_elements(bind); i++)
- {
+ {
data[i]= rc+i;
rc+= 12;
}
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
}
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
mysql_stmt_close(stmt);
@@ -3370,113 +3276,128 @@ static void bind_fetch(int row_count)
assert(row_count == (int)
my_stmt_result("SELECT * FROM test_bind_fetch"));
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_bind_fetch");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_bind_fetch");
myquery(rc);
for (i= 0; i < (int) array_elements(bind); i++)
{
- bind[i].buffer= (char *) &data[i];
+ bind[i].buffer= (void *) &data[i];
bind[i].length= &length[i];
bind[i].is_null= &is_null[i];
}
bind[0].buffer_type= MYSQL_TYPE_TINY;
+ bind[0].buffer= (void *)&i8_data;
+
bind[1].buffer_type= MYSQL_TYPE_SHORT;
+ bind[1].buffer= (void *)&i16_data;
+
bind[2].buffer_type= MYSQL_TYPE_LONG;
+ bind[2].buffer= (void *)&i32_data;
+
bind[3].buffer_type= MYSQL_TYPE_LONGLONG;
+ bind[3].buffer= (void *)&i64_data;
bind[4].buffer_type= MYSQL_TYPE_FLOAT;
- bind[4].buffer= (char *)&f_data;
+ bind[4].buffer= (void *)&f_data;
bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
- bind[5].buffer= (char *)&d_data;
+ bind[5].buffer= (void *)&d_data;
bind[6].buffer_type= MYSQL_TYPE_STRING;
- bind[6].buffer= (char *)&s_data;
+ bind[6].buffer= (void *)&s_data;
bind[6].buffer_length= sizeof(s_data);
- rc = mysql_bind_result(stmt, bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
while (row_count--)
{
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
fprintf(stdout, "\n");
- fprintf(stdout, "\n tiny : %ld(%lu)", data[0], length[0]);
- fprintf(stdout, "\n short : %ld(%lu)", data[1], length[1]);
- fprintf(stdout, "\n int : %ld(%lu)", data[2], length[2]);
- fprintf(stdout, "\n longlong : %ld(%lu)", data[3], length[3]);
+ fprintf(stdout, "\n tiny : %ld(%lu)", (ulong) i8_data, length[0]);
+ fprintf(stdout, "\n short : %ld(%lu)", (ulong) i16_data, length[1]);
+ fprintf(stdout, "\n int : %ld(%lu)", (ulong) i32_data, length[2]);
+ fprintf(stdout, "\n longlong : %ld(%lu)", (ulong) i64_data, length[3]);
fprintf(stdout, "\n float : %f(%lu)", f_data, length[4]);
fprintf(stdout, "\n double : %g(%lu)", d_data, length[5]);
fprintf(stdout, "\n char : %s(%lu)", s_data, length[6]);
- bit= 1;
rc= 10+row_count;
- for (i=0; i < 4; i++)
- {
- assert(data[i] == rc+i);
- assert(length[i] == bit);
- bit<<= 1;
- rc+= 12;
- }
+
+ /* TINY */
+ assert((int) i8_data == rc);
+ assert(length[0] == 1);
+ rc+= 13;
+
+ /* SHORT */
+ assert((int) i16_data == rc);
+ assert(length[1] == 2);
+ rc+= 13;
+
+ /* LONG */
+ assert((int) i32_data == rc);
+ assert(length[2] == 4);
+ rc+= 13;
+
+ /* LONGLONG */
+ assert((int) i64_data == rc);
+ assert(length[3] == 8);
+ rc+= 13;
/* FLOAT */
- rc+= i;
assert((int)f_data == rc);
assert(length[4] == 4);
+ rc+= 13;
/* DOUBLE */
- rc+= 13;
assert((int)d_data == rc);
assert(length[5] == 8);
+ rc+= 13;
/* CHAR */
- rc+= 13;
{
char buff[20];
long len= my_sprintf(buff, (buff, "%d", rc));
- assert(strcmp(s_data,buff)==0);
+ assert(strcmp(s_data, buff) == 0);
assert(length[6] == (ulong) len);
}
}
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test fetching of date, time and ts *
-*********************************************************/
+
+/* Test fetching of date, time and ts */
+
static void test_fetch_date()
{
MYSQL_STMT *stmt;
- uint i;
+ uint i;
int rc, year;
char date[25], time[25], ts[25], ts_4[15], ts_6[20], dt[20];
- ulong d_length, t_length, ts_length, ts4_length, ts6_length,
+ ulong d_length, t_length, ts_length, ts4_length, ts6_length,
dt_length, y_length;
MYSQL_BIND bind[8];
my_bool is_null[8];
- ulong length[8];
+ ulong length[8];
myheader("test_fetch_date");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_bind_result(c1 date, c2 time, \
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_result(c1 date, c2 time, \
c3 timestamp(14), \
c4 year, \
c5 datetime, \
@@ -3484,18 +3405,15 @@ static void test_fetch_date()
c7 timestamp(6))");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES('2002-01-02',\
- '12:49:00',\
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES('2002-01-02', \
+ '12:49:00', \
'2002-01-02 17:46:59', \
- 2010,\
+ 2010, \
'2010-07-10', \
- '2020','1999-12-29')");
+ '2020', '1999-12-29')");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
for (i= 0; i < array_elements(bind); i++)
@@ -3504,54 +3422,54 @@ static void test_fetch_date()
bind[i].length= &length[i];
}
- bind[0].buffer_type=MYSQL_TYPE_STRING;
- bind[1]=bind[2]=bind[0];
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[1]= bind[2]= bind[0];
- bind[0].buffer=(char *)&date;
+ bind[0].buffer= (void *)&date;
bind[0].buffer_length= sizeof(date);
bind[0].length= &d_length;
- bind[1].buffer=(char *)&time;
+ bind[1].buffer= (void *)&time;
bind[1].buffer_length= sizeof(time);
bind[1].length= &t_length;
- bind[2].buffer=(char *)&ts;
+ bind[2].buffer= (void *)&ts;
bind[2].buffer_length= sizeof(ts);
bind[2].length= &ts_length;
- bind[3].buffer_type=MYSQL_TYPE_LONG;
- bind[3].buffer=(char *)&year;
+ bind[3].buffer_type= MYSQL_TYPE_LONG;
+ bind[3].buffer= (void *)&year;
bind[3].length= &y_length;
- bind[4].buffer_type=MYSQL_TYPE_STRING;
- bind[4].buffer=(char *)&dt;
+ bind[4].buffer_type= MYSQL_TYPE_STRING;
+ bind[4].buffer= (void *)&dt;
bind[4].buffer_length= sizeof(dt);
bind[4].length= &dt_length;
- bind[5].buffer_type=MYSQL_TYPE_STRING;
- bind[5].buffer=(char *)&ts_4;
+ bind[5].buffer_type= MYSQL_TYPE_STRING;
+ bind[5].buffer= (void *)&ts_4;
bind[5].buffer_length= sizeof(ts_4);
bind[5].length= &ts4_length;
- bind[6].buffer_type=MYSQL_TYPE_STRING;
- bind[6].buffer=(char *)&ts_6;
+ bind[6].buffer_type= MYSQL_TYPE_STRING;
+ bind[6].buffer= (void *)&ts_6;
bind[6].buffer_length= sizeof(ts_6);
bind[6].length= &ts6_length;
assert(1 == my_stmt_result("SELECT * FROM test_bind_result"));
- stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_bind_result");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_bind_result");
check_stmt(stmt);
- rc = mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ ts_4[0]= '\0';
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
-
- ts_4[0]='\0';
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
fprintf(stdout, "\n date : %s(%lu)", date, d_length);
fprintf(stdout, "\n time : %s(%lu)", time, t_length);
@@ -3561,371 +3479,313 @@ static void test_fetch_date()
fprintf(stdout, "\n ts(4) : %s(%lu)", ts_4, ts4_length);
fprintf(stdout, "\n ts(6) : %s(%lu)", ts_6, ts6_length);
- assert(strcmp(date,"2002-01-02")==0);
+ assert(strcmp(date, "2002-01-02") == 0);
assert(d_length == 10);
- assert(strcmp(time,"12:49:00")==0);
+ assert(strcmp(time, "12:49:00") == 0);
assert(t_length == 8);
- assert(strcmp(ts,"2002-01-02 17:46:59")==0);
+ assert(strcmp(ts, "2002-01-02 17:46:59") == 0);
assert(ts_length == 19);
assert(year == 2010);
assert(y_length == 4);
-
- assert(strcmp(dt,"2010-07-10 00:00:00")==0);
+
+ assert(strcmp(dt, "2010-07-10 00:00:00") == 0);
assert(dt_length == 19);
assert(ts_4[0] == '\0');
assert(ts4_length == 0);
- assert(strcmp(ts_6,"1999-12-29 00:00:00")==0);
+ assert(strcmp(ts_6, "1999-12-29 00:00:00") == 0);
assert(ts6_length == 19);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test fetching of str to all types *
-*********************************************************/
+
+/* Test fetching of str to all types */
+
static void test_fetch_str()
{
int rc;
myheader("test_fetch_str");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 char(10),\
- c2 char(10),\
- c3 char(20),\
- c4 char(20),\
- c5 char(30),\
- c6 char(40),\
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 char(10), \
+ c2 char(10), \
+ c3 char(20), \
+ c4 char(20), \
+ c5 char(30), \
+ c6 char(40), \
c7 char(20))");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
bind_fetch(3);
}
-/********************************************************
-* to test fetching of long to all types *
-*********************************************************/
+
+/* Test fetching of long to all types */
+
static void test_fetch_long()
{
int rc;
myheader("test_fetch_long");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 int unsigned,\
- c2 int unsigned,\
- c3 int,\
- c4 int,\
- c5 int,\
- c6 int unsigned,\
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 int unsigned, \
+ c2 int unsigned, \
+ c3 int, \
+ c4 int, \
+ c5 int, \
+ c6 int unsigned, \
c7 int)");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
bind_fetch(4);
}
-/********************************************************
-* to test fetching of short to all types *
-*********************************************************/
+/* Test fetching of short to all types */
+
static void test_fetch_short()
{
int rc;
myheader("test_fetch_short");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 smallint unsigned,\
- c2 smallint,\
- c3 smallint unsigned,\
- c4 smallint,\
- c5 smallint,\
- c6 smallint,\
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 smallint unsigned, \
+ c2 smallint, \
+ c3 smallint unsigned, \
+ c4 smallint, \
+ c5 smallint, \
+ c6 smallint, \
c7 smallint unsigned)");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
bind_fetch(5);
}
-/********************************************************
-* to test fetching of tiny to all types *
-*********************************************************/
+/* Test fetching of tiny to all types */
+
static void test_fetch_tiny()
{
int rc;
myheader("test_fetch_tiny");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 tinyint unsigned,\
- c2 tinyint,\
- c3 tinyint unsigned,\
- c4 tinyint,\
- c5 tinyint,\
- c6 tinyint,\
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 tinyint unsigned, \
+ c2 tinyint, \
+ c3 tinyint unsigned, \
+ c4 tinyint, \
+ c5 tinyint, \
+ c6 tinyint, \
c7 tinyint unsigned)");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
bind_fetch(3);
}
-/********************************************************
-* to test fetching of longlong to all types *
-*********************************************************/
+/* Test fetching of longlong to all types */
+
static void test_fetch_bigint()
{
int rc;
myheader("test_fetch_bigint");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 bigint,\
- c2 bigint,\
- c3 bigint unsigned,\
- c4 bigint unsigned,\
- c5 bigint unsigned,\
- c6 bigint unsigned,\
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 bigint, \
+ c2 bigint, \
+ c3 bigint unsigned, \
+ c4 bigint unsigned, \
+ c5 bigint unsigned, \
+ c6 bigint unsigned, \
c7 bigint unsigned)");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
bind_fetch(2);
}
-/********************************************************
-* to test fetching of float to all types *
-*********************************************************/
+/* Test fetching of float to all types */
+
static void test_fetch_float()
{
int rc;
myheader("test_fetch_float");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 float(3),\
- c2 float,\
- c3 float unsigned,\
- c4 float,\
- c5 float,\
- c6 float,\
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 float(3), \
+ c2 float, \
+ c3 float unsigned, \
+ c4 float, \
+ c5 float, \
+ c6 float, \
c7 float(10) unsigned)");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
bind_fetch(2);
}
-/********************************************************
-* to test fetching of double to all types *
-*********************************************************/
+
+/* Test fetching of double to all types */
+
static void test_fetch_double()
{
int rc;
myheader("test_fetch_double");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_fetch");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_bind_fetch(c1 double(5,2),\
- c2 double unsigned,\
- c3 double unsigned,\
- c4 double unsigned,\
- c5 double unsigned,\
- c6 double unsigned,\
- c7 double unsigned)");
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 double(5, 2), "
+ "c2 double unsigned, c3 double unsigned, "
+ "c4 double unsigned, c5 double unsigned, "
+ "c6 double unsigned, c7 double unsigned)");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
bind_fetch(3);
}
-/********************************************************
-* to test simple prepare with all possible types *
-*********************************************************/
+
+/* Test simple prepare with all possible types */
+
static void test_prepare_ext()
{
MYSQL_STMT *stmt;
- uint i;
int rc;
char *sql;
- int nData=1;
- char tData=1;
- short sData=10;
- longlong bData=20;
+ int nData= 1;
+ char tData= 1;
+ short sData= 10;
+ longlong bData= 20;
MYSQL_BIND bind[6];
myheader("test_prepare_ext");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_ext");
- myquery(rc);
-
- rc = mysql_commit(mysql);
- myquery(rc);
-
- sql = (char *)"CREATE TABLE test_prepare_ext\
- (\
- 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,\
- 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,\
- c29 longblob,\
- c30 longtext,\
- c31 enum('one','two','three'),\
- c32 set('monday','tuesday','wednesday'))";
-
- rc = mysql_query(mysql,sql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_ext");
+ myquery(rc);
+
+ sql= (char *)"CREATE TABLE test_prepare_ext\
+ (\
+ 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, \
+ 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, \
+ c29 longblob, \
+ c30 longtext, \
+ c31 enum('one', 'two', 'three'), \
+ c32 set('monday', 'tuesday', 'wednesday'))";
+
+ rc= mysql_query(mysql, sql);
myquery(rc);
/* insert by prepare - all integers */
- strmov(query,(char *)"INSERT INTO test_prepare_ext(c1,c2,c3,c4,c5,c6) VALUES(?,?,?,?,?,?)");
- stmt = mysql_simple_prepare(mysql,query);
+ strmov(query, (char *)"INSERT INTO test_prepare_ext(c1, c2, c3, c4, c5, c6) VALUES(?, ?, ?, ?, ?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,6);
+ verify_param_count(stmt, 6);
+
+ /* Always bzero all members of bind parameter */
+ bzero((char*) bind, sizeof(bind));
/*tinyint*/
- bind[0].buffer_type=FIELD_TYPE_TINY;
- bind[0].buffer= (char *)&tData;
+ bind[0].buffer_type= MYSQL_TYPE_TINY;
+ bind[0].buffer= (void *)&tData;
/*smallint*/
- bind[1].buffer_type=FIELD_TYPE_SHORT;
- bind[1].buffer= (char *)&sData;
+ bind[1].buffer_type= MYSQL_TYPE_SHORT;
+ bind[1].buffer= (void *)&sData;
/*mediumint*/
- bind[2].buffer_type=FIELD_TYPE_LONG;
- bind[2].buffer= (char *)&nData;
+ bind[2].buffer_type= MYSQL_TYPE_LONG;
+ bind[2].buffer= (void *)&nData;
/*int*/
- bind[3].buffer_type=FIELD_TYPE_LONG;
- bind[3].buffer= (char *)&nData;
+ bind[3].buffer_type= MYSQL_TYPE_LONG;
+ bind[3].buffer= (void *)&nData;
/*integer*/
- bind[4].buffer_type=FIELD_TYPE_LONG;
- bind[4].buffer= (char *)&nData;
+ bind[4].buffer_type= MYSQL_TYPE_LONG;
+ bind[4].buffer= (void *)&nData;
/*bigint*/
- bind[5].buffer_type=FIELD_TYPE_LONGLONG;
- bind[5].buffer= (char *)&bData;
+ bind[5].buffer_type= MYSQL_TYPE_LONGLONG;
+ bind[5].buffer= (void *)&bData;
- for (i= 0; i < array_elements(bind); i++)
- {
- bind[i].is_null=0;
- bind[i].buffer_length= 0;
- bind[i].length= 0;
- }
-
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
/*
* integer to integer
*/
- for (nData=0; nData<10; nData++, tData++, sData++,bData++)
+ for (nData= 0; nData<10; nData++, tData++, sData++, bData++)
{
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
}
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
- myquery(rc);
- stmt = mysql_simple_prepare(mysql,"SELECT c1,c2,c3,c4,c5,c6 FROM test_prepare_ext");
+ stmt= mysql_simple_prepare(mysql, "SELECT c1, c2, c3, c4, c5, c6 "
+ "FROM test_prepare_ext");
check_stmt(stmt);
/* get the result */
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(nData == (int)my_process_stmt_result(stmt));
@@ -3934,10 +3794,8 @@ static void test_prepare_ext()
}
+/* Test real and alias names */
-/********************************************************
-* to test real and alias names *
-*********************************************************/
static void test_field_names()
{
int rc;
@@ -3945,49 +3803,43 @@ static void test_field_names()
myheader("test_field_names");
- fprintf(stdout,"\n %d,%d,%d",MYSQL_TYPE_DECIMAL,MYSQL_TYPE_NEWDATE,MYSQL_TYPE_ENUM);
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_field_names1");
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_field_names2");
+ fprintf(stdout, "\n %d, %d, %d", MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NEWDATE, MYSQL_TYPE_ENUM);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names1");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names2");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_field_names1(id int,name varchar(50))");
+ rc= mysql_query(mysql, "CREATE TABLE test_field_names1(id int, name varchar(50))");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_field_names2(id int,name varchar(50))");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_field_names2(id int, name varchar(50))");
myquery(rc);
/* with table name included with TRUE column name */
- rc = mysql_query(mysql,"SELECT id as 'id-alias' FROM test_field_names1");
+ rc= mysql_query(mysql, "SELECT id as 'id-alias' FROM test_field_names1");
myquery(rc);
- result = mysql_use_result(mysql);
+ result= mysql_use_result(mysql);
mytest(result);
assert(0 == my_process_result_set(result));
mysql_free_result(result);
/* with table name included with TRUE column name */
- rc = mysql_query(mysql,"SELECT t1.id as 'id-alias',test_field_names2.name FROM test_field_names1 t1,test_field_names2");
+ rc= mysql_query(mysql, "SELECT t1.id as 'id-alias', test_field_names2.name FROM test_field_names1 t1, test_field_names2");
myquery(rc);
- result = mysql_use_result(mysql);
+ result= mysql_use_result(mysql);
mytest(result);
assert(0 == my_process_result_set(result));
mysql_free_result(result);
}
-/********************************************************
-* to test warnings *
-*********************************************************/
+
+/* Test warnings */
+
static void test_warnings()
{
int rc;
@@ -3997,23 +3849,23 @@ static void test_warnings()
mysql_query(mysql, "DROP TABLE if exists test_non_exists");
- rc = mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
myquery(rc);
fprintf(stdout, "\n total warnings: %d", mysql_warning_count(mysql));
- rc = mysql_query(mysql,"SHOW WARNINGS");
+ rc= mysql_query(mysql, "SHOW WARNINGS");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
mysql_free_result(result);
}
-/********************************************************
-* to test errors *
-*********************************************************/
+
+/* Test errors */
+
static void test_errors()
{
int rc;
@@ -4023,13 +3875,13 @@ static void test_errors()
mysql_query(mysql, "DROP TABLE if exists test_non_exists");
- rc = mysql_query(mysql, "DROP TABLE test_non_exists");
+ rc= mysql_query(mysql, "DROP TABLE test_non_exists");
myquery_r(rc);
- rc = mysql_query(mysql,"SHOW ERRORS");
+ rc= mysql_query(mysql, "SHOW ERRORS");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
my_process_result_set(result);
@@ -4037,10 +3889,8 @@ static void test_errors()
}
+/* Test simple prepare-insert */
-/********************************************************
-* to test simple prepare-insert *
-*********************************************************/
static void test_insert()
{
MYSQL_STMT *stmt;
@@ -4049,65 +3899,66 @@ static void test_insert()
char tiny_data;
MYSQL_RES *result;
MYSQL_BIND bind[2];
- ulong length;
+ ulong length;
myheader("test_insert");
- rc = mysql_autocommit(mysql, TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_insert");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_insert");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_prep_insert(col1 tinyint,\
+ rc= mysql_query(mysql, "CREATE TABLE test_prep_insert(col1 tinyint, \
col2 varchar(50))");
myquery(rc);
/* insert by prepare */
- stmt = mysql_simple_prepare(mysql, "INSERT INTO test_prep_insert VALUES(?,?)");
+ stmt= mysql_simple_prepare(mysql,
+ "INSERT INTO test_prep_insert VALUES(?, ?)");
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
/* tinyint */
- bind[0].buffer_type=FIELD_TYPE_TINY;
- bind[0].buffer=(char *)&tiny_data;
- bind[0].is_null= 0;
- bind[0].length= 0;
+ bind[0].buffer_type= MYSQL_TYPE_TINY;
+ bind[0].buffer= (void *)&tiny_data;
/* string */
- bind[1].buffer_type=FIELD_TYPE_STRING;
- bind[1].buffer=str_data;
- bind[1].buffer_length=sizeof(str_data);;
- bind[1].is_null= 0;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= str_data;
+ bind[1].buffer_length= sizeof(str_data);;
bind[1].length= &length;
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
/* now, execute the prepared statement to insert 10 records.. */
- for (tiny_data=0; tiny_data < 3; tiny_data++)
+ for (tiny_data= 0; tiny_data < 3; tiny_data++)
{
- length = my_sprintf(str_data, (str_data, "MySQL%d",tiny_data));
- rc = mysql_execute(stmt);
+ length= my_sprintf(str_data, (str_data, "MySQL%d", tiny_data));
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
}
mysql_stmt_close(stmt);
/* now fetch the results ..*/
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* test the results now, only one row should exists */
- rc = mysql_query(mysql,"SELECT * FROM test_prep_insert");
+ rc= mysql_query(mysql, "SELECT * FROM test_prep_insert");
myquery(rc);
/* get the result */
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert((int)tiny_data == my_process_result_set(result));
@@ -4115,9 +3966,9 @@ static void test_insert()
}
-/********************************************************
-* to test simple prepare-resultset info *
-*********************************************************/
+
+/* Test simple prepare-resultset info */
+
static void test_prepare_resultset()
{
MYSQL_STMT *stmt;
@@ -4126,34 +3977,30 @@ static void test_prepare_resultset()
myheader("test_prepare_resultset");
- rc = mysql_autocommit(mysql, TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prepare_resultset");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_resultset");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_prepare_resultset(id int,\
- name varchar(50),extra double)");
+ rc= mysql_query(mysql, "CREATE TABLE test_prepare_resultset(id int, \
+ name varchar(50), extra double)");
myquery(rc);
- stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_prepare_resultset");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_prepare_resultset");
check_stmt(stmt);
- verify_param_count(stmt,0);
+ verify_param_count(stmt, 0);
- result = mysql_get_metadata(stmt);
+ result= mysql_stmt_result_metadata(stmt);
mytest(result);
my_print_result_metadata(result);
mysql_free_result(result);
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test field flags (verify .NET provider) *
-*********************************************************/
+
+/* Test field flags (verify .NET provider) */
static void test_field_flags()
{
@@ -4165,56 +4012,50 @@ static void test_field_flags()
myheader("test_field_flags");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_field_flags");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_flags");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_field_flags(id int NOT NULL AUTO_INCREMENT PRIMARY KEY,\
- id1 int NOT NULL,\
- id2 int UNIQUE,\
- id3 int,\
- id4 int NOT NULL,\
- id5 int,\
- KEY(id3,id4))");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_field_flags(id int NOT NULL AUTO_INCREMENT PRIMARY KEY, \
+ id1 int NOT NULL, \
+ id2 int UNIQUE, \
+ id3 int, \
+ id4 int NOT NULL, \
+ id5 int, \
+ KEY(id3, id4))");
myquery(rc);
/* with table name included with TRUE column name */
- rc = mysql_query(mysql,"SELECT * FROM test_field_flags");
+ rc= mysql_query(mysql, "SELECT * FROM test_field_flags");
myquery(rc);
- result = mysql_use_result(mysql);
+ result= mysql_use_result(mysql);
mytest(result);
- mysql_field_seek(result,0);
- fputc('\n', stdout);
+ mysql_field_seek(result, 0);
+ fputc('\n', stdout);
- for(i=0; i< mysql_num_fields(result); i++)
+ for(i= 0; i< mysql_num_fields(result); i++)
{
- field = mysql_fetch_field(result);
- fprintf(stdout,"\n field:%d",i);
+ field= mysql_fetch_field(result);
+ fprintf(stdout, "\n field:%d", i);
if (field->flags & NOT_NULL_FLAG)
- fprintf(stdout,"\n NOT_NULL_FLAG");
+ fprintf(stdout, "\n NOT_NULL_FLAG");
if (field->flags & PRI_KEY_FLAG)
- fprintf(stdout,"\n PRI_KEY_FLAG");
+ fprintf(stdout, "\n PRI_KEY_FLAG");
if (field->flags & UNIQUE_KEY_FLAG)
- fprintf(stdout,"\n UNIQUE_KEY_FLAG");
+ fprintf(stdout, "\n UNIQUE_KEY_FLAG");
if (field->flags & MULTIPLE_KEY_FLAG)
- fprintf(stdout,"\n MULTIPLE_KEY_FLAG");
+ fprintf(stdout, "\n MULTIPLE_KEY_FLAG");
if (field->flags & AUTO_INCREMENT_FLAG)
- fprintf(stdout,"\n AUTO_INCREMENT_FLAG");
+ fprintf(stdout, "\n AUTO_INCREMENT_FLAG");
}
mysql_free_result(result);
}
-/**************************************************************
- * Test mysql_stmt_close for open stmts *
-**************************************************************/
+
+/* Test mysql_stmt_close for open stmts */
+
static void test_stmt_close()
{
MYSQL *lmysql;
@@ -4223,97 +4064,100 @@ static void test_stmt_close()
MYSQL_RES *result;
unsigned int count;
int rc;
-
- myheader("test_stmt_close");
+
+ myheader("test_stmt_close");
fprintf(stdout, "\n Establishing a test connection ...");
- if (!(lmysql = mysql_init(NULL)))
- {
+ if (!(lmysql= mysql_init(NULL)))
+ {
myerror("mysql_init() failed");
exit(0);
}
- if (!(mysql_real_connect(lmysql,opt_host,opt_user,
- opt_password, current_db, opt_port,
- opt_unix_socket, 0)))
+ if (!(mysql_real_connect(lmysql, opt_host, opt_user,
+ opt_password, current_db, opt_port,
+ opt_unix_socket, 0)))
{
myerror("connection failed");
exit(0);
- }
- fprintf(stdout," OK");
-
+ }
+ fprintf(stdout, " OK");
+
/* set AUTOCOMMIT to ON*/
mysql_autocommit(lmysql, TRUE);
-
- rc = mysql_query(lmysql,"DROP TABLE IF EXISTS test_stmt_close");
+
+ rc= mysql_query(lmysql, "DROP TABLE IF EXISTS test_stmt_close");
myquery(rc);
-
- rc = mysql_query(lmysql,"CREATE TABLE test_stmt_close(id int)");
+
+ rc= mysql_query(lmysql, "CREATE TABLE test_stmt_close(id int)");
myquery(rc);
- strmov(query,"DO \"nothing\"");
+ strmov(query, "DO \"nothing\"");
stmt1= mysql_simple_prepare(lmysql, query);
check_stmt(stmt1);
-
+
verify_param_count(stmt1, 0);
-
- strmov(query,"INSERT INTO test_stmt_close(id) VALUES(?)");
+
+ strmov(query, "INSERT INTO test_stmt_close(id) VALUES(?)");
stmt_x= mysql_simple_prepare(mysql, query);
check_stmt(stmt_x);
verify_param_count(stmt_x, 1);
-
- strmov(query,"UPDATE test_stmt_close SET id=? WHERE id=?");
+
+ strmov(query, "UPDATE test_stmt_close SET id= ? WHERE id= ?");
stmt3= mysql_simple_prepare(lmysql, query);
check_stmt(stmt3);
-
+
verify_param_count(stmt3, 2);
-
- strmov(query,"SELECT * FROM test_stmt_close WHERE id=?");
+
+ strmov(query, "SELECT * FROM test_stmt_close WHERE id= ?");
stmt2= mysql_simple_prepare(lmysql, query);
check_stmt(stmt2);
verify_param_count(stmt2, 1);
rc= mysql_stmt_close(stmt1);
- fprintf(stdout,"\n mysql_close_stmt(1) returned: %d", rc);
+ fprintf(stdout, "\n mysql_close_stmt(1) returned: %d", rc);
assert(rc == 0);
-
+
/*
Originally we were going to close all statements automatically in
mysql_close(). This proved to not work well - users weren't able to
close statements by hand once mysql_close() had been called.
Now mysql_close() doesn't free any statements, so this test doesn't
- serve its original destination any more.
+ serve its original designation any more.
Here we free stmt2 and stmt3 by hande to avoid memory leaks.
*/
mysql_stmt_close(stmt2);
mysql_stmt_close(stmt3);
mysql_close(lmysql);
-
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
+ bind[0].buffer= (void *)&count;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
count= 100;
- bind[0].buffer=(char *)&count;
- bind[0].buffer_type=MYSQL_TYPE_LONG;
- bind[0].buffer_length= 0;
- bind[0].length= 0;
- bind[0].is_null=0;
- rc = mysql_bind_param(stmt_x, bind);
+ rc= mysql_stmt_bind_param(stmt_x, bind);
check_execute(stmt_x, rc);
-
- rc = mysql_execute(stmt_x);
+
+ rc= mysql_stmt_execute(stmt_x);
check_execute(stmt_x, rc);
verify_st_affected_rows(stmt_x, 1);
rc= mysql_stmt_close(stmt_x);
- fprintf(stdout,"\n mysql_close_stmt(x) returned: %d", rc);
+ fprintf(stdout, "\n mysql_close_stmt(x) returned: %d", rc);
assert( rc == 0);
- rc = mysql_query(mysql,"SELECT id FROM test_stmt_close");
+ rc= mysql_query(mysql, "SELECT id FROM test_stmt_close");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
@@ -4321,9 +4165,8 @@ static void test_stmt_close()
}
-/********************************************************
- * To test simple set-variable prepare *
-*********************************************************/
+/* Test simple set-variable prepare */
+
static void test_set_variable()
{
MYSQL_STMT *stmt, *stmt1;
@@ -4336,90 +4179,97 @@ static void test_set_variable()
myheader("test_set_variable");
mysql_autocommit(mysql, TRUE);
-
- stmt1 = mysql_simple_prepare(mysql, "show variables like 'max_error_count'");
+
+ stmt1= mysql_simple_prepare(mysql, "show variables like 'max_error_count'");
check_stmt(stmt1);
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) get_bind, sizeof(get_bind));
+
get_bind[0].buffer_type= MYSQL_TYPE_STRING;
- get_bind[0].buffer= (char *)var;
- get_bind[0].is_null= 0;
+ get_bind[0].buffer= (void *)var;
get_bind[0].length= &length;
get_bind[0].buffer_length= (int)NAME_LEN;
length= NAME_LEN;
get_bind[1].buffer_type= MYSQL_TYPE_LONG;
- get_bind[1].buffer= (char *)&get_count;
+ get_bind[1].buffer= (void *)&get_count;
get_bind[1].is_null= 0;
get_bind[1].length= 0;
- rc = mysql_execute(stmt1);
+ rc= mysql_stmt_execute(stmt1);
check_execute(stmt1, rc);
-
- rc = mysql_bind_result(stmt1, get_bind);
+
+ rc= mysql_stmt_bind_result(stmt1, get_bind);
check_execute(stmt1, rc);
- rc = mysql_fetch(stmt1);
+ rc= mysql_stmt_fetch(stmt1);
check_execute(stmt1, rc);
fprintf(stdout, "\n max_error_count(default): %d", get_count);
def_count= get_count;
- assert(strcmp(var,"max_error_count") == 0);
- rc = mysql_fetch(stmt1);
+ assert(strcmp(var, "max_error_count") == 0);
+ rc= mysql_stmt_fetch(stmt1);
assert(rc == MYSQL_NO_DATA);
- stmt = mysql_simple_prepare(mysql, "set max_error_count=?");
+ stmt= mysql_simple_prepare(mysql, "set max_error_count= ?");
check_stmt(stmt);
+ bzero((char*) set_bind, sizeof(set_bind));
+
set_bind[0].buffer_type= MYSQL_TYPE_LONG;
- set_bind[0].buffer= (char *)&set_count;
- set_bind[0].is_null= 0;
- set_bind[0].length= 0;
-
- rc = mysql_bind_param(stmt, set_bind);
- check_execute(stmt,rc);
-
+ set_bind[0].buffer= (void *)&set_count;
+
+ rc= mysql_stmt_bind_param(stmt, set_bind);
+ check_execute(stmt, rc);
+
set_count= 31;
- rc= mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
mysql_commit(mysql);
- rc = mysql_execute(stmt1);
+ rc= mysql_stmt_execute(stmt1);
check_execute(stmt1, rc);
-
- rc = mysql_fetch(stmt1);
+
+ rc= mysql_stmt_fetch(stmt1);
check_execute(stmt1, rc);
fprintf(stdout, "\n max_error_count : %d", get_count);
assert(get_count == set_count);
- rc = mysql_fetch(stmt1);
+ rc= mysql_stmt_fetch(stmt1);
assert(rc == MYSQL_NO_DATA);
-
+
/* restore back to default */
set_count= def_count;
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
- rc = mysql_execute(stmt1);
+
+ rc= mysql_stmt_execute(stmt1);
check_execute(stmt1, rc);
-
- rc = mysql_fetch(stmt1);
+
+ rc= mysql_stmt_fetch(stmt1);
check_execute(stmt1, rc);
fprintf(stdout, "\n max_error_count(default): %d", get_count);
assert(get_count == set_count);
- rc = mysql_fetch(stmt1);
+ rc= mysql_stmt_fetch(stmt1);
assert(rc == MYSQL_NO_DATA);
-
+
mysql_stmt_close(stmt);
mysql_stmt_close(stmt1);
}
#if NOT_USED
+
/* Insert meta info .. */
+
static void test_insert_meta()
{
MYSQL_STMT *stmt;
@@ -4429,35 +4279,32 @@ static void test_insert_meta()
myheader("test_insert_meta");
- rc = mysql_autocommit(mysql, TRUE);
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_insert");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_insert");
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_prep_insert(col1 tinyint,\
+ rc= mysql_query(mysql, "CREATE TABLE test_prep_insert(col1 tinyint, \
col2 varchar(50), col3 varchar(30))");
myquery(rc);
- strmov(query,"INSERT INTO test_prep_insert VALUES(10,'venu1','test')");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_prep_insert VALUES(10, 'venu1', 'test')");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,0);
+ verify_param_count(stmt, 0);
result= mysql_param_result(stmt);
mytest_r(result);
mysql_stmt_close(stmt);
- strmov(query,"INSERT INTO test_prep_insert VALUES(?,'venu',?)");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "INSERT INTO test_prep_insert VALUES(?, 'venu', ?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
result= mysql_param_result(stmt);
mytest(result);
@@ -4468,12 +4315,12 @@ static void test_insert_meta()
field= mysql_fetch_field(result);
mytest(field);
fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col1");
- assert(strcmp(field->name,"col1")==0);
+ assert(strcmp(field->name, "col1") == 0);
field= mysql_fetch_field(result);
mytest(field);
fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col3");
- assert(strcmp(field->name,"col3")==0);
+ assert(strcmp(field->name, "col3") == 0);
field= mysql_fetch_field(result);
mytest_r(field);
@@ -4482,7 +4329,9 @@ static void test_insert_meta()
mysql_stmt_close(stmt);
}
+
/* Update meta info .. */
+
static void test_update_meta()
{
MYSQL_STMT *stmt;
@@ -4492,35 +4341,32 @@ static void test_update_meta()
myheader("test_update_meta");
- rc = mysql_autocommit(mysql, TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_update");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_update");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_prep_update(col1 tinyint,\
+ rc= mysql_query(mysql, "CREATE TABLE test_prep_update(col1 tinyint, \
col2 varchar(50), col3 varchar(30))");
myquery(rc);
- strmov(query,"UPDATE test_prep_update SET col1=10, col2='venu1' WHERE col3='test'");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "UPDATE test_prep_update SET col1=10, col2='venu1' WHERE col3='test'");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,0);
+ verify_param_count(stmt, 0);
result= mysql_param_result(stmt);
mytest_r(result);
mysql_stmt_close(stmt);
- strmov(query,"UPDATE test_prep_update SET col1=?, col2='venu' WHERE col3=?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "UPDATE test_prep_update SET col1=?, col2='venu' WHERE col3=?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
result= mysql_param_result(stmt);
mytest(result);
@@ -4532,15 +4378,15 @@ static void test_update_meta()
mytest(field);
fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
- assert(strcmp(field->name,"col1")==0);
- assert(strcmp(field->table,"test_prep_update")==0);
+ assert(strcmp(field->name, "col1") == 0);
+ assert(strcmp(field->table, "test_prep_update") == 0);
field= mysql_fetch_field(result);
mytest(field);
fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col3");
fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
- assert(strcmp(field->name,"col3")==0);
- assert(strcmp(field->table,"test_prep_update")==0);
+ assert(strcmp(field->name, "col3") == 0);
+ assert(strcmp(field->table, "test_prep_update") == 0);
field= mysql_fetch_field(result);
mytest_r(field);
@@ -4549,7 +4395,9 @@ static void test_update_meta()
mysql_stmt_close(stmt);
}
+
/* Select meta info .. */
+
static void test_select_meta()
{
MYSQL_STMT *stmt;
@@ -4559,33 +4407,30 @@ static void test_select_meta()
myheader("test_select_meta");
- rc = mysql_autocommit(mysql, TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_select");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_select");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_prep_select(col1 tinyint,\
+ rc= mysql_query(mysql, "CREATE TABLE test_prep_select(col1 tinyint, \
col2 varchar(50), col3 varchar(30))");
myquery(rc);
- strmov(query,"SELECT * FROM test_prep_select WHERE col1=10");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "SELECT * FROM test_prep_select WHERE col1=10");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,0);
+ verify_param_count(stmt, 0);
result= mysql_param_result(stmt);
mytest_r(result);
- strmov(query,"SELECT col1, col3 from test_prep_select WHERE col1=? AND col3='test' AND col2= ?");
- stmt = mysql_simple_prepare(mysql, query);
+ strmov(query, "SELECT col1, col3 from test_prep_select WHERE col1=? AND col3='test' AND col2= ?");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- verify_param_count(stmt,2);
+ verify_param_count(stmt, 2);
result= mysql_param_result(stmt);
mytest(result);
@@ -4597,15 +4442,15 @@ static void test_select_meta()
mytest(field);
fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
- assert(strcmp(field->name,"col1")==0);
- assert(strcmp(field->table,"test_prep_select")==0);
+ assert(strcmp(field->name, "col1") == 0);
+ assert(strcmp(field->table, "test_prep_select") == 0);
field= mysql_fetch_field(result);
mytest(field);
fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col2");
fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
- assert(strcmp(field->name,"col2")==0);
- assert(strcmp(field->table,"test_prep_select")==0);
+ assert(strcmp(field->name, "col2") == 0);
+ assert(strcmp(field->table, "test_prep_select") == 0);
field= mysql_fetch_field(result);
mytest_r(field);
@@ -4617,6 +4462,7 @@ static void test_select_meta()
/* Test FUNCTION field info / DATE_FORMAT() table_name . */
+
static void test_func_fields()
{
int rc;
@@ -4625,71 +4471,68 @@ static void test_func_fields()
myheader("test_func_fields");
- rc = mysql_autocommit(mysql, TRUE);
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_dateformat");
+ rc= mysql_autocommit(mysql, TRUE);
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_dateformat");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_dateformat(id int, \
+ rc= mysql_query(mysql, "CREATE TABLE test_dateformat(id int, \
ts timestamp)");
myquery(rc);
- rc = mysql_query(mysql, "INSERT INTO test_dateformat(id) values(10)");
+ rc= mysql_query(mysql, "INSERT INTO test_dateformat(id) values(10)");
myquery(rc);
- rc = mysql_query(mysql, "SELECT ts FROM test_dateformat");
+ rc= mysql_query(mysql, "SELECT ts FROM test_dateformat");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
- field = mysql_fetch_field(result);
+ field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout,"\n table name: `%s` (expected: `%s`)", field->table,
+ fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table,
"test_dateformat");
- assert(strcmp(field->table, "test_dateformat")==0);
+ assert(strcmp(field->table, "test_dateformat") == 0);
- field = mysql_fetch_field(result);
+ field= mysql_fetch_field(result);
mytest_r(field); /* no more fields */
mysql_free_result(result);
/* DATE_FORMAT */
- rc = mysql_query(mysql, "SELECT DATE_FORMAT(ts,'%Y') AS 'venu' FROM test_dateformat");
+ rc= mysql_query(mysql, "SELECT DATE_FORMAT(ts, '%Y') AS 'venu' FROM test_dateformat");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
- field = mysql_fetch_field(result);
+ field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout,"\n table name: `%s` (expected: `%s`)", field->table, "");
+ fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table, "");
assert(field->table[0] == '\0');
- field = mysql_fetch_field(result);
+ field= mysql_fetch_field(result);
mytest_r(field); /* no more fields */
mysql_free_result(result);
/* FIELD ALIAS TEST */
- rc = mysql_query(mysql, "SELECT DATE_FORMAT(ts,'%Y') AS 'YEAR' FROM test_dateformat");
+ rc= mysql_query(mysql, "SELECT DATE_FORMAT(ts, '%Y') AS 'YEAR' FROM test_dateformat");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
- field = mysql_fetch_field(result);
+ field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout,"\n field name: `%s` (expected: `%s`)", field->name, "YEAR");
- fprintf(stdout,"\n field org name: `%s` (expected: `%s`)",field->org_name,"");
- assert(strcmp(field->name, "YEAR")==0);
+ fprintf(stdout, "\n field name: `%s` (expected: `%s`)", field->name, "YEAR");
+ fprintf(stdout, "\n field org name: `%s` (expected: `%s`)", field->org_name, "");
+ assert(strcmp(field->name, "YEAR") == 0);
assert(field->org_name[0] == '\0');
- field = mysql_fetch_field(result);
+ field= mysql_fetch_field(result);
mytest_r(field); /* no more fields */
mysql_free_result(result);
@@ -4697,109 +4540,119 @@ static void test_func_fields()
/* Multiple stmts .. */
+
static void test_multi_stmt()
{
MYSQL_STMT *stmt, *stmt1, *stmt2;
- int rc, id;
+ int rc;
+ ulong id;
char name[50];
MYSQL_BIND bind[2];
ulong length[2];
my_bool is_null[2];
myheader("test_multi_stmt");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_multi_table");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_multi_table");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_multi_table(id int, name char(20))");
+ rc= mysql_query(mysql, "CREATE TABLE test_multi_table(id int, name char(20))");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_multi_table values(10,'mysql')");
+ rc= mysql_query(mysql, "INSERT INTO test_multi_table values(10, 'mysql')");
myquery(rc);
- stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_multi_table WHERE id = ?");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_multi_table "
+ "WHERE id= ?");
check_stmt(stmt);
- stmt2 = mysql_simple_prepare(mysql, "UPDATE test_multi_table SET name='updated' WHERE id=10");
+ stmt2= mysql_simple_prepare(mysql, "UPDATE test_multi_table "
+ "SET name='updated' WHERE id=10");
check_stmt(stmt2);
- verify_param_count(stmt,1);
+ verify_param_count(stmt, 1);
- bind[0].buffer_type= MYSQL_TYPE_SHORT;
- bind[0].buffer= (char *)&id;
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void *)&id;
bind[0].is_null= &is_null[0];
- bind[0].buffer_length= 0;
bind[0].length= &length[0];
is_null[0]= 0;
length[0]= 0;
- bind[1].buffer_type = MYSQL_TYPE_STRING;
- bind[1].buffer = (char *)name;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= (void *)name;
bind[1].buffer_length= sizeof(name);
- bind[1].length = &length[1];
+ bind[1].length= &length[1];
bind[1].is_null= &is_null[1];
-
- rc = mysql_bind_param(stmt, bind);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
-
- rc = mysql_bind_result(stmt, bind);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- id = 10;
- rc = mysql_execute(stmt);
+ id= 10;
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
- id = 999;
- rc = mysql_fetch(stmt);
+
+ id= 999;
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n int_data: %d(%lu)", id, length[0]);
+ fprintf(stdout, "\n int_data: %lu(%lu)", id, length[0]);
fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
assert(id == 10);
- assert(strcmp(name,"mysql")==0);
+ assert(strcmp(name, "mysql") == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
/* alter the table schema now */
- stmt1 = mysql_simple_prepare(mysql,"DELETE FROM test_multi_table WHERE id = ? AND name=?");
+ stmt1= mysql_simple_prepare(mysql, "DELETE FROM test_multi_table "
+ "WHERE id= ? AND name=?");
check_stmt(stmt1);
- verify_param_count(stmt1,2);
+ verify_param_count(stmt1, 2);
- rc = mysql_bind_param(stmt1, bind);
+ rc= mysql_stmt_bind_param(stmt1, bind);
check_execute(stmt1, rc);
-
- rc = mysql_execute(stmt2);
+
+ rc= mysql_stmt_execute(stmt2);
check_execute(stmt2, rc);
verify_st_affected_rows(stmt2, 1);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
- rc = mysql_fetch(stmt);
+
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n int_data: %d(%lu)", id, length[0]);
+ fprintf(stdout, "\n int_data: %lu(%lu)", id, length[0]);
fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
assert(id == 10);
- assert(strcmp(name,"updated")==0);
+ assert(strcmp(name, "updated") == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
- rc = mysql_execute(stmt1);
+ rc= mysql_stmt_execute(stmt1);
check_execute(stmt1, rc);
verify_st_affected_rows(stmt1, 1);
mysql_stmt_close(stmt1);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
assert(0 == my_stmt_result("SELECT * FROM test_multi_table"));
@@ -4810,9 +4663,8 @@ static void test_multi_stmt()
}
-/********************************************************
-* to test simple sample - manual *
-*********************************************************/
+/* Test simple sample - manual */
+
static void test_manual_sample()
{
unsigned int param_count;
@@ -4827,29 +4679,29 @@ static void test_manual_sample()
myheader("test_manual_sample");
/*
- Sample which is incorporated directly in the manual under Prepared
- statements section (Example from mysql_execute()
+ Sample which is incorporated directly in the manual under Prepared
+ statements section (Example from mysql_stmt_execute()
*/
mysql_autocommit(mysql, 1);
- if (mysql_query(mysql,"DROP TABLE IF EXISTS test_table"))
+ if (mysql_query(mysql, "DROP TABLE IF EXISTS test_table"))
{
fprintf(stderr, "\n drop table failed");
fprintf(stderr, "\n %s", mysql_error(mysql));
exit(0);
}
- if (mysql_query(mysql,"CREATE TABLE test_table(col1 int, col2 varchar(50), \
- col3 smallint,\
+ if (mysql_query(mysql, "CREATE TABLE test_table(col1 int, col2 varchar(50), \
+ col3 smallint, \
col4 timestamp(14))"))
{
fprintf(stderr, "\n create table failed");
fprintf(stderr, "\n %s", mysql_error(mysql));
exit(0);
}
-
+
/* Prepare a insert query with 3 parameters */
- strmov(query, "INSERT INTO test_table(col1,col2,col3) values(?,?,?)");
- if (!(stmt = mysql_simple_prepare(mysql,query)))
+ strmov(query, "INSERT INTO test_table(col1, col2, col3) values(?, ?, ?)");
+ if (!(stmt= mysql_simple_prepare(mysql, query)))
{
fprintf(stderr, "\n prepare, insert failed");
fprintf(stderr, "\n %s", mysql_error(mysql));
@@ -4858,7 +4710,7 @@ static void test_manual_sample()
fprintf(stdout, "\n prepare, insert successful");
/* Get the parameter count from the statement */
- param_count= mysql_param_count(stmt);
+ param_count= mysql_stmt_param_count(stmt);
fprintf(stdout, "\n total parameters in insert: %d", param_count);
if (param_count != 3) /* validate parameter count */
@@ -4869,28 +4721,29 @@ static void test_manual_sample()
/* Bind the data for the parameters */
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
/* INTEGER PART */
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&int_data;
- bind[0].is_null= 0;
- bind[0].length= 0;
+ bind[0].buffer= (void *)&int_data;
/* STRING PART */
bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
- bind[1].buffer= (char *)str_data;
+ bind[1].buffer= (void *)str_data;
bind[1].buffer_length= sizeof(str_data);
- bind[1].is_null= 0;
- bind[1].length= 0;
-
+
/* SMALLINT PART */
bind[2].buffer_type= MYSQL_TYPE_SHORT;
- bind[2].buffer= (char *)&small_data;
+ bind[2].buffer= (void *)&small_data;
bind[2].is_null= &is_null;
- bind[2].length= 0;
is_null= 0;
/* Bind the buffers */
- if (mysql_bind_param(stmt, bind))
+ if (mysql_stmt_bind_param(stmt, bind))
{
fprintf(stderr, "\n param bind failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
@@ -4899,20 +4752,20 @@ static void test_manual_sample()
/* Specify the data */
int_data= 10; /* integer */
- strmov(str_data,"MySQL"); /* string */
-
+ strmov(str_data, "MySQL"); /* string */
+
/* INSERT SMALLINT data as NULL */
is_null= 1;
/* Execute the insert statement - 1*/
- if (mysql_execute(stmt))
+ if (mysql_stmt_execute(stmt))
{
fprintf(stderr, "\n execute 1 failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}
-
- /* Get the total rows affected */
+
+ /* Get the total rows affected */
affected_rows= mysql_stmt_affected_rows(stmt);
fprintf(stdout, "\n total affected rows: %lld", affected_rows);
@@ -4923,20 +4776,20 @@ static void test_manual_sample()
}
/* Re-execute the insert, by changing the values */
- int_data= 1000;
- strmov(str_data,"The most popular open source database");
+ int_data= 1000;
+ strmov(str_data, "The most popular open source database");
small_data= 1000; /* smallint */
is_null= 0; /* reset */
/* Execute the insert statement - 2*/
- if (mysql_execute(stmt))
+ if (mysql_stmt_execute(stmt))
{
fprintf(stderr, "\n execute 2 failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}
-
- /* Get the total rows affected */
+
+ /* Get the total rows affected */
affected_rows= mysql_stmt_affected_rows(stmt);
fprintf(stdout, "\n total affected rows: %lld", affected_rows);
@@ -4956,7 +4809,7 @@ static void test_manual_sample()
assert(2 == my_stmt_result("SELECT * FROM test_table"));
/* DROP THE TABLE */
- if (mysql_query(mysql,"DROP TABLE test_table"))
+ if (mysql_query(mysql, "DROP TABLE test_table"))
{
fprintf(stderr, "\n drop table failed");
fprintf(stderr, "\n %s", mysql_error(mysql));
@@ -4966,9 +4819,8 @@ static void test_manual_sample()
}
-/********************************************************
-* to test alter table scenario in the middle of prepare *
-*********************************************************/
+/* Test alter table scenario in the middle of prepare */
+
static void test_prepare_alter()
{
MYSQL_STMT *stmt;
@@ -4979,39 +4831,44 @@ static void test_prepare_alter()
myheader("test_prepare_alter");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_alter");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_alter");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_prep_alter(id int, name char(20))");
+ rc= mysql_query(mysql, "CREATE TABLE test_prep_alter(id int, name char(20))");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_prep_alter values(10,'venu'),(20,'mysql')");
+ rc= mysql_query(mysql, "INSERT INTO test_prep_alter values(10, 'venu'), (20, 'mysql')");
myquery(rc);
- stmt = mysql_simple_prepare(mysql, "INSERT INTO test_prep_alter VALUES(?,'monty')");
+ stmt= mysql_simple_prepare(mysql, "INSERT INTO test_prep_alter VALUES(?, 'monty')");
check_stmt(stmt);
- verify_param_count(stmt,1);
+ verify_param_count(stmt, 1);
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
is_null= 0;
bind[0].buffer_type= MYSQL_TYPE_SHORT;
- bind[0].buffer= (char *)&id;
- bind[0].buffer_length= 0;
- bind[0].length= 0;
+ bind[0].buffer= (void *)&id;
bind[0].is_null= &is_null;
- rc = mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
-
- id = 30; length= 0;
- rc = mysql_execute(stmt);
+
+ id= 30;
+ length= 0;
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
if (thread_query((char *)"ALTER TABLE test_prep_alter change id id_new varchar(20)"))
exit(0);
- is_null=1;
- rc = mysql_execute(stmt);
+ is_null= 1;
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(4 == my_stmt_result("SELECT * FROM test_prep_alter"));
@@ -5019,9 +4876,8 @@ static void test_prepare_alter()
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test the support of multi-statement executions *
-*********************************************************/
+
+/* Test the support of multi-statement executions */
static void test_multi_statements()
{
@@ -5029,11 +4885,11 @@ static void test_multi_statements()
MYSQL_RES *result;
int rc;
- const char *query="\
+ const char *query= "\
DROP TABLE IF EXISTS test_multi_tab;\
-CREATE TABLE test_multi_tab(id int,name char(20));\
-INSERT INTO test_multi_tab(id) VALUES(10),(20);\
-INSERT INTO test_multi_tab VALUES(20,'insert;comma');\
+CREATE TABLE test_multi_tab(id int, name char(20));\
+INSERT INTO test_multi_tab(id) VALUES(10), (20);\
+INSERT INTO test_multi_tab VALUES(20, 'insert;comma');\
SELECT * FROM test_multi_tab;\
UPDATE test_multi_tab SET name='new;name' WHERE id=20;\
DELETE FROM test_multi_tab WHERE name='new;name';\
@@ -5052,64 +4908,64 @@ DROP TABLE IF EXISTS test_multi_tab";
First test that we get an error for multi statements
(Becasue default connection is not opened with CLIENT_MULTI_STATEMENTS)
*/
- rc = mysql_query(mysql, query); /* syntax error */
+ rc= mysql_query(mysql, query); /* syntax error */
myquery_r(rc);
assert(-1 == mysql_next_result(mysql));
assert(0 == mysql_more_results(mysql));
- if (!(mysql_local = mysql_init(NULL)))
- {
- fprintf(stdout,"\n mysql_init() failed");
+ if (!(mysql_local= mysql_init(NULL)))
+ {
+ fprintf(stdout, "\n mysql_init() failed");
exit(1);
}
/* Create connection that supprot multi statements */
- if (!(mysql_real_connect(mysql_local,opt_host,opt_user,
- opt_password, current_db, opt_port,
- opt_unix_socket, CLIENT_MULTI_STATEMENTS)))
+ if (!(mysql_real_connect(mysql_local, opt_host, opt_user,
+ opt_password, current_db, opt_port,
+ opt_unix_socket, CLIENT_MULTI_STATEMENTS)))
{
- fprintf(stdout,"\n connection failed(%s)", mysql_error(mysql_local));
+ fprintf(stdout, "\n connection failed(%s)", mysql_error(mysql_local));
exit(1);
}
- rc = mysql_query(mysql_local, query);
+ rc= mysql_query(mysql_local, query);
myquery(rc);
- for (count=0 ; count < array_elements(rows) ; count++)
+ for (count= 0 ; count < array_elements(rows) ; count++)
{
- fprintf(stdout,"\n Query %d: ", count);
+ fprintf(stdout, "\n Query %d: ", count);
if ((result= mysql_store_result(mysql_local)))
{
my_process_result_set(result);
mysql_free_result(result);
}
else
- fprintf(stdout,"OK, %lld row(s) affected, %d warning(s)\n",
- mysql_affected_rows(mysql_local),
- mysql_warning_count(mysql_local));
+ fprintf(stdout, "OK, %lld row(s) affected, %d warning(s)\n",
+ mysql_affected_rows(mysql_local),
+ mysql_warning_count(mysql_local));
exp_value= (uint) mysql_affected_rows(mysql_local);
if (rows[count] != exp_value)
{
fprintf(stdout, "row %d had affected rows: %d, should be %d\n",
- count, exp_value, rows[count]);
+ count, exp_value, rows[count]);
exit(1);
}
if (count != array_elements(rows) -1)
{
if (!(rc= mysql_more_results(mysql_local)))
{
- fprintf(stdout,
- "mysql_more_result returned wrong value: %d for row %d\n",
- rc, count);
- exit(1);
+ fprintf(stdout,
+ "mysql_more_result returned wrong value: %d for row %d\n",
+ rc, count);
+ exit(1);
}
if ((rc= mysql_next_result(mysql_local)))
{
- exp_value= mysql_errno(mysql_local);
+ exp_value= mysql_errno(mysql_local);
- exit(1);
+ exit(1);
}
}
else
@@ -5148,38 +5004,40 @@ DROP TABLE IF EXISTS test_multi_tab";
mysql_close(mysql_local);
}
-/********************************************************
-* Check that Prepared statement cannot contain several *
-* SQL statements *
-*********************************************************/
+
+/*
+ Check that Prepared statement cannot contain several
+ SQL statements
+*/
+
static void test_prepare_multi_statements()
{
MYSQL *mysql_local;
MYSQL_STMT *stmt;
myheader("test_prepare_multi_statements");
- if (!(mysql_local = mysql_init(NULL)))
- {
- fprintf(stdout,"\n mysql_init() failed");
+ if (!(mysql_local= mysql_init(NULL)))
+ {
+ fprintf(stdout, "\n mysql_init() failed");
exit(1);
}
- if (!(mysql_real_connect(mysql_local,opt_host,opt_user,
+ if (!(mysql_real_connect(mysql_local, opt_host, opt_user,
opt_password, current_db, opt_port,
opt_unix_socket, CLIENT_MULTI_STATEMENTS)))
{
- fprintf(stdout,"\n connection failed(%s)", mysql_error(mysql_local));
+ fprintf(stdout, "\n connection failed(%s)", mysql_error(mysql_local));
exit(1);
}
strmov(query, "select 1; select 'another value'");
- stmt = mysql_simple_prepare(mysql_local,query);
+ stmt= mysql_simple_prepare(mysql_local, query);
check_stmt_r(stmt);
mysql_close(mysql_local);
}
-/********************************************************
-* to test simple bind store result *
-*********************************************************/
+
+/* Test simple bind store result */
+
static void test_store_result()
{
MYSQL_STMT *stmt;
@@ -5187,129 +5045,122 @@ static void test_store_result()
long nData;
char szData[100];
MYSQL_BIND bind[2];
- ulong length, length1;
+ ulong length, length1;
my_bool is_null[2];
myheader("test_store_result");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_store_result");
- myquery(rc);
-
- rc = mysql_commit(mysql);
- myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_store_result(col1 int ,col2 varchar(50))");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_store_result(col1 int , col2 varchar(50))");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_store_result VALUES(10,'venu'),(20,'mysql')");
+ rc= mysql_query(mysql, "INSERT INTO test_store_result VALUES(10, 'venu'), (20, 'mysql')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_store_result(col2) VALUES('monty')");
+ rc= mysql_query(mysql, "INSERT INTO test_store_result(col2) VALUES('monty')");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* fetch */
- bind[0].buffer_type=FIELD_TYPE_LONG;
- bind[0].buffer= (char*) &nData; /* integer data */
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void *) &nData; /* integer data */
bind[0].length= &length;
bind[0].is_null= &is_null[0];
- length= 0;
- bind[1].buffer_type=FIELD_TYPE_STRING;
- bind[1].buffer=szData; /* string data */
- bind[1].buffer_length=sizeof(szData);
+ length= 0;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= szData; /* string data */
+ bind[1].buffer_length= sizeof(szData);
bind[1].length= &length1;
bind[1].is_null= &is_null[1];
length1= 0;
- stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_store_result");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_store_result");
check_stmt(stmt);
- rc = mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 1: %ld,%s(%lu)", nData, szData, length1);
+ fprintf(stdout, "\n row 1: %ld, %s(%lu)", nData, szData, length1);
assert(nData == 10);
- assert(strcmp(szData,"venu")==0);
+ assert(strcmp(szData, "venu") == 0);
assert(length1 == 4);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 2: %ld,%s(%lu)",nData, szData, length1);
+ fprintf(stdout, "\n row 2: %ld, %s(%lu)", nData, szData, length1);
assert(nData == 20);
- assert(strcmp(szData,"mysql")==0);
+ assert(strcmp(szData, "mysql") == 0);
assert(length1 == 5);
- length=99;
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
-
+ length= 99;
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
if (is_null[0])
- fprintf(stdout,"\n row 3: NULL,%s(%lu)", szData, length1);
+ fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1);
assert(is_null[0]);
- assert(strcmp(szData,"monty")==0);
+ assert(strcmp(szData, "monty") == 0);
assert(length1 == 5);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
-
- rc = mysql_execute(stmt);
+
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 1: %ld,%s(%lu)",nData, szData, length1);
+ fprintf(stdout, "\n row 1: %ld, %s(%lu)", nData, szData, length1);
assert(nData == 10);
- assert(strcmp(szData,"venu")==0);
+ assert(strcmp(szData, "venu") == 0);
assert(length1 == 4);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 2: %ld,%s(%lu)",nData, szData, length1);
+ fprintf(stdout, "\n row 2: %ld, %s(%lu)", nData, szData, length1);
assert(nData == 20);
- assert(strcmp(szData,"mysql")==0);
+ assert(strcmp(szData, "mysql") == 0);
assert(length1 == 5);
- length=99;
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
-
+ length= 99;
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
if (is_null[0])
- fprintf(stdout,"\n row 3: NULL,%s(%lu)", szData, length1);
+ fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1);
assert(is_null[0]);
- assert(strcmp(szData,"monty")==0);
+ assert(strcmp(szData, "monty") == 0);
assert(length1 == 5);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test simple bind store result *
-*********************************************************/
+/* Test simple bind store result */
+
static void test_store_result1()
{
MYSQL_STMT *stmt;
@@ -5317,50 +5168,44 @@ static void test_store_result1()
myheader("test_store_result1");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_store_result");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_store_result(col1 int ,col2 varchar(50))");
+ rc= mysql_query(mysql, "CREATE TABLE test_store_result(col1 int , col2 varchar(50))");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_store_result VALUES(10, 'venu'), (20, 'mysql')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_store_result VALUES(10,'venu'),(20,'mysql')");
+ rc= mysql_query(mysql, "INSERT INTO test_store_result(col2) VALUES('monty')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_store_result(col2) VALUES('monty')");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_store_result");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_store_result");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
- rc = 0;
- while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
rc++;
fprintf(stdout, "\n total rows: %d", rc);
assert(rc == 3);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
- rc = 0;
- while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
rc++;
fprintf(stdout, "\n total rows: %d", rc);
assert(rc == 3);
@@ -5369,9 +5214,8 @@ static void test_store_result1()
}
-/********************************************************
-* to test simple bind store result *
-*********************************************************/
+/* Another test for bind and store result */
+
static void test_store_result2()
{
MYSQL_STMT *stmt;
@@ -5382,85 +5226,83 @@ static void test_store_result2()
myheader("test_store_result2");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_store_result");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_store_result(col1 int , col2 varchar(50))");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_store_result(col1 int ,col2 varchar(50))");
+ rc= mysql_query(mysql, "INSERT INTO test_store_result VALUES(10, 'venu'), (20, 'mysql')");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_store_result(col2) VALUES('monty')");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_store_result VALUES(10,'venu'),(20,'mysql')");
- myquery(rc);
-
- rc = mysql_query(mysql,"INSERT INTO test_store_result(col2) VALUES('monty')");
+ rc= mysql_commit(mysql);
myquery(rc);
- rc = mysql_commit(mysql);
- myquery(rc);
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
- bind[0].buffer_type=FIELD_TYPE_LONG;
- bind[0].buffer= (char *) &nData; /* integer data */
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void *) &nData; /* integer data */
bind[0].length= &length;
bind[0].is_null= 0;
strmov((char *)query , "SELECT col1 FROM test_store_result where col1= ?");
- stmt = mysql_simple_prepare(mysql, query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
-
- nData = 10; length= 0;
- rc = mysql_execute(stmt);
+
+ nData= 10; length= 0;
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- nData = 0;
- rc = mysql_stmt_store_result(stmt);
+ nData= 0;
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 1: %d",nData);
+ fprintf(stdout, "\n row 1: %d", nData);
assert(nData == 10);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
- nData = 20;
- rc = mysql_execute(stmt);
+ nData= 20;
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- nData = 0;
- rc = mysql_stmt_store_result(stmt);
+ nData= 0;
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 1: %d",nData);
+ fprintf(stdout, "\n row 1: %d", nData);
assert(nData == 20);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test simple subselect prepare *
-*********************************************************/
+/* Test simple subselect prepare */
+
static void test_subselect()
{
-#if TO_BE_FIXED_IN_SERVER
MYSQL_STMT *stmt;
int rc, id;
@@ -5468,56 +5310,56 @@ static void test_subselect()
myheader("test_subselect");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_sub1");
- myquery(rc);
-
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_sub2");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sub1");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sub2");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_sub1(id int)");
+ rc= mysql_query(mysql, "CREATE TABLE test_sub1(id int)");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_sub2(id int, id1 int)");
+ rc= mysql_query(mysql, "CREATE TABLE test_sub2(id int, id1 int)");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_sub1 values(2)");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_sub1 values(2)");
+ rc= mysql_query(mysql, "INSERT INTO test_sub2 VALUES(1, 7), (2, 7)");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_sub2 VALUES(1,7),(2,7)");
- myquery(rc);
-
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
/* fetch */
- bind[0].buffer_type= FIELD_TYPE_LONG;
- bind[0].buffer= (char *) &id;
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void *) &id;
bind[0].length= 0;
bind[0].is_null= 0;
- stmt = mysql_simple_prepare(mysql, "INSERT INTO test_sub2(id) SELECT * FROM test_sub1 WHERE id=?", 100);
+ stmt= mysql_simple_prepare(mysql, "INSERT INTO test_sub2(id) SELECT * FROM test_sub1 WHERE id= ?");
check_stmt(stmt);
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- id = 2;
- rc = mysql_execute(stmt);
+ id= 2;
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_st_affected_rows(stmt, 1);
- id = 9;
- rc = mysql_execute(stmt);
+ id= 9;
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_st_affected_rows(stmt, 0);
@@ -5526,101 +5368,108 @@ static void test_subselect()
assert(3 == my_stmt_result("SELECT * FROM test_sub2"));
- strmov((char *)query , "SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=?)");
- assert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=8)"));
- assert(1 == my_stmt_result("SELECT ROW(1,7) IN (select id, id1 from test_sub2 WHERE id1=7)"));
+ strmov((char *)query , "SELECT ROW(1, 7) IN (select id, id1 from test_sub2 WHERE id1= ?)");
+ assert(1 == my_stmt_result("SELECT ROW(1, 7) IN (select id, id1 from test_sub2 WHERE id1= 8)"));
+ assert(1 == my_stmt_result("SELECT ROW(1, 7) IN (select id, id1 from test_sub2 WHERE id1= 7)"));
- stmt = mysql_simple_prepare(mysql, query, 150);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc = mysql_bind_param(stmt,bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_bind_result(stmt,bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- id = 7;
- rc = mysql_execute(stmt);
+ id= 7;
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 1: %d",id);
+ fprintf(stdout, "\n row 1: %d", id);
assert(id == 1);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
-
+
id= 8;
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n row 1: %d",id);
+ fprintf(stdout, "\n row 1: %d", id);
assert(id == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
-#endif
}
+
/*
Generalized conversion routine to handle DATE, TIME and DATETIME
conversion using MYSQL_TIME structure
*/
+
static void test_bind_date_conv(uint row_count)
-{
+{
MYSQL_STMT *stmt= 0;
uint rc, i, count= row_count;
- ulong length[4];
+ ulong length[4];
MYSQL_BIND bind[4];
- my_bool is_null[4]={0};
- MYSQL_TIME tm[4];
+ my_bool is_null[4]= {0};
+ MYSQL_TIME tm[4];
ulong second_part;
uint year, month, day, hour, minute, sec;
- stmt = mysql_simple_prepare(mysql,"INSERT INTO test_date VALUES(?,?,?,?)");
+ stmt= mysql_simple_prepare(mysql, "INSERT INTO test_date VALUES(?, ?, ?, ?)");
check_stmt(stmt);
- verify_param_count(stmt, 4);
+ verify_param_count(stmt, 4);
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_TIMESTAMP;
bind[1].buffer_type= MYSQL_TYPE_TIME;
bind[2].buffer_type= MYSQL_TYPE_DATETIME;
bind[3].buffer_type= MYSQL_TYPE_DATE;
-
- second_part= 0;
-
- year=2000;
- month=01;
- day=10;
-
- hour=11;
- minute=16;
- sec= 20;
for (i= 0; i < (int) array_elements(bind); i++)
- {
- bind[i].buffer= (char *) &tm[i];
+ {
+ bind[i].buffer= (void *) &tm[i];
bind[i].is_null= &is_null[i];
bind[i].length= &length[i];
bind[i].buffer_length= 30;
- length[i]=20;
- }
+ length[i]= 20;
+ }
+
+ second_part= 0;
+
+ year= 2000;
+ month= 01;
+ day= 10;
+
+ hour= 11;
+ minute= 16;
+ sec= 20;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
-
for (count= 0; count < row_count; count++)
- {
+ {
for (i= 0; i < (int) array_elements(bind); i++)
{
- tm[i].neg= 0;
+ tm[i].neg= 0;
tm[i].second_part= second_part+count;
if (bind[i].buffer_type != MYSQL_TYPE_TIME)
{
@@ -5637,51 +5486,51 @@ static void test_bind_date_conv(uint row_count)
tm[i].second= sec+count;
}
else
- tm[i].hour= tm[i].minute= tm[i].second = 0;
- }
- rc = mysql_execute(stmt);
- check_execute(stmt, rc);
+ tm[i].hour= tm[i].minute= tm[i].second= 0;
+ }
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
}
- rc = mysql_commit(mysql);
+ rc= mysql_commit(mysql);
myquery(rc);
mysql_stmt_close(stmt);
assert(row_count == my_stmt_result("SELECT * FROM test_date"));
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_date");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_date");
myquery(rc);
- rc = mysql_bind_result(stmt, bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
- for (count=0; count < row_count; count++)
+ for (count= 0; count < row_count; count++)
{
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
fprintf(stdout, "\n");
for (i= 0; i < array_elements(bind); i++)
- {
+ {
fprintf(stdout, "\n");
- fprintf(stdout," time[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu",
- i, tm[i].year, tm[i].month, tm[i].day,
+ fprintf(stdout, " time[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu",
+ i, tm[i].year, tm[i].month, tm[i].day,
tm[i].hour, tm[i].minute, tm[i].second,
- tm[i].second_part);
+ tm[i].second_part);
assert(tm[i].year == 0 || tm[i].year == year+count);
assert(tm[i].month == 0 || tm[i].month == month+count);
assert(tm[i].day == 0 || tm[i].day == day+count);
assert(tm[i].hour == 0 || tm[i].hour == hour+count);
- /*
+ /*
minute causes problems from date<->time, don't assert, instead
validate separatly in another routine
*/
@@ -5691,15 +5540,14 @@ static void test_bind_date_conv(uint row_count)
assert(tm[i].second_part == 0 || tm[i].second_part == second_part+count);
}
}
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/*
- Test DATE, TIME, DATETIME and TS with MYSQL_TIME conversion
-*/
+
+/* Test DATE, TIME, DATETIME and TS with MYSQL_TIME conversion */
static void test_date()
{
@@ -5707,25 +5555,21 @@ static void test_date()
myheader("test_date");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_date(c1 TIMESTAMP(14), \
- c2 TIME,\
- c3 DATETIME,\
- c4 DATE)");
- myquery(rc);
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 TIMESTAMP(14), \
+ c2 TIME, \
+ c3 DATETIME, \
+ c4 DATE)");
- rc = mysql_commit(mysql);
myquery(rc);
test_bind_date_conv(5);
}
-/*
- Test all time types to DATE and DATE to all types
-*/
+
+/* Test all time types to DATE and DATE to all types */
static void test_date_date()
{
@@ -5733,25 +5577,21 @@ static void test_date_date()
myheader("test_date_date");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_date(c1 DATE, \
- c2 DATE,\
- c3 DATE,\
- c4 DATE)");
- myquery(rc);
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 DATE, \
+ c2 DATE, \
+ c3 DATE, \
+ c4 DATE)");
- rc = mysql_commit(mysql);
myquery(rc);
test_bind_date_conv(3);
}
-/*
- Test all time types to TIME and TIME to all types
-*/
+
+/* Test all time types to TIME and TIME to all types */
static void test_date_time()
{
@@ -5759,25 +5599,21 @@ static void test_date_time()
myheader("test_date_time");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_date(c1 TIME, \
- c2 TIME,\
- c3 TIME,\
- c4 TIME)");
- myquery(rc);
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 TIME, \
+ c2 TIME, \
+ c3 TIME, \
+ c4 TIME)");
- rc = mysql_commit(mysql);
myquery(rc);
test_bind_date_conv(3);
}
-/*
- Test all time types to TIMESTAMP and TIMESTAMP to all types
-*/
+
+/* Test all time types to TIMESTAMP and TIMESTAMP to all types */
static void test_date_ts()
{
@@ -5785,129 +5621,123 @@ static void test_date_ts()
myheader("test_date_ts");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_date(c1 TIMESTAMP(10), \
- c2 TIMESTAMP(14),\
- c3 TIMESTAMP,\
- c4 TIMESTAMP(6))");
- myquery(rc);
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 TIMESTAMP(10), \
+ c2 TIMESTAMP(14), \
+ c3 TIMESTAMP, \
+ c4 TIMESTAMP(6))");
- rc = mysql_commit(mysql);
myquery(rc);
test_bind_date_conv(2);
}
-/*
- Test all time types to DATETIME and DATETIME to all types
-*/
+
+/* Test all time types to DATETIME and DATETIME to all types */
static void test_date_dt()
{
- int rc;
+ int rc;
myheader("test_date_dt");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_date");
- myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_date(c1 datetime, \
- c2 datetime,\
- c3 datetime,\
- c4 date)");
-
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 datetime, "
+ " c2 datetime, c3 datetime, c4 date)");
myquery(rc);
test_bind_date_conv(2);
}
-/*
- Misc tests to keep pure coverage happy
-*/
+
+/* Misc tests to keep pure coverage happy */
+
static void test_pure_coverage()
{
MYSQL_STMT *stmt;
MYSQL_BIND bind[1];
int rc;
ulong length;
-
+
myheader("test_pure_coverage");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_pure");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_pure");
myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_pure(c1 int, c2 varchar(20))");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_pure(c1 int, c2 varchar(20))");
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"insert into test_pure(c67788) values(10)");
+ stmt= mysql_simple_prepare(mysql, "insert into test_pure(c67788) values(10)");
check_stmt_r(stmt);
-
+
/* Query without params and result should allow to bind 0 arrays */
- stmt = mysql_simple_prepare(mysql,"insert into test_pure(c2) values(10)");
+ stmt= mysql_simple_prepare(mysql, "insert into test_pure(c2) values(10)");
check_stmt(stmt);
-
- rc = mysql_bind_param(stmt, (MYSQL_BIND*)0);
+
+ rc= mysql_stmt_bind_param(stmt, (MYSQL_BIND*)0);
check_execute(stmt, rc);
-
- rc = mysql_execute(stmt);
+
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_bind_result(stmt, (MYSQL_BIND*)0);
+ rc= mysql_stmt_bind_result(stmt, (MYSQL_BIND*)0);
check_execute(stmt, rc);
-
+
mysql_stmt_close(stmt);
- stmt = mysql_simple_prepare(mysql,"insert into test_pure(c2) values(?)");
+ stmt= mysql_simple_prepare(mysql, "insert into test_pure(c2) values(?)");
check_stmt(stmt);
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
bind[0].length= &length;
bind[0].is_null= 0;
bind[0].buffer_length= 0;
bind[0].buffer_type= MYSQL_TYPE_GEOMETRY;
- rc = mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute_r(stmt, rc); /* unsupported buffer type */
-
+
bind[0].buffer_type= MYSQL_TYPE_STRING;
- rc = mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
- check_execute(stmt, rc);
+ rc= mysql_stmt_store_result(stmt);
+ check_execute(stmt, rc);
mysql_stmt_close(stmt);
- stmt = mysql_simple_prepare(mysql,"select * from test_pure");
+ stmt= mysql_simple_prepare(mysql, "select * from test_pure");
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
bind[0].buffer_type= MYSQL_TYPE_GEOMETRY;
- rc = mysql_bind_result(stmt, bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute_r(stmt, rc); /* unsupported buffer type */
- rc = mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
-
- rc = mysql_stmt_store_result(stmt);
+
+ rc= mysql_stmt_store_result(stmt);
check_execute_r(stmt, rc); /* commands out of sync */
mysql_stmt_close(stmt);
- mysql_query(mysql,"DROP TABLE test_pure");
- mysql_commit(mysql);
+ mysql_query(mysql, "DROP TABLE test_pure");
}
-/*
- test for string buffer fetch
-*/
+
+/* Test for string buffer fetch */
static void test_buffers()
{
@@ -5917,132 +5747,132 @@ static void test_buffers()
ulong length;
my_bool is_null;
char buffer[20];
-
+
myheader("test_buffers");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_buffer");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_buffer");
myquery(rc);
-
- rc = mysql_query(mysql,"CREATE TABLE test_buffer(str varchar(20))");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_buffer(str varchar(20))");
myquery(rc);
- rc = mysql_query(mysql,"insert into test_buffer values('MySQL')\
- ,('Database'),('Open-Source'),('Popular')");
+ rc= mysql_query(mysql, "insert into test_buffer values('MySQL')\
+ , ('Database'), ('Open-Source'), ('Popular')");
myquery(rc);
-
- stmt = mysql_simple_prepare(mysql,"select str from test_buffer");
+
+ stmt= mysql_simple_prepare(mysql, "select str from test_buffer");
check_stmt(stmt);
-
- rc = mysql_execute(stmt);
+
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- bzero(buffer, 20); /* Avoid overruns in printf() */
+ bzero(buffer, 20); /* Avoid overruns in printf() */
bind[0].length= &length;
bind[0].is_null= &is_null;
bind[0].buffer_length= 1;
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *)buffer;
-
- rc = mysql_bind_result(stmt, bind);
+ bind[0].buffer= (void *)buffer;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
- buffer[1]='X';
- rc = mysql_fetch(stmt);
+ buffer[1]= 'X';
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
fprintf(stdout, "\n data: %s (%lu)", buffer, length);
assert(buffer[0] == 'M');
assert(buffer[1] == 'X');
assert(length == 5);
- bind[0].buffer_length=8;
- rc = mysql_bind_result(stmt, bind);/* re-bind */
+ bind[0].buffer_length= 8;
+ rc= mysql_stmt_bind_result(stmt, bind);/* re-bind */
check_execute(stmt, rc);
-
- rc = mysql_fetch(stmt);
+
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
fprintf(stdout, "\n data: %s (%lu)", buffer, length);
- assert(strncmp(buffer,"Database",8) == 0);
+ assert(strncmp(buffer, "Database", 8) == 0);
assert(length == 8);
-
- bind[0].buffer_length=12;
- rc = mysql_bind_result(stmt, bind);/* re-bind */
+
+ bind[0].buffer_length= 12;
+ rc= mysql_stmt_bind_result(stmt, bind);/* re-bind */
check_execute(stmt, rc);
-
- rc = mysql_fetch(stmt);
+
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
fprintf(stdout, "\n data: %s (%lu)", buffer, length);
- assert(strcmp(buffer,"Open-Source") == 0);
+ assert(strcmp(buffer, "Open-Source") == 0);
assert(length == 11);
-
- bind[0].buffer_length=6;
- rc = mysql_bind_result(stmt, bind);/* re-bind */
+
+ bind[0].buffer_length= 6;
+ rc= mysql_stmt_bind_result(stmt, bind);/* re-bind */
check_execute(stmt, rc);
-
- rc = mysql_fetch(stmt);
+
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
fprintf(stdout, "\n data: %s (%lu)", buffer, length);
- assert(strncmp(buffer,"Popula",6) == 0);
+ assert(strncmp(buffer, "Popula", 6) == 0);
assert(length == 7);
-
+
mysql_stmt_close(stmt);
}
-/*
- Test the direct query execution in the middle of open stmts
-*/
+
+/* Test the direct query execution in the middle of open stmts */
+
static void test_open_direct()
{
MYSQL_STMT *stmt;
MYSQL_RES *result;
int rc;
-
+
myheader("test_open_direct");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_open_direct");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_open_direct");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_open_direct(id int, name char(6))");
+ rc= mysql_query(mysql, "CREATE TABLE test_open_direct(id int, name char(6))");
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"INSERT INTO test_open_direct values(10,'mysql')");
+ stmt= mysql_simple_prepare(mysql, "INSERT INTO test_open_direct values(10, 'mysql')");
check_stmt(stmt);
- rc = mysql_query(mysql, "SELECT * FROM test_open_direct");
+ rc= mysql_query(mysql, "SELECT * FROM test_open_direct");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(0 == my_process_result_set(result));
mysql_free_result(result);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_st_affected_rows(stmt, 1);
-
- rc = mysql_query(mysql, "SELECT * FROM test_open_direct");
+
+ rc= mysql_query(mysql, "SELECT * FROM test_open_direct");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
mysql_free_result(result);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_st_affected_rows(stmt, 1);
-
- rc = mysql_query(mysql, "SELECT * FROM test_open_direct");
+
+ rc= mysql_query(mysql, "SELECT * FROM test_open_direct");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(2 == my_process_result_set(result));
@@ -6051,47 +5881,47 @@ static void test_open_direct()
mysql_stmt_close(stmt);
/* run a direct query in the middle of a fetch */
- stmt= mysql_simple_prepare(mysql,"SELECT * FROM test_open_direct");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_open_direct");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- rc = mysql_query(mysql,"INSERT INTO test_open_direct(id) VALUES(20)");
+ rc= mysql_query(mysql, "INSERT INTO test_open_direct(id) VALUES(20)");
myquery_r(rc);
- rc = mysql_stmt_close(stmt);
+ rc= mysql_stmt_close(stmt);
check_execute(stmt, rc);
- rc = mysql_query(mysql,"INSERT INTO test_open_direct(id) VALUES(20)");
+ rc= mysql_query(mysql, "INSERT INTO test_open_direct(id) VALUES(20)");
myquery(rc);
/* run a direct query with store result */
- stmt= mysql_simple_prepare(mysql,"SELECT * FROM test_open_direct");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_open_direct");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- rc = mysql_query(mysql,"drop table test_open_direct");
+ rc= mysql_query(mysql, "drop table test_open_direct");
myquery(rc);
- rc = mysql_stmt_close(stmt);
+ rc= mysql_stmt_close(stmt);
check_execute(stmt, rc);
}
-/*
- To test fetch without prior bound buffers
-*/
+
+/* Test fetch without prior bound buffers */
+
static void test_fetch_nobuffs()
{
MYSQL_STMT *stmt;
@@ -6101,38 +5931,38 @@ static void test_fetch_nobuffs()
myheader("test_fetch_nobuffs");
- stmt = mysql_simple_prepare(mysql,"SELECT DATABASE(), CURRENT_USER(), \
+ stmt= mysql_simple_prepare(mysql, "SELECT DATABASE(), CURRENT_USER(), \
CURRENT_DATE(), CURRENT_TIME()");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = 0;
- while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
rc++;
fprintf(stdout, "\n total rows : %d", rc);
assert(rc == 1);
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *)str[0];
+ bind[0].buffer= (void *)str[0];
bind[0].is_null= 0;
bind[0].length= 0;
bind[0].buffer_length= sizeof(str[0]);
bind[1]= bind[2]= bind[3]= bind[0];
- bind[1].buffer= (char *)str[1];
- bind[2].buffer= (char *)str[2];
- bind[3].buffer= (char *)str[3];
+ bind[1].buffer= (void *)str[1];
+ bind[2].buffer= (void *)str[2];
+ bind[3].buffer= (void *)str[3];
- rc = mysql_bind_result(stmt, bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = 0;
- while (mysql_fetch(stmt) != MYSQL_NO_DATA)
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
{
rc++;
fprintf(stdout, "\n CURRENT_DATABASE(): %s", str[0]);
@@ -6146,9 +5976,9 @@ static void test_fetch_nobuffs()
mysql_stmt_close(stmt);
}
-/*
- To test a misc bug
-*/
+
+/* Test a misc bug */
+
static void test_ushort_bug()
{
MYSQL_STMT *stmt;
@@ -6162,59 +5992,59 @@ static void test_ushort_bug()
myheader("test_ushort_bug");
- rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_ushort");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ushort");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_ushort(a smallint unsigned, \
+
+ rc= mysql_query(mysql, "CREATE TABLE test_ushort(a smallint unsigned, \
b smallint unsigned, \
c smallint unsigned, \
d smallint unsigned)");
myquery(rc);
-
- rc= mysql_query(mysql,"INSERT INTO test_ushort VALUES(35999, 35999, 35999, 200)");
+
+ rc= mysql_query(mysql, "INSERT INTO test_ushort VALUES(35999, 35999, 35999, 200)");
myquery(rc);
-
-
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_ushort");
+
+
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_ushort");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
bind[0].buffer_type= MYSQL_TYPE_SHORT;
- bind[0].buffer= (char *)&short_value;
+ bind[0].buffer= (void *)&short_value;
bind[0].is_null= 0;
bind[0].length= &s_length;
-
+
bind[1].buffer_type= MYSQL_TYPE_LONG;
- bind[1].buffer= (char *)&long_value;
+ bind[1].buffer= (void *)&long_value;
bind[1].is_null= 0;
bind[1].length= &l_length;
bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
- bind[2].buffer= (char *)&longlong_value;
+ bind[2].buffer= (void *)&longlong_value;
bind[2].is_null= 0;
bind[2].length= &ll_length;
-
+
bind[3].buffer_type= MYSQL_TYPE_TINY;
- bind[3].buffer= (char *)&tiny_value;
+ bind[3].buffer= (void *)&tiny_value;
bind[3].is_null= 0;
bind[3].length= &t_length;
-
- rc = mysql_bind_result(stmt, bind);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
-
- fprintf(stdout,"\n ushort : %d (%ld)", short_value, s_length);
- fprintf(stdout,"\n ulong : %ld (%ld)", long_value, l_length);
- fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length);
- fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length);
-
+
+ fprintf(stdout, "\n ushort : %d (%ld)", short_value, s_length);
+ fprintf(stdout, "\n ulong : %ld (%ld)", long_value, l_length);
+ fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
+
assert(short_value == 35999);
assert(s_length == 2);
-
+
assert(long_value == 35999);
assert(l_length == 4);
@@ -6223,16 +6053,16 @@ static void test_ushort_bug()
assert(tiny_value == 200);
assert(t_length == 1);
-
- rc = mysql_fetch(stmt);
+
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/*
- To test a misc smallint-signed conversion bug
-*/
+
+/* Test a misc smallint-signed conversion bug */
+
static void test_sshort_bug()
{
MYSQL_STMT *stmt;
@@ -6246,59 +6076,59 @@ static void test_sshort_bug()
myheader("test_sshort_bug");
- rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_sshort");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sshort");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_sshort(a smallint signed, \
+
+ rc= mysql_query(mysql, "CREATE TABLE test_sshort(a smallint signed, \
b smallint signed, \
c smallint unsigned, \
d smallint unsigned)");
myquery(rc);
-
- rc= mysql_query(mysql,"INSERT INTO test_sshort VALUES(-5999, -5999, 35999, 200)");
+
+ rc= mysql_query(mysql, "INSERT INTO test_sshort VALUES(-5999, -5999, 35999, 200)");
myquery(rc);
-
-
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_sshort");
+
+
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_sshort");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
bind[0].buffer_type= MYSQL_TYPE_SHORT;
- bind[0].buffer= (char *)&short_value;
+ bind[0].buffer= (void *)&short_value;
bind[0].is_null= 0;
bind[0].length= &s_length;
-
+
bind[1].buffer_type= MYSQL_TYPE_LONG;
- bind[1].buffer= (char *)&long_value;
+ bind[1].buffer= (void *)&long_value;
bind[1].is_null= 0;
bind[1].length= &l_length;
bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
- bind[2].buffer= (char *)&longlong_value;
+ bind[2].buffer= (void *)&longlong_value;
bind[2].is_null= 0;
bind[2].length= &ll_length;
-
+
bind[3].buffer_type= MYSQL_TYPE_TINY;
- bind[3].buffer= (char *)&tiny_value;
+ bind[3].buffer= (void *)&tiny_value;
bind[3].is_null= 0;
bind[3].length= &t_length;
-
- rc = mysql_bind_result(stmt, bind);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
-
- fprintf(stdout,"\n sshort : %d (%ld)", short_value, s_length);
- fprintf(stdout,"\n slong : %ld (%ld)", long_value, l_length);
- fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length);
- fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length);
-
+
+ fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length);
+ fprintf(stdout, "\n slong : %ld (%ld)", long_value, l_length);
+ fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
+
assert(short_value == -5999);
assert(s_length == 2);
-
+
assert(long_value == -5999);
assert(l_length == 4);
@@ -6307,16 +6137,16 @@ static void test_sshort_bug()
assert(tiny_value == 200);
assert(t_length == 1);
-
- rc = mysql_fetch(stmt);
+
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/*
- To test a misc tinyint-signed conversion bug
-*/
+
+/* Test a misc tinyint-signed conversion bug */
+
static void test_stiny_bug()
{
MYSQL_STMT *stmt;
@@ -6330,59 +6160,59 @@ static void test_stiny_bug()
myheader("test_stiny_bug");
- rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_stiny");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_stiny");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_stiny(a tinyint signed, \
+
+ rc= mysql_query(mysql, "CREATE TABLE test_stiny(a tinyint signed, \
b tinyint signed, \
c tinyint unsigned, \
d tinyint unsigned)");
myquery(rc);
-
- rc= mysql_query(mysql,"INSERT INTO test_stiny VALUES(-128, -127, 255, 0)");
+
+ rc= mysql_query(mysql, "INSERT INTO test_stiny VALUES(-128, -127, 255, 0)");
myquery(rc);
-
-
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_stiny");
+
+
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_stiny");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
bind[0].buffer_type= MYSQL_TYPE_SHORT;
- bind[0].buffer= (char *)&short_value;
+ bind[0].buffer= (void *)&short_value;
bind[0].is_null= 0;
bind[0].length= &s_length;
-
+
bind[1].buffer_type= MYSQL_TYPE_LONG;
- bind[1].buffer= (char *)&long_value;
+ bind[1].buffer= (void *)&long_value;
bind[1].is_null= 0;
bind[1].length= &l_length;
bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
- bind[2].buffer= (char *)&longlong_value;
+ bind[2].buffer= (void *)&longlong_value;
bind[2].is_null= 0;
bind[2].length= &ll_length;
-
+
bind[3].buffer_type= MYSQL_TYPE_TINY;
- bind[3].buffer= (char *)&tiny_value;
+ bind[3].buffer= (void *)&tiny_value;
bind[3].is_null= 0;
bind[3].length= &t_length;
-
- rc = mysql_bind_result(stmt, bind);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
-
- fprintf(stdout,"\n sshort : %d (%ld)", short_value, s_length);
- fprintf(stdout,"\n slong : %ld (%ld)", long_value, l_length);
- fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length);
- fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length);
-
+
+ fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length);
+ fprintf(stdout, "\n slong : %ld (%ld)", long_value, l_length);
+ fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
+
assert(short_value == -128);
assert(s_length == 2);
-
+
assert(long_value == -127);
assert(l_length == 4);
@@ -6391,16 +6221,16 @@ static void test_stiny_bug()
assert(tiny_value == 0);
assert(t_length == 1);
-
- rc = mysql_fetch(stmt);
+
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/********************************************************
-* to test misc field information, bug: #74 *
-*********************************************************/
+
+/* Test misc field information, bug: #74 */
+
static void test_field_misc()
{
MYSQL_STMT *stmt;
@@ -6412,47 +6242,47 @@ static void test_field_misc()
myheader("test_field_misc");
- rc = mysql_query(mysql,"SELECT @@autocommit");
+ rc= mysql_query(mysql, "SELECT @@autocommit");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(1 == my_process_result_set(result));
-
- verify_prepare_field(result,0,
- "@@autocommit","", /* field and its org name */
+
+ verify_prepare_field(result, 0,
+ "@@autocommit", "", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",1,0); /* db name, length(its bool flag)*/
+ "", 1, 0); /* db name, length(its bool flag)*/
mysql_free_result(result);
-
- stmt = mysql_simple_prepare(mysql,"SELECT @@autocommit");
+
+ stmt= mysql_simple_prepare(mysql, "SELECT @@autocommit");
check_stmt(stmt);
-
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
- result = mysql_get_metadata(stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ result= mysql_stmt_result_metadata(stmt);
mytest(result);
-
+
assert(1 == my_process_stmt_result(stmt));
-
- verify_prepare_field(result,0,
- "@@autocommit","", /* field and its org name */
+
+ verify_prepare_field(result, 0,
+ "@@autocommit", "", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",1,0); /* db name, length(its bool flag)*/
+ "", 1, 0); /* db name, length(its bool flag)*/
mysql_free_result(result);
mysql_stmt_close(stmt);
- stmt = mysql_simple_prepare(mysql, "SELECT @@table_type");
+ stmt= mysql_simple_prepare(mysql, "SELECT @@table_type");
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= table_type;
@@ -6460,94 +6290,95 @@ static void test_field_misc()
bind[0].is_null= 0;
bind[0].buffer_length= NAME_LEN;
- rc = mysql_bind_result(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
- fprintf(stdout,"\n default table type: %s(%ld)", table_type, type_length);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ fprintf(stdout, "\n default table type: %s(%ld)", table_type, type_length);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
- stmt = mysql_simple_prepare(mysql, "SELECT @@table_type");
+ stmt= mysql_simple_prepare(mysql, "SELECT @@table_type");
check_stmt(stmt);
- result = mysql_get_metadata(stmt);
+ result= mysql_stmt_result_metadata(stmt);
mytest(result);
+ assert(mysql_stmt_field_count(stmt) == mysql_num_fields(result));
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
-
- verify_prepare_field(result,0,
- "@@table_type","", /* field and its org name */
+
+ verify_prepare_field(result, 0,
+ "@@table_type", "", /* field and its org name */
MYSQL_TYPE_STRING, /* field type */
"", "", /* table and its org name */
- "",type_length*3,0); /* db name, length */
+ "", type_length*3, 0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
- stmt = mysql_simple_prepare(mysql, "SELECT @@max_error_count");
+ stmt= mysql_simple_prepare(mysql, "SELECT @@max_error_count");
check_stmt(stmt);
- result = mysql_get_metadata(stmt);
+ result= mysql_stmt_result_metadata(stmt);
mytest(result);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
-
- verify_prepare_field(result,0,
- "@@max_error_count","", /* field and its org name */
+
+ verify_prepare_field(result, 0,
+ "@@max_error_count", "", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",10,0); /* db name, length */
+ "", 10, 0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
-
- stmt = mysql_simple_prepare(mysql, "SELECT @@max_allowed_packet");
+
+ stmt= mysql_simple_prepare(mysql, "SELECT @@max_allowed_packet");
check_stmt(stmt);
- result = mysql_get_metadata(stmt);
+ result= mysql_stmt_result_metadata(stmt);
mytest(result);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
-
- verify_prepare_field(result,0,
- "@@max_allowed_packet","", /* field and its org name */
+
+ verify_prepare_field(result, 0,
+ "@@max_allowed_packet", "", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",10,0); /* db name, length */
+ "", 10, 0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
-
- stmt = mysql_simple_prepare(mysql, "SELECT @@sql_warnings");
+
+ stmt= mysql_simple_prepare(mysql, "SELECT @@sql_warnings");
check_stmt(stmt);
-
- result = mysql_get_metadata(stmt);
+
+ result= mysql_stmt_result_metadata(stmt);
mytest(result);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
-
- verify_prepare_field(result,0,
- "@@sql_warnings","", /* field and its org name */
+
+ verify_prepare_field(result, 0,
+ "@@sql_warnings", "", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",1,0); /* db name, length */
+ "", 1, 0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -6555,9 +6386,10 @@ static void test_field_misc()
/*
- To test SET OPTION feature with prepare stmts
+ Test SET OPTION feature with prepare stmts
bug #85 (reported by mark@mysql.com)
*/
+
static void test_set_option()
{
MYSQL_STMT *stmt;
@@ -6569,60 +6401,62 @@ static void test_set_option()
mysql_autocommit(mysql, TRUE);
/* LIMIT the rows count to 2 */
- rc= mysql_query(mysql,"SET OPTION SQL_SELECT_LIMIT=2");
+ rc= mysql_query(mysql, "SET OPTION SQL_SELECT_LIMIT= 2");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_limit");
myquery(rc);
- rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_limit");
+ rc= mysql_query(mysql, "CREATE TABLE test_limit(a tinyint)");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_limit(a tinyint)");
+
+ rc= mysql_query(mysql, "INSERT INTO test_limit VALUES(10), (20), (30), (40)");
myquery(rc);
-
- rc= mysql_query(mysql,"INSERT INTO test_limit VALUES(10),(20),(30),(40)");
- myquery(rc);
-
- fprintf(stdout,"\n with SQL_SELECT_LIMIT=2 (direct)");
- rc = mysql_query(mysql,"SELECT * FROM test_limit");
+
+ fprintf(stdout, "\n with SQL_SELECT_LIMIT= 2 (direct)");
+ rc= mysql_query(mysql, "SELECT * FROM test_limit");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(2 == my_process_result_set(result));
mysql_free_result(result);
-
- fprintf(stdout,"\n with SQL_SELECT_LIMIT=2 (prepare)");
- stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_limit");
+
+ fprintf(stdout, "\n with SQL_SELECT_LIMIT=2 (prepare)");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_limit");
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
assert(2 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt);
- /* RESET the LIMIT the rows count to 0 */
- fprintf(stdout,"\n with SQL_SELECT_LIMIT=DEFAULT (prepare)");
- rc= mysql_query(mysql,"SET OPTION SQL_SELECT_LIMIT=DEFAULT");
+ /* RESET the LIMIT the rows count to 0 */
+ fprintf(stdout, "\n with SQL_SELECT_LIMIT=DEFAULT (prepare)");
+ rc= mysql_query(mysql, "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
myquery(rc);
-
- stmt = mysql_simple_prepare(mysql, "SELECT * FROM test_limit");
+
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_limit");
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
assert(4 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt);
}
+
/*
- To test a misc GRANT option
+ Test a misc GRANT option
bug #89 (reported by mark@mysql.com)
*/
+
static void test_prepare_grant()
{
int rc;
@@ -6631,80 +6465,80 @@ static void test_prepare_grant()
mysql_autocommit(mysql, TRUE);
- rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_grant");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_grant");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_grant(a tinyint primary key auto_increment)");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_grant(a tinyint primary key auto_increment)");
myquery(rc);
- strxmov(query,"GRANT INSERT,UPDATE,SELECT ON ", current_db,
+ strxmov(query, "GRANT INSERT, UPDATE, SELECT ON ", current_db,
".test_grant TO 'test_grant'@",
opt_host ? opt_host : "'localhost'", NullS);
- if (mysql_query(mysql,query))
+ if (mysql_query(mysql, query))
{
myerror("GRANT failed");
-
- /*
+
+ /*
If server started with --skip-grant-tables, skip this test, else
exit to indicate an error
- ER_UNKNOWN_COM_ERROR = 1047
- */
- if (mysql_errno(mysql) != 1047)
- exit(0);
+ ER_UNKNOWN_COM_ERROR= 1047
+ */
+ if (mysql_errno(mysql) != 1047)
+ exit(0);
}
else
{
MYSQL *org_mysql= mysql, *lmysql;
MYSQL_STMT *stmt;
-
+
fprintf(stdout, "\n Establishing a test connection ...");
- if (!(lmysql = mysql_init(NULL)))
- {
+ if (!(lmysql= mysql_init(NULL)))
+ {
myerror("mysql_init() failed");
exit(0);
}
- if (!(mysql_real_connect(lmysql,opt_host,"test_grant",
- "", current_db, opt_port,
- opt_unix_socket, 0)))
+ if (!(mysql_real_connect(lmysql, opt_host, "test_grant",
+ "", current_db, opt_port,
+ opt_unix_socket, 0)))
{
- myerror("connection failed");
+ myerror("connection failed");
mysql_close(lmysql);
exit(0);
- }
- fprintf(stdout," OK");
+ }
+ fprintf(stdout, " OK");
mysql= lmysql;
- rc = mysql_query(mysql,"INSERT INTO test_grant VALUES(NULL)");
+ rc= mysql_query(mysql, "INSERT INTO test_grant VALUES(NULL)");
myquery(rc);
- rc = mysql_query(mysql,"INSERT INTO test_grant(a) VALUES(NULL)");
+ rc= mysql_query(mysql, "INSERT INTO test_grant(a) VALUES(NULL)");
myquery(rc);
-
- execute_prepare_query("INSERT INTO test_grant(a) VALUES(NULL)",1);
- execute_prepare_query("INSERT INTO test_grant VALUES(NULL)",1);
- execute_prepare_query("UPDATE test_grant SET a=9 WHERE a=1",1);
+
+ execute_prepare_query("INSERT INTO test_grant(a) VALUES(NULL)", 1);
+ execute_prepare_query("INSERT INTO test_grant VALUES(NULL)", 1);
+ execute_prepare_query("UPDATE test_grant SET a=9 WHERE a=1", 1);
assert(4 == my_stmt_result("SELECT a FROM test_grant"));
/* Both DELETE expected to fail as user does not have DELETE privs */
- rc = mysql_query(mysql,"DELETE FROM test_grant");
+ rc= mysql_query(mysql, "DELETE FROM test_grant");
myquery_r(rc);
- stmt= mysql_simple_prepare(mysql,"DELETE FROM test_grant");
+ stmt= mysql_simple_prepare(mysql, "DELETE FROM test_grant");
check_stmt_r(stmt);
-
+
assert(4 == my_stmt_result("SELECT * FROM test_grant"));
-
- mysql_close(lmysql);
+
+ mysql_close(lmysql);
mysql= org_mysql;
- rc = mysql_query(mysql,"delete from mysql.user where User='test_grant'");
+ rc= mysql_query(mysql, "delete from mysql.user where User='test_grant'");
myquery(rc);
assert(1 == mysql_affected_rows(mysql));
- rc = mysql_query(mysql,"delete from mysql.tables_priv where User='test_grant'");
+ rc= mysql_query(mysql, "delete from mysql.tables_priv where User='test_grant'");
myquery(rc);
assert(1 == mysql_affected_rows(mysql));
@@ -6713,10 +6547,11 @@ static void test_prepare_grant()
/*
- To test a crash when invalid/corrupted .frm is used in the
+ Test a crash when invalid/corrupted .frm is used in the
SHOW TABLE STATUS
bug #93 (reported by serg@mysql.com).
*/
+
static void test_frm_bug()
{
MYSQL_STMT *stmt;
@@ -6732,74 +6567,74 @@ static void test_frm_bug()
mysql_autocommit(mysql, TRUE);
- rc= mysql_query(mysql,"drop table if exists test_frm_bug");
+ rc= mysql_query(mysql, "drop table if exists test_frm_bug");
myquery(rc);
- rc= mysql_query(mysql,"flush tables");
+ rc= mysql_query(mysql, "flush tables");
myquery(rc);
-
- stmt = mysql_simple_prepare(mysql, "show variables like 'datadir'");
+
+ stmt= mysql_simple_prepare(mysql, "show variables like 'datadir'");
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= data_dir;
bind[0].buffer_length= NAME_LEN;
bind[0].is_null= 0;
bind[0].length= 0;
- bind[1]=bind[0];
+ bind[1]= bind[0];
- rc = mysql_bind_result(stmt,bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout,"\n data directory: %s", data_dir);
+ fprintf(stdout, "\n data directory: %s", data_dir);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
- strxmov(test_frm,data_dir,"/",current_db,"/","test_frm_bug.frm",NullS);
+ strxmov(test_frm, data_dir, "/", current_db, "/", "test_frm_bug.frm", NullS);
- fprintf(stdout,"\n test_frm: %s", test_frm);
+ fprintf(stdout, "\n test_frm: %s", test_frm);
if (!(test_file= my_fopen(test_frm, (int) (O_RDWR | O_CREAT), MYF(MY_WME))))
{
- fprintf(stdout,"\n ERROR: my_fopen failed for '%s'", test_frm);
- fprintf(stdout,"\n test cancelled");
- return;
+ fprintf(stdout, "\n ERROR: my_fopen failed for '%s'", test_frm);
+ fprintf(stdout, "\n test cancelled");
+ return;
}
- fprintf(test_file,"this is a junk file for test");
+ fprintf(test_file, "this is a junk file for test");
- rc = mysql_query(mysql,"SHOW TABLE STATUS like 'test_frm_bug'");
+ rc= mysql_query(mysql, "SHOW TABLE STATUS like 'test_frm_bug'");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);/* It can't be NULL */
assert(1 == my_process_result_set(result));
- mysql_data_seek(result,0);
+ mysql_data_seek(result, 0);
row= mysql_fetch_row(result);
mytest(row);
- fprintf(stdout,"\n Comment: %s", row[16]);
- assert(row[16] != 0);
+ fprintf(stdout, "\n Comment: %s", row[17]);
+ assert(row[17] != 0);
mysql_free_result(result);
mysql_stmt_close(stmt);
- my_fclose(test_file,MYF(0));
- mysql_query(mysql,"drop table if exists test_frm_bug");
+ my_fclose(test_file, MYF(0));
+ mysql_query(mysql, "drop table if exists test_frm_bug");
}
-/*
- To test DECIMAL conversion
-*/
+
+/* Test DECIMAL conversion */
+
static void test_decimal_bug()
{
MYSQL_STMT *stmt;
@@ -6812,94 +6647,96 @@ static void test_decimal_bug()
mysql_autocommit(mysql, TRUE);
- rc= mysql_query(mysql,"drop table if exists test_decimal_bug");
+ rc= mysql_query(mysql, "drop table if exists test_decimal_bug");
myquery(rc);
-
- rc = mysql_query(mysql, "create table test_decimal_bug(c1 decimal(10,2))");
+
+ rc= mysql_query(mysql, "create table test_decimal_bug(c1 decimal(10, 2))");
myquery(rc);
-
- rc = mysql_query(mysql, "insert into test_decimal_bug value(8),(10.22),(5.61)");
+
+ rc= mysql_query(mysql, "insert into test_decimal_bug value(8), (10.22), (5.61)");
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"select c1 from test_decimal_bug where c1= ?");
+ stmt= mysql_simple_prepare(mysql, "select c1 from test_decimal_bug where c1= ?");
check_stmt(stmt);
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *)data;
+ bind[0].buffer= (void *)data;
bind[0].buffer_length= 25;
bind[0].is_null= &is_null;
- bind[0].length= 0;
- is_null= 0;
- rc = mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
+ is_null= 0;
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
strcpy(data, "8.0");
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- data[0]=0;
- rc = mysql_bind_result(stmt, bind);
- check_execute(stmt,rc);
+ data[0]= 0;
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
fprintf(stdout, "\n data: %s", data);
- assert(strcmp(data, "8.00")==0);
+ assert(strcmp(data, "8.00") == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
strcpy(data, "5.61");
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- data[0]=0;
- rc = mysql_bind_result(stmt, bind);
- check_execute(stmt,rc);
+ data[0]= 0;
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
fprintf(stdout, "\n data: %s", data);
- assert(strcmp(data, "5.61")==0);
+ assert(strcmp(data, "5.61") == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
is_null= 1;
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
strcpy(data, "10.22"); is_null= 0;
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- data[0]=0;
- rc = mysql_bind_result(stmt, bind);
- check_execute(stmt,rc);
+ data[0]= 0;
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
fprintf(stdout, "\n data: %s", data);
- assert(strcmp(data, "10.22")==0);
+ assert(strcmp(data, "10.22") == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/*
- To test EXPLAIN bug
- bug #115 (reported by mark@mysql.com & georg@php.net).
-*/
+/* Test EXPLAIN bug (#115, reported by mark@mysql.com & georg@php.net). */
static void test_explain_bug()
{
@@ -6909,94 +6746,94 @@ static void test_explain_bug()
myheader("test_explain_bug");
- mysql_autocommit(mysql,TRUE);
+ mysql_autocommit(mysql, TRUE);
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS test_explain");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_explain");
myquery(rc);
-
- rc = mysql_query(mysql, "CREATE TABLE test_explain(id int, name char(2))");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_explain(id int, name char(2))");
myquery(rc);
- stmt = mysql_simple_prepare(mysql, "explain test_explain");
+ stmt= mysql_simple_prepare(mysql, "explain test_explain");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- assert( 2 == my_process_stmt_result(stmt));
+ assert( 2 == my_process_stmt_result(stmt));
- result = mysql_get_metadata(stmt);
+ result= mysql_stmt_result_metadata(stmt);
mytest(result);
- fprintf(stdout, "\n total fields in the result: %d",
+ fprintf(stdout, "\n total fields in the result: %d",
mysql_num_fields(result));
assert(6 == mysql_num_fields(result));
- verify_prepare_field(result,0,"Field","",MYSQL_TYPE_VAR_STRING,
- "","","",NAME_LEN,0);
+ verify_prepare_field(result, 0, "Field", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", NAME_LEN, 0);
- verify_prepare_field(result,1,"Type","",MYSQL_TYPE_VAR_STRING,
- "","","",40,0);
+ verify_prepare_field(result, 1, "Type", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", 40, 0);
- verify_prepare_field(result,2,"Null","",MYSQL_TYPE_VAR_STRING,
- "","","",1,0);
+ verify_prepare_field(result, 2, "Null", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", 1, 0);
- verify_prepare_field(result,3,"Key","",MYSQL_TYPE_VAR_STRING,
- "","","",3,0);
+ verify_prepare_field(result, 3, "Key", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", 3, 0);
- verify_prepare_field(result,4,"Default","",MYSQL_TYPE_VAR_STRING,
- "","","",NAME_LEN,0);
+ verify_prepare_field(result, 4, "Default", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", NAME_LEN, 0);
- verify_prepare_field(result,5,"Extra","",MYSQL_TYPE_VAR_STRING,
- "","","",20,0);
+ verify_prepare_field(result, 5, "Extra", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", 20, 0);
mysql_free_result(result);
mysql_stmt_close(stmt);
-
- stmt = mysql_simple_prepare(mysql, "explain select id, name FROM test_explain");
+
+ stmt= mysql_simple_prepare(mysql, "explain select id, name FROM test_explain");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- assert( 1 == my_process_stmt_result(stmt));
+ assert( 1 == my_process_stmt_result(stmt));
- result = mysql_get_metadata(stmt);
+ result= mysql_stmt_result_metadata(stmt);
mytest(result);
- fprintf(stdout, "\n total fields in the result: %d",
+ fprintf(stdout, "\n total fields in the result: %d",
mysql_num_fields(result));
assert(10 == mysql_num_fields(result));
- verify_prepare_field(result,0,"id","",MYSQL_TYPE_LONGLONG,
- "","","",3,0);
+ verify_prepare_field(result, 0, "id", "", MYSQL_TYPE_LONGLONG,
+ "", "", "", 3, 0);
- verify_prepare_field(result,1,"select_type","",MYSQL_TYPE_VAR_STRING,
- "","","",19,0);
+ verify_prepare_field(result, 1, "select_type", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", 19, 0);
- verify_prepare_field(result,2,"table","",MYSQL_TYPE_VAR_STRING,
- "","","",NAME_LEN,0);
+ verify_prepare_field(result, 2, "table", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", NAME_LEN, 0);
- verify_prepare_field(result,3,"type","",MYSQL_TYPE_VAR_STRING,
- "","","",10,0);
+ verify_prepare_field(result, 3, "type", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", 10, 0);
- verify_prepare_field(result,4,"possible_keys","",MYSQL_TYPE_VAR_STRING,
- "","","",NAME_LEN*64,0);
+ verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", NAME_LEN*64, 0);
- verify_prepare_field(result,5,"key","",MYSQL_TYPE_VAR_STRING,
- "","","",NAME_LEN,0);
+ verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", NAME_LEN, 0);
- verify_prepare_field(result,6,"key_len","",MYSQL_TYPE_VAR_STRING,
- "","","",NAME_LEN*64,0);
+ verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_LONGLONG,
+ "", "", "", 3, 0);
- verify_prepare_field(result,7,"ref","",MYSQL_TYPE_VAR_STRING,
- "","","",NAME_LEN*16,0);
+ verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", NAME_LEN*16, 0);
- verify_prepare_field(result,8,"rows","",MYSQL_TYPE_LONGLONG,
- "","","",10,0);
+ verify_prepare_field(result, 8, "rows", "", MYSQL_TYPE_LONGLONG,
+ "", "", "", 10, 0);
- verify_prepare_field(result,9,"Extra","",MYSQL_TYPE_VAR_STRING,
- "","","",255,0);
+ verify_prepare_field(result, 9, "Extra", "", MYSQL_TYPE_VAR_STRING,
+ "", "", "", 255, 0);
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -7005,131 +6842,132 @@ static void test_explain_bug()
#ifdef NOT_YET_WORKING
/*
- To test math functions
- bug #148 (reported by salle@mysql.com).
+ Test math functions.
+ Bug #148 (reported by salle@mysql.com).
*/
#define myerrno(n) check_errcode(n)
static void check_errcode(const unsigned int err)
-{
+{
if (mysql->server_version)
- fprintf(stdout,"\n [MySQL-%s]",mysql->server_version);
+ fprintf(stdout, "\n [MySQL-%s]", mysql->server_version);
else
- fprintf(stdout,"\n [MySQL]");
- fprintf(stdout,"[%d] %s\n",mysql_errno(mysql),mysql_error(mysql));
+ fprintf(stdout, "\n [MySQL]");
+ fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql));
assert(mysql_errno(mysql) == err);
}
+
static void test_drop_temp()
{
int rc;
myheader("test_drop_temp");
- rc= mysql_query(mysql,"DROP DATABASE IF EXISTS test_drop_temp_db");
+ rc= mysql_query(mysql, "DROP DATABASE IF EXISTS test_drop_temp_db");
myquery(rc);
- rc= mysql_query(mysql,"CREATE DATABASE test_drop_temp_db");
+ rc= mysql_query(mysql, "CREATE DATABASE test_drop_temp_db");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_drop_temp_db.t1(c1 int, c2 char(1))");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_drop_temp_db.t1(c1 int, c2 char(1))");
myquery(rc);
- rc = mysql_query(mysql,"delete from mysql.db where Db='test_drop_temp_db'");
+ rc= mysql_query(mysql, "delete from mysql.db where Db='test_drop_temp_db'");
myquery(rc);
- rc = mysql_query(mysql,"delete from mysql.db where Db='test_drop_temp_db'");
+ rc= mysql_query(mysql, "delete from mysql.db where Db='test_drop_temp_db'");
myquery(rc);
- strxmov(query,"GRANT SELECT,USAGE,DROP ON test_drop_temp_db.* TO test_temp@",
+ strxmov(query, "GRANT SELECT, USAGE, DROP ON test_drop_temp_db.* TO test_temp@",
opt_host ? opt_host : "localhost", NullS);
- if (mysql_query(mysql,query))
+ if (mysql_query(mysql, query))
{
myerror("GRANT failed");
-
- /*
+
+ /*
If server started with --skip-grant-tables, skip this test, else
exit to indicate an error
- ER_UNKNOWN_COM_ERROR = 1047
- */
- if (mysql_errno(mysql) != 1047)
- exit(0);
+ ER_UNKNOWN_COM_ERROR= 1047
+ */
+ if (mysql_errno(mysql) != 1047)
+ exit(0);
}
else
{
MYSQL *org_mysql= mysql, *lmysql;
-
+
fprintf(stdout, "\n Establishing a test connection ...");
- if (!(lmysql = mysql_init(NULL)))
- {
+ if (!(lmysql= mysql_init(NULL)))
+ {
myerror("mysql_init() failed");
exit(0);
}
- rc = mysql_query(mysql,"flush privileges");
+ rc= mysql_query(mysql, "flush privileges");
myquery(rc);
- if (!(mysql_real_connect(lmysql,opt_host ? opt_host : "localhost","test_temp",
- "", "test_drop_temp_db", opt_port,
- opt_unix_socket, 0)))
+ if (!(mysql_real_connect(lmysql, opt_host ? opt_host : "localhost", "test_temp",
+ "", "test_drop_temp_db", opt_port,
+ opt_unix_socket, 0)))
{
mysql= lmysql;
- myerror("connection failed");
+ myerror("connection failed");
mysql_close(lmysql);
exit(0);
- }
- fprintf(stdout," OK");
+ }
+ fprintf(stdout, " OK");
mysql= lmysql;
- rc = mysql_query(mysql,"INSERT INTO t1 VALUES(10,'C')");
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES(10, 'C')");
myerrno((uint)1142);
- rc = mysql_query(mysql,"DROP TABLE t1");
+ rc= mysql_query(mysql, "DROP TABLE t1");
myerrno((uint)1142);
-
+
mysql= org_mysql;
- rc= mysql_query(mysql,"CREATE TEMPORARY TABLE test_drop_temp_db.t1(c1 int)");
+ rc= mysql_query(mysql, "CREATE TEMPORARY TABLE test_drop_temp_db.t1(c1 int)");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TEMPORARY TABLE test_drop_temp_db.t2 LIKE test_drop_temp_db.t1");
+
+ rc= mysql_query(mysql, "CREATE TEMPORARY TABLE test_drop_temp_db.t2 LIKE test_drop_temp_db.t1");
myquery(rc);
mysql= lmysql;
- rc = mysql_query(mysql,"DROP TABLE t1,t2");
+ rc= mysql_query(mysql, "DROP TABLE t1, t2");
myquery_r(rc);
- rc = mysql_query(mysql,"DROP TEMPORARY TABLE t1");
+ rc= mysql_query(mysql, "DROP TEMPORARY TABLE t1");
myquery_r(rc);
- rc = mysql_query(mysql,"DROP TEMPORARY TABLE t2");
+ rc= mysql_query(mysql, "DROP TEMPORARY TABLE t2");
myquery_r(rc);
-
- mysql_close(lmysql);
+
+ mysql_close(lmysql);
mysql= org_mysql;
- rc = mysql_query(mysql,"drop database test_drop_temp_db");
+ rc= mysql_query(mysql, "drop database test_drop_temp_db");
myquery(rc);
assert(1 == mysql_affected_rows(mysql));
- rc = mysql_query(mysql,"delete from mysql.user where User='test_temp'");
+ rc= mysql_query(mysql, "delete from mysql.user where User='test_temp'");
myquery(rc);
assert(1 == mysql_affected_rows(mysql));
- rc = mysql_query(mysql,"delete from mysql.tables_priv where User='test_temp'");
+ rc= mysql_query(mysql, "delete from mysql.tables_priv where User='test_temp'");
myquery(rc);
assert(1 == mysql_affected_rows(mysql));
}
}
#endif
-/*
- To test warnings for cuted rows
-*/
+
+/* Test warnings for cuted rows */
+
static void test_cuted_rows()
{
int rc, count;
@@ -7137,58 +6975,58 @@ static void test_cuted_rows()
myheader("test_cuted_rows");
- mysql_query(mysql, "DROP TABLE if exists t1");
+ mysql_query(mysql, "DROP TABLE if exists t1");
mysql_query(mysql, "DROP TABLE if exists t2");
- rc = mysql_query(mysql, "CREATE TABLE t1(c1 tinyint)");
+ rc= mysql_query(mysql, "CREATE TABLE t1(c1 tinyint)");
myquery(rc);
- rc = mysql_query(mysql, "CREATE TABLE t2(c1 int not null)");
+ rc= mysql_query(mysql, "CREATE TABLE t2(c1 int not null)");
myquery(rc);
- rc = mysql_query(mysql, "INSERT INTO t1 values(10),(NULL),(NULL)");
+ rc= mysql_query(mysql, "INSERT INTO t1 values(10), (NULL), (NULL)");
myquery(rc);
count= mysql_warning_count(mysql);
fprintf(stdout, "\n total warnings: %d", count);
assert(count == 0);
- rc = mysql_query(mysql, "INSERT INTO t2 SELECT * FROM t1");
+ rc= mysql_query(mysql, "INSERT INTO t2 SELECT * FROM t1");
myquery(rc);
count= mysql_warning_count(mysql);
fprintf(stdout, "\n total warnings: %d", count);
assert(count == 2);
- rc = mysql_query(mysql, "SHOW WARNINGS");
+ rc= mysql_query(mysql, "SHOW WARNINGS");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(2 == my_process_result_set(result));
mysql_free_result(result);
- rc = mysql_query(mysql, "INSERT INTO t1 VALUES('junk'),(876789)");
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES('junk'), (876789)");
myquery(rc);
count= mysql_warning_count(mysql);
fprintf(stdout, "\n total warnings: %d", count);
assert(count == 2);
- rc = mysql_query(mysql, "SHOW WARNINGS");
+ rc= mysql_query(mysql, "SHOW WARNINGS");
myquery(rc);
- result = mysql_store_result(mysql);
+ result= mysql_store_result(mysql);
mytest(result);
assert(2 == my_process_result_set(result));
mysql_free_result(result);
}
-/*
- To test update/binary logs
-*/
+
+/* Test update/binary logs */
+
static void test_logs()
{
MYSQL_STMT *stmt;
@@ -7201,138 +7039,140 @@ static void test_logs()
myheader("test_logs");
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS test_logs");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_logs");
myquery(rc);
- rc = mysql_query(mysql, "CREATE TABLE test_logs(id smallint, name varchar(20))");
+ rc= mysql_query(mysql, "CREATE TABLE test_logs(id smallint, name varchar(20))");
myquery(rc);
- length= (ulong)(strmov((char *)data,"INSERT INTO test_logs VALUES(?,?)") - data);
- stmt = mysql_prepare(mysql, data, length);
- check_stmt(stmt);
-
+ strmov((char *)data, "INSERT INTO test_logs VALUES(?, ?)");
+ stmt= mysql_simple_prepare(mysql, data);
+ check_stmt(stmt);
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
bind[0].buffer_type= MYSQL_TYPE_SHORT;
- bind[0].buffer= (char *)&id;
- bind[0].is_null= 0;
- bind[0].length= 0;
-
+ bind[0].buffer= (void *)&id;
+
bind[1].buffer_type= MYSQL_TYPE_STRING;
- bind[1].buffer= (char *)&data;
- bind[1].is_null= 0;
+ bind[1].buffer= (void *)&data;
bind[1].buffer_length= 255;
bind[1].length= &length;
id= 9876;
- length= (ulong)(strmov((char *)data,"MySQL - Open Source Database")- data);
+ length= (ulong)(strmov((char *)data, "MySQL - Open Source Database")- data);
- rc = mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
strmov((char *)data, "'");
length= 1;
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
+
strmov((char *)data, "\"");
length= 1;
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
+
length= (ulong)(strmov((char *)data, "my\'sql\'")-data);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
+
length= (ulong)(strmov((char *)data, "my\"sql\"")-data);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
mysql_stmt_close(stmt);
- length= (ulong)(strmov((char *)data,"INSERT INTO test_logs VALUES(20,'mysql')") - data);
- stmt = mysql_prepare(mysql, data, length);
- check_stmt(stmt);
+ strmov((char *)data, "INSERT INTO test_logs VALUES(20, 'mysql')");
+ stmt= mysql_simple_prepare(mysql, data);
+ check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
mysql_stmt_close(stmt);
- length= (ulong)(strmov((char *)data, "SELECT * FROM test_logs WHERE id=?") - data);
- stmt = mysql_prepare(mysql, data, length);
- check_stmt(stmt);
+ strmov((char *)data, "SELECT * FROM test_logs WHERE id=?");
+ stmt= mysql_simple_prepare(mysql, data);
+ check_stmt(stmt);
- rc = mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
bind[1].buffer_length= 255;
- rc = mysql_bind_result(stmt, bind);
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
fprintf(stdout, "\n id : %d", id);
fprintf(stdout, "\n name : %s(%ld)", data, length);
- assert(id == 9876);
+ assert(id == 9876);
assert(length == 19); /* Due to VARCHAR(20) */
- assert(strcmp(data,"MySQL - Open Source")==0);
+ assert(strcmp(data, "MySQL - Open Source") == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
-
+
fprintf(stdout, "\n name : %s(%ld)", data, length);
assert(length == 1);
- assert(strcmp(data,"'")==0);
+ assert(strcmp(data, "'") == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
-
+
fprintf(stdout, "\n name : %s(%ld)", data, length);
assert(length == 1);
- assert(strcmp(data,"\"")==0);
+ assert(strcmp(data, "\"") == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
-
+
fprintf(stdout, "\n name : %s(%ld)", data, length);
assert(length == 7);
- assert(strcmp(data,"my\'sql\'")==0);
+ assert(strcmp(data, "my\'sql\'") == 0);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
-
+
fprintf(stdout, "\n name : %s(%ld)", data, length);
assert(length == 7);
- /*assert(strcmp(data,"my\"sql\"")==0); */
+ /*assert(strcmp(data, "my\"sql\"") == 0); */
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
- rc = mysql_query(mysql,"DROP TABLE test_logs");
+ rc= mysql_query(mysql, "DROP TABLE test_logs");
myquery(rc);
}
-/*
- To test 'n' statements create and close
-*/
+
+/* Test 'n' statements create and close */
static void test_nstmts()
{
@@ -7340,69 +7180,71 @@ static void test_nstmts()
char query[255];
int rc;
static uint i, total_stmts= 2000;
- long length;
MYSQL_BIND bind[1];
myheader("test_nstmts");
- mysql_autocommit(mysql,TRUE);
+ mysql_autocommit(mysql, TRUE);
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS test_nstmts");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_nstmts");
myquery(rc);
-
- rc = mysql_query(mysql, "CREATE TABLE test_nstmts(id int)");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_nstmts(id int)");
myquery(rc);
- bind[0].buffer= (char *)&i;
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
+ bind[0].buffer= (void *)&i;
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].length= 0;
- bind[0].is_null= 0;
- bind[0].buffer_length= 0;
-
- for (i=0; i < total_stmts; i++)
+
+ for (i= 0; i < total_stmts; i++)
{
fprintf(stdout, "\r stmt: %d", i);
-
- length = (long)(strmov(query, "insert into test_nstmts values(?)")-query);
- stmt = mysql_prepare(mysql, query, length);
+
+ strmov(query, "insert into test_nstmts values(?)");
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc = mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
mysql_stmt_close(stmt);
}
- stmt = mysql_simple_prepare(mysql," select count(*) from test_nstmts");
+ stmt= mysql_simple_prepare(mysql, " select count(*) from test_nstmts");
check_stmt(stmt);
- rc = mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- i = 0;
- rc = mysql_bind_result(stmt, bind);
+ i= 0;
+ rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
fprintf(stdout, "\n total rows: %d", i);
assert( i == total_stmts);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
-
- rc = mysql_query(mysql,"DROP TABLE test_nstmts");
+
+ rc= mysql_query(mysql, "DROP TABLE test_nstmts");
myquery(rc);
}
-/*
- To test stmt seek() functions
-*/
+
+/* Test stmt seek() functions */
+
static void test_fetch_seek()
{
MYSQL_STMT *stmt;
@@ -7414,89 +7256,89 @@ static void test_fetch_seek()
myheader("test_fetch_seek");
- rc= mysql_query(mysql,"drop table if exists test_seek");
+ rc= mysql_query(mysql, "drop table if exists test_seek");
myquery(rc);
-
- rc = mysql_query(mysql, "create table test_seek(c1 int primary key auto_increment, c2 char(10), c3 timestamp(14))");
+
+ rc= mysql_query(mysql, "create table test_seek(c1 int primary key auto_increment, c2 char(10), c3 timestamp(14))");
myquery(rc);
-
- rc = mysql_query(mysql, "insert into test_seek(c2) values('venu'),('mysql'),('open'),('source')");
+
+ rc= mysql_query(mysql, "insert into test_seek(c2) values('venu'), ('mysql'), ('open'), ('source')");
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"select * from test_seek");
+ stmt= mysql_simple_prepare(mysql, "select * from test_seek");
check_stmt(stmt);
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&c1;
+ bind[0].buffer= (void *)&c1;
bind[0].buffer_length= 0;
bind[0].is_null= 0;
bind[0].length= 0;
bind[1].buffer_type= MYSQL_TYPE_STRING;
- bind[1].buffer= (char *)c2;
+ bind[1].buffer= (void *)c2;
bind[1].buffer_length= sizeof(c2);
bind[1].is_null= 0;
bind[1].length= 0;
bind[2]= bind[1];
- bind[2].buffer= (char *)c3;
+ bind[2].buffer= (void *)c3;
bind[2].buffer_length= sizeof(c3);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_bind_result(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_store_result(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout, "\n row 0: %ld,%s,%s", c1,c2,c3);
+ fprintf(stdout, "\n row 0: %ld, %s, %s", c1, c2, c3);
- row = mysql_stmt_row_tell(stmt);
+ row= mysql_stmt_row_tell(stmt);
- row = mysql_stmt_row_seek(stmt, row);
+ row= mysql_stmt_row_seek(stmt, row);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout, "\n row 2: %ld,%s,%s", c1,c2,c3);
+ fprintf(stdout, "\n row 2: %ld, %s, %s", c1, c2, c3);
- row = mysql_stmt_row_seek(stmt, row);
+ row= mysql_stmt_row_seek(stmt, row);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout, "\n row 2: %ld,%s,%s", c1,c2,c3);
+ fprintf(stdout, "\n row 2: %ld, %s, %s", c1, c2, c3);
mysql_stmt_data_seek(stmt, 0);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout, "\n row 0: %ld,%s,%s", c1,c2,c3);
+ fprintf(stdout, "\n row 0: %ld, %s, %s", c1, c2, c3);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
-/*
- To test mysql_fetch_column() with offset
-*/
+
+/* Test mysql_stmt_fetch_column() with offset */
+
static void test_fetch_offset()
{
MYSQL_STMT *stmt;
@@ -7509,76 +7351,77 @@ static void test_fetch_offset()
myheader("test_fetch_offset");
- rc= mysql_query(mysql,"drop table if exists test_column");
+ rc= mysql_query(mysql, "drop table if exists test_column");
myquery(rc);
-
- rc = mysql_query(mysql, "create table test_column(a char(10))");
+
+ rc= mysql_query(mysql, "create table test_column(a char(10))");
myquery(rc);
-
- rc = mysql_query(mysql, "insert into test_column values('abcdefghij'),(null)");
+
+ rc= mysql_query(mysql, "insert into test_column values('abcdefghij'), (null)");
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"select * from test_column");
+ stmt= mysql_simple_prepare(mysql, "select * from test_column");
check_stmt(stmt);
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *)data;
+ bind[0].buffer= (void *)data;
bind[0].buffer_length= 11;
bind[0].is_null= &is_null;
bind[0].length= &length;
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch_column(stmt,bind,0,0);
- check_execute_r(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
+ check_execute_r(stmt, rc);
- rc = mysql_bind_result(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_store_result(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
-
data[0]= '\0';
- rc = mysql_fetch_column(stmt,bind,0,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 1: %s (%ld)", data, length);
- assert(strncmp(data,"abcd",4) == 0 && length == 10);
-
- rc = mysql_fetch_column(stmt,bind,0,5);
- check_execute(stmt,rc);
+ assert(strncmp(data, "abcd", 4) == 0 && length == 10);
+
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 5);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 1: %s (%ld)", data, length);
- assert(strncmp(data,"fg",2) == 0 && length == 10);
+ assert(strncmp(data, "fg", 2) == 0 && length == 10);
- rc = mysql_fetch_column(stmt,bind,0,9);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 9);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 0: %s (%ld)", data, length);
- assert(strncmp(data,"j",1) == 0 && length == 10);
+ assert(strncmp(data, "j", 1) == 0 && length == 10);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
is_null= 0;
- rc = mysql_fetch_column(stmt,bind,0,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
+ check_execute(stmt, rc);
assert(is_null == 1);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
- rc = mysql_fetch_column(stmt,bind,1,0);
- check_execute_r(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
+ check_execute_r(stmt, rc);
mysql_stmt_close(stmt);
}
-/*
- To test mysql_fetch_column()
-*/
+
+
+/* Test mysql_stmt_fetch_column() */
+
static void test_fetch_column()
{
MYSQL_STMT *stmt;
@@ -7589,218 +7432,218 @@ static void test_fetch_column()
myheader("test_fetch_column");
- rc= mysql_query(mysql,"drop table if exists test_column");
+ rc= mysql_query(mysql, "drop table if exists test_column");
myquery(rc);
-
- rc = mysql_query(mysql, "create table test_column(c1 int primary key auto_increment, c2 char(10))");
+
+ rc= mysql_query(mysql, "create table test_column(c1 int primary key auto_increment, c2 char(10))");
myquery(rc);
-
- rc = mysql_query(mysql, "insert into test_column(c2) values('venu'),('mysql')");
+
+ rc= mysql_query(mysql, "insert into test_column(c2) values('venu'), ('mysql')");
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"select * from test_column order by c2 desc");
+ stmt= mysql_simple_prepare(mysql, "select * from test_column order by c2 desc");
check_stmt(stmt);
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&bc1;
+ bind[0].buffer= (void *)&bc1;
bind[0].buffer_length= 0;
bind[0].is_null= 0;
bind[0].length= &bl1;
bind[1].buffer_type= MYSQL_TYPE_STRING;
- bind[1].buffer= (char *)bc2;
+ bind[1].buffer= (void *)bc2;
bind[1].buffer_length= 7;
bind[1].is_null= 0;
bind[1].length= &bl2;
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_bind_result(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_store_result(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch_column(stmt,bind,1,0); /* No-op at this point */
- check_execute_r(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 1, 0); /* No-op at this point */
+ check_execute_r(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout, "\n row 0: %d,%s", bc1,bc2);
+ fprintf(stdout, "\n row 0: %d, %s", bc1, bc2);
c2[0]= '\0'; l2= 0;
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *)c2;
+ bind[0].buffer= (void *)c2;
bind[0].buffer_length= 7;
bind[0].is_null= 0;
bind[0].length= &l2;
- rc = mysql_fetch_column(stmt,bind,1,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
- assert(strncmp(c2,"venu",4)==0 && l2 == 4);
-
+ assert(strncmp(c2, "venu", 4) == 0 && l2 == 4);
+
c2[0]= '\0'; l2= 0;
- rc = mysql_fetch_column(stmt,bind,1,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
- assert(strcmp(c2,"venu")==0 && l2 == 4);
+ assert(strcmp(c2, "venu") == 0 && l2 == 4);
- c1= 0;
+ c1= 0;
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&c1;
+ bind[0].buffer= (void *)&c1;
bind[0].buffer_length= 0;
bind[0].is_null= 0;
bind[0].length= &l1;
- rc = mysql_fetch_column(stmt,bind,0,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 0: %d(%ld)", c1, l1);
assert(c1 == 1 && l1 == 4);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- fprintf(stdout, "\n row 1: %d,%s", bc1,bc2);
+ fprintf(stdout, "\n row 1: %d, %s", bc1, bc2);
c2[0]= '\0'; l2= 0;
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *)c2;
+ bind[0].buffer= (void *)c2;
bind[0].buffer_length= 7;
bind[0].is_null= 0;
bind[0].length= &l2;
- rc = mysql_fetch_column(stmt,bind,1,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
- assert(strncmp(c2,"mysq",4)==0 && l2 == 5);
-
+ assert(strncmp(c2, "mysq", 4) == 0 && l2 == 5);
+
c2[0]= '\0'; l2= 0;
- rc = mysql_fetch_column(stmt,bind,1,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 1: %si(%ld)", c2, l2);
- assert(strcmp(c2,"mysql")==0 && l2 == 5);
+ assert(strcmp(c2, "mysql") == 0 && l2 == 5);
- c1= 0;
+ c1= 0;
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&c1;
+ bind[0].buffer= (void *)&c1;
bind[0].buffer_length= 0;
bind[0].is_null= 0;
bind[0].length= &l1;
- rc = mysql_fetch_column(stmt,bind,0,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 0: %d(%ld)", c1, l1);
assert(c1 == 2 && l1 == 4);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
- rc = mysql_fetch_column(stmt,bind,1,0);
- check_execute_r(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
+ check_execute_r(stmt, rc);
mysql_stmt_close(stmt);
}
-/*
- To test mysql_list_fields()
-*/
+
+/* Test mysql_list_fields() */
+
static void test_list_fields()
{
MYSQL_RES *result;
int rc;
myheader("test_list_fields");
- rc= mysql_query(mysql,"drop table if exists test_list_fields");
+ rc= mysql_query(mysql, "drop table if exists test_list_fields");
myquery(rc);
-
- rc = mysql_query(mysql, "create table test_list_fields(c1 int primary key auto_increment, c2 char(10) default 'mysql')");
+
+ rc= mysql_query(mysql, "create table test_list_fields(c1 int primary key auto_increment, c2 char(10) default 'mysql')");
myquery(rc);
- result = mysql_list_fields(mysql, "test_list_fields",NULL);
+ result= mysql_list_fields(mysql, "test_list_fields", NULL);
mytest(result);
assert( 0 == my_process_result_set(result));
-
- verify_prepare_field(result,0,"c1","c1",MYSQL_TYPE_LONG,
- "test_list_fields","test_list_fields",current_db,11,"0");
-
- verify_prepare_field(result,1,"c2","c2",MYSQL_TYPE_STRING,
- "test_list_fields","test_list_fields",current_db,10,"mysql");
+
+ verify_prepare_field(result, 0, "c1", "c1", MYSQL_TYPE_LONG,
+ "test_list_fields", "test_list_fields", current_db, 11, "0");
+
+ verify_prepare_field(result, 1, "c2", "c2", MYSQL_TYPE_STRING,
+ "test_list_fields", "test_list_fields", current_db, 10, "mysql");
mysql_free_result(result);
}
-/*
- To test a memory ovverun bug
-*/
+
+/* Test a memory ovverun bug */
+
static void test_mem_overun()
{
char buffer[10000], field[10];
MYSQL_STMT *stmt;
MYSQL_RES *field_res;
- int rc,i, length;
+ int rc, i, length;
myheader("test_mem_overun");
/*
- Test a memory ovverun bug when a table had 1000 fields with
+ Test a memory ovverun bug when a table had 1000 fields with
a row of data
*/
- rc= mysql_query(mysql,"drop table if exists t_mem_overun");
+ rc= mysql_query(mysql, "drop table if exists t_mem_overun");
myquery(rc);
- strxmov(buffer,"create table t_mem_overun(",NullS);
- for (i=0; i < 1000; i++)
+ strxmov(buffer, "create table t_mem_overun(", NullS);
+ for (i= 0; i < 1000; i++)
{
- sprintf(field,"c%d int", i);
- strxmov(buffer,buffer,field,",",NullS);
+ sprintf(field, "c%d int", i);
+ strxmov(buffer, buffer, field, ", ", NullS);
}
- length= (int)(strmov(buffer,buffer) - buffer);
- buffer[length-1]='\0';
- strxmov(buffer,buffer,")",NullS);
-
- rc = mysql_real_query(mysql, buffer, length);
+ length= strlen(buffer);
+ buffer[length-2]= ')';
+ buffer[--length]= '\0';
+
+ rc= mysql_real_query(mysql, buffer, length);
myquery(rc);
- strxmov(buffer,"insert into t_mem_overun values(",NullS);
- for (i=0; i < 1000; i++)
+ strxmov(buffer, "insert into t_mem_overun values(", NullS);
+ for (i= 0; i < 1000; i++)
{
- strxmov(buffer,buffer,"1,",NullS);
+ strxmov(buffer, buffer, "1, ", NullS);
}
- length= (int)(strmov(buffer,buffer) - buffer);
- buffer[length-1]='\0';
- strxmov(buffer,buffer,")",NullS);
-
- rc = mysql_real_query(mysql, buffer, length);
+ length= strlen(buffer);
+ buffer[length-2]= ')';
+ buffer[--length]= '\0';
+
+ rc= mysql_real_query(mysql, buffer, length);
myquery(rc);
- rc = mysql_query(mysql,"select * from t_mem_overun");
+ rc= mysql_query(mysql, "select * from t_mem_overun");
myquery(rc);
assert(1 == my_process_result(mysql));
-
- stmt = mysql_simple_prepare(mysql, "select * from t_mem_overun");
+
+ stmt= mysql_simple_prepare(mysql, "select * from t_mem_overun");
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
-
- field_res = mysql_get_metadata(stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ field_res= mysql_stmt_result_metadata(stmt);
mytest(field_res);
- fprintf(stdout,"\n total fields : %d", mysql_num_fields(field_res));
+ fprintf(stdout, "\n total fields : %d", mysql_num_fields(field_res));
assert( 1000 == mysql_num_fields(field_res));
- rc = mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_store_result(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
mysql_free_result(field_res);
@@ -7808,9 +7651,9 @@ static void test_mem_overun()
mysql_stmt_close(stmt);
}
-/*
- To test mysql_stmt_free_result()
-*/
+
+/* Test mysql_stmt_free_result() */
+
static void test_free_result()
{
MYSQL_STMT *stmt;
@@ -7821,75 +7664,76 @@ static void test_free_result()
myheader("test_free_result");
- rc= mysql_query(mysql,"drop table if exists test_free_result");
+ rc= mysql_query(mysql, "drop table if exists test_free_result");
myquery(rc);
-
- rc = mysql_query(mysql, "create table test_free_result(c1 int primary key auto_increment)");
+
+ rc= mysql_query(mysql, "create table test_free_result("
+ "c1 int primary key auto_increment)");
myquery(rc);
-
- rc = mysql_query(mysql, "insert into test_free_result values(),(),()");
+
+ rc= mysql_query(mysql, "insert into test_free_result values(), (), ()");
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"select * from test_free_result");
+ stmt= mysql_simple_prepare(mysql, "select * from test_free_result");
check_stmt(stmt);
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&bc1;
+ bind[0].buffer= (void *)&bc1;
bind[0].buffer_length= 0;
bind[0].is_null= 0;
bind[0].length= &bl1;
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_bind_result(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
c2[0]= '\0'; l2= 0;
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *)c2;
+ bind[0].buffer= (void *)c2;
bind[0].buffer_length= 7;
bind[0].is_null= 0;
bind[0].length= &l2;
- rc = mysql_fetch_column(stmt,bind,0,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 0: %s(%ld)", c2, l2);
- assert(strncmp(c2,"1",1)==0 && l2 == 1);
+ assert(strncmp(c2, "1", 1) == 0 && l2 == 1);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- c1= 0, l2= 0;
+ c1= 0, l2= 0;
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&c1;
+ bind[0].buffer= (void *)&c1;
bind[0].buffer_length= 0;
bind[0].is_null= 0;
bind[0].length= &l2;
- rc = mysql_fetch_column(stmt,bind,0,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 0: %d(%ld)", c1, l2);
- assert(c1 == 2 && l2 == 4);
+ assert(c1 == 2 && l2 == 4);
- rc = mysql_query(mysql,"drop table test_free_result");
+ rc= mysql_query(mysql, "drop table test_free_result");
myquery_r(rc); /* error should be, COMMANDS OUT OF SYNC */
- rc = mysql_stmt_free_result(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_free_result(stmt);
+ check_execute(stmt, rc);
- rc = mysql_query(mysql,"drop table test_free_result");
+ rc= mysql_query(mysql, "drop table test_free_result");
myquery(rc); /* should be successful */
mysql_stmt_close(stmt);
}
-/*
- To test mysql_stmt_free_result()
-*/
+
+/* Test mysql_stmt_store_result() */
+
static void test_free_store_result()
{
MYSQL_STMT *stmt;
@@ -7900,75 +7744,74 @@ static void test_free_store_result()
myheader("test_free_store_result");
- rc= mysql_query(mysql,"drop table if exists test_free_result");
+ rc= mysql_query(mysql, "drop table if exists test_free_result");
myquery(rc);
-
- rc = mysql_query(mysql, "create table test_free_result(c1 int primary key auto_increment)");
+
+ rc= mysql_query(mysql, "create table test_free_result(c1 int primary key auto_increment)");
myquery(rc);
-
- rc = mysql_query(mysql, "insert into test_free_result values(),(),()");
+
+ rc= mysql_query(mysql, "insert into test_free_result values(), (), ()");
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"select * from test_free_result");
+ stmt= mysql_simple_prepare(mysql, "select * from test_free_result");
check_stmt(stmt);
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&bc1;
+ bind[0].buffer= (void *)&bc1;
bind[0].buffer_length= 0;
bind[0].is_null= 0;
bind[0].length= &bl1;
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_bind_result(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_store_result(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
c2[0]= '\0'; l2= 0;
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *)c2;
+ bind[0].buffer= (void *)c2;
bind[0].buffer_length= 7;
bind[0].is_null= 0;
bind[0].length= &l2;
- rc = mysql_fetch_column(stmt,bind,0,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
- assert(strncmp(c2,"1",1)==0 && l2 == 1);
+ assert(strncmp(c2, "1", 1) == 0 && l2 == 1);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- c1= 0, l2= 0;
+ c1= 0, l2= 0;
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&c1;
+ bind[0].buffer= (void *)&c1;
bind[0].buffer_length= 0;
bind[0].is_null= 0;
bind[0].length= &l2;
- rc = mysql_fetch_column(stmt,bind,0,0);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
+ check_execute(stmt, rc);
fprintf(stdout, "\n col 0: %d(%ld)", c1, l2);
assert(c1 == 2 && l2 == 4);
- rc = mysql_stmt_free_result(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_free_result(stmt);
+ check_execute(stmt, rc);
- rc = mysql_query(mysql,"drop table test_free_result");
- myquery(rc);
+ rc= mysql_query(mysql, "drop table test_free_result");
+ myquery(rc);
mysql_stmt_close(stmt);
}
-/********************************************************
- To test SQLmode
-*********************************************************/
+
+/* Test SQLmode */
static void test_sqlmode()
{
@@ -7979,125 +7822,124 @@ static void test_sqlmode()
myheader("test_sqlmode");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_piping");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_piping");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_piping(name varchar(10))");
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_piping(name varchar(10))");
- myquery(rc);
-
/* PIPES_AS_CONCAT */
- strcpy(query,"SET SQL_MODE=\"PIPES_AS_CONCAT\"");
- fprintf(stdout,"\n With %s", query);
- rc = mysql_query(mysql,query);
+ strcpy(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\"");
+ fprintf(stdout, "\n With %s", query);
+ rc= mysql_query(mysql, query);
myquery(rc);
strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
- fprintf(stdout,"\n query: %s", query);
- stmt = mysql_simple_prepare(mysql, query);
+ fprintf(stdout, "\n query: %s", query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- fprintf(stdout,"\n total parameters: %ld", mysql_param_count(stmt));
+ fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt));
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *)c1;
+ bind[0].buffer= (void *)c1;
bind[0].buffer_length= 2;
- bind[0].is_null= 0;
- bind[0].length= 0;
bind[1].buffer_type= MYSQL_TYPE_STRING;
- bind[1].buffer= (char *)c2;
+ bind[1].buffer= (void *)c2;
bind[1].buffer_length= 3;
- bind[1].is_null= 0;
- bind[1].length= 0;
- rc = mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
- strcpy(c1,"My"); strcpy(c2, "SQL");
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ strcpy(c1, "My"); strcpy(c2, "SQL");
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
mysql_stmt_close(stmt);
- verify_col_data("test_piping","name","MySQL");
+ verify_col_data("test_piping", "name", "MySQL");
- rc = mysql_query(mysql,"DELETE FROM test_piping");
+ rc= mysql_query(mysql, "DELETE FROM test_piping");
myquery(rc);
-
+
strcpy(query, "SELECT connection_id ()");
- fprintf(stdout,"\n query: %s", query);
- stmt = mysql_simple_prepare(mysql, query);
+ fprintf(stdout, "\n query: %s", query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt_r(stmt);
/* ANSI */
- strcpy(query,"SET SQL_MODE=\"ANSI\"");
- fprintf(stdout,"\n With %s", query);
- rc = mysql_query(mysql,query);
+ strcpy(query, "SET SQL_MODE= \"ANSI\"");
+ fprintf(stdout, "\n With %s", query);
+ rc= mysql_query(mysql, query);
myquery(rc);
strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
- fprintf(stdout,"\n query: %s", query);
- stmt = mysql_simple_prepare(mysql, query);
+ fprintf(stdout, "\n query: %s", query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- fprintf(stdout,"\n total parameters: %ld", mysql_param_count(stmt));
+ fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt));
- rc = mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
- strcpy(c1,"My"); strcpy(c2, "SQL");
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ strcpy(c1, "My"); strcpy(c2, "SQL");
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
mysql_stmt_close(stmt);
- verify_col_data("test_piping","name","MySQL");
+ verify_col_data("test_piping", "name", "MySQL");
/* ANSI mode spaces ... */
strcpy(query, "SELECT connection_id ()");
- fprintf(stdout,"\n query: %s", query);
- stmt = mysql_simple_prepare(mysql, query);
+ fprintf(stdout, "\n query: %s", query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
- fprintf(stdout,"\n returned 1 row\n");
+ fprintf(stdout, "\n returned 1 row\n");
mysql_stmt_close(stmt);
-
+
/* IGNORE SPACE MODE */
- strcpy(query,"SET SQL_MODE=\"IGNORE_SPACE\"");
- fprintf(stdout,"\n With %s", query);
- rc = mysql_query(mysql,query);
+ strcpy(query, "SET SQL_MODE= \"IGNORE_SPACE\"");
+ fprintf(stdout, "\n With %s", query);
+ rc= mysql_query(mysql, query);
myquery(rc);
strcpy(query, "SELECT connection_id ()");
- fprintf(stdout,"\n query: %s", query);
- stmt = mysql_simple_prepare(mysql, query);
+ fprintf(stdout, "\n query: %s", query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
assert(rc == MYSQL_NO_DATA);
- fprintf(stdout,"\n returned 1 row");
+ fprintf(stdout, "\n returned 1 row");
mysql_stmt_close(stmt);
}
-/*
- test for timestamp handling
-*/
+
+/* Test for timestamp handling */
+
static void test_ts()
{
MYSQL_STMT *stmt;
@@ -8111,16 +7953,13 @@ static void test_ts()
myheader("test_ts");
- rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_ts");
- myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_ts(a DATE, b TIME, c TIMESTAMP)");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ts");
myquery(rc);
- rc = mysql_commit(mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_ts(a DATE, b TIME, c TIMESTAMP)");
myquery(rc);
- stmt = mysql_simple_prepare(mysql,"INSERT INTO test_ts VALUES(?,?,?),(?,?,?)");
+ stmt= mysql_simple_prepare(mysql, "INSERT INTO test_ts VALUES(?, ?, ?), (?, ?, ?)");
check_stmt(stmt);
ts.year= 2003;
@@ -8130,46 +7969,49 @@ static void test_ts()
ts.minute= 07;
ts.second= 46;
ts.second_part= 0;
- length= (long)(strmov(strts,"2003-07-12 21:07:46") - strts);
+ length= (long)(strmov(strts, "2003-07-12 21:07:46") - strts);
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_TIMESTAMP;
- bind[0].buffer= (char *)&ts;
+ bind[0].buffer= (void *)&ts;
bind[0].buffer_length= sizeof(ts);
- bind[0].is_null= 0;
- bind[0].length= 0;
bind[2]= bind[1]= bind[0];
bind[3].buffer_type= MYSQL_TYPE_STRING;
- bind[3].buffer= (char *)strts;
+ bind[3].buffer= (void *)strts;
bind[3].buffer_length= sizeof(strts);
- bind[3].is_null= 0;
bind[3].length= &length;
bind[5]= bind[4]= bind[3];
- rc = mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
mysql_stmt_close(stmt);
- verify_col_data("test_ts","a","2003-07-12");
- verify_col_data("test_ts","b","21:07:46");
- verify_col_data("test_ts","c","2003-07-12 21:07:46");
+ verify_col_data("test_ts", "a", "2003-07-12");
+ verify_col_data("test_ts", "b", "21:07:46");
+ verify_col_data("test_ts", "c", "2003-07-12 21:07:46");
- stmt = mysql_simple_prepare(mysql,"SELECT * FROM test_ts");
+ stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_ts");
check_stmt(stmt);
- prep_res = mysql_get_metadata(stmt);
+ prep_res= mysql_stmt_result_metadata(stmt);
mytest(prep_res);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- assert( 2== my_process_stmt_result(stmt));
+ assert(2 == my_process_stmt_result(stmt));
field_count= mysql_num_fields(prep_res);
mysql_free_result(prep_res);
@@ -8179,20 +8021,19 @@ static void test_ts()
{
int row_count= 0;
- sprintf(query,"SELECT a,b,c FROM test_ts WHERE %c=?",name);
- length= (long)(strmov(query,query)- query);
+ sprintf(query, "SELECT a, b, c FROM test_ts WHERE %c=?", name);
- fprintf(stdout,"\n %s", query);
- stmt = mysql_prepare(mysql, query, length);
+ fprintf(stdout, "\n %s", query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc = mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- while (mysql_fetch(stmt) == 0)
+ while (mysql_stmt_fetch(stmt) == 0)
row_count++;
fprintf(stdout, "\n returned '%d' rows", row_count);
@@ -8201,63 +8042,65 @@ static void test_ts()
}
}
-/*
- Test for bug #1500.
-*/
+
+/* Test for bug #1500. */
static void test_bug1500()
{
MYSQL_STMT *stmt;
MYSQL_BIND bind[3];
int rc;
- long int_data[3]= {2,3,4};
+ long int_data[3]= {2, 3, 4};
const char *data;
myheader("test_bug1500");
- rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_bg1500");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bg1500");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_bg1500 (i INT)");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bg1500 (i INT)");
myquery(rc);
-
- rc= mysql_query(mysql,"INSERT INTO test_bg1500 VALUES (1),(2)");
+
+ rc= mysql_query(mysql, "INSERT INTO test_bg1500 VALUES (1), (2)");
myquery(rc);
rc= mysql_commit(mysql);
myquery(rc);
- stmt= mysql_simple_prepare(mysql,"SELECT i FROM test_bg1500 WHERE i IN (?,?,?)");
+ stmt= mysql_simple_prepare(mysql, "SELECT i FROM test_bg1500 WHERE i IN (?, ?, ?)");
check_stmt(stmt);
- verify_param_count(stmt,3);
+ verify_param_count(stmt, 3);
- bind[0].buffer= (char *)int_data;
- bind[0].buffer_type= FIELD_TYPE_LONG;
- bind[0].is_null= 0;
- bind[0].length= NULL;
- bind[0].buffer_length= 0;
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
+ bind[0].buffer= (void *)int_data;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[2]= bind[1]= bind[0];
- bind[1].buffer= (char *)(int_data + 1);
- bind[2].buffer= (char *)(int_data + 2);
-
- rc= mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
-
- rc= mysql_execute(stmt);
- check_execute(stmt,rc);
-
+ bind[1].buffer= (void *)(int_data + 1);
+ bind[2].buffer= (void *)(int_data + 2);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
assert(1 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt);
- rc= mysql_query(mysql,"DROP TABLE test_bg1500");
+ rc= mysql_query(mysql, "DROP TABLE test_bg1500");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_bg1500 (s VARCHAR(25), FULLTEXT(s))");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bg1500 (s VARCHAR(25), FULLTEXT(s))");
myquery(rc);
-
+
rc= mysql_query(mysql,
- "INSERT INTO test_bg1500 VALUES ('Gravedigger'), ('Greed'),('Hollow Dogs')");
+ "INSERT INTO test_bg1500 VALUES ('Gravedigger'), ('Greed'), ('Hollow Dogs')");
myquery(rc);
rc= mysql_commit(mysql);
@@ -8266,55 +8109,54 @@ static void test_bug1500()
stmt= mysql_simple_prepare(mysql,
"SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (?)");
check_stmt(stmt);
-
- verify_param_count(stmt,1);
-
+
+ verify_param_count(stmt, 1);
+
data= "Dogs";
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *) data;
+ bind[0].buffer= (void *) data;
bind[0].buffer_length= strlen(data);
bind[0].is_null= 0;
bind[0].length= 0;
-
- rc= mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
-
- rc= mysql_execute(stmt);
- check_execute(stmt,rc);
-
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
assert(1 == my_process_stmt_result(stmt));
- /*
- FIXME If we comment out next string server will crash too :(
+ /*
+ FIXME If we comment out next string server will crash too :(
This is another manifestation of bug #1663
*/
mysql_stmt_close(stmt);
-
+
/* This should work too */
stmt= mysql_simple_prepare(mysql,
- "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (CONCAT(?,'digger'))");
+ "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (CONCAT(?, 'digger'))");
check_stmt(stmt);
-
- verify_param_count(stmt,1);
-
+
+ verify_param_count(stmt, 1);
+
data= "Grave";
bind[0].buffer_type= MYSQL_TYPE_STRING;
- bind[0].buffer= (char *) data;
+ bind[0].buffer= (void *) data;
bind[0].buffer_length= strlen(data);
- bind[0].is_null= 0;
- bind[0].length= 0;
-
- rc= mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
-
- rc= mysql_execute(stmt);
- check_execute(stmt,rc);
-
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
assert(1 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt);
}
+
static void test_bug1946()
{
MYSQL_STMT *stmt;
@@ -8322,14 +8164,14 @@ static void test_bug1946()
const char *query= "INSERT INTO prepare_command VALUES (?)";
myheader("test_bug1946");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS prepare_command");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS prepare_command");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE prepare_command(ID INT)");
+
+ rc= mysql_query(mysql, "CREATE TABLE prepare_command(ID INT)");
myquery(rc);
- stmt = mysql_simple_prepare(mysql, query);
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
rc= mysql_real_query(mysql, query, strlen(query));
assert(rc != 0);
@@ -8337,9 +8179,10 @@ static void test_bug1946()
myerror(NULL);
mysql_stmt_close(stmt);
- rc= mysql_query(mysql,"DROP TABLE prepare_command");
+ rc= mysql_query(mysql, "DROP TABLE prepare_command");
}
+
static void test_parse_error_and_bad_length()
{
MYSQL_STMT *stmt;
@@ -8348,19 +8191,21 @@ static void test_parse_error_and_bad_length()
/* check that we get 4 syntax errors over the 4 calls */
myheader("test_parse_error_and_bad_length");
- rc= mysql_query(mysql,"SHOW DATABAAAA");
+ rc= mysql_query(mysql, "SHOW DATABAAAA");
assert(rc);
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
- rc= mysql_real_query(mysql,"SHOW DATABASES",100);
+ rc= mysql_real_query(mysql, "SHOW DATABASES", 100);
assert(rc);
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
- stmt= mysql_simple_prepare(mysql,"SHOW DATABAAAA");
- assert(!stmt);
- fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
- stmt= mysql_prepare(mysql,"SHOW DATABASES",100);
+ stmt= mysql_simple_prepare(mysql, "SHOW DATABAAAA");
assert(!stmt);
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
+ stmt= mysql_stmt_init(mysql);
+ assert(stmt);
+ assert(mysql_stmt_prepare(stmt, "SHOW DATABASES", 100) != 0);
+ fprintf(stdout, "Got error (as expected): '%s'\n", mysql_stmt_error(stmt));
+ mysql_stmt_close(stmt);
}
@@ -8379,21 +8224,21 @@ static void test_bug2247()
enum { NUM_ROWS= 5 };
myheader("test_bug2247");
-
+
fprintf(stdout, "\nChecking if stmt_affected_rows is not affected by\n"
"mysql_query ... ");
/* create table and insert few rows */
- rc = mysql_query(mysql, drop);
+ rc= mysql_query(mysql, drop);
myquery(rc);
-
+
rc= mysql_query(mysql, create);
myquery(rc);
- stmt= mysql_prepare(mysql, insert, strlen(insert));
+ stmt= mysql_simple_prepare(mysql, insert);
check_stmt(stmt);
for (i= 0; i < NUM_ROWS; ++i)
{
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
}
exp_count= mysql_stmt_affected_rows(stmt);
@@ -8401,7 +8246,7 @@ static void test_bug2247()
rc= mysql_query(mysql, select);
myquery(rc);
- /*
+ /*
mysql_store_result overwrites mysql->affected_rows. Check that
mysql_stmt_affected_rows() returns the same value, whereas
mysql_affected_rows() value is correct.
@@ -8411,7 +8256,7 @@ static void test_bug2247()
assert(mysql_affected_rows(mysql) == NUM_ROWS);
assert(exp_count == mysql_stmt_affected_rows(stmt));
-
+
rc= mysql_query(mysql, update);
myquery(rc);
assert(mysql_affected_rows(mysql) == NUM_ROWS);
@@ -8421,10 +8266,10 @@ static void test_bug2247()
mysql_stmt_close(stmt);
/* check that mysql_stmt_store_result modifies mysql_stmt_affected_rows */
- stmt= mysql_prepare(mysql, select, strlen(select));
+ stmt= mysql_simple_prepare(mysql, select);
check_stmt(stmt);
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
@@ -8435,7 +8280,7 @@ static void test_bug2247()
myquery(rc);
assert(mysql_affected_rows(mysql) == 1);
assert(mysql_stmt_affected_rows(stmt) == exp_count);
-
+
mysql_stmt_close(stmt);
fprintf(stdout, "OK");
}
@@ -8445,34 +8290,34 @@ static void test_subqueries()
{
MYSQL_STMT *stmt;
int rc, i;
- const char *query= "SELECT (SELECT SUM(a+b) FROM t2 where t1.b=t2.b GROUP BY t1.a LIMIT 1) as scalar_s, exists (select 1 from t2 where t2.a/2=t1.a) as exists_s, a in (select a+3 from t2) as in_s, (a-1,b-1) in (select a,b from t2) as in_row_s FROM t1, (select a x, b y from t2) tt WHERE x=a";
+ const char *query= "SELECT (SELECT SUM(a+b) FROM t2 where t1.b=t2.b GROUP BY t1.a LIMIT 1) as scalar_s, exists (select 1 from t2 where t2.a/2=t1.a) as exists_s, a in (select a+3 from t2) as in_s, (a-1, b-1) in (select a, b from t2) as in_row_s FROM t1, (select a x, b y from t2) tt WHERE x=a";
myheader("test_subquery");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE t1 (a int , b int);");
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
myquery(rc);
rc= mysql_query(mysql,
- "insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5);");
+ "insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);");
myquery(rc);
- rc= mysql_query(mysql,"create table t2 select * from t1;");
+ rc= mysql_query(mysql, "create table t2 select * from t1;");
myquery(rc);
- stmt= mysql_prepare(mysql, query, strlen(query));
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
for (i= 0; i < 3; i++)
{
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(5 == my_process_stmt_result(stmt));
}
mysql_stmt_close(stmt);
- rc= mysql_query(mysql, "DROP TABLE t1,t2");
+ rc= mysql_query(mysql, "DROP TABLE t1, t2");
myquery(rc);
}
@@ -8483,37 +8328,38 @@ static void test_bad_union()
const char *query= "SELECT 1, 2 union SELECT 1";
myheader("test_bad_union");
-
- stmt= mysql_prepare(mysql, query, strlen(query));
+
+ stmt= mysql_simple_prepare(mysql, query);
assert(stmt == 0);
- myerror(NULL);
+ myerror(NULL);
}
+
static void test_distinct()
{
MYSQL_STMT *stmt;
int rc, i;
- const char *query=
+ const char *query=
"SELECT 2+count(distinct b), group_concat(a) FROM t1 group by a";
myheader("test_subquery");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE t1 (a int , b int);");
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
myquery(rc);
rc= mysql_query(mysql,
- "insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5),\
-(1,10), (2, 20), (3,30), (4,40), (5,50);");
+ "insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), \
+(1, 10), (2, 20), (3, 30), (4, 40), (5, 50);");
myquery(rc);
for (i= 0; i < 3; i++)
{
- stmt= mysql_prepare(mysql, query, strlen(query));
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(5 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt);
@@ -8523,8 +8369,9 @@ static void test_distinct()
myquery(rc);
}
+
/*
- Test for bug#2248 "mysql_fetch without prior mysql_execute hangs"
+ Test for bug#2248 "mysql_fetch without prior mysql_stmt_execute hangs"
*/
static void test_bug2248()
@@ -8533,53 +8380,54 @@ static void test_bug2248()
int rc;
const char *query1= "SELECT DATABASE()";
const char *query2= "INSERT INTO test_bug2248 VALUES (10)";
-
+
myheader("test_bug2248");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bug2248");
myquery(rc);
-
+
rc= mysql_query(mysql, "CREATE TABLE test_bug2248 (id int)");
myquery(rc);
-
- stmt= mysql_prepare(mysql, query1, strlen(query1));
+
+ stmt= mysql_simple_prepare(mysql, query1);
check_stmt(stmt);
/* This should not hang */
- rc= mysql_fetch(stmt);
- check_execute_r(stmt,rc);
-
+ rc= mysql_stmt_fetch(stmt);
+ check_execute_r(stmt, rc);
+
/* And this too */
rc= mysql_stmt_store_result(stmt);
- check_execute_r(stmt,rc);
-
+ check_execute_r(stmt, rc);
+
mysql_stmt_close(stmt);
-
- stmt= mysql_prepare(mysql, query2, strlen(query2));
+
+ stmt= mysql_simple_prepare(mysql, query2);
check_stmt(stmt);
-
- rc= mysql_execute(stmt);
- check_execute(stmt,rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
/* This too should not hang but should return proper error */
- rc= mysql_fetch(stmt);
- assert(rc==MYSQL_NO_DATA);
-
+ rc= mysql_stmt_fetch(stmt);
+ assert(rc == MYSQL_NO_DATA);
+
/* This too should not hang but should not bark */
rc= mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
-
+ check_execute(stmt, rc);
+
/* This should return proper error */
- rc= mysql_fetch(stmt);
- check_execute_r(stmt,rc);
- assert(rc==MYSQL_NO_DATA);
-
+ rc= mysql_stmt_fetch(stmt);
+ check_execute_r(stmt, rc);
+ assert(rc == MYSQL_NO_DATA);
+
mysql_stmt_close(stmt);
-
- rc= mysql_query(mysql,"DROP TABLE test_bug2248");
+
+ rc= mysql_query(mysql, "DROP TABLE test_bug2248");
myquery(rc);
}
+
static void test_subqueries_ref()
{
MYSQL_STMT *stmt;
@@ -8587,22 +8435,22 @@ static void test_subqueries_ref()
const char *query= "SELECT a as ccc from t1 where a+1=(SELECT 1+ccc from t1 where ccc+1=a+1 and a=1)";
myheader("test_subquery_ref");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE t1 (a int);");
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int);");
myquery(rc);
rc= mysql_query(mysql,
- "insert into t1 values (1), (2), (3), (4), (5);");
+ "insert into t1 values (1), (2), (3), (4), (5);");
myquery(rc);
- stmt= mysql_prepare(mysql, query, strlen(query));
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
for (i= 0; i < 3; i++)
{
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
}
@@ -8619,7 +8467,7 @@ static void test_union()
int rc;
myheader("test_union");
-
+
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
myquery(rc);
@@ -8649,14 +8497,14 @@ static void test_union()
"(10, 'Azerbaijan'), (11, 'Afghanistan'), "
"(12, 'Burkina Faso'), (13, 'Faroe Islands')");
myquery(rc);
-
+
stmt= mysql_simple_prepare(mysql,
"SELECT t1.name FROM t1 UNION "
"SELECT t2.name FROM t2");
check_stmt(stmt);
rc= mysql_stmt_execute(stmt);
- check_execute(stmt,rc);
+ check_execute(stmt, rc);
assert(20 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt);
@@ -8664,6 +8512,7 @@ static void test_union()
myquery(rc);
}
+
static void test_bug3117()
{
MYSQL_STMT *stmt;
@@ -8674,51 +8523,52 @@ static void test_bug3117()
int rc;
myheader("test_bug3117");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE t1 (id int auto_increment primary key)");
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (id int auto_increment primary key)");
myquery(rc);
- stmt = mysql_simple_prepare(mysql, "SELECT LAST_INSERT_ID()");
+ stmt= mysql_simple_prepare(mysql, "SELECT LAST_INSERT_ID()");
check_stmt(stmt);
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)");
myquery(rc);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ bzero((char*) &buffer, sizeof(buffer));
buffer.buffer_type= MYSQL_TYPE_LONGLONG;
buffer.buffer_length= sizeof(lii);
- buffer.buffer= (char *)&lii;
+ buffer.buffer= (void *)&lii;
buffer.length= &length;
buffer.is_null= &is_null;
- rc= mysql_bind_result(stmt, &buffer);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_result(stmt, &buffer);
+ check_execute(stmt, rc);
rc= mysql_stmt_store_result(stmt);
- check_execute(stmt,rc);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
assert(is_null == 0 && lii == 1);
- fprintf(stdout, "\n\tLAST_INSERT_ID() = 1 ok\n");
+ fprintf(stdout, "\n\tLAST_INSERT_ID()= 1 ok\n");
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)");
myquery(rc);
- rc = mysql_execute(stmt);
- check_execute(stmt,rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
- rc = mysql_fetch(stmt);
+ rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
assert(is_null == 0 && lii == 2);
- fprintf(stdout, "\tLAST_INSERT_ID() = 2 ok\n");
+ fprintf(stdout, "\tLAST_INSERT_ID()= 2 ok\n");
mysql_stmt_close(stmt);
@@ -8731,49 +8581,49 @@ static void test_join()
{
MYSQL_STMT *stmt;
int rc, i, j;
- const char *query[]={"SELECT * FROM t2 join t1 on (t1.a=t2.a)",
- "SELECT * FROM t2 natural join t1",
- "SELECT * FROM t2 join t1 using(a)",
- "SELECT * FROM t2 left join t1 on(t1.a=t2.a)",
- "SELECT * FROM t2 natural left join t1",
- "SELECT * FROM t2 left join t1 using(a)",
- "SELECT * FROM t2 right join t1 on(t1.a=t2.a)",
- "SELECT * FROM t2 natural right join t1",
- "SELECT * FROM t2 right join t1 using(a)"};
+ const char *query[]= {"SELECT * FROM t2 join t1 on (t1.a=t2.a)",
+ "SELECT * FROM t2 natural join t1",
+ "SELECT * FROM t2 join t1 using(a)",
+ "SELECT * FROM t2 left join t1 on(t1.a=t2.a)",
+ "SELECT * FROM t2 natural left join t1",
+ "SELECT * FROM t2 left join t1 using(a)",
+ "SELECT * FROM t2 right join t1 on(t1.a=t2.a)",
+ "SELECT * FROM t2 natural right join t1",
+ "SELECT * FROM t2 right join t1 using(a)"};
myheader("test_join");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE t1 (a int , b int);");
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
myquery(rc);
rc= mysql_query(mysql,
- "insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5);");
+ "insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);");
myquery(rc);
- rc= mysql_query(mysql,"CREATE TABLE t2 (a int , c int);");
+ rc= mysql_query(mysql, "CREATE TABLE t2 (a int , c int);");
myquery(rc);
rc= mysql_query(mysql,
- "insert into t2 values (1,1), (2, 2), (3,3), (4,4), (5,5);");
+ "insert into t2 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);");
myquery(rc);
for (j= 0; j < 9; j++)
{
- stmt= mysql_prepare(mysql, query[j], strlen(query[j]));
+ stmt= mysql_simple_prepare(mysql, query[j]);
check_stmt(stmt);
for (i= 0; i < 3; i++)
{
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(5 == my_process_stmt_result(stmt));
}
mysql_stmt_close(stmt);
}
- rc= mysql_query(mysql, "DROP TABLE t1,t2");
+ rc= mysql_query(mysql, "DROP TABLE t1, t2");
myquery(rc);
}
@@ -8782,44 +8632,44 @@ static void test_selecttmp()
{
MYSQL_STMT *stmt;
int rc, i;
- const char *query= "select a,(select count(distinct t1.b) as sum from t1,t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3";
+ const char *query= "select a, (select count(distinct t1.b) as sum from t1, t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3";
myheader("test_select_tmp");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2,t3");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE t1 (a int , b int);");
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
myquery(rc);
- rc= mysql_query(mysql,"create table t2 (a int, b int);");
+ rc= mysql_query(mysql, "create table t2 (a int, b int);");
myquery(rc);
- rc= mysql_query(mysql,"create table t3 (a int, b int);");
+ rc= mysql_query(mysql, "create table t3 (a int, b int);");
myquery(rc);
rc= mysql_query(mysql,
- "insert into t1 values (0,100),(1,2), (1,3), (2,2), (2,7), \
-(2,-1), (3,10);");
+ "insert into t1 values (0, 100), (1, 2), (1, 3), (2, 2), (2, 7), \
+(2, -1), (3, 10);");
myquery(rc);
rc= mysql_query(mysql,
- "insert into t2 values (0,0), (1,1), (2,1), (3,1), (4,1);");
+ "insert into t2 values (0, 0), (1, 1), (2, 1), (3, 1), (4, 1);");
myquery(rc);
rc= mysql_query(mysql,
- "insert into t3 values (3,3), (2,2), (1,1);");
+ "insert into t3 values (3, 3), (2, 2), (1, 1);");
myquery(rc);
- stmt= mysql_prepare(mysql, query, strlen(query));
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
for (i= 0; i < 3; i++)
{
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(3 == my_process_stmt_result(stmt));
}
mysql_stmt_close(stmt);
- rc= mysql_query(mysql, "DROP TABLE t1,t2,t3");
+ rc= mysql_query(mysql, "DROP TABLE t1, t2, t3");
myquery(rc);
}
@@ -8830,65 +8680,65 @@ static void test_create_drop()
char *query;
int rc, i;
myheader("test_table_manipulation");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
myquery(rc);
- rc= mysql_query(mysql,"create table t2 (a int);");
+ rc= mysql_query(mysql, "create table t2 (a int);");
myquery(rc);
- rc= mysql_query(mysql,"create table t1 (a int);");
+ rc= mysql_query(mysql, "create table t1 (a int);");
myquery(rc);
rc= mysql_query(mysql, "insert into t2 values (3), (2), (1);");
myquery(rc);
-
+
query= (char*)"create table t1 (a int)";
- stmt_create= mysql_prepare(mysql, query, strlen(query));
+ stmt_create= mysql_simple_prepare(mysql, query);
check_stmt(stmt_create);
query= (char*)"drop table t1";
- stmt_drop= mysql_prepare(mysql, query, strlen(query));
+ stmt_drop= mysql_simple_prepare(mysql, query);
check_stmt(stmt_drop);
query= (char*)"select a in (select a from t2) from t1";
- stmt_select= mysql_prepare(mysql, query, strlen(query));
+ stmt_select= mysql_simple_prepare(mysql, query);
check_stmt(stmt_select);
-
+
rc= mysql_query(mysql, "DROP TABLE t1");
myquery(rc);
query= (char*)"create table t1 select a from t2";
- stmt_create_select= mysql_prepare(mysql, query, strlen(query));
+ stmt_create_select= mysql_simple_prepare(mysql, query);
check_stmt(stmt_create_select);
for (i= 0; i < 3; i++)
{
- rc= mysql_execute(stmt_create);
+ rc= mysql_stmt_execute(stmt_create);
check_execute(stmt_create, rc);
fprintf(stdout, "created %i\n", i);
- rc= mysql_execute(stmt_select);
+ rc= mysql_stmt_execute(stmt_select);
check_execute(stmt_select, rc);
assert(0 == my_process_stmt_result(stmt_select));
- rc= mysql_execute(stmt_drop);
+ rc= mysql_stmt_execute(stmt_drop);
check_execute(stmt_drop, rc);
fprintf(stdout, "droped %i\n", i);
- rc= mysql_execute(stmt_create_select);
+ rc= mysql_stmt_execute(stmt_create_select);
check_execute(stmt_create, rc);
fprintf(stdout, "created select %i\n", i);
- rc= mysql_execute(stmt_select);
+ rc= mysql_stmt_execute(stmt_select);
check_execute(stmt_select, rc);
assert(3 == my_process_stmt_result(stmt_select));
- rc= mysql_execute(stmt_drop);
+ rc= mysql_stmt_execute(stmt_drop);
check_execute(stmt_drop, rc);
fprintf(stdout, "droped %i\n", i);
}
-
+
mysql_stmt_close(stmt_create);
mysql_stmt_close(stmt_drop);
mysql_stmt_close(stmt_select);
@@ -8905,41 +8755,41 @@ static void test_rename()
const char *query= "rename table t1 to t2, t3 to t4";
int rc;
myheader("test_table_manipulation");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2,t3,t4");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3, t4");
myquery(rc);
-
- stmt= mysql_prepare(mysql, query, strlen(query));
+
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- rc= mysql_query(mysql,"create table t1 (a int)");
+ rc= mysql_query(mysql, "create table t1 (a int)");
myquery(rc);
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute_r(stmt, rc);
fprintf(stdout, "rename without t3\n");
- rc= mysql_query(mysql,"create table t3 (a int)");
+ rc= mysql_query(mysql, "create table t3 (a int)");
myquery(rc);
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
fprintf(stdout, "rename with t3\n");
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute_r(stmt, rc);
fprintf(stdout, "rename renamed\n");
- rc= mysql_query(mysql,"rename table t2 to t1, t4 to t3");
+ rc= mysql_query(mysql, "rename table t2 to t1, t4 to t3");
myquery(rc);
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
fprintf(stdout, "rename reverted\n");
mysql_stmt_close(stmt);
- rc= mysql_query(mysql, "DROP TABLE t2,t4");
+ rc= mysql_query(mysql, "DROP TABLE t2, t4");
myquery(rc);
}
@@ -8950,35 +8800,36 @@ static void test_do_set()
char *query;
int rc, i;
myheader("test_do_set");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
- rc= mysql_query(mysql,"create table t1 (a int)");
+ rc= mysql_query(mysql, "create table t1 (a int)");
myquery(rc);
-
+
query= (char*)"do @var:=(1 in (select * from t1))";
- stmt_do= mysql_prepare(mysql, query, strlen(query));
+ stmt_do= mysql_simple_prepare(mysql, query);
check_stmt(stmt_do);
query= (char*)"set @var=(1 in (select * from t1))";
- stmt_set= mysql_prepare(mysql, query, strlen(query));
+ stmt_set= mysql_simple_prepare(mysql, query);
check_stmt(stmt_set);
for (i= 0; i < 3; i++)
{
- rc= mysql_execute(stmt_do);
+ rc= mysql_stmt_execute(stmt_do);
check_execute(stmt_do, rc);
fprintf(stdout, "do %i\n", i);
- rc= mysql_execute(stmt_set);
+ rc= mysql_stmt_execute(stmt_set);
check_execute(stmt_set, rc);
- fprintf(stdout, "set %i\n", i);
+ fprintf(stdout, "set %i\n", i);
}
-
+
mysql_stmt_close(stmt_do);
mysql_stmt_close(stmt_set);
}
+
static void test_multi()
{
MYSQL_STMT *stmt_delete, *stmt_update, *stmt_select1, *stmt_select2;
@@ -8989,61 +8840,65 @@ static void test_multi()
ulong length= 1;
myheader("test_multi");
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
bind[0].buffer_type= MYSQL_TYPE_LONG;
- bind[0].buffer= (char *)&param;
- bind[0].buffer_length= 0;
- bind[0].is_null= 0;
+ bind[0].buffer= (void *)&param;
bind[0].length= &length;
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
myquery(rc);
- rc= mysql_query(mysql,"create table t1 (a int, b int)");
+ rc= mysql_query(mysql, "create table t1 (a int, b int)");
myquery(rc);
- rc= mysql_query(mysql,"create table t2 (a int, b int)");
+ rc= mysql_query(mysql, "create table t2 (a int, b int)");
myquery(rc);
- rc= mysql_query(mysql,"insert into t1 values (3,3), (2,2), (1,1)");
+ rc= mysql_query(mysql, "insert into t1 values (3, 3), (2, 2), (1, 1)");
myquery(rc);
- rc= mysql_query(mysql,"insert into t2 values (3,3), (2,2), (1,1)");
+ rc= mysql_query(mysql, "insert into t2 values (3, 3), (2, 2), (1, 1)");
myquery(rc);
-
- query= (char*)"delete t1,t2 from t1,t2 where t1.a=t2.a and t1.b=10";
- stmt_delete= mysql_prepare(mysql, query, strlen(query));
+
+ query= (char*)"delete t1, t2 from t1, t2 where t1.a=t2.a and t1.b=10";
+ stmt_delete= mysql_simple_prepare(mysql, query);
check_stmt(stmt_delete);
- query= (char*)"update t1,t2 set t1.b=10,t2.b=10 where t1.a=t2.a and t1.b=?";
- stmt_update= mysql_prepare(mysql, query, strlen(query));
+ query= (char*)"update t1, t2 set t1.b=10, t2.b=10 where t1.a=t2.a and t1.b=?";
+ stmt_update= mysql_simple_prepare(mysql, query);
check_stmt(stmt_update);
query= (char*)"select * from t1";
- stmt_select1= mysql_prepare(mysql, query, strlen(query));
+ stmt_select1= mysql_simple_prepare(mysql, query);
check_stmt(stmt_select1);
query= (char*)"select * from t2";
- stmt_select2= mysql_prepare(mysql, query, strlen(query));
+ stmt_select2= mysql_simple_prepare(mysql, query);
check_stmt(stmt_select2);
for(i= 0; i < 3; i++)
{
- rc= mysql_bind_param(stmt_update, bind);
- check_execute(stmt_update,rc);
+ rc= mysql_stmt_bind_param(stmt_update, bind);
+ check_execute(stmt_update, rc);
- rc= mysql_execute(stmt_update);
+ rc= mysql_stmt_execute(stmt_update);
check_execute(stmt_update, rc);
fprintf(stdout, "update %ld\n", param);
-
- rc= mysql_execute(stmt_delete);
+
+ rc= mysql_stmt_execute(stmt_delete);
check_execute(stmt_delete, rc);
fprintf(stdout, "delete %ld\n", param);
- rc= mysql_execute(stmt_select1);
+ rc= mysql_stmt_execute(stmt_select1);
check_execute(stmt_select1, rc);
assert((uint)(3-param) == my_process_stmt_result(stmt_select1));
- rc= mysql_execute(stmt_select2);
+ rc= mysql_stmt_execute(stmt_select2);
check_execute(stmt_select2, rc);
assert((uint)(3-param) == my_process_stmt_result(stmt_select2));
@@ -9054,7 +8909,7 @@ static void test_multi()
mysql_stmt_close(stmt_update);
mysql_stmt_close(stmt_select1);
mysql_stmt_close(stmt_select2);
- rc= mysql_query(mysql,"drop table t1,t2");
+ rc= mysql_query(mysql, "drop table t1, t2");
myquery(rc);
}
@@ -9067,40 +8922,40 @@ static void test_insert_select()
uint i;
myheader("test_insert_select");
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
myquery(rc);
- rc= mysql_query(mysql,"create table t1 (a int)");
+ rc= mysql_query(mysql, "create table t1 (a int)");
myquery(rc);
- rc= mysql_query(mysql,"create table t2 (a int)");
+ rc= mysql_query(mysql, "create table t2 (a int)");
myquery(rc);
- rc= mysql_query(mysql,"insert into t2 values (1)");
+ rc= mysql_query(mysql, "insert into t2 values (1)");
myquery(rc);
-
+
query= (char*)"insert into t1 select a from t2";
- stmt_insert= mysql_prepare(mysql, query, strlen(query));
+ stmt_insert= mysql_simple_prepare(mysql, query);
check_stmt(stmt_insert);
query= (char*)"select * from t1";
- stmt_select= mysql_prepare(mysql, query, strlen(query));
+ stmt_select= mysql_simple_prepare(mysql, query);
check_stmt(stmt_select);
for(i= 0; i < 3; i++)
{
- rc= mysql_execute(stmt_insert);
+ rc= mysql_stmt_execute(stmt_insert);
check_execute(stmt_insert, rc);
fprintf(stdout, "insert %u\n", i);
-
- rc= mysql_execute(stmt_select);
+
+ rc= mysql_stmt_execute(stmt_select);
check_execute(stmt_select, rc);
assert((i+1) == my_process_stmt_result(stmt_select));
}
mysql_stmt_close(stmt_insert);
mysql_stmt_close(stmt_select);
- rc= mysql_query(mysql,"drop table t1,t2");
+ rc= mysql_query(mysql, "drop table t1, t2");
myquery(rc);
}
@@ -9111,79 +8966,87 @@ static void test_bind_nagative()
char *query;
int rc;
MYSQL_BIND bind[1];
- long my_val = 0L;
- ulong my_length = 0L;
- long my_null = 0L;
+ long my_val= 0L;
+ ulong my_length= 0L;
+ long my_null= 0L;
myheader("test_insert_select");
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
- rc= mysql_query(mysql,"create temporary table t1 (c1 int unsigned)");
+ rc= mysql_query(mysql, "create temporary table t1 (c1 int unsigned)");
myquery(rc);
- rc= mysql_query(mysql,"INSERT INTO t1 VALUES (1),(-1)");
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (-1)");
myquery(rc);
query= (char*)"INSERT INTO t1 VALUES (?)";
- stmt_insert= mysql_prepare(mysql, query, strlen(query));
+ stmt_insert= mysql_simple_prepare(mysql, query);
check_stmt(stmt_insert);
/* bind parameters */
- bind[0].buffer_type = FIELD_TYPE_LONG;
- bind[0].buffer = (char *)&my_val;
- bind[0].length = &my_length;
- bind[0].is_null = (char*)&my_null;
+ bzero((char*) bind, sizeof(bind));
- rc= mysql_bind_param(stmt_insert, bind);
- check_execute(stmt_insert,rc);
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void *)&my_val;
+ bind[0].length= &my_length;
+ bind[0].is_null= (char*)&my_null;
- my_val = -1;
- rc= mysql_execute(stmt_insert);
+ rc= mysql_stmt_bind_param(stmt_insert, bind);
+ check_execute(stmt_insert, rc);
+
+ my_val= -1;
+ rc= mysql_stmt_execute(stmt_insert);
check_execute(stmt_insert, rc);
mysql_stmt_close(stmt_insert);
- rc= mysql_query(mysql,"drop table t1");
+ rc= mysql_query(mysql, "drop table t1");
myquery(rc);
}
+
static void test_derived()
{
MYSQL_STMT *stmt;
int rc, i;
MYSQL_BIND bind[1];
- long my_val = 0L;
- ulong my_length = 0L;
- long my_null = 0L;
+ long my_val= 0L;
+ ulong my_length= 0L;
+ long my_null= 0L;
const char *query=
"select count(1) from (select f.id from t1 f where f.id=?) as x";
myheader("test_derived");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
-
- rc= mysql_query(mysql,"create table t1 (id int(8), primary key (id)) \
+
+ rc= mysql_query(mysql, "create table t1 (id int(8), primary key (id)) \
TYPE=InnoDB DEFAULT CHARSET=utf8");
myquery(rc);
rc= mysql_query(mysql, "insert into t1 values (1)");
myquery(rc);
- stmt= mysql_prepare(mysql, query, strlen(query));
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
- bind[0].buffer_type = FIELD_TYPE_LONG;
- bind[0].buffer = (char *)&my_val;
- bind[0].length = &my_length;
- bind[0].is_null = (char*)&my_null;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void *)&my_val;
+ bind[0].length= &my_length;
+ bind[0].is_null= (char*)&my_null;
my_val= 1;
- rc= mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
for (i= 0; i < 3; i++)
{
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
}
@@ -9199,52 +9062,53 @@ static void test_xjoin()
MYSQL_STMT *stmt;
int rc, i;
const char *query=
- "select t.id,p1.value, n1.value, p2.value, n2.value from t3 t LEFT JOIN t1 p1 ON (p1.id=t.param1_id) LEFT JOIN t2 p2 ON (p2.id=t.param2_id) LEFT JOIN t4 n1 ON (n1.id=p1.name_id) LEFT JOIN t4 n2 ON (n2.id=p2.name_id) where t.id=1";
+ "select t.id, p1.value, n1.value, p2.value, n2.value from t3 t LEFT JOIN t1 p1 ON (p1.id=t.param1_id) LEFT JOIN t2 p2 ON (p2.id=t.param2_id) LEFT JOIN t4 n1 ON (n1.id=p1.name_id) LEFT JOIN t4 n2 ON (n2.id=p2.name_id) where t.id=1";
myheader("test_xjoin");
-
- rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2,t3,t4");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3, t4");
myquery(rc);
-
- rc= mysql_query(mysql,"create table t3 (id int(8), param1_id int(8), param2_id int(8)) TYPE=InnoDB DEFAULT CHARSET=utf8");
+
+ rc= mysql_query(mysql, "create table t3 (id int(8), param1_id int(8), param2_id int(8)) TYPE=InnoDB DEFAULT CHARSET=utf8");
myquery(rc);
-
- rc= mysql_query(mysql,"create table t1 ( id int(8), name_id int(8), value varchar(10)) TYPE=InnoDB DEFAULT CHARSET=utf8");
+
+ rc= mysql_query(mysql, "create table t1 ( id int(8), name_id int(8), value varchar(10)) TYPE=InnoDB DEFAULT CHARSET=utf8");
myquery(rc);
- rc= mysql_query(mysql,"create table t2 (id int(8), name_id int(8), value varchar(10)) TYPE=InnoDB DEFAULT CHARSET=utf8;");
+ rc= mysql_query(mysql, "create table t2 (id int(8), name_id int(8), value varchar(10)) TYPE=InnoDB DEFAULT CHARSET=utf8;");
myquery(rc);
- rc= mysql_query(mysql,"create table t4(id int(8), value varchar(10)) TYPE=InnoDB DEFAULT CHARSET=utf8");
+ rc= mysql_query(mysql, "create table t4(id int(8), value varchar(10)) TYPE=InnoDB DEFAULT CHARSET=utf8");
myquery(rc);
- rc= mysql_query(mysql, "insert into t3 values (1,1,1),(2,2,null)");
+ rc= mysql_query(mysql, "insert into t3 values (1, 1, 1), (2, 2, null)");
myquery(rc);
-
- rc= mysql_query(mysql, "insert into t1 values (1,1,'aaa'),(2,null,'bbb')");
+
+ rc= mysql_query(mysql, "insert into t1 values (1, 1, 'aaa'), (2, null, 'bbb')");
myquery(rc);
- rc= mysql_query(mysql,"insert into t2 values (1,2,'ccc')");
+ rc= mysql_query(mysql, "insert into t2 values (1, 2, 'ccc')");
myquery(rc);
- rc= mysql_query(mysql, "insert into t4 values (1,'Name1'),(2,null)");
+ rc= mysql_query(mysql, "insert into t4 values (1, 'Name1'), (2, null)");
myquery(rc);
- stmt= mysql_prepare(mysql, query, strlen(query));
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
for (i= 0; i < 3; i++)
{
- rc= mysql_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
}
mysql_stmt_close(stmt);
- rc= mysql_query(mysql, "DROP TABLE t1,t2,t3,t4");
+ rc= mysql_query(mysql, "DROP TABLE t1, t2, t3, t4");
myquery(rc);
}
+
static void test_bug3035()
{
MYSQL_STMT *stmt;
@@ -9259,14 +9123,14 @@ static void test_bug3035()
longlong int64_val;
ulonglong uint64_val;
double double_val, udouble_val;
- char longlong_as_string[22],ulonglong_as_string[22];
+ char longlong_as_string[22], ulonglong_as_string[22];
/* mins and maxes */
const int8 int8_min= -128;
const int8 int8_max= 127;
const uint8 uint8_min= 0;
const uint8 uint8_max= 255;
-
+
const int16 int16_min= -32768;
const int16 int16_max= 32767;
const uint16 uint16_min= 0;
@@ -9283,11 +9147,11 @@ static void test_bug3035()
const ulonglong uint64_min= 0U;
const ulonglong uint64_max= ULL(18446744073709551615);
-
+
const char *stmt_text;
-
+
myheader("test_bug3035");
-
+
stmt_text= "DROP TABLE IF EXISTS t1";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
@@ -9303,31 +9167,31 @@ static void test_bug3035()
bzero(bind_array, sizeof(bind_array));
bind_array[0].buffer_type= MYSQL_TYPE_TINY;
- bind_array[0].buffer= (char*) &int8_val;
+ bind_array[0].buffer= (void *) &int8_val;
bind_array[1].buffer_type= MYSQL_TYPE_TINY;
- bind_array[1].buffer= (char*) &uint8_val;
+ bind_array[1].buffer= (void *) &uint8_val;
bind_array[1].is_unsigned= 1;
bind_array[2].buffer_type= MYSQL_TYPE_SHORT;
- bind_array[2].buffer= (char*) &int16_val;
-
+ bind_array[2].buffer= (void *) &int16_val;
+
bind_array[3].buffer_type= MYSQL_TYPE_SHORT;
- bind_array[3].buffer= (char*) &uint16_val;
+ bind_array[3].buffer= (void *) &uint16_val;
bind_array[3].is_unsigned= 1;
bind_array[4].buffer_type= MYSQL_TYPE_LONG;
- bind_array[4].buffer= (char*) &int32_val;
+ bind_array[4].buffer= (void *) &int32_val;
bind_array[5].buffer_type= MYSQL_TYPE_LONG;
- bind_array[5].buffer= (char*) &uint32_val;
+ bind_array[5].buffer= (void *) &uint32_val;
bind_array[5].is_unsigned= 1;
bind_array[6].buffer_type= MYSQL_TYPE_LONGLONG;
- bind_array[6].buffer= (char*) &int64_val;
-
+ bind_array[6].buffer= (void *) &int64_val;
+
bind_array[7].buffer_type= MYSQL_TYPE_LONGLONG;
- bind_array[7].buffer= (char*) &uint64_val;
+ bind_array[7].buffer= (void *) &uint64_val;
bind_array[7].is_unsigned= 1;
stmt= mysql_stmt_init(mysql);
@@ -9351,7 +9215,7 @@ static void test_bug3035()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
+
int8_val= int8_max;
uint8_val= uint8_max;
int16_val= int16_max;
@@ -9365,7 +9229,7 @@ static void test_bug3035()
check_execute(stmt, rc);
stmt_text= "SELECT i8, ui8, i16, ui16, i32, ui32, i64, ui64, ui64, "
- "cast(ui64 as signed),ui64, cast(ui64 as signed)"
+ "cast(ui64 as signed), ui64, cast(ui64 as signed)"
"FROM t1 ORDER BY id ASC";
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
@@ -9375,19 +9239,19 @@ static void test_bug3035()
check_execute(stmt, rc);
bind_array[8].buffer_type= MYSQL_TYPE_DOUBLE;
- bind_array[8].buffer= (char*) &udouble_val;
+ bind_array[8].buffer= (void *) &udouble_val;
bind_array[9].buffer_type= MYSQL_TYPE_DOUBLE;
- bind_array[9].buffer= (char*) &double_val;
+ bind_array[9].buffer= (void *) &double_val;
bind_array[10].buffer_type= MYSQL_TYPE_STRING;
- bind_array[10].buffer= (char*) &ulonglong_as_string;
+ bind_array[10].buffer= (void *) &ulonglong_as_string;
bind_array[10].buffer_length= sizeof(ulonglong_as_string);
bind_array[11].buffer_type= MYSQL_TYPE_STRING;
- bind_array[11].buffer= (char*) &longlong_as_string;
+ bind_array[11].buffer= (void *) &longlong_as_string;
bind_array[11].buffer_length= sizeof(longlong_as_string);
-
+
mysql_stmt_bind_result(stmt, bind_array);
rc= mysql_stmt_fetch(stmt);
@@ -9408,7 +9272,7 @@ static void test_bug3035()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
-
+
assert(int8_val == int8_max);
assert(uint8_val == uint8_max);
assert(int16_val == int16_max);
@@ -9423,7 +9287,7 @@ static void test_bug3035()
assert(!strcmp(ulonglong_as_string, "18446744073709551615"));
rc= mysql_stmt_fetch(stmt);
- assert(rc == MYSQL_NO_DATA);
+ assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
@@ -9431,31 +9295,32 @@ static void test_bug3035()
mysql_real_query(mysql, stmt_text, strlen(stmt_text));
}
+
static void test_union2()
{
MYSQL_STMT *stmt;
int rc, i;
myheader("test_union2");
-
+
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
- rc= mysql_query(mysql,"CREATE TABLE t1(col1 INT,\
- col2 VARCHAR(40), \
- col3 SMALLINT,\
+ rc= mysql_query(mysql, "CREATE TABLE t1(col1 INT, \
+ col2 VARCHAR(40), \
+ col3 SMALLINT, \
col4 TIMESTAMP)");
myquery(rc);
stmt= mysql_simple_prepare(mysql,
- "select col1 FROM t1 where col1=1 union distinct \
-select col1 FROM t1 where col1=2");
+ "select col1 FROM t1 where col1=1 union distinct "
+ "select col1 FROM t1 where col1=2");
check_stmt(stmt);
for (i= 0; i < 3; i++)
{
rc= mysql_stmt_execute(stmt);
- check_execute(stmt,rc);
+ check_execute(stmt, rc);
assert(0 == my_process_stmt_result(stmt));
}
@@ -9467,7 +9332,7 @@ select col1 FROM t1 where col1=2");
/*
- This tests for various mysql_send_long_data bugs described in #1664
+ This tests for various mysql_stmt_send_long_data bugs described in #1664
*/
static void test_bug1664()
@@ -9477,54 +9342,54 @@ static void test_bug1664()
const char *data;
const char *str_data= "Simple string";
MYSQL_BIND bind[2];
- const char *query= "INSERT INTO test_long_data(col2, col1) VALUES(?,?)";
-
+ const char *query= "INSERT INTO test_long_data(col2, col1) VALUES(?, ?)";
+
myheader("test_bug1664");
-
- rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data");
myquery(rc);
-
- rc= mysql_query(mysql,"CREATE TABLE test_long_data(col1 int, col2 long varchar)");
+
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data(col1 int, col2 long varchar)");
myquery(rc);
-
+
stmt= mysql_stmt_init(mysql);
check_stmt(stmt);
rc= mysql_stmt_prepare(stmt, query, strlen(query));
check_execute(stmt, rc);
-
+
verify_param_count(stmt, 2);
-
+
bzero(&bind, sizeof(bind));
-
- bind[0].buffer_type= FIELD_TYPE_STRING;
- bind[0].buffer= (char *)str_data;
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *)str_data;
bind[0].buffer_length= strlen(str_data);
- bind[1].buffer= (char *)&int_data;
- bind[1].buffer_type= FIELD_TYPE_LONG;
-
- rc= mysql_stmt_bind_param(stmt,bind);
+ bind[1].buffer= (void *)&int_data;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
-
+
int_data= 1;
- /*
- Let us supply empty long_data. This should work and should
+ /*
+ Let us supply empty long_data. This should work and should
not break following execution.
*/
data= "";
- rc= mysql_stmt_send_long_data(stmt,0,data,strlen(data));
- check_execute(stmt,rc);
+ rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data));
+ check_execute(stmt, rc);
rc= mysql_stmt_execute(stmt);
- check_execute(stmt,rc);
-
- verify_col_data("test_long_data","col1","1");
- verify_col_data("test_long_data","col2","");
+ check_execute(stmt, rc);
+
+ verify_col_data("test_long_data", "col1", "1");
+ verify_col_data("test_long_data", "col2", "");
- rc= mysql_query(mysql,"DELETE FROM test_long_data");
+ rc= mysql_query(mysql, "DELETE FROM test_long_data");
myquery(rc);
-
+
/* This should pass OK */
data= (char *)"Data";
rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data));
@@ -9532,7 +9397,7 @@ static void test_bug1664()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
+
verify_col_data("test_long_data", "col1", "1");
verify_col_data("test_long_data", "col2", "Data");
@@ -9542,51 +9407,51 @@ static void test_bug1664()
/*
Now we are changing int parameter and don't do anything
- with first parameter. Second mysql_execute() should run
+ with first parameter. Second mysql_stmt_execute() should run
OK treating this first parameter as string parameter.
*/
-
+
int_data= 2;
/* execute */
- rc = mysql_stmt_execute(stmt);
+ rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
+
verify_col_data("test_long_data", "col1", "2");
verify_col_data("test_long_data", "col2", str_data);
/* clean up */
rc= mysql_query(mysql, "DELETE FROM test_long_data");
myquery(rc);
-
+
/*
- Now we are sending other long data. It should not be
+ Now we are sending other long data. It should not be
concatened to previous.
*/
data= (char *)"SomeOtherData";
rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data));
check_execute(stmt, rc);
-
+
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
verify_col_data("test_long_data", "col1", "2");
verify_col_data("test_long_data", "col2", "SomeOtherData");
-
+
mysql_stmt_close(stmt);
/* clean up */
rc= mysql_query(mysql, "DELETE FROM test_long_data");
myquery(rc);
-
+
/* Now let us test how mysql_stmt_reset works. */
stmt= mysql_stmt_init(mysql);
check_stmt(stmt);
rc= mysql_stmt_prepare(stmt, query, strlen(query));
check_execute(stmt, rc);
- rc= mysql_bind_param(stmt, bind);
+ rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
-
+
data= (char *)"SomeData";
rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data));
check_execute(stmt, rc);
@@ -9596,12 +9461,12 @@ static void test_bug1664()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
+
verify_col_data("test_long_data", "col1", "2");
verify_col_data("test_long_data", "col2", str_data);
mysql_stmt_close(stmt);
-
+
/* Final clean up */
rc= mysql_query(mysql, "DROP TABLE test_long_data");
myquery(rc);
@@ -9614,35 +9479,31 @@ static void test_order_param()
int rc;
myheader("test_order_param");
-
+
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
- rc= mysql_query(mysql,"CREATE TABLE t1(a INT, b char(10))");
+ rc= mysql_query(mysql, "CREATE TABLE t1(a INT, b char(10))");
myquery(rc);
stmt= mysql_simple_prepare(mysql,
- "select sum(a) + 200, 1 from t1 \
-union distinct \
-select sum(a) + 200, 1 from t1 \
-group by b ");
+ "select sum(a) + 200, 1 from t1 "
+ " union distinct "
+ "select sum(a) + 200, 1 from t1 group by b ");
check_stmt(stmt);
mysql_stmt_close(stmt);
- stmt= mysql_simple_prepare(mysql,
- "select sum(a) + 200, ? from t1 \
-group by b \
-union distinct \
-select sum(a) + 200, 1 from t1 \
-group by b ");
+ stmt= mysql_simple_prepare(mysql,
+ "select sum(a) + 200, ? from t1 group by b "
+ " union distinct "
+ "select sum(a) + 200, 1 from t1 group by b ");
check_stmt(stmt);
mysql_stmt_close(stmt);
stmt= mysql_simple_prepare(mysql,
- "select sum(a) + 200, ? from t1 \
-union distinct \
-select sum(a) + 200, 1 from t1 \
-group by b ");
+ "select sum(a) + 200, ? from t1 "
+ " union distinct "
+ "select sum(a) + 200, 1 from t1 group by b ");
check_stmt(stmt);
mysql_stmt_close(stmt);
@@ -9658,35 +9519,41 @@ static void test_union_param()
int rc, i;
MYSQL_BIND bind[2];
char my_val[4];
- ulong my_length = 3L;
- long my_null = 0L;
+ ulong my_length= 3L;
+ long my_null= 0L;
myheader("test_union_param");
strcpy(my_val, "abc");
-
+
query= (char*)"select ? as my_col union distinct select ?";
- stmt= mysql_prepare(mysql, query, strlen(query));
+ stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ bzero((char*) bind, sizeof(bind));
+
/* bind parameters */
- bind[0].buffer_type= FIELD_TYPE_STRING;
- bind[0].buffer= &my_val;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char*) &my_val;
bind[0].buffer_length= 4;
bind[0].length= &my_length;
bind[0].is_null= (char*)&my_null;
- bind[1].buffer_type= FIELD_TYPE_STRING;
- bind[1].buffer= &my_val;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= (char*) &my_val;
bind[1].buffer_length= 4;
bind[1].length= &my_length;
bind[1].is_null= (char*)&my_null;
- rc= mysql_bind_param(stmt, bind);
- check_execute(stmt,rc);
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
for (i= 0; i < 3; i++)
{
rc= mysql_stmt_execute(stmt);
- check_execute(stmt,rc);
+ check_execute(stmt, rc);
assert(1 == my_process_stmt_result(stmt));
}
@@ -9716,31 +9583,31 @@ static void test_ps_i18n()
/*
Create table with binary columns, set session character set to cp1251,
client character set to koi8, and make sure that there is conversion
- on insert and no conversion on select
+ on insert and no conversion on select
*/
stmt_text= "CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255))";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
-
+
stmt_text= "SET CHARACTER_SET_CLIENT=koi8r, "
"CHARACTER_SET_CONNECTION=cp1251, "
"CHARACTER_SET_RESULTS=koi8r";
-
+
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
-
+
bzero(bind_array, sizeof(bind_array));
bind_array[0].buffer_type= MYSQL_TYPE_STRING;
- bind_array[0].buffer= (char*) koi8;
+ bind_array[0].buffer= (void *) koi8;
bind_array[0].buffer_length= strlen(koi8);
-
+
bind_array[1].buffer_type= MYSQL_TYPE_STRING;
- bind_array[1].buffer= (char*) koi8;
+ bind_array[1].buffer= (void *) koi8;
bind_array[1].buffer_length= strlen(koi8);
-
+
stmt= mysql_stmt_init(mysql);
check_stmt(stmt);
@@ -9784,7 +9651,7 @@ static void test_ps_i18n()
assert(!memcmp(buf2, cp1251, buf1_len));
rc= mysql_stmt_fetch(stmt);
- assert(rc == MYSQL_NO_DATA);
+ assert(rc == MYSQL_NO_DATA);
stmt_text= "DROP TABLE IF EXISTS t1";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
@@ -9796,25 +9663,25 @@ static void test_ps_i18n()
binary data. Binary data must not be converted on insert, and both
columns must be converted to client character set on select.
*/
-
+
stmt_text= "CREATE TABLE t1 (c1 VARCHAR(255) CHARACTER SET cp1251, "
"c2 VARCHAR(255) CHARACTER SET cp1251)";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
-
+
stmt_text= "INSERT INTO t1 (c1, c2) VALUES (?, ?)";
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
check_execute(stmt, rc);
-
+
/* this data must be converted */
bind_array[0].buffer_type= MYSQL_TYPE_STRING;
- bind_array[0].buffer= (char*) koi8;
+ bind_array[0].buffer= (void *) koi8;
bind_array[0].buffer_length= strlen(koi8);
-
+
bind_array[1].buffer_type= MYSQL_TYPE_STRING;
- bind_array[1].buffer= (char*) koi8;
+ bind_array[1].buffer= (void *) koi8;
bind_array[1].buffer_length= strlen(koi8);
mysql_stmt_bind_param(stmt, bind_array);
@@ -9823,16 +9690,16 @@ static void test_ps_i18n()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
-
+
/* this data must not be converted */
bind_array[0].buffer_type= MYSQL_TYPE_BLOB;
- bind_array[0].buffer= (char*) cp1251;
+ bind_array[0].buffer= (void *) cp1251;
bind_array[0].buffer_length= strlen(cp1251);
-
+
bind_array[1].buffer_type= MYSQL_TYPE_BLOB;
- bind_array[1].buffer= (char*) cp1251;
+ bind_array[1].buffer= (void *) cp1251;
bind_array[1].buffer_length= strlen(cp1251);
-
+
mysql_stmt_bind_param(stmt, bind_array);
mysql_stmt_send_long_data(stmt, 0, cp1251, strlen(cp1251));
@@ -9841,7 +9708,7 @@ static void test_ps_i18n()
check_execute(stmt, rc);
/* Fetch data and verify that rows are in koi8 */
-
+
stmt_text= "SELECT c1, c2 FROM t1";
/* c1 and c2 are binary so no conversion will be done on select */
@@ -9868,13 +9735,309 @@ static void test_ps_i18n()
assert(!memcmp(buf1, koi8, buf1_len));
assert(!memcmp(buf2, koi8, buf1_len));
}
- assert(rc == MYSQL_NO_DATA);
+ assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
stmt_text= "DROP TABLE t1";
- mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "SET NAMES DEFAULT";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
}
+
+static void test_bug3796()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ const char *concat_arg0= "concat_with_";
+ enum { OUT_BUFF_SIZE= 30 };
+ char out_buff[OUT_BUFF_SIZE];
+ char canonical_buff[OUT_BUFF_SIZE];
+ ulong out_length;
+ const char *stmt_text;
+ int rc;
+
+ myheader("test_bug3796");
+
+ /* Create and fill test table */
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "CREATE TABLE t1 (a INT, b VARCHAR(30))";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "INSERT INTO t1 VALUES(1, 'ONE'), (2, 'TWO')";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ /* Create statement handle and prepare it with select */
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT concat(?, b) FROM t1";
+
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ /* Bind input buffers */
+ bzero(bind, sizeof(bind));
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void *) concat_arg0;
+ bind[0].buffer_length= strlen(concat_arg0);
+
+ mysql_stmt_bind_param(stmt, bind);
+
+ /* Execute the select statement */
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bind[0].buffer= (void *) out_buff;
+ bind[0].buffer_length= OUT_BUFF_SIZE;
+ bind[0].length= &out_length;
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ printf("Concat result: '%s'\n", out_buff);
+ check_execute(stmt, rc);
+ strcpy(canonical_buff, concat_arg0);
+ strcat(canonical_buff, "ONE");
+ assert(strlen(canonical_buff) == out_length &&
+ strncmp(out_buff, canonical_buff, out_length) == 0);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ strcpy(canonical_buff + strlen(concat_arg0), "TWO");
+ assert(strlen(canonical_buff) == out_length &&
+ strncmp(out_buff, canonical_buff, out_length) == 0);
+ printf("Concat result: '%s'\n", out_buff);
+
+ rc= mysql_stmt_fetch(stmt);
+ assert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+}
+
+
+static void test_bug4026()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[2];
+ MYSQL_TIME time_in, time_out;
+ MYSQL_TIME datetime_in, datetime_out;
+ const char *stmt_text;
+ int rc;
+
+ myheader("test_bug4026");
+
+ /* Check that microseconds are inserted and selected successfully */
+
+ /* Create a statement handle and prepare it with select */
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT ?, ?";
+
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ /* Bind input buffers */
+ bzero(bind, sizeof(bind));
+ bzero(&time_in, sizeof(time_in));
+ bzero(&time_out, sizeof(time_out));
+ bzero(&datetime_in, sizeof(datetime_in));
+ bzero(&datetime_out, sizeof(datetime_out));
+
+ bind[0].buffer_type= MYSQL_TYPE_TIME;
+ bind[0].buffer= (void *) &time_in;
+ bind[1].buffer_type= MYSQL_TYPE_DATETIME;
+ bind[1].buffer= (void *) &datetime_in;
+
+ time_in.hour= 23;
+ time_in.minute= 59;
+ time_in.second= 59;
+ time_in.second_part= 123456;
+
+ datetime_in= time_in;
+ datetime_in.year= 2003;
+ datetime_in.month= 12;
+ datetime_in.day= 31;
+
+ mysql_stmt_bind_param(stmt, bind);
+
+ /* Execute the select statement */
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bind[0].buffer= (void *) &time_out;
+ bind[1].buffer= (void *) &datetime_out;
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ assert(rc == 0);
+ printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second,
+ time_out.second_part);
+ printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month,
+ datetime_out.day, datetime_out.hour,
+ datetime_out.minute, datetime_out.second,
+ datetime_out.second_part);
+ assert(memcmp(&time_in, &time_out, sizeof(time_in)) == 0);
+ assert(memcmp(&datetime_in, &datetime_out, sizeof(datetime_in)) == 0);
+ mysql_stmt_close(stmt);
+}
+
+
+static void test_bug4079()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ const char *stmt_text;
+ unsigned long res;
+ int rc;
+
+ myheader("test_bug4079");
+
+ /* Create and fill table */
+ mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2)");
+
+ /* Prepare erroneous statement */
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT 1 < (SELECT a FROM t1)";
+
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ /* Execute the select statement */
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ /* Bind input buffers */
+ bzero(bind, sizeof(bind));
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void *) &res;
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ assert(rc != 0 && rc != MYSQL_NO_DATA);
+ printf("Got error from mysql_stmt_fetch (as expected):\n%s\n",
+ mysql_stmt_error(stmt));
+ /* buggy version of libmysql hanged up here */
+ mysql_stmt_close(stmt);
+}
+
+
+static void test_bug4236()
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ MYSQL_STMT backup;
+
+ myheader("test_bug4296");
+
+ stmt= mysql_stmt_init(mysql);
+
+ /* mysql_stmt_execute() of statement with statement id= 0 crashed server */
+ stmt_text= "SELECT 1";
+ /* We need to prepare statement to pass by possible check in libmysql */
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ /* Hack to check that server works OK if statement wasn't found */
+ backup.stmt_id= stmt->stmt_id;
+ stmt->stmt_id= 0;
+ rc= mysql_stmt_execute(stmt);
+ assert(rc);
+ /* Restore original statement id to be able to reprepare it */
+ stmt->stmt_id= backup.stmt_id;
+
+ mysql_stmt_close(stmt);
+}
+
+
+static void test_bug4030()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[3];
+ MYSQL_TIME time_canonical, time_out;
+ MYSQL_TIME date_canonical, date_out;
+ MYSQL_TIME datetime_canonical, datetime_out;
+ const char *stmt_text;
+ int rc;
+
+ myheader("test_bug4030");
+
+ /* Check that microseconds are inserted and selected successfully */
+
+ /* Execute a query with time values in prepared mode */
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT '23:59:59.123456', '2003-12-31', "
+ "'2003-12-31 23:59:59.123456'";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ /* Bind output buffers */
+ bzero(bind, sizeof(bind));
+ bzero(&time_canonical, sizeof(time_canonical));
+ bzero(&time_out, sizeof(time_out));
+ bzero(&date_canonical, sizeof(date_canonical));
+ bzero(&date_out, sizeof(date_out));
+ bzero(&datetime_canonical, sizeof(datetime_canonical));
+ bzero(&datetime_out, sizeof(datetime_out));
+
+ bind[0].buffer_type= MYSQL_TYPE_TIME;
+ bind[0].buffer= (void *) &time_out;
+ bind[1].buffer_type= MYSQL_TYPE_DATE;
+ bind[1].buffer= (void *) &date_out;
+ bind[2].buffer_type= MYSQL_TYPE_DATETIME;
+ bind[2].buffer= (void *) &datetime_out;
+
+ time_canonical.hour= 23;
+ time_canonical.minute= 59;
+ time_canonical.second= 59;
+ time_canonical.second_part= 123456;
+ time_canonical.time_type= MYSQL_TIMESTAMP_TIME;
+
+ date_canonical.year= 2003;
+ date_canonical.month= 12;
+ date_canonical.day= 31;
+ date_canonical.time_type= MYSQL_TIMESTAMP_DATE;
+
+ datetime_canonical= time_canonical;
+ datetime_canonical.year= 2003;
+ datetime_canonical.month= 12;
+ datetime_canonical.day= 31;
+ datetime_canonical.time_type= MYSQL_TIMESTAMP_DATETIME;
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ assert(rc == 0);
+ printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second,
+ time_out.second_part);
+ printf("%d-%d-%d\n", date_out.year, date_out.month, date_out.day);
+ printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month,
+ datetime_out.day, datetime_out.hour,
+ datetime_out.minute, datetime_out.second,
+ datetime_out.second_part);
+ assert(memcmp(&time_canonical, &time_out, sizeof(time_out)) == 0);
+ assert(memcmp(&date_canonical, &date_out, sizeof(date_out)) == 0);
+ assert(memcmp(&datetime_canonical, &datetime_out, sizeof(datetime_out)) == 0);
+ mysql_stmt_close(stmt);
+}
+
+
/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -9911,7 +10074,7 @@ static struct my_option client_test_long_options[] =
static void client_test_print_version(void)
{
fprintf(stdout, "%s Distrib %s, for %s (%s)\n\n",
- my_progname,MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+ my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
}
@@ -9919,18 +10082,18 @@ static void usage(void)
{
/*
* show the usage string when the user asks for this
- */
- putc('\n',stdout);
+ */
+ putc('\n', stdout);
puts("***********************************************************************\n");
puts(" Test for client-server protocol 4.1");
puts(" By Monty & Venu \n");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
+ puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software, ");
puts("and you are welcome to modify and redistribute it under the GPL license\n");
puts(" Copyright (C) 1995-2003 MySQL AB ");
puts("-----------------------------------------------------------------------\n");
client_test_print_version();
- fprintf(stdout,"Usage: %s [OPTIONS]\n\n", my_progname);
-
+ fprintf(stdout, "Usage: %s [OPTIONS]\n\n", my_progname);
+
my_print_help(client_test_long_options);
print_defaults("my", client_test_load_default_groups);
my_print_variables(client_test_long_options);
@@ -9940,7 +10103,7 @@ static void usage(void)
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
+ char *argument)
{
switch (optid) {
case '#':
@@ -9952,7 +10115,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *start=argument;
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
opt_password= my_strdup(argument, MYF(MY_FAE));
- while (*argument) *argument++= 'x'; /* Destroy argument */
+ while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
start[1]=0;
}
@@ -9960,7 +10123,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
tty_password= 1;
break;
case '?':
- case 'I': /* Info */
+ case 'I': /* Info */
usage();
exit(0);
break;
@@ -9972,12 +10135,12 @@ static void get_options(int argc, char **argv)
{
int ho_error;
- if ((ho_error= handle_options(&argc, &argv, client_test_long_options,
+ if ((ho_error= handle_options(&argc, &argv, client_test_long_options,
get_one_option)))
exit(ho_error);
if (tty_password)
- opt_password=get_tty_password(NullS);
+ opt_password= get_tty_password(NullS);
return;
}
@@ -9987,49 +10150,51 @@ static void get_options(int argc, char **argv)
static void print_test_output()
{
- fprintf(stdout,"\n\n");
- fprintf(stdout,"All '%d' tests were successful (in '%d' iterations)",
+ fprintf(stdout, "\n\n");
+ fprintf(stdout, "All '%d' tests were successful (in '%d' iterations)",
test_count-1, opt_count);
- fprintf(stdout,"\n Total execution time: %g SECS", total_time);
+ fprintf(stdout, "\n Total execution time: %g SECS", total_time);
if (opt_count > 1)
- fprintf(stdout," (Avg: %g SECS)", total_time/opt_count);
-
- fprintf(stdout,"\n\n!!! SUCCESS !!!\n");
+ fprintf(stdout, " (Avg: %g SECS)", total_time/opt_count);
+
+ fprintf(stdout, "\n\n!!! SUCCESS !!!\n");
}
-/********************************************************
-* main routine *
-*********************************************************/
+
+/***************************************************************************
+ main routine
+***************************************************************************/
+
int main(int argc, char **argv)
-{
+{
DEBUGGER_OFF;
MY_INIT(argv[0]);
- load_defaults("my",client_test_load_default_groups,&argc,&argv);
+ load_defaults("my", client_test_load_default_groups, &argc, &argv);
defaults_argv= argv;
- get_options(argc,argv);
-
+ get_options(argc, argv);
+
client_connect(); /* connect to server */
-
+
total_time= 0;
- for (iter_count=1; iter_count <= opt_count; iter_count++)
+ for (iter_count= 1; iter_count <= opt_count; iter_count++)
{
/* Start of tests */
test_count= 1;
-
+
start_time= time((time_t *)0);
client_query(); /* simple client query test */
#if NOT_YET_WORKING
/* Used for internal new development debugging */
- test_drop_temp(); /* to test DROP TEMPORARY TABLE Access checks */
+ test_drop_temp(); /* Test DROP TEMPORARY TABLE Access checks */
#endif
- test_fetch_seek(); /* to test stmt seek() functions */
+ test_fetch_seek(); /* Test stmt seek() functions */
test_fetch_nobuffs(); /* to fecth without prior bound buffers */
test_open_direct(); /* direct execution in the middle of open stmts */
test_fetch_null(); /* to fetch null data */
test_ps_null_param(); /* Fetch value of null parameter */
- test_fetch_date(); /* to fetch date,time and timestamp */
+ test_fetch_date(); /* to fetch date, time and timestamp */
test_fetch_str(); /* to fetch string to all types */
test_fetch_long(); /* to fetch long to all types */
test_fetch_short(); /* to fetch short to all types */
@@ -10046,12 +10211,12 @@ int main(int argc, char **argv)
test_ps_conj_select(); /* prepare select with "where a=? or b=?" */
test_select_show_table();/* simple show prepare */
#if NOT_USED
- /*
- Enable this tests from 4.1.1 when mysql_param_result() is
- supported
+ /*
+ Enable this tests from 4.1.1 when mysql_param_result() is
+ supported
*/
test_select_meta(); /* select param meta information */
- test_update_meta(); /* update param meta information */
+ test_update_meta(); /* update param meta information */
test_insert_meta(); /* insert param meta information */
#endif
test_func_fields(); /* test for new 4.1 MYSQL_FIELD members */
@@ -10060,21 +10225,21 @@ int main(int argc, char **argv)
test_set_variable(); /* prepare with set variables */
test_select_show(); /* prepare - show test */
test_prepare_noparam(); /* prepare without parameters */
- test_bind_result(); /* result bind test */
- test_prepare_simple(); /* simple prepare */
+ test_bind_result(); /* result bind test */
+ test_prepare_simple(); /* simple prepare */
test_prepare(); /* prepare test */
test_null(); /* test null data handling */
test_debug_example(); /* some debugging case */
test_update(); /* prepare-update test */
test_simple_update(); /* simple prepare with update */
test_simple_delete(); /* prepare with delete */
- test_double_compare(); /* float comparision */
+ test_double_compare(); /* float comparision */
client_store_result(); /* usage of mysql_store_result() */
- client_use_result(); /* usage of mysql_use_result() */
+ client_use_result(); /* usage of mysql_use_result() */
test_tran_bdb(); /* transaction test on BDB table type */
- test_tran_innodb(); /* transaction test on InnoDB table type */
+ test_tran_innodb(); /* transaction test on InnoDB table type */
test_prepare_ext(); /* test prepare with all types
- conversion -- TODO */
+ conversion -- TODO */
test_prepare_syntax(); /* syntax check for prepares */
test_field_names(); /* test for field names */
test_field_flags(); /* test to help .NET provider team */
@@ -10088,7 +10253,7 @@ int main(int argc, char **argv)
test_prepare_field_result(); /* prepare meta info */
test_multi_stmt(); /* multi stmt test */
test_multi_statements();/* test multi statement execution */
- test_prepare_multi_statements(); /* check that multi statements are
+ test_prepare_multi_statements(); /* check that multi statements are
disabled in PS */
test_store_result(); /* test the store_result */
test_store_result1(); /* test store result without buffers */
@@ -10106,71 +10271,81 @@ int main(int argc, char **argv)
test_ushort_bug(); /* test a simple conv bug from php */
test_sshort_bug(); /* test a simple conv bug from php */
test_stiny_bug(); /* test a simple conv bug from php */
- test_field_misc(); /* check the field info for misc case, bug: #74 */
+ test_field_misc(); /* check the field info for misc case, bug: #74 */
test_set_option(); /* test the SET OPTION feature, bug #85 */
/*TODO HF: here should be NO_EMBEDDED_ACCESS_CHECKS*/
#ifndef EMBEDDED_LIBRARY
- test_prepare_grant(); /* to test the GRANT command, bug #89 */
+ test_prepare_grant(); /* Test the GRANT command, bug #89 */
#endif
test_frm_bug(); /* test the crash when .frm is invalid, bug #93 */
test_explain_bug(); /* test for the EXPLAIN, bug #115 */
test_decimal_bug(); /* test for the decimal bug */
test_nstmts(); /* test n statements */
- test_logs(); ; /* to test logs */
- test_cuted_rows(); /* to test for WARNINGS from cuted rows */
- test_fetch_offset(); /* to test mysql_fetch_column with offset */
- test_fetch_column(); /* to test mysql_fetch_column */
+ test_logs(); ; /* Test logs */
+ test_cuted_rows(); /* Test for WARNINGS from cuted rows */
+ test_fetch_offset(); /* Test mysql_stmt_fetch_column with offset */
+ test_fetch_column(); /* Test mysql_stmt_fetch_column */
test_mem_overun(); /* test DBD ovverun bug */
test_list_fields(); /* test COM_LIST_FIELDS for DEFAULT */
test_free_result(); /* test mysql_stmt_free_result() */
- test_free_store_result(); /* test to make sure stmt results are cleared
+ test_free_store_result(); /* test to make sure stmt results are cleared
during stmt_free_result() */
test_sqlmode(); /* test for SQL_MODE */
test_ts(); /* test for timestamp BR#819 */
test_bug1115(); /* BUG#1115 */
test_bug1180(); /* BUG#1180 */
test_bug1500(); /* BUG#1500 */
- test_bug1644(); /* BUG#1644 */
- test_bug1946(); /* test that placeholders are allowed only in
+ test_bug1644(); /* BUG#1644 */
+ test_bug1946(); /* test that placeholders are allowed only in
prepared queries */
- test_bug2248(); /* BUG#2248 */
+ test_bug2248(); /* BUG#2248 */
test_parse_error_and_bad_length(); /* test if bad length param in
- mysql_prepare() triggers error */
+ mysql_stmt_prepare() triggers error */
test_bug2247(); /* test that mysql_stmt_affected_rows() returns
- number of rows affected by last prepared
+ number of rows affected by last prepared
statement execution */
- test_subqueries(); /* repeatable subqueries */
+ test_subqueries(); /* repeatable subqueries */
test_bad_union(); /* correct setup of UNION */
- test_distinct(); /* distinct aggregate functions */
+ test_distinct(); /* distinct aggregate functions */
test_subqueries_ref(); /* outer reference in subqueries converted
- Item_field -> Item_ref */
- test_union(); /* test union with prepared statements */
- test_bug3117(); /* BUG#3117: LAST_INSERT_ID() */
- test_join(); /* different kinds of join, BUG#2794 */
- test_selecttmp(); /* temporary table used in select execution */
- test_create_drop(); /* some table manipulation BUG#2811 */
- test_rename(); /* rename test */
- test_do_set(); /* DO & SET commands test BUG#3393 */
- test_multi(); /* test of multi delete & update */
+ Item_field -> Item_ref */
+ test_union(); /* test union with prepared statements */
+ test_bug3117(); /* BUG#3117: LAST_INSERT_ID() */
+ test_join(); /* different kinds of join, BUG#2794 */
+ test_selecttmp(); /* temporary table used in select execution */
+ test_create_drop(); /* some table manipulation BUG#2811 */
+ test_rename(); /* rename test */
+ test_do_set(); /* DO & SET commands test BUG#3393 */
+ test_multi(); /* test of multi delete & update */
test_insert_select(); /* test INSERT ... SELECT */
test_bind_nagative(); /* bind negative to unsigned BUG#3223 */
- test_derived(); /* derived table with parameter BUG#3020 */
- test_xjoin(); /* complex join test */
+ test_derived(); /* derived table with parameter BUG#3020 */
+ test_xjoin(); /* complex join test */
test_bug3035(); /* inserts of INT32_MAX/UINT32_MAX */
- test_union2(); /* repeatable execution of union (Bug #3577) */
- test_bug1664(); /* test for bugs in mysql_stmt_send_long_data()
+ test_union2(); /* repeatable execution of union (Bug #3577) */
+ test_bug1664(); /* test for bugs in mysql_stmt_send_long_data()
call (Bug #1664) */
test_union_param();
- test_order_param(); /* ORDER BY with parameters in select list
- (Bug #3686 */
+ test_order_param(); /* ORDER BY with parameters in select list
+ (Bug #3686 */
test_ps_i18n(); /* test for i18n support in binary protocol */
+ test_bug3796(); /* test for select concat(?, <string>) */
+ test_bug4026(); /* test microseconds precision of time types */
+ test_bug4079(); /* erroneous subquery in prepared statement */
+ test_bug4236(); /* init -> execute */
+ test_bug4030(); /* test conversion string -> time types in
+ libmysql */
+ /*
+ XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
+ DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
+ */
end_time= time((time_t *)0);
total_time+= difftime(end_time, start_time);
-
+
/* End of tests */
}
-
+
client_disconnect(); /* disconnect from server */
free_defaults(defaults_argv);
print_test_output();
@@ -10178,3 +10353,4 @@ int main(int argc, char **argv)
return(0);
}
+
diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c
index 2e9f980bb5d..bb0a76d6c49 100644
--- a/tools/mysqlmanager.c
+++ b/tools/mysqlmanager.c
@@ -357,7 +357,7 @@ LOG_MSG_FUNC(log_info,LOG_INFO)
#ifndef DBUG_OFF
LOG_MSG_FUNC(log_debug,LOG_DEBUG)
#else
-void log_debug(const char* __attribute__((unused)) fmt,...) {}
+void log_debug(const char* fmt __attribute__((unused)),...) {}
#endif
static void handle_sigterm(int sig __attribute__((unused)))
@@ -687,7 +687,7 @@ HANDLE_DECL(handle_stop_exec)
error="Process not running";
goto err;
}
- if (mysql_shutdown(&e->mysql))
+ if (mysql_shutdown(&e->mysql, SHUTDOWN_DEFAULT))
{
/* e->th=0; */ /* th may be a struct */
pthread_mutex_unlock(&e->lock);
diff --git a/vio/test-sslserver.c b/vio/test-sslserver.c
index 71b194838c7..d05e50af16b 100644
--- a/vio/test-sslserver.c
+++ b/vio/test-sslserver.c
@@ -91,7 +91,12 @@ main(int argc __attribute__((unused)), char** argv)
struct sockaddr_in sa_cli;
int listen_sd;
int err;
+
+#if defined(__sgi) && _NO_XOPEN4 && _NO_XOPEN5
+ socklen_t client_len;
+#else
size_t client_len;
+#endif
int reuseaddr = 1; /* better testing, uh? */
MY_INIT(argv[0]);